diff options
Diffstat (limited to 'pbr.cginc')
| -rw-r--r-- | pbr.cginc | 67 |
1 files changed, 64 insertions, 3 deletions
@@ -27,6 +27,63 @@ struct Pbr { #define MIN_PERCEPTUAL_ROUGHNESS 5e-2f #define MIN_ROUGHNESS 5e-3f +#if defined(_PARALLAX_HEIGHTMAP) +float2 parallax_offset(float2 uv, float3 view_dir_world, float3x3 tbn) { + float3 view_dir_tangent = mul(tbn, view_dir_world); + float2 uv_step = view_dir_tangent.xy / max(view_dir_tangent.z, 1e-3f) * _Parallax_Heightmap_Scale; + +#if defined(_PARALLAX_HEIGHTMAP_RAY_MARCHING) + float step_count = _Parallax_Heightmap_Ray_Marching_Steps; + float2 delta_uv = uv_step / step_count; + float delta_depth = 1.0 / step_count; + + float2 cur_uv = uv; + float cur_depth = 0.0; + float cur_height = 1.0 - _Parallax_Heightmap.Sample(linear_repeat_s, + cur_uv * _Parallax_Heightmap_ST.xy + _Parallax_Heightmap_ST.zw).r; + cur_height = (cur_height - (1.0 - _Parallax_Heightmap_Bias)); + + // If starting inside geometry, march backwards + bool inside = cur_depth < cur_height; + if (!inside) { + delta_uv = -delta_uv; + delta_depth = -delta_depth; + } + + float prev_depth = cur_depth; + float prev_height = cur_height; + + [loop] + for (int i = 0; i < (int)step_count; i++) { + bool was_inside = cur_depth < cur_height; + if (was_inside != inside) break; + + prev_depth = cur_depth; + prev_height = cur_height; + + cur_uv += delta_uv; + cur_depth += delta_depth; + cur_height = 1.0 - _Parallax_Heightmap.Sample(linear_repeat_s, + cur_uv * _Parallax_Heightmap_ST.xy + _Parallax_Heightmap_ST.zw).r; + cur_height = (cur_height - (1.0 - _Parallax_Heightmap_Bias)); + } + + // Linear interpolation between last two samples + float after = cur_height - cur_depth; + float before = prev_height - prev_depth; + float t = after / (after - before); + + return cur_uv - uv - delta_uv * t; +#else + float2 heightmap_uv = uv * _Parallax_Heightmap_ST.xy + _Parallax_Heightmap_ST.zw; + float height = _Parallax_Heightmap.Sample(linear_repeat_s, heightmap_uv).r; + height = height - _Parallax_Heightmap_Bias; + + return uv_step * height; +#endif +} +#endif // _PARALLAX_HEIGHTMAP + // TODO consider normal filtering like filamented void propagateSmoothness(inout Pbr pbr) { pbr.roughness_perceptual = max(MIN_PERCEPTUAL_ROUGHNESS, 1.0f - pbr.smoothness); @@ -54,10 +111,17 @@ void apply_marble(float3 world_pos, inout float3 albedo) { Pbr getPbr(v2f i) { Pbr pbr = (Pbr) 0; + float3 bitangent = cross(i.normal, i.tangent.xyz) * i.tangent.w; + pbr.tbn = float3x3(i.tangent.xyz, bitangent, i.normal); + #if defined(_UV_SCROLL) i.uv01.xy += getTime() * _UV_Scroll_Speed; #endif // _UV_SCROLL +#if defined(_PARALLAX_HEIGHTMAP) + i.uv01.xy += parallax_offset(i.uv01.xy, normalize(i.eyeVec.xyz), pbr.tbn); +#endif // _PARALLAX_HEIGHTMAP + pbr.albedo = _MainTex.Sample(aniso16_trilinear_repeat_s, i.uv01.xy * _MainTex_ST.xy + _MainTex_ST.zw); pbr.albedo *= _Color; apply_marble(i.worldPos, pbr.albedo.xyz); @@ -74,9 +138,6 @@ Pbr getPbr(v2f i) { normal_tangent = blendNormalsHill12(normal_tangent, detail_normal); #endif - // Map from tangent space to world space. - float3 bitangent = cross(i.normal, i.tangent.xyz) * i.tangent.w; - pbr.tbn = float3x3(i.tangent.xyz, bitangent, i.normal); pbr.normal = normalize(mul(normal_tangent, pbr.tbn)); float4 metallic_gloss = _MetallicGlossMap.Sample(aniso16_trilinear_repeat_s, i.uv01.xy * _MetallicGlossMap_ST.xy); |
