hair particle updates
This commit is contained in:
@@ -316,9 +316,15 @@
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel>
|
||||
</FxCompile>
|
||||
<FxCompile Include="hairparticlePS_forward_transparent.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
|
||||
</FxCompile>
|
||||
<FxCompile Include="hairparticlePS_simplest.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
|
||||
</FxCompile>
|
||||
<FxCompile Include="hairparticlePS_tiledforward_transparent.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
|
||||
</FxCompile>
|
||||
<FxCompile Include="hairparticle_simulateCS.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel>
|
||||
|
||||
@@ -810,6 +810,12 @@
|
||||
<FxCompile Include="chromatic_aberrationCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="hairparticlePS_forward_transparent.hlsl">
|
||||
<Filter>PS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="hairparticlePS_tiledforward_transparent.hlsl">
|
||||
<Filter>PS</Filter>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="PS">
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#define TRANSPARENT
|
||||
#include "hairparticlePS_forward.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);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#define TRANSPARENT
|
||||
#include "hairparticlePS_tiledforward.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;
|
||||
}
|
||||
|
||||
@@ -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<const VertexShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticleVS.cso", wiResourceManager::VERTEXSHADER));
|
||||
|
||||
ps[RENDERPASS_DEPTHONLY] = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_alphatestonly.cso", wiResourceManager::PIXELSHADER));
|
||||
ps[RENDERPASS_DEFERRED] = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_deferred.cso", wiResourceManager::PIXELSHADER));
|
||||
ps[RENDERPASS_FORWARD] = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_forward.cso", wiResourceManager::PIXELSHADER));
|
||||
ps[RENDERPASS_TILEDFORWARD] = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_tiledforward.cso", wiResourceManager::PIXELSHADER));
|
||||
ps_alphatestonly = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_alphatestonly.cso", wiResourceManager::PIXELSHADER));
|
||||
ps_deferred = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_deferred.cso", wiResourceManager::PIXELSHADER));
|
||||
ps_forward = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_forward.cso", wiResourceManager::PIXELSHADER));
|
||||
ps_forward_transparent = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_forward_transparent.cso", wiResourceManager::PIXELSHADER));
|
||||
ps_tiledforward = static_cast<const PixelShader*>(wiResourceManager::GetShaderManager().add(path + "hairparticlePS_tiledforward.cso", wiResourceManager::PIXELSHADER));
|
||||
ps_tiledforward_transparent = static_cast<const PixelShader*>(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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user