hairparticle, wind, water, ocean updates
This commit is contained in:
@@ -68,23 +68,38 @@ WeatherWindow::WeatherWindow(wiGUI* gui) : GUI(gui)
|
||||
});
|
||||
weatherWindow->AddWidget(cloudSpeedSlider);
|
||||
|
||||
windSpeedSlider = new wiSlider(0.001f, 0.2f, 0.1f, 10000, "Wind Speed: ");
|
||||
windSpeedSlider = new wiSlider(0.0f, 0.2f, 0.0f, 10000, "Wind Speed: ");
|
||||
windSpeedSlider->SetSize(XMFLOAT2(100, 30));
|
||||
windSpeedSlider->SetPos(XMFLOAT2(x, y += step));
|
||||
windSpeedSlider->OnSlide([&](wiEventArgs args) {
|
||||
UpdateWind();
|
||||
});
|
||||
weatherWindow->AddWidget(windSpeedSlider);
|
||||
|
||||
windDirectionSlider = new wiSlider(0, 1, 0, 10000, "Wind Direction: ");
|
||||
windDirectionSlider->SetSize(XMFLOAT2(100, 30));
|
||||
windDirectionSlider->SetPos(XMFLOAT2(x, y += step));
|
||||
windDirectionSlider->OnSlide([&](wiEventArgs args) {
|
||||
XMMATRIX rot = XMMatrixRotationY(args.fValue * XM_PI * 2);
|
||||
XMVECTOR dir = XMVectorSet(1, 0, 0, 0);
|
||||
dir = XMVector3TransformNormal(dir, rot);
|
||||
dir *= windSpeedSlider->GetValue();
|
||||
XMStoreFloat3(&GetWeather().windDirection, dir);
|
||||
UpdateWind();
|
||||
});
|
||||
weatherWindow->AddWidget(windDirectionSlider);
|
||||
|
||||
windWaveSizeSlider = new wiSlider(0, 1, 0, 10000, "Wind Wave Size: ");
|
||||
windWaveSizeSlider->SetSize(XMFLOAT2(100, 30));
|
||||
windWaveSizeSlider->SetPos(XMFLOAT2(x, y += step));
|
||||
windWaveSizeSlider->OnSlide([&](wiEventArgs args) {
|
||||
GetWeather().windWaveSize = args.fValue;
|
||||
});
|
||||
weatherWindow->AddWidget(windWaveSizeSlider);
|
||||
|
||||
windRandomnessSlider = new wiSlider(0, 1, 0, 10000, "Wind Randomness: ");
|
||||
windRandomnessSlider->SetSize(XMFLOAT2(100, 30));
|
||||
windRandomnessSlider->SetPos(XMFLOAT2(x, y += step));
|
||||
windRandomnessSlider->OnSlide([&](wiEventArgs args) {
|
||||
GetWeather().windRandomness = args.fValue;
|
||||
});
|
||||
weatherWindow->AddWidget(windRandomnessSlider);
|
||||
|
||||
|
||||
skyButton = new wiButton("Load Sky");
|
||||
skyButton->SetTooltip("Load a skybox cubemap texture...");
|
||||
@@ -508,3 +523,12 @@ void WeatherWindow::InvalidateProbes() const
|
||||
scene.probes[i].SetDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void WeatherWindow::UpdateWind()
|
||||
{
|
||||
XMMATRIX rot = XMMatrixRotationY(windDirectionSlider->GetValue() * XM_PI * 2);
|
||||
XMVECTOR dir = XMVectorSet(1, 0, 0, 0);
|
||||
dir = XMVector3TransformNormal(dir, rot);
|
||||
dir *= windSpeedSlider->GetValue();
|
||||
XMStoreFloat3(&GetWeather().windDirection, dir);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class wiButton;
|
||||
|
||||
class WeatherWindow
|
||||
{
|
||||
void UpdateWind();
|
||||
public:
|
||||
WeatherWindow(wiGUI* gui);
|
||||
~WeatherWindow();
|
||||
@@ -30,6 +31,8 @@ public:
|
||||
wiSlider* cloudSpeedSlider;
|
||||
wiSlider* windSpeedSlider;
|
||||
wiSlider* windDirectionSlider;
|
||||
wiSlider* windWaveSizeSlider;
|
||||
wiSlider* windRandomnessSlider;
|
||||
wiButton* skyButton;
|
||||
wiColorPicker* ambientColorPicker;
|
||||
wiColorPicker* horizonColorPicker;
|
||||
|
||||
@@ -76,8 +76,9 @@ VertexToPixel main(uint fakeIndex : SV_VERTEXID)
|
||||
patchPos.xyz *= frame.xyx * 0.5f;
|
||||
|
||||
// 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;
|
||||
const float3 posrand = (position.x + position.y + position.z) * g_xFrame_WindRandomness;
|
||||
float3 wind = sin(g_xFrame_Time * (1 + g_xFrame_WindWaveSize) + posrand) * g_xFrame_WindDirection * patchPos.y;
|
||||
float3 windPrev = sin(g_xFrame_TimePrev * (1 + g_xFrame_WindWaveSize) + posrand) * g_xFrame_WindDirection * patchPos.y;
|
||||
|
||||
// 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!
|
||||
|
||||
@@ -17,7 +17,16 @@ struct LDS_ForceField
|
||||
float range_rcp;
|
||||
float3 normal;
|
||||
};
|
||||
groupshared LDS_ForceField forceFields[NUM_LDS_FORCEFIELDS];
|
||||
groupshared LDS_ForceField forceFields[NUM_LDS_FORCEFIELDS];
|
||||
|
||||
// https://www.shadertoy.com/view/llGSzw
|
||||
float hash1(uint n)
|
||||
{
|
||||
// integer hash copied from Hugo Elias
|
||||
n = (n << 13U) ^ n;
|
||||
n = n * (n * n * 15731U + 789221U) + 1376312589U;
|
||||
return float(n & 0x7fffffffU) / float(0x7fffffff);
|
||||
}
|
||||
|
||||
[numthreads(THREADCOUNT_SIMULATEHAIR, 1, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex)
|
||||
@@ -35,14 +44,16 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
|
||||
forceFields[groupIndex].range_rcp = forceField.range; // it is actually uploaded from CPU as 1.0f / range
|
||||
forceFields[groupIndex].normal = forceField.directionWS;
|
||||
}
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
if (DTid.x >= xHairParticleCount)
|
||||
return;
|
||||
|
||||
// Generate patch:
|
||||
float2 uv = float2((Gid.x + 1.0f) / (float)xHairNumDispatchGroups, (DTid.x + 1.0f) / (float)THREADCOUNT_SIMULATEHAIR);
|
||||
float seed = xHairRandomSeed;
|
||||
|
||||
// random triangle on emitter surface:
|
||||
uint tri = (uint)((xHairBaseMeshIndexCount / 3) * rand(seed, uv));
|
||||
// (Note that the usual rand() function is not used because that introduces unnatural clustering with high triangle count)
|
||||
uint tri = (uint)((xHairBaseMeshIndexCount / 3) * hash1(DTid.x));
|
||||
|
||||
// load indices of triangle from index buffer
|
||||
uint i0 = meshIndexBuffer[tri * 3 + 0];
|
||||
@@ -61,6 +72,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
|
||||
float length2 = meshVertexBuffer_length[i2];
|
||||
|
||||
// random barycentric coords:
|
||||
float2 uv = hammersley2d(DTid.x, xHairStrandCount);
|
||||
float seed = xHairRandomSeed;
|
||||
float f = rand(seed, uv);
|
||||
float g = rand(seed, uv);
|
||||
[flatten]
|
||||
@@ -95,10 +108,10 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
|
||||
// Transform particle by the emitter object matrix:
|
||||
float3 base = mul(xWorld, float4(position.xyz, 1)).xyz;
|
||||
target = normalize(mul((float3x3)xWorld, target));
|
||||
const float3 root = base;
|
||||
|
||||
float3 normal = 0;
|
||||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
for (uint segmentID = 0; segmentID < xHairSegmentCount; ++segmentID)
|
||||
{
|
||||
// Identifies the hair strand segment particle:
|
||||
|
||||
@@ -753,7 +753,6 @@ GBUFFEROutputType_Thin main(PIXELINPUT input)
|
||||
|
||||
#ifndef SIMPLE_INPUT
|
||||
float3 bumpColor = 0;
|
||||
float opacity = color.a;
|
||||
float depth = input.pos.z;
|
||||
#ifndef ENVMAPRENDERING
|
||||
input.pos2D.xy /= input.pos2D.w;
|
||||
@@ -900,9 +899,6 @@ GBUFFEROutputType_Thin main(PIXELINPUT input)
|
||||
#endif // ENVMAPRENDERING
|
||||
#endif // WATER
|
||||
|
||||
ApplyLighting(surface, lighting, color);
|
||||
|
||||
|
||||
#ifdef WATER
|
||||
// REFRACTION
|
||||
const float lineardepth = input.pos2D.w;
|
||||
@@ -911,9 +907,10 @@ GBUFFEROutputType_Thin main(PIXELINPUT input)
|
||||
const float3 refractiveColor = texture_refraction.SampleLevel(sampler_linear_mirror, ScreenCoord.xy + bumpColor.rg * saturate(0.5 * depth_difference), 0).rgb;
|
||||
|
||||
// WATER FOG
|
||||
color.rgb = lerp(refractiveColor, color.rgb, saturate(surface.baseColor.a * 0.1f * depth_difference));
|
||||
surface.albedo = lerp(refractiveColor, color.rgb, saturate(surface.baseColor.a * 0.1f * depth_difference));
|
||||
#endif // WATER
|
||||
|
||||
ApplyLighting(surface, lighting, color);
|
||||
|
||||
ApplyFog(dist, color);
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@ float4 main(PSIn input) : SV_TARGET
|
||||
|
||||
TiledLighting(pixel, surface, lighting);
|
||||
|
||||
ApplyLighting(surface, lighting, color);
|
||||
|
||||
// REFRACTION
|
||||
const float lineardepth = input.pos2D.w;
|
||||
const float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + surface.N.xz * 0.04f, 0) * g_xCamera_ZFarP;
|
||||
@@ -46,7 +44,9 @@ float4 main(PSIn input) : SV_TARGET
|
||||
const float3 refractiveColor = texture_refraction.SampleLevel(sampler_linear_mirror, ScreenCoord.xy + surface.N.xz * 0.04f * saturate(0.5 * depth_difference), 0).rgb;
|
||||
|
||||
// WATER FOG
|
||||
color.rgb = lerp(refractiveColor, color.rgb, saturate(0.1f * depth_difference));
|
||||
surface.albedo = lerp(refractiveColor, color.rgb, saturate(0.1f * depth_difference));
|
||||
|
||||
ApplyLighting(surface, lighting, color);
|
||||
|
||||
ApplyFog(dist, color);
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen
|
||||
hcb.xHairBaseMeshIndexCount = (indices.empty() ? (uint)mesh.indices.size() : (uint)indices.size());
|
||||
hcb.xHairBaseMeshVertexPositionStride = sizeof(MeshComponent::Vertex_POS);
|
||||
// segmentCount will be loop in the shader, not a threadgroup so we don't need it here:
|
||||
hcb.xHairNumDispatchGroups = (uint)ceilf((float)strandCount / (float)THREADCOUNT_SIMULATEHAIR);
|
||||
hcb.xHairNumDispatchGroups = (hcb.xHairParticleCount + THREADCOUNT_SIMULATEHAIR - 1) / THREADCOUNT_SIMULATEHAIR;
|
||||
device->UpdateBuffer(&cb, &hcb, cmd);
|
||||
|
||||
device->BindConstantBuffer(CS, &cb, CB_GETBINDSLOT(HairParticleCB), cmd);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wiVersion
|
||||
// minor features, major updates
|
||||
const int minor = 39;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 34;
|
||||
const int revision = 35;
|
||||
|
||||
|
||||
long GetVersion()
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user