From 537d60c29a009747e7615b0f7ecfa33d3bfefd9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Mon, 20 Oct 2025 09:35:02 +0200 Subject: [PATCH] initial water shader handling for path tracing --- WickedEngine/shaders/ShaderInterop_Renderer.h | 29 ++++++++++++++---- WickedEngine/shaders/raytraceCS.hlsl | 29 ++++++++++++++++-- WickedEngine/shaders/surfaceHF.hlsli | 30 ++++++++++++++++++- WickedEngine/wiScene_Components.cpp | 5 ---- WickedEngine/wiVersion.cpp | 2 +- 5 files changed, 81 insertions(+), 14 deletions(-) diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index 9a5d96d53..b6a2a1b3f 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -76,11 +76,29 @@ enum SHADERMATERIAL_OPTIONS SHADERMATERIAL_OPTION_BIT_DOUBLE_SIDED = 1 << 7, SHADERMATERIAL_OPTION_BIT_TRANSPARENT = 1 << 8, SHADERMATERIAL_OPTION_BIT_ADDITIVE = 1 << 9, - SHADERMATERIAL_OPTION_BIT_UNLIT = 1 << 10, - SHADERMATERIAL_OPTION_BIT_USE_VERTEXAO = 1 << 11, - SHADERMATERIAL_OPTION_BIT_CAPSULE_SHADOW_DISABLED = 1 << 12, + SHADERMATERIAL_OPTION_BIT_USE_VERTEXAO = 1 << 10, + SHADERMATERIAL_OPTION_BIT_CAPSULE_SHADOW_DISABLED = 1 << 11, }; +#ifndef __cplusplus +enum SHADERTYPE +{ + SHADERTYPE_PBR, + SHADERTYPE_PBR_PLANARREFLECTION, + SHADERTYPE_PBR_PARALLAXOCCLUSIONMAPPING, + SHADERTYPE_PBR_ANISOTROPIC, + SHADERTYPE_WATER, + SHADERTYPE_CARTOON, + SHADERTYPE_UNLIT, + SHADERTYPE_PBR_CLOTH, + SHADERTYPE_PBR_CLEARCOAT, + SHADERTYPE_PBR_CLOTH_CLEARCOAT, + SHADERTYPE_PBR_TERRAINBLENDED, + SHADERTYPE_INTERIORMAPPING, + SHADERTYPE_COUNT +}; +#endif // __cplusplus + // Same as MaterialComponent::TEXTURESLOT enum TEXTURESLOT { @@ -445,7 +463,6 @@ struct alignas(16) ShaderMaterial inline uint GetStencilRef() { return options_stencilref >> 24u; } inline uint GetShaderType() { return shaderType_meshblend & 0xFFFF; } inline half GetMeshBlend() { return f16tof32(shaderType_meshblend >> 16u); } -#endif // __cplusplus inline uint GetOptions() { return options_stencilref; } inline bool IsUsingVertexColors() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_USE_VERTEXCOLORS; } @@ -456,11 +473,13 @@ struct alignas(16) ShaderMaterial inline bool IsUsingWind() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_USE_WIND; } inline bool IsReceiveShadow() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_RECEIVE_SHADOW; } inline bool IsCastingShadow() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_CAST_SHADOW; } - inline bool IsUnlit() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_UNLIT; } inline bool IsTransparent() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_TRANSPARENT; } inline bool IsAdditive() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_ADDITIVE; } inline bool IsDoubleSided() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_DOUBLE_SIDED; } inline bool IsCapsuleShadowDisabled() { return GetOptions() & SHADERMATERIAL_OPTION_BIT_CAPSULE_SHADOW_DISABLED; } + inline bool IsUnlit() { return GetShaderType() == SHADERTYPE_UNLIT; } + +#endif // __cplusplus }; // For binning shading based on shader types: diff --git a/WickedEngine/shaders/raytraceCS.hlsl b/WickedEngine/shaders/raytraceCS.hlsl index 85c0ac6b6..38cb4ea5d 100644 --- a/WickedEngine/shaders/raytraceCS.hlsl +++ b/WickedEngine/shaders/raytraceCS.hlsl @@ -3,6 +3,7 @@ #define SURFACE_LOAD_MIPCONE #define SVT_FEEDBACK #define TEXTURE_SLOT_NONUNIFORM +#define WATER #include "globals.hlsli" #include "raytracingHF.hlsli" #include "lightingHF.hlsli" @@ -57,6 +58,10 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) RayCone raycone = pixel_ray_cone_from_image_height(xTraceResolution.y); + float4 water_opacity = 0; + float water_depth = -1; + float3 extinction = 1; + float depth = 0; uint stencil = 0; @@ -194,6 +199,14 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) surface.V = -ray.Direction; surface.update(); + if (water_depth >= 0) + { + water_depth += surface.hit_depth; + float waterfog = saturate(exp(-water_depth * water_opacity)); + float3 transmittance = saturate(exp(-water_depth * extinction * water_opacity)); + energy *= transmittance; + } + result += energy * surface.emissiveColor; float roughnessBRDF = sqr(clamp(surface.roughness, min_roughness, 1)); @@ -425,14 +438,26 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) energy /= termination_chance; // Set up next bounce: + const bool is_water = surface.material.GetShaderType() == SHADERTYPE_WATER; + if (is_water) + { + surface.transmission = 0.9; // hack the water into the transmission path somehow to still have a bit of reflection + extinction *= surface.material.GetSheenColor().rgb; // Note: sheen color is repurposed as extinction color for water + water_opacity = surface.baseColor.a; + water_depth = max(0, water_depth); + } + if (rng.next_float() < surface.transmission) { // Refraction const float3 R = refract(ray.Direction, surface.N, 1 - lerp(surface.material.GetRefraction(), 0.1, surface.material.GetCloak())); float roughnessBRDF = sqr(clamp(lerp(surface.roughness, 0.1, surface.material.GetCloak()), min_roughness, 1)); ray.Direction = lerp(R, sample_hemisphere_cos(R, rng), roughnessBRDF); - energy *= lerp(surface.albedo, 1, surface.material.GetCloak()) / max(0.001, surface.transmission); - + if (!is_water) // water will have depth based extinction instead of simple tint + { + energy *= lerp(surface.albedo, 1, surface.material.GetCloak()) / max(0.001, surface.transmission); + } + // Add a new bounce iteration, otherwise the transparent effect can disappear: bounce--; } diff --git a/WickedEngine/shaders/surfaceHF.hlsli b/WickedEngine/shaders/surfaceHF.hlsli index a5ca8e0e3..b94486530 100644 --- a/WickedEngine/shaders/surfaceHF.hlsli +++ b/WickedEngine/shaders/surfaceHF.hlsli @@ -499,6 +499,31 @@ struct Surface [branch] if (geometry.vb_tan >= 0 && material.textures[NORMALMAP].IsValid()) { +#ifdef WATER + [branch] + if (material.GetShaderType() == SHADERTYPE_WATER) + { + // WATER NORMALMAP + half2 bumpColor0 = 0; + half2 bumpColor1 = 0; +#ifdef SURFACE_LOAD_QUAD_DERIVATIVES + bumpColor0 = material.textures[NORMALMAP].SampleGrad(sam, uvsets - material.texMulAdd.wwww, uvsets_dx, uvsets_dy).rg * 2 - 1; + bumpColor1 = material.textures[NORMALMAP].SampleGrad(sam, uvsets + material.texMulAdd.zwzw, uvsets_dx, uvsets_dy).rg * 2 - 1; +#else + float lod = 0; +#ifdef SURFACE_LOAD_MIPCONE + lod = compute_texture_lod(material.textures[NORMALMAP].GetTexture(), material.textures[NORMALMAP].GetUVSet() == 0 ? lod_constant0 : lod_constant1, ray_direction, surf_normal, cone_width); +#endif // SURFACE_LOAD_MIPCONE + bumpColor0 = material.textures[NORMALMAP].SampleLevel(sam, uvsets - material.texMulAdd.wwww, lod).rg * 2 - 1; + bumpColor1 = material.textures[NORMALMAP].SampleLevel(sam, uvsets + material.texMulAdd.zwzw, lod).rg * 2 - 1; +#endif // SURFACE_LOAD_QUAD_DERIVATIVES + bumpColor = half3(bumpColor0 + bumpColor1, 1) * material.GetRefraction(); + N = normalize(lerp(N, mul(normalize(bumpColor), TBN), material.GetNormalMapStrength())); + bumpColor.rg *= material.GetNormalMapStrength(); + } + else { +#endif // WATER + #ifdef SURFACE_LOAD_QUAD_DERIVATIVES bumpColor = half3(material.textures[NORMALMAP].SampleGrad(sam, uvsets, uvsets_dx, uvsets_dy).rg, 1); #else @@ -510,9 +535,12 @@ struct Surface #endif // SURFACE_LOAD_QUAD_DERIVATIVES bumpColor = bumpColor * 2 - 1; bumpColor.rg *= material.GetNormalMapStrength(); + +#ifdef WATER + } // water else +#endif // WATER } - #ifdef ANISOTROPIC aniso.strength = material.GetAnisotropy(); aniso.direction = half2(material.GetAnisotropyCos(), material.GetAnisotropySin()); diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp index 8e291d1ae..c491f0e99 100644 --- a/WickedEngine/wiScene_Components.cpp +++ b/WickedEngine/wiScene_Components.cpp @@ -379,10 +379,6 @@ namespace wi::scene { material.options_stencilref |= SHADERMATERIAL_OPTION_BIT_ADDITIVE; } - if (shaderType == SHADERTYPE_UNLIT) - { - material.options_stencilref |= SHADERMATERIAL_OPTION_BIT_UNLIT; - } if (!IsVertexAODisabled()) { material.options_stencilref |= SHADERMATERIAL_OPTION_BIT_USE_VERTEXAO; @@ -2661,7 +2657,6 @@ namespace wi::scene XMStoreFloat4x4(&InvProjection, _InvP); XMMATRIX _VP = XMMatrixMultiply(_V, _P); - XMStoreFloat4x4(&View, _V); XMStoreFloat4x4(&VP, _VP); XMMATRIX _InvV = XMMatrixInverse(nullptr, _V); XMStoreFloat4x4(&InvView, _InvV); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 7afa58195..a92d41fea 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 841; + const int revision = 842; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);