diff options
| -rw-r--r-- | 3ner.cginc | 3 | ||||
| -rw-r--r-- | features.cginc | 4 | ||||
| -rw-r--r-- | ray_marching.cginc | 66 | ||||
| -rw-r--r-- | ray_marching_maps.slang | 40 | ||||
| -rw-r--r-- | vertex.cginc | 239 | ||||
| -rw-r--r-- | vertex_deformation.slang | 14 |
6 files changed, 180 insertions, 186 deletions
@@ -257,8 +257,7 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace) : SV_Target { i.objPos = res.objPos; i.normal = res.objNorm; i.tangent.xyz = res.objTan; -#endif -#if defined(_VERTEX_DEFORMATION_FRAGMENT_NORMALS) +#elif defined(_VERTEX_DEFORMATION_FRAGMENT_NORMALS) deform_normal(i.objPos_orig, i.normal, i.tangent.xyz); #endif diff --git a/features.cginc b/features.cginc index b5c7e64..4547929 100644 --- a/features.cginc +++ b/features.cginc @@ -70,6 +70,10 @@ //ifex _Ray_Marching_Enabled==0 #pragma shader_feature_local _RAY_MARCHING +#if defined(_RAY_MARCHING) +#undef _VERTEX_DEFORMATION_FRAGMENT_NORMALS +#undef _VERTEX_DEFORMATION_TESSELLATION +#endif //endex //ifex _Ray_Marching_Baked_Origins_Enabled==0 diff --git a/ray_marching.cginc b/ray_marching.cginc index e5ae03d..9c6653f 100644 --- a/ray_marching.cginc +++ b/ray_marching.cginc @@ -4,6 +4,7 @@ #include "math.cginc" #include "ray_marching_maps.hlsl" #include "texture_utils.cginc" +#include "vertex.cginc" struct RayMarchResult { float3 objPos; @@ -13,68 +14,28 @@ struct RayMarchResult { float3 getObjPos(v2f i) { -#if defined(_VERTEX_DEFORMATION_FRAGMENT_NORMALS) || defined(_VERTEX_DEFORMATION_TESSELLATION) - return i.objPos_orig; -#else return i.objPos; -#endif } -#if defined(_RAY_MARCHING_BAKED_ORIGINS) -float3 GetFragToOrigin(v2f i) { - return (i.color * 2.0f - 1.0f) / i.color.a; -} -float4 GetRotation(v2f i, float2 uv_channels) { - float4 quat; - quat.xy = get_uv_by_channel(i, uv_channels.x); - quat.zw = get_uv_by_channel(i, uv_channels.y); - return quat; -} -void GetRoRd(v2f i, out float3 ro, out float3 rd) { - float3 obj_space_camera_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0)); - float3 frag_to_origin = GetFragToOrigin(i); - - float2 uv_channels = float2(_Baked_Origins_UV_Channel_Index, _Baked_Origins_UV_Channel_Index+1); - float4 quat = GetRotation(i, uv_channels); - float4 iquat = float4(-quat.xyz, quat.w); - - ro = -frag_to_origin; - rd = normalize(getObjPos(i) - obj_space_camera_pos); - rd = rotate_vector(rd, iquat); -} -void GetObjPosNorm(v2f i, float3 lclPos, float3 lclNorm, float3 lclTang, - out float3 objPos, out float3 objNorm, out float3 objTan) { - float3 frag_to_origin = GetFragToOrigin(i); - float2 uv_channels = float2(_Baked_Origins_UV_Channel_Index, _Baked_Origins_UV_Channel_Index+1); - float4 quat = GetRotation(i, uv_channels); - float4 iquat = float4(-quat.xyz, quat.w); - - float3 objHit = rotate_vector(lclPos, quat); - float3 objCenterOffset = rotate_vector(frag_to_origin, quat); - objPos = objHit + (getObjPos(i) + objCenterOffset); - - objNorm = rotate_vector(lclNorm, quat); - objTan = rotate_vector(lclTang, quat); -} -#else void GetRoRd(v2f i, out float3 ro, out float3 rd) { ro = getObjPos(i); float3 objCamPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1)); float3 obj_space_camera_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0)); rd = normalize(getObjPos(i) - obj_space_camera_pos); } -void GetObjPosNorm(v2f i, float3 lclPos, float3 lclNorm, float3 lclTang, - out float3 objPos, out float3 objNorm, out float3 objTan) { - objPos = lclPos; - objNorm = lclNorm; - objTan = lclTang; -} -#endif // _RAY_MARCHING_BAKED_ORIGINS RayMarchResult ray_march(v2f i) { float3 ro, rd; GetRoRd(i, ro, rd); +#if defined(_VERTEX_DEFORMATION) + float3 rd_perp = i.normal * dot(i.normal, rd); + float3 rd_tan = rd - rd_perp; + float3 tmp = ro; + deform_normal(tmp, rd_perp, rd_tan); + rd = rd_perp + rd_tan; +#endif + const float kMinDist = 1e-3; // TODO dial this in & parameterize const float kMaxDist = 10; @@ -96,12 +57,13 @@ RayMarchResult ray_march(v2f i) { // TODO clip / hit detection float3 lclPos = ro + rd * d_acc; float3 lclNorm; - float3 lclTang; - map_normal(lclPos, lclNorm, lclTang); + float3 lclTan; + map_normal(lclPos, lclNorm, lclTan); RayMarchResult res; - GetObjPosNorm(i, lclPos, lclNorm, lclTang, - res.objPos, res.objNorm, res.objTan); + res.objPos = lclPos; + res.objNorm = lclNorm; + res.objTan = lclTan; return res; } diff --git a/ray_marching_maps.slang b/ray_marching_maps.slang index d98248b..649a557 100644 --- a/ray_marching_maps.slang +++ b/ray_marching_maps.slang @@ -31,51 +31,19 @@ R3R1_AUTODIFF_BASIS_VECTORS(fun, ##__VA_ARGS__); \ R3R1_DEFORM_NORMAL_AND_TANGENT(normal, tangent) -float distance_from_hex_comb( - float3 p, - float3 period, - float count) { - float3 p_hex = cart_to_hex(p.yz); - - float3 half_period = period * 0.5; - float3 which = abs(floor((p_hex + half_period) / period)); - - // The original code here was this: - // p_hex = glsl_mod(p_hex + half_period, period) - half_period; - // - // But you can simplify it. Given the definition of glsl_mod: - // #define glsl_mod(x,y) (((x)-(y)*floor((x)/(y)))) - // - // You can plug in terms: - // (p_hex + half_period) - (period) * floor((p_hex + half_period) / period) - // = p_hex + half_period - period * floor(p_hex/period + 0.5) - // - // For all x, - // round(x) = floor(x + 0.5) - // - // Continuing to simplify: - // (p_hex + half_period - period * round(p_hex/period)) - half_period - // = p_hex - period * round(p_hex / period) - p_hex = p_hex - period * round(p_hex / period); - - p.yz = hex_to_cart(p_hex); - - float hex_d = length(p) - 0.15; - return hex_d; -} - // Just trace a sphere of radius 0.1 for now. [Differentiable] public float map(float3 p) { - float period = 0.2f; - float3 count = float3(6,5,1); - float half_period = period * 0.5f; + 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; } diff --git a/vertex.cginc b/vertex.cginc index b5750c6..303fc00 100644 --- a/vertex.cginc +++ b/vertex.cginc @@ -6,130 +6,179 @@ #define FOO(x) (x) +#if defined(_VERTEX_DEFORMATION_XZ_TUBE) +#define VERTEX_DEFORM_XZ_TUBE_PREAMBLE \ + float t = _Vertex_Deformation_XZ_Tube_t +#define VERTEX_DEFORM_XZ_TUBE_POS \ + objPos = plane_to_tube(objPos.xyz, t) +#define VERTEX_DEFORM_XZ_TUBE_NORM \ + plane_to_tube_normal(objPos, objNorm, objTan, t) +#else +#define VERTEX_DEFORM_XZ_TUBE_PREAMBLE +#define VERTEX_DEFORM_XZ_TUBE_POS +#define VERTEX_DEFORM_XZ_TUBE_NORM +#endif // VERTEX_DEFORMATION_XZ_TUBE + +#if defined(_VERTEX_DEFORMATION_YZ_TUBE) +#define VERTEX_DEFORM_YZ_TUBE_PREAMBLE \ + float t = _Vertex_Deformation_YZ_Tube_t +#define VERTEX_DEFORM_YZ_TUBE_POS \ + objPos = plane_to_tube(objPos.yxz, t); \ + objPos = objPos.yxz +#define VERTEX_DEFORM_YZ_TUBE_NORM \ + float3 yzPos = objPos.yxz; \ + float3 yzNorm = objNorm.yxz; \ + float3 yzTan = objTan.yxz; \ + plane_to_tube_normal(yzPos, yzNorm, yzTan, t); \ + objPos = yzPos.yxz; \ + objNorm = yzNorm.yxz; \ + objTan = yzTan.yxz +#else +#define VERTEX_DEFORM_YZ_TUBE_PREAMBLE +#define VERTEX_DEFORM_YZ_TUBE_POS +#define VERTEX_DEFORM_YZ_TUBE_NORM +#endif // VERTEX_DEFORMATION_YZ_TUBE + +#if defined(_VERTEX_DEFORMATION_XY_TUBE) +#define VERTEX_DEFORM_XY_TUBE_PREAMBLE \ + float t = _Vertex_Deformation_XY_Tube_t +#define VERTEX_DEFORM_XY_TUBE_POS \ + objPos = plane_to_tube(objPos.xzy, t); \ + objPos = objPos.xzy +#define VERTEX_DEFORM_XY_TUBE_NORM \ + float3 xyPos = objPos.xzy; \ + float3 xyNorm = objNorm.xzy; \ + float3 xyTan = objTan.xzy; \ + plane_to_tube_normal(xyPos, xyNorm, xyTan, t); \ + objPos = xyPos.xzy; \ + objNorm = xyNorm.xzy; \ + objTan = xyTan.xzy +#else +#define VERTEX_DEFORM_XY_TUBE_PREAMBLE +#define VERTEX_DEFORM_XY_TUBE_POS +#define VERTEX_DEFORM_XY_TUBE_NORM +#endif // VERTEX_DEFORMATION_XY_TUBE + +#if defined(_VERTEX_DEFORMATION_SEAL) +#define VERTEX_DEFORM_SEAL_PREAMBLE \ + float A = _Vertex_Deformation_Seal_A; \ + float k = _Vertex_Deformation_Seal_k; \ + float st = t * _Vertex_Deformation_Seal_t +#define VERTEX_DEFORM_SEAL_POS \ + objPos = seal(objPos.xyz, A, k, st) +#define VERTEX_DEFORM_SEAL_NORM \ + seal_normal(objPos, objNorm, objTan, A, k, st) +#else +#define VERTEX_DEFORM_SEAL_PREAMBLE +#define VERTEX_DEFORM_SEAL_POS +#define VERTEX_DEFORM_SEAL_NORM +#endif // _VERTEX_DEFORMATION_SEAL + +#if defined(_VERTEX_DEFORMATION_SINE_WAVES) +#define VERTEX_DEFORM_SINE_WAVES_PREAMBLE \ + float st = t * 10; \ + float3 amplitude = _Vertex_Deformation_Sine_Waves_Amplitude; \ + float3 direction = _Vertex_Deformation_Sine_Waves_Direction; \ + float3 k = _Vertex_Deformation_Sine_Waves_k; \ + float3 omega = _Vertex_Deformation_Sine_Waves_omega +#define VERTEX_DEFORM_SINE_WAVES_POS \ + objPos = sine_wave(objPos.xyz, amplitude, direction, k, omega, st) +#define VERTEX_DEFORM_SINE_WAVES_NORM \ + sine_wave_normal(objPos, objNorm, objTan, amplitude, direction, k, omega, st) +#else +#define VERTEX_DEFORM_SINE_WAVES_PREAMBLE +#define VERTEX_DEFORM_SINE_WAVES_POS +#define VERTEX_DEFORM_SINE_WAVES_NORM +#endif // _VERTEX_DEFORMATION_SINE_WAVES + +#if defined(_VERTEX_DEFORMATION_FBM) +#define VERTEX_DEFORM_FBM_PREAMBLE \ + float st = t; \ + float amplitude = _Vertex_Deformation_FBM_Amplitude; \ + float gain = _Vertex_Deformation_FBM_Gain; \ + float lacunarity = _Vertex_Deformation_FBM_Lacunarity; \ + float scale = _Vertex_Deformation_FBM_Scale; \ + float octaves = _Vertex_Deformation_FBM_Octaves; \ + float3 velocity = _Vertex_Deformation_FBM_Velocity +#define VERTEX_DEFORM_FBM_POS \ + objPos = fbm(objPos, st, amplitude, gain, lacunarity, scale, octaves, velocity) +#define VERTEX_DEFORM_FBM_NORM \ + fbm_normal(objPos, objNorm, objTan, st, amplitude, gain, lacunarity, scale, octaves, velocity) +#else +#define VERTEX_DEFORM_FBM_PREAMBLE +#define VERTEX_DEFORM_FBM_POS +#define VERTEX_DEFORM_FBM_NORM +#endif // _VERTEX_DEFORMATION_FBM + void deform(inout float3 objPos) { const float t = getTime(); - -#if defined(_VERTEX_DEFORMATION_XZ_TUBE) { - float t = _Vertex_Deformation_XZ_Tube_t; - objPos = plane_to_tube(objPos.xyz, t); + VERTEX_DEFORM_XZ_TUBE_PREAMBLE; + VERTEX_DEFORM_XZ_TUBE_POS; } -#endif // _VERTEX_DEFORMATION_XZ_TUBE -#if defined(_VERTEX_DEFORMATION_YZ_TUBE) { - float t = _Vertex_Deformation_YZ_Tube_t; - objPos = plane_to_tube(objPos.yxz, t); - objPos = objPos.yxz; + VERTEX_DEFORM_YZ_TUBE_PREAMBLE; + VERTEX_DEFORM_YZ_TUBE_POS; } -#endif // _VERTEX_DEFORMATION_YZ_TUBE -#if defined(_VERTEX_DEFORMATION_XY_TUBE) { - float t = _Vertex_Deformation_XY_Tube_t; - objPos = plane_to_tube(objPos.xzy, t); - objPos = objPos.xzy; + VERTEX_DEFORM_XY_TUBE_PREAMBLE; + VERTEX_DEFORM_XY_TUBE_POS; } -#endif // _VERTEX_DEFORMATION_XY_TUBE -#if defined(_VERTEX_DEFORMATION_SEAL) { - float A = _Vertex_Deformation_Seal_A; - float k = _Vertex_Deformation_Seal_k; - float st = t * _Vertex_Deformation_Seal_t; - objPos = seal(objPos.xyz, A, k, st); + VERTEX_DEFORM_SEAL_PREAMBLE; + VERTEX_DEFORM_SEAL_POS; } -#endif // _VERTEX_DEFORMATION_SEAL -#if defined(_VERTEX_DEFORMATION_SINE_WAVES) { - float st = t * 10; - float3 amplitude = _Vertex_Deformation_Sine_Waves_Amplitude; - float3 direction = _Vertex_Deformation_Sine_Waves_Direction; - float3 k = _Vertex_Deformation_Sine_Waves_k; - float3 omega = _Vertex_Deformation_Sine_Waves_omega; - objPos = sine_wave(objPos.xyz, amplitude, direction, k, omega, st); + VERTEX_DEFORM_SINE_WAVES_PREAMBLE; + VERTEX_DEFORM_SINE_WAVES_POS; } -#endif // _VERTEX_DEFORMATION_SINE_WAVES -#if defined(_VERTEX_DEFORMATION_FBM) { - float st = t; - float amplitude = _Vertex_Deformation_FBM_Amplitude; - float gain = _Vertex_Deformation_FBM_Gain; - float lacunarity = _Vertex_Deformation_FBM_Lacunarity; - float scale = _Vertex_Deformation_FBM_Scale; - float octaves = _Vertex_Deformation_FBM_Octaves; - float3 velocity = _Vertex_Deformation_FBM_Velocity; - objPos = fbm( - objPos, - st, - amplitude, - gain, - lacunarity, - scale, - octaves, - velocity); + VERTEX_DEFORM_FBM_PREAMBLE; + VERTEX_DEFORM_FBM_POS; } -#endif // _VERTEX_DEFORMATION_FBM } -void deform_normal(float3 objPos, inout float3 objNorm, inout float3 objTan) { +void deform_normal(inout float3 objPos, inout float3 objNorm, inout float3 objTan) { const float t = getTime(); - -#if defined(_VERTEX_DEFORMATION_XZ_TUBE) { - float t = _Vertex_Deformation_XZ_Tube_t; - plane_to_tube_normal(objPos, objNorm, objTan, t); + VERTEX_DEFORM_XZ_TUBE_PREAMBLE; + VERTEX_DEFORM_XZ_TUBE_NORM; } -#endif // _VERTEX_DEFORMATION_XZ_TUBE -#if defined(_VERTEX_DEFORMATION_YZ_TUBE) { - float t = _Vertex_Deformation_YZ_Tube_t; - plane_to_tube_normal(objPos.yxz, objNorm.yxz, objTan.yxz, t); + VERTEX_DEFORM_YZ_TUBE_PREAMBLE; + VERTEX_DEFORM_YZ_TUBE_NORM; } -#endif // _VERTEX_DEFORMATION_YZ_TUBE -#if defined(_VERTEX_DEFORMATION_XY_TUBE) { - float t = _Vertex_Deformation_XY_Tube_t; - plane_to_tube_normal(objPos.xzy, objNorm.xzy, objTan.xzy, t); + VERTEX_DEFORM_XY_TUBE_PREAMBLE; + VERTEX_DEFORM_XY_TUBE_NORM; } -#endif // _VERTEX_DEFORMATION_XY_TUBE -#if defined(_VERTEX_DEFORMATION_SEAL) { - float A = _Vertex_Deformation_Seal_A; - float k = _Vertex_Deformation_Seal_k; - float st = t * _Vertex_Deformation_Seal_t; - seal_normal(objPos, objNorm, objTan, A, k, st); + VERTEX_DEFORM_SEAL_PREAMBLE; + VERTEX_DEFORM_SEAL_NORM; } -#endif // _VERTEX_DEFORMATION_SEAL -#if defined(_VERTEX_DEFORMATION_SINE_WAVES) { - float st = t * 10; - float3 amplitude = _Vertex_Deformation_Sine_Waves_Amplitude; - float3 direction = _Vertex_Deformation_Sine_Waves_Direction; - float3 k = _Vertex_Deformation_Sine_Waves_k; - float3 omega = _Vertex_Deformation_Sine_Waves_omega; - sine_wave_normal(objPos, objNorm, objTan, amplitude, direction, k, omega, st); + VERTEX_DEFORM_SINE_WAVES_PREAMBLE; + VERTEX_DEFORM_SINE_WAVES_NORM; } -#endif // _VERTEX_DEFORMATION_SINE_WAVES -#if defined(_VERTEX_DEFORMATION_FBM) { - float st = t; - float amplitude = _Vertex_Deformation_FBM_Amplitude; - float gain = _Vertex_Deformation_FBM_Gain; - float lacunarity = _Vertex_Deformation_FBM_Lacunarity; - float scale = _Vertex_Deformation_FBM_Scale; - float octaves = _Vertex_Deformation_FBM_Octaves; - float3 velocity = _Vertex_Deformation_FBM_Velocity; - fbm_normal( - objPos, - objNorm, - objTan, - st, - amplitude, - gain, - lacunarity, - scale, - octaves, - velocity); + VERTEX_DEFORM_FBM_PREAMBLE; + VERTEX_DEFORM_FBM_NORM; } -#endif // _VERTEX_DEFORMATION_FBM +} + +// `objPos` is in the un-deformed coordinate system, while `objNorm` and +// `objTan` are in the deformed coordinate system. The task is to map `objNorm` +// and `objTan` to the un-deformed coordinate system. +// We do this, coarsely, as follows: +// 1. Map objPos into the deformed coordinate system through stepwise +// transformations, like `deform`. We remember each position along the way. +// 2. Map objNorm and objTan back one step using the deformed final position. +// For the first iteration, we use the last (deformed) `objPos` that we +// remembered from step 1. +// 3. Repeat step 2 until we're back in the un-deforme coordinate system. At +// each step, we use the cached objPos from the forward pass (step 1), so +// that we evaluate the normal deformation at the correct point in space. +void undeform_normal(float3 objPos, inout float3 objNorm, inout float3 objTan) { } void propagateObjPos(inout v2f i) { diff --git a/vertex_deformation.slang b/vertex_deformation.slang index 42cf6b8..63804de 100644 --- a/vertex_deformation.slang +++ b/vertex_deformation.slang @@ -35,7 +35,7 @@ DifferentialPair<float3> dp_y_out = fwd_diff(fun)(dp_y, __VA_ARGS__); \ DifferentialPair<float3> dp_z_out = fwd_diff(fun)(dp_z, __VA_ARGS__) -#define R3R3_DEFORM_NORMAL_AND_TANGENT(normal, tangent) \ +#define R3R3_DEFORM_NORMAL_AND_TANGENT(normal, tangent) \ float3x3 jacobian = float3x3( \ float3(dp_x_out.d.x, dp_y_out.d.x, dp_z_out.d.x), \ float3(dp_x_out.d.y, dp_y_out.d.y, dp_z_out.d.y), \ @@ -46,6 +46,18 @@ normal = mul(itjac, normal) * sign(jac_det); \ tangent = mul(jacobian, tangent) +#define R3R3_UNDEFORM_NORMAL_AND_TANGENT(normal, tangent) \ + float3x3 jacobian = float3x3( \ + float3(dp_x_out.d.x, dp_y_out.d.x, dp_z_out.d.x), \ + float3(dp_x_out.d.y, dp_y_out.d.y, dp_z_out.d.y), \ + float3(dp_x_out.d.z, dp_y_out.d.z, dp_z_out.d.z) \ + ); \ + float jac_det = determinant(jacobian); \ + float3x3 inv_jac = inverse(jacobian, jac_det); \ + float3x3 trans_jac = transpose(jacobian); \ + normal = mul(trans_jac, normal) * sign(jac_det); \ + tangent = mul(inv_jac, tangent) + // Syntactic sugar - wraps the previous three macros. #define R3R3_NORMALS(xyz, normal, tangent, fun, ...) \ R3R3_DECLARE_BASIS_VECTORS(xyz); \ |
