From f564e0e7248f977ea2397ea49e3d2e1804a65f7c Mon Sep 17 00:00:00 2001 From: Tim Vaughan Date: Thu, 23 Feb 2023 16:07:33 +0100 Subject: [PATCH] Textures now take "mapped" pigments as arguments. --- Textures.lua | 52 +++++++++++++++++++++++++++++++++++++----------- mandel_floor.lua | 37 +++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/Textures.lua b/Textures.lua index 3a4abaf..2b2e701 100644 --- a/Textures.lua +++ b/Textures.lua @@ -1,8 +1,9 @@ -- Textures for raymarcher + require "Vector" local V = Vector -local function make_phong_texture(lights, pigment, amb, diff, spec, shiny) +local function make_phong_texture(lights, mapped_pigment, amb, diff, spec, shiny) local normalize = V.normalize local eps = 0.0001 @@ -19,7 +20,7 @@ local function make_phong_texture(lights, pigment, amb, diff, spec, shiny) end return function (location, ray_dir, normal, count, sdf) - local colour = pigment(location[1],location[2]) + local colour = mapped_pigment(location) local thiscol = {colour[1]*amb, colour[2]*amb, colour[3]*amb} local reflected_ray = ray_dir - normal*(ray_dir*normal*2) @@ -47,20 +48,23 @@ local function make_count_texture(scale) end end -local function make_flat_texture(pigment) +local function make_flat_texture(mapped_pigment) return function (location, ray_dir, normal, count, sdf) - return pigment(location[1], location[2]) + return mapped_pigment(location) end end + +-- Pigments + local function make_solid_pigment(colour) - return function (x,y) + return function(x,y) return colour end end local function make_checkered_pigment(colour1, colour2) - return function (x,y) + return function(x,y) if (x%1 < 0.5 and y%1 < 0.5) or (x%1 > 0.5 and y%1 > 0.5) then return colour1 else @@ -69,14 +73,13 @@ local function make_checkered_pigment(colour1, colour2) end end -local function make_mandelbrot_pigment(set_colour, max_iter) +local function make_mandelbrot_pigment(set_pigment, nonset_pigment, max_iter) local function get_col(x,y,cx,cy,iter) if iter == 0 then - return set_colour + return set_pigment(cx, cy) elseif x^2 + y^2 > 4 then - local I = iter/max_iter - return {I,I,1-I} + return nonset_pigment(cx, cy) else return get_col(x^2 - y^2 + cx, 2*x*y + cy, @@ -85,7 +88,30 @@ local function make_mandelbrot_pigment(set_colour, max_iter) end return function (x,y) - get_col(0,0,x,y,max_iter) + return get_col(0,0,x,y,max_iter) + end +end + +-- Mapping functions + +-- These functions define mappings from 3D world coordinates to 2D +-- texture/pigment coordinates + +local function map_rectangular(pigment, xvec, yvec) + return function(location) + return pigment(location*xvec, location*yvec) + end +end + +local function map_spherical(pigment, centre, scale_theta, scale_phi) + return function(location) + local r = location-centre + local rnorm = V.norm(r) + + local phi = math.acos((V.z*r)/rnorm) + local theta = math.acos((V.x*r)/V.norm(V.cross(V.z,r))) + + return pigment(theta*scale_theta/math.pi, phi*scale_phi/math.pi) end end @@ -95,7 +121,9 @@ Textures = { make_count_texture = make_count_texture, make_solid_pigment = make_solid_pigment, make_checkered_pigment = make_checkered_pigment, - make_mandelbrot_pigment = make_mandelbrot_pigment + make_mandelbrot_pigment = make_mandelbrot_pigment, + map_rectangular = map_rectangular, + map_spherical = map_spherical } return Textures diff --git a/mandel_floor.lua b/mandel_floor.lua index 518a41f..0071eb0 100644 --- a/mandel_floor.lua +++ b/mandel_floor.lua @@ -16,26 +16,31 @@ local lights = {V.new{3,-3,1}} local scene = { sdf = - O.union( - O.diff( - O.diff( - O.diff( - P.make_sphere(V.new{0,0,1}, 1, - T.make_phong_texture(lights, - T.make_solid_pigment({0,1,0}), - 0.2, 0.7, 1.0, 100)), - P.make_sphere(V.new{0,0,1}, 0.8)), - P.make_pipe(V.new{0,0,1}, 0.5, V.new{0,1,0})), - P.make_pipe(V.new{0,0,1}, 0.5, V.new{1,0,0})), - - P.make_plane(V.new{0,0,0}, V.new{0,0,1}, + O.union{ + O.diff{P.make_sphere(V.new{0,0,0}, 1, + T.make_phong_texture(lights, + T.map_spherical( + T.make_checkered_pigment({0,1,0},{1,1,1}), + V.origin, 10, 10), + 0.2, 0.7, 1.0, 100)), + P.make_sphere(V.new{0,0,0}, 0.8), + P.make_pipe(V.new{0,0,0}, 0.5, V.new{0,1,0}), + P.make_pipe(V.new{0,0,0}, 0.5, V.new{1,0,0})}, + + P.make_plane(V.new{0,0,-1}, V.new{0,0,1}, T.make_phong_texture(lights, - T.make_mandelbrot_pigment({0,0,0}, 20), - 0.2, 1.0, 0, 1))), + T.map_rectangular( + T.make_mandelbrot_pigment( + T.make_checkered_pigment({0.5,0.2,1.0},{1,1,1}), + T.make_checkered_pigment({1,1,1},{0.5,0.2,1.0}), + 20), + V.x, V.y), + 0.2, 1.0, 0, 1))}, camera = {location = V.new{2,-5,1}, point_at = V.new{0,0,0}, right = V.x, fov = 1}} -Render.render(scene, 320, 200, "mandel_floor.ppm") +Render.render(scene, 1280, 960, "mandel_floor.ppm") +-- Render.render(scene, 320, 200, "mandel_floor.ppm") -- 2.20.1