#ifndef __RAY_MARCHING_MAPS_INC #define __RAY_MARCHING_MAPS_INC #include "math.cginc" #include "pema99.cginc" // Macros for transforming normal and tangent using autodiff. // r3r1 refers to "r3 to r1 transform", aka a mapping from a 3d real-valued // space to a 1d space. This is intended for use with a ray marcher. #define R3R1_DECLARE_BASIS_VECTORS(xyz) \ DifferentialPair dp_x = diffPair(xyz, float3(1, 0, 0)); \ DifferentialPair dp_y = diffPair(xyz, float3(0, 1, 0)); \ DifferentialPair dp_z = diffPair(xyz, float3(0, 0, 1)) #define R3R1_AUTODIFF_BASIS_VECTORS(fun, ...) \ DifferentialPair dp_x_out = fwd_diff(fun)(dp_x, ##__VA_ARGS__); \ DifferentialPair dp_y_out = fwd_diff(fun)(dp_y, ##__VA_ARGS__); \ DifferentialPair dp_z_out = fwd_diff(fun)(dp_z, ##__VA_ARGS__) #define R3R1_DEFORM_NORMAL_AND_TANGENT(normal, tangent) \ { \ float3 gradient = float3(dp_x_out.d, dp_y_out.d, dp_z_out.d); \ normal = normalize(gradient); \ float3 helper = abs(normal.z) < 0.999 ? float3(0, 0, 1) : float3(0, 1, 0); \ tangent = normalize(cross(helper, normal)); \ } // Syntactic sugar - wraps the previous three macros. #define R3R1_RAY_MARCH_NORMALS(xyz, normal, tangent, fun, ...) \ R3R1_DECLARE_BASIS_VECTORS(xyz); \ R3R1_AUTODIFF_BASIS_VECTORS(fun, ##__VA_ARGS__); \ R3R1_DEFORM_NORMAL_AND_TANGENT(normal, tangent) // Just trace a sphere of radius 0.1 for now. [Differentiable] public float map(float3 p) { float3 count = float3(5,5,1); float3 period = 0.2f; float3 half_period = period*0.5f; float3 which = abs(floor((p + half_period) / period)); if (any(abs(which) >= count)) { p = 1e6; } else { p = glsl_mod(p + half_period, period) - half_period; } p.z += 0.1f; return length(p) - 0.1f; } public void map_normal(inout float3 xyz, inout float3 normal, inout float3 tangent) { R3R1_RAY_MARCH_NORMALS(xyz, normal, tangent, map); } #endif // __RAY_MARCHING_MAPS_INC