From a8c218661efed3cc5085077e47b3649609f97c12 Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Sun, 10 Nov 2019 14:24:14 +0000 Subject: [PATCH] hair particle updates --- WickedEngine/WickedEngine_SHADERS.vcxproj | 6 + .../WickedEngine_SHADERS.vcxproj.filters | 6 + .../hairparticlePS_alphatestonly.hlsl | 2 +- WickedEngine/hairparticlePS_deferred.hlsl | 2 +- WickedEngine/hairparticlePS_forward.hlsl | 8 +- .../hairparticlePS_forward_transparent.hlsl | 2 + WickedEngine/hairparticlePS_tiledforward.hlsl | 4 + ...irparticlePS_tiledforward_transparent.hlsl | 2 + WickedEngine/hairparticleVS.hlsl | 121 ++++++++-------- WickedEngine/wiHairParticle.cpp | 136 +++++++++++------- WickedEngine/wiVersion.cpp | 2 +- 11 files changed, 176 insertions(+), 115 deletions(-) create mode 100644 WickedEngine/hairparticlePS_forward_transparent.hlsl create mode 100644 WickedEngine/hairparticlePS_tiledforward_transparent.hlsl diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj b/WickedEngine/WickedEngine_SHADERS.vcxproj index 1f2420671..2ebf374b8 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj @@ -316,9 +316,15 @@ Compute 5.0 + + Pixel + Pixel + + Pixel + Compute 5.0 diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters index 469e02be9..9048309ed 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters @@ -810,6 +810,12 @@ CS + + PS + + + PS + diff --git a/WickedEngine/hairparticlePS_alphatestonly.hlsl b/WickedEngine/hairparticlePS_alphatestonly.hlsl index 68706bf85..73fe13df9 100644 --- a/WickedEngine/hairparticlePS_alphatestonly.hlsl +++ b/WickedEngine/hairparticlePS_alphatestonly.hlsl @@ -3,7 +3,7 @@ void main(VertexToPixel input) { - clip(dither(input.pos.xy) - input.fade); + clip(dither(input.pos.xy + GetTemporalAASampleRotation()) - input.fade); float4 color = texture_0.Sample(sampler_linear_clamp,input.tex); ALPHATEST(color.a) diff --git a/WickedEngine/hairparticlePS_deferred.hlsl b/WickedEngine/hairparticlePS_deferred.hlsl index 8d88e01b2..6fe2040a3 100644 --- a/WickedEngine/hairparticlePS_deferred.hlsl +++ b/WickedEngine/hairparticlePS_deferred.hlsl @@ -4,7 +4,7 @@ GBUFFEROutputType main(VertexToPixel input) { - clip(dither(input.pos.xy) - input.fade); + clip(dither(input.pos.xy + GetTemporalAASampleRotation()) - input.fade); float4 color = texture_0.Sample(sampler_linear_clamp, input.tex); color.rgb = DEGAMMA(color.rgb); diff --git a/WickedEngine/hairparticlePS_forward.hlsl b/WickedEngine/hairparticlePS_forward.hlsl index c2e10fe8f..931ada915 100644 --- a/WickedEngine/hairparticlePS_forward.hlsl +++ b/WickedEngine/hairparticlePS_forward.hlsl @@ -2,12 +2,18 @@ #include "objectHF.hlsli" #include "hairparticleHF.hlsli" +#ifndef TRANSPARENT +[earlydepthstencil] +#endif // TRANSPARENT GBUFFEROutputType_Thin main(VertexToPixel input) { float4 color = texture_0.Sample(sampler_linear_clamp, input.tex); color.rgb = DEGAMMA(color.rgb); color.rgb *= input.color; - ALPHATEST(color.a) +#ifdef TRANSPARENT + color.a *= 1.0 - input.fade; + clip(color.a - 1.0f / 255.0f); // cancel heaviest overdraw for the alpha composition effect +#endif // TRANSPARENT float opacity = 1; // keep edge diffuse shading float3 V = g_xCamera_CamPos - input.pos3D; float dist = length(V); diff --git a/WickedEngine/hairparticlePS_forward_transparent.hlsl b/WickedEngine/hairparticlePS_forward_transparent.hlsl new file mode 100644 index 000000000..caa0a1bca --- /dev/null +++ b/WickedEngine/hairparticlePS_forward_transparent.hlsl @@ -0,0 +1,2 @@ +#define TRANSPARENT +#include "hairparticlePS_forward.hlsl" diff --git a/WickedEngine/hairparticlePS_tiledforward.hlsl b/WickedEngine/hairparticlePS_tiledforward.hlsl index 2e9642d3f..012d8024f 100644 --- a/WickedEngine/hairparticlePS_tiledforward.hlsl +++ b/WickedEngine/hairparticlePS_tiledforward.hlsl @@ -4,14 +4,18 @@ #include "objectHF.hlsli" #include "hairparticleHF.hlsli" +#ifndef TRANSPARENT [earlydepthstencil] +#endif // TRANSPARENT GBUFFEROutputType_Thin main(VertexToPixel input) { float4 color = texture_0.Sample(sampler_linear_wrap, input.tex); color.rgb = DEGAMMA(color.rgb); color.rgb *= input.color; +#ifdef TRANSPARENT color.a *= 1.0 - input.fade; clip(color.a - 1.0f / 255.0f); // cancel heaviest overdraw for the alpha composition effect +#endif // TRANSPARENT float opacity = 1; float3 V = g_xCamera_CamPos - input.pos3D; float dist = length(V); diff --git a/WickedEngine/hairparticlePS_tiledforward_transparent.hlsl b/WickedEngine/hairparticlePS_tiledforward_transparent.hlsl new file mode 100644 index 000000000..0e14af4b7 --- /dev/null +++ b/WickedEngine/hairparticlePS_tiledforward_transparent.hlsl @@ -0,0 +1,2 @@ +#define TRANSPARENT +#include "hairparticlePS_tiledforward.hlsl" diff --git a/WickedEngine/hairparticleVS.hlsl b/WickedEngine/hairparticleVS.hlsl index dafd6787c..9cdc32d16 100644 --- a/WickedEngine/hairparticleVS.hlsl +++ b/WickedEngine/hairparticleVS.hlsl @@ -2,8 +2,6 @@ #include "hairparticleHF.hlsli" #include "ShaderInterop_HairParticle.h" -static const float hairPopDistanceThreshold = 0.9f; - // billboard cross section: static const float3 HAIRPATCH[] = { float3(-1, -1, 0), @@ -32,75 +30,84 @@ VertexToPixel main(uint fakeIndex : SV_VERTEXID) const uint segmentID = (fakeIndex / 12) % xHairSegmentCount; const uint particleID = fakeIndex / 12; - // convert the raw loaded particle data: float3 position = particleBuffer[particleID].position; - uint tangent_random = particleBuffer[particleID].tangent_random; - float3 normal = particleBuffer[particleID].normal; - uint binormal_length = particleBuffer[particleID].binormal_length; + Out.fade = saturate(distance(position.xyz, g_xCamera_CamPos.xyz) / xHairViewDistance); + Out.fade = saturate(Out.fade - 0.8f) * 5.0f; // fade will be on edge and inwards 20% - float3 tangent; - tangent.x = (tangent_random >> 0) & 0x000000FF; - tangent.y = (tangent_random >> 8) & 0x000000FF; - tangent.z = (tangent_random >> 16) & 0x000000FF; - tangent = tangent / 255.0f * 2 - 1; + [branch] + if (Out.fade < 1.0 - 1.0f / 255.0f) + { + uint tangent_random = particleBuffer[particleID].tangent_random; + float3 normal = particleBuffer[particleID].normal; + uint binormal_length = particleBuffer[particleID].binormal_length; - uint rand = (tangent_random >> 24) & 0x000000FF; + float3 tangent; + tangent.x = (tangent_random >> 0) & 0x000000FF; + tangent.y = (tangent_random >> 8) & 0x000000FF; + tangent.z = (tangent_random >> 16) & 0x000000FF; + tangent = tangent / 255.0f * 2 - 1; - float3 binormal; - binormal.x = (binormal_length >> 0) & 0x000000FF; - binormal.y = (binormal_length >> 8) & 0x000000FF; - binormal.z = (binormal_length >> 16) & 0x000000FF; - binormal = binormal / 255.0f * 2 - 1; + uint rand = (tangent_random >> 24) & 0x000000FF; - float len = (binormal_length >> 24) & 0x000000FF; - len /= 255.0f; - len += 1; - len *= xLength; + float3 binormal; + binormal.x = (binormal_length >> 0) & 0x000000FF; + binormal.y = (binormal_length >> 8) & 0x000000FF; + binormal.z = (binormal_length >> 16) & 0x000000FF; + binormal = binormal / 255.0f * 2 - 1; - // expand the particle into a billboard cross section, the patch: - float3 patchPos = HAIRPATCH[vertexID]; - float2 uv = vertexID < 6 ? patchPos.xy : patchPos.zy; - uv = uv * float2(0.5f, 0.5f) + 0.5f; - uv.y = lerp((float)segmentID / (float)xHairSegmentCount, ((float)segmentID + 1) / (float)xHairSegmentCount, uv.y); - uv.y = 1 - uv.y; - uv.x = rand % 2 == 0 ? uv.x : 1 - uv.x; - patchPos.y += 1; + float len = (binormal_length >> 24) & 0x000000FF; + len /= 255.0f; + len += 1; + len *= xLength; - // scale the billboard by the texture aspect: - float2 frame; - texture_0.GetDimensions(frame.x, frame.y); - frame.xy /= frame.y; - frame.xy *= len; - patchPos.xyz *= frame.xyx * 0.5f; + // expand the particle into a billboard cross section, the patch: + float3 patchPos = HAIRPATCH[vertexID]; + float2 uv = vertexID < 6 ? patchPos.xy : patchPos.zy; + uv = uv * float2(0.5f, 0.5f) + 0.5f; + uv.y = lerp((float)segmentID / (float)xHairSegmentCount, ((float)segmentID + 1) / (float)xHairSegmentCount, uv.y); + uv.y = 1 - uv.y; + uv.x = rand % 2 == 0 ? uv.x : 1 - uv.x; + patchPos.y += 1; - // simplistic wind effect only affects the top, but leaves the base as is: - float3 wind = sin(g_xFrame_Time + (position.x + position.y + position.z))*g_xFrame_WindDirection.xyz * patchPos.y * 0.03f; - float3 windPrev = sin(g_xFrame_TimePrev + (position.x + position.y + position.z))*g_xFrame_WindDirection.xyz * patchPos.y * 0.03f; + // scale the billboard by the texture aspect: + float2 frame; + texture_0.GetDimensions(frame.x, frame.y); + frame.xy /= frame.y; + frame.xy *= len; + patchPos.xyz *= frame.xyx * 0.5f; - // rotate the patch into the tangent space of the emitting triangle: - float3x3 TBN = float3x3(tangent, normal, binormal); // don't derive binormal, because we want the shear! - patchPos = mul(patchPos, TBN); + // simplistic wind effect only affects the top, but leaves the base as is: + float3 wind = sin(g_xFrame_Time + (position.x + position.y + position.z)) * g_xFrame_WindDirection.xyz * patchPos.y * 0.03f; + float3 windPrev = sin(g_xFrame_TimePrev + (position.x + position.y + position.z)) * g_xFrame_WindDirection.xyz * patchPos.y * 0.03f; - // inset to the emitter a bit, to avoid disconnect: - position.xyz -= normal * 0.1 * len; + // rotate the patch into the tangent space of the emitting triangle: + float3x3 TBN = float3x3(tangent, normal, binormal); // don't derive binormal, because we want the shear! + patchPos = mul(patchPos, TBN); + + // inset to the emitter a bit, to avoid disconnect: + position.xyz -= normal * 0.1 * len; - // copy to output: - Out.pos = float4(position, 1); - Out.pos.xyz += patchPos; - float3 savedPos = Out.pos.xyz; - Out.pos.xyz += wind; - Out.pos3D = Out.pos.xyz; - Out.pos = mul(g_xCamera_VP, Out.pos); + // copy to output: + Out.pos = float4(position, 1); + Out.pos.xyz += patchPos; + float3 savedPos = Out.pos.xyz; + Out.pos.xyz += wind; + Out.pos3D = Out.pos.xyz; + Out.pos = mul(g_xCamera_VP, Out.pos); - Out.nor = normal; - Out.tex = uv; - - Out.fade = pow(saturate(distance(position.xyz, g_xCamera_CamPos.xyz) / (xHairViewDistance*hairPopDistanceThreshold)), 10); - Out.pos2D = Out.pos; - Out.pos2DPrev = mul(g_xFrame_MainCamera_PrevVP, float4(savedPos + windPrev, 1)); + Out.nor = normal; + Out.tex = uv; - Out.color = xColor.rgb; + Out.pos2D = Out.pos; + Out.pos2DPrev = mul(g_xFrame_MainCamera_PrevVP, float4(savedPos + windPrev, 1)); + + Out.color = xColor.rgb; + } + else + { + Out = (VertexToPixel)0; + } return Out; } diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index f1896402d..3cf67c348 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -19,7 +19,12 @@ namespace wiSceneSystem { static const VertexShader *vs = nullptr; -static const PixelShader *ps[RENDERPASS_COUNT] = {}; +static const PixelShader* ps_alphatestonly = nullptr; +static const PixelShader* ps_deferred = nullptr; +static const PixelShader* ps_forward = nullptr; +static const PixelShader* ps_forward_transparent = nullptr; +static const PixelShader* ps_tiledforward = nullptr; +static const PixelShader* ps_tiledforward_transparent = nullptr; static const PixelShader *ps_simplest = nullptr; static const ComputeShader *cs_simulate = nullptr; static DepthStencilState dss_default, dss_equal, dss_rejectopaque_keeptransparent; @@ -213,68 +218,91 @@ void wiHairParticle::LoadShaders() vs = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticleVS.cso", wiResourceManager::VERTEXSHADER)); - ps[RENDERPASS_DEPTHONLY] = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_alphatestonly.cso", wiResourceManager::PIXELSHADER)); - ps[RENDERPASS_DEFERRED] = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_deferred.cso", wiResourceManager::PIXELSHADER)); - ps[RENDERPASS_FORWARD] = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_forward.cso", wiResourceManager::PIXELSHADER)); - ps[RENDERPASS_TILEDFORWARD] = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_tiledforward.cso", wiResourceManager::PIXELSHADER)); + ps_alphatestonly = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_alphatestonly.cso", wiResourceManager::PIXELSHADER)); + ps_deferred = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_deferred.cso", wiResourceManager::PIXELSHADER)); + ps_forward = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_forward.cso", wiResourceManager::PIXELSHADER)); + ps_forward_transparent = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_forward_transparent.cso", wiResourceManager::PIXELSHADER)); + ps_tiledforward = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_tiledforward.cso", wiResourceManager::PIXELSHADER)); + ps_tiledforward_transparent = static_cast(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_tiledforward_transparent.cso", wiResourceManager::PIXELSHADER)); GraphicsDevice* device = wiRenderer::GetDevice(); for (int i = 0; i < RENDERPASS_COUNT; ++i) { - if (ps[i] == nullptr) + if (i == RENDERPASS_DEPTHONLY || i == RENDERPASS_DEFERRED || i == RENDERPASS_FORWARD || i == RENDERPASS_TILEDFORWARD) { - continue; - } - - for (int j = 0; j < 2; ++j) - { - if ((i == RENDERPASS_DEPTHONLY || i == RENDERPASS_DEFERRED) && j == 1) + for (int j = 0; j < 2; ++j) { - continue; + if ((i == RENDERPASS_DEPTHONLY || i == RENDERPASS_DEFERRED) && j == 1) + { + continue; + } + + PipelineStateDesc desc; + desc.vs = vs; + desc.bs = &bs[j]; + desc.rs = &ncrs; + desc.dss = &dss_default; + + desc.DSFormat = wiRenderer::DSFormat_full; + + switch (i) + { + case RENDERPASS_DEPTHONLY: + desc.ps = ps_alphatestonly; + break; + case RENDERPASS_DEFERRED: + desc.ps = ps_deferred; + break; + case RENDERPASS_FORWARD: + if (j == 0) + { + desc.ps = ps_forward; + } + else + { + desc.ps = ps_forward_transparent; + } + break; + case RENDERPASS_TILEDFORWARD: + if (j == 0) + { + desc.ps = ps_tiledforward; + } + else + { + desc.ps = ps_tiledforward_transparent; + } + break; + } + + switch (i) + { + case RENDERPASS_FORWARD: + case RENDERPASS_TILEDFORWARD: + desc.numRTs = 2; + desc.RTFormats[0] = wiRenderer::RTFormat_hdr; + desc.RTFormats[1] = wiRenderer::RTFormat_gbuffer_1; + desc.dss = &dss_equal; // opaque + break; + case RENDERPASS_DEFERRED: + desc.numRTs = 5; + desc.RTFormats[0] = wiRenderer::RTFormat_gbuffer_0; + desc.RTFormats[1] = wiRenderer::RTFormat_gbuffer_1; + desc.RTFormats[2] = wiRenderer::RTFormat_gbuffer_2; + desc.RTFormats[3] = wiRenderer::RTFormat_deferred_lightbuffer; + desc.RTFormats[4] = wiRenderer::RTFormat_deferred_lightbuffer; + } + + if (j == 1) + { + desc.dss = &dss_rejectopaque_keeptransparent; // transparent + desc.numRTs = 1; + } + + device->CreatePipelineState(&desc, &PSO[i][j]); } - - PipelineStateDesc desc; - desc.vs = vs; - desc.ps = ps[i]; - desc.bs = &bs[j]; - desc.rs = &ncrs; - desc.dss = &dss_default; - - desc.DSFormat = wiRenderer::DSFormat_full; - - switch (i) - { - case RENDERPASS_TEXTURE: - desc.numRTs = 1; - desc.RTFormats[0] = wiRenderer::RTFormat_hdr; - break; - case RENDERPASS_FORWARD: - case RENDERPASS_TILEDFORWARD: - desc.numRTs = 2; - desc.RTFormats[0] = wiRenderer::RTFormat_hdr; - desc.RTFormats[1] = wiRenderer::RTFormat_gbuffer_1; - desc.dss = &dss_equal; // opaque - break; - case RENDERPASS_DEFERRED: - desc.numRTs = 5; - desc.RTFormats[0] = wiRenderer::RTFormat_gbuffer_0; - desc.RTFormats[1] = wiRenderer::RTFormat_gbuffer_1; - desc.RTFormats[2] = wiRenderer::RTFormat_gbuffer_2; - desc.RTFormats[3] = wiRenderer::RTFormat_deferred_lightbuffer; - desc.RTFormats[4] = wiRenderer::RTFormat_deferred_lightbuffer; - default: - break; - } - - if (j == 1) - { - desc.dss = &dss_rejectopaque_keeptransparent; // transparent - desc.numRTs = 1; - } - - device->CreatePipelineState(&desc, &PSO[i][j]); } } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 90733b0de..03060861b 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 31; // minor bug fixes, alterations, refactors, updates - const int revision = 9; + const int revision = 10; long GetVersion()