summaryrefslogtreecommitdiffstats
path: root/pbr.cginc
diff options
context:
space:
mode:
Diffstat (limited to 'pbr.cginc')
-rw-r--r--pbr.cginc67
1 files changed, 64 insertions, 3 deletions
diff --git a/pbr.cginc b/pbr.cginc
index 73ff970..8501edc 100644
--- a/pbr.cginc
+++ b/pbr.cginc
@@ -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);