添加体积阴影和光照:统一与Unity版本一致
This commit is contained in:
@@ -4,14 +4,12 @@
|
||||
|
||||
cbuffer CB0 : register(b1)
|
||||
{
|
||||
float4x4 _InverseViewProjection;
|
||||
float3 _CameraPos;
|
||||
float _DensityScale;
|
||||
float3 _BBoxMin;
|
||||
float _StepSize;
|
||||
float3 _BBoxMax;
|
||||
uint _MaxSteps;
|
||||
float _RotationY;
|
||||
float4x4 _InverseViewProjection; // 64 bytes
|
||||
float4 _CameraPos_Density; // xyz = CameraPos, w = DensityScale
|
||||
float4 _BBoxMin_Step; // xyz = BBoxMin, w = StepSize
|
||||
float4 _BBoxMax_MaxSteps; // xyz = BBoxMax, w = MaxSteps
|
||||
float4 _Rotation_Pad_LightSamples; // x = RotationY, yzw = pad, but we'll use differently
|
||||
float4 _LightDir_Samples; // xyz = LightDir, w = LightSamples
|
||||
};
|
||||
|
||||
StructuredBuffer<uint> buf : register(t1);
|
||||
@@ -90,6 +88,47 @@ float phase_function()
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
uint rand_xorshift(uint seed)
|
||||
{
|
||||
seed ^= (seed << 13);
|
||||
seed ^= (seed >> 17);
|
||||
seed ^= (seed << 5);
|
||||
return seed;
|
||||
}
|
||||
|
||||
float random_float(float3 pos)
|
||||
{
|
||||
uint seed = asuint(pos.x + pos.y + pos.z);
|
||||
float res = float(rand_xorshift(seed)) * (1.0 / 4294967296.0);
|
||||
res = float(rand_xorshift(asuint(res))) * (1.0 / 4294967296.0);
|
||||
return res;
|
||||
}
|
||||
|
||||
float volumetric_shadow(float3 pos, float densityScale, inout pnanovdb_readaccessor_t acc)
|
||||
{
|
||||
float lightSamples = _LightDir_Samples.w;
|
||||
if (lightSamples < 1) { return 0.0; }
|
||||
|
||||
float3 light_dir = _LightDir_Samples.xyz;
|
||||
|
||||
float shadow = 1.0;
|
||||
float step_size = 1.0;
|
||||
|
||||
int steps = 10;
|
||||
for (int step = 0; step < steps; step++)
|
||||
{
|
||||
float3 sample_pos = pos + step_size * light_dir;
|
||||
|
||||
float sigmaS = get_value_coord(acc, sample_pos) * densityScale;
|
||||
float sigmaE = max(0.000001, sigmaS) * 2.0;
|
||||
shadow *= exp(-sigmaE * step_size);
|
||||
|
||||
step_size *= (2.0 + random_float(sample_pos));
|
||||
}
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
PSInput MainVS(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
@@ -116,7 +155,7 @@ bool intersectBox(float3 origin, float3 dir, float3 boxMin, float3 boxMax, out f
|
||||
|
||||
float4 MainPS(PSInput input) : SV_TARGET
|
||||
{
|
||||
float3 rayDir = normalize(input.worldPos - _CameraPos);
|
||||
float3 rayDir = normalize(input.worldPos - _CameraPos_Density.xyz);
|
||||
|
||||
float tmin = 0.01;
|
||||
float tmax = 5000.0;
|
||||
@@ -126,6 +165,14 @@ float4 MainPS(PSInput input) : SV_TARGET
|
||||
|
||||
float3 color = float3(0, 0, 0);
|
||||
float transmittance = 1.0;
|
||||
float acc_density = 0.0;
|
||||
float3 ambient_light = 0.005;
|
||||
|
||||
float _DensityScale = _CameraPos_Density.w;
|
||||
float _StepSize = _BBoxMin_Step.w;
|
||||
float _MaxSteps = _BBoxMax_MaxSteps.w;
|
||||
float _RotationY = _Rotation_Pad_LightSamples.x;
|
||||
float _LightSamples = _LightDir_Samples.w;
|
||||
|
||||
float cosR = cos(_RotationY);
|
||||
float sinR = sin(_RotationY);
|
||||
@@ -135,7 +182,7 @@ float4 MainPS(PSInput input) : SV_TARGET
|
||||
-sinR, 0, cosR
|
||||
);
|
||||
|
||||
float3 localCameraPos = mul(invRotY, _CameraPos);
|
||||
float3 localCameraPos = mul(invRotY, _CameraPos_Density.xyz);
|
||||
float3 localRayDir = mul(invRotY, rayDir);
|
||||
|
||||
float not_used;
|
||||
@@ -144,7 +191,7 @@ float4 MainPS(PSInput input) : SV_TARGET
|
||||
|
||||
float skip = 0;
|
||||
|
||||
for (uint i = 0; i < _MaxSteps; i++) {
|
||||
for (int i = 0; i < (int)_MaxSteps; i++) {
|
||||
if (tmin >= tmax || transmittance < 0.01) break;
|
||||
|
||||
float3 localPos = localCameraPos + localRayDir * tmin;
|
||||
@@ -174,14 +221,20 @@ float4 MainPS(PSInput input) : SV_TARGET
|
||||
|
||||
float sigmaS = density;
|
||||
float sigmaE = max(0.000001, sigmaS);
|
||||
float3 S = sigmaS * phase_function() * float3(1, 1, 1);
|
||||
acc_density += sigmaS;
|
||||
|
||||
float shadow = volumetric_shadow(localPos, _DensityScale, volume.acc);
|
||||
float3 S = sigmaS * phase_function() * shadow * float3(1, 1, 1);
|
||||
float3 Sint = (S - S * exp(-sigmaE * _StepSize)) / sigmaE;
|
||||
color += transmittance * Sint;
|
||||
transmittance *= exp(-sigmaE * _StepSize);
|
||||
|
||||
if (acc_density > 1.0) break;
|
||||
|
||||
tmin += _StepSize;
|
||||
}
|
||||
|
||||
float alpha = 1.0 - transmittance;
|
||||
return float4(color, alpha);
|
||||
float3 final_color = (color + ambient_light) * acc_density;
|
||||
final_color = pow(final_color, 1.0 / 2.2);
|
||||
return float4(final_color, acc_density);
|
||||
}
|
||||
13
main.cpp
13
main.cpp
@@ -290,7 +290,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
DirectX::XMFLOAT4X4 invViewProjMat;
|
||||
DirectX::XMStoreFloat4x4(&invViewProjMat, invViewProj);
|
||||
|
||||
float volumeCBData[32];
|
||||
float volumeCBData[36];
|
||||
memcpy(volumeCBData, &invViewProjMat, sizeof(float) * 16);
|
||||
volumeCBData[16] = -10.0f;
|
||||
volumeCBData[17] = 73.0f;
|
||||
@@ -303,9 +303,16 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
||||
volumeCBData[24] = (float)nanoVDBData.worldBBox[3];
|
||||
volumeCBData[25] = (float)nanoVDBData.worldBBox[4];
|
||||
volumeCBData[26] = (float)nanoVDBData.worldBBox[5];
|
||||
volumeCBData[27] = 2000;
|
||||
volumeCBData[27] = 2000.0f; // MaxSteps as float
|
||||
volumeCBData[28] = timeSinceAppStartInSecond * 0.3f; // RotationY
|
||||
UpdateConstantBuffer(volumeCB, volumeCBData, sizeof(float) * 29);
|
||||
volumeCBData[29] = 0.0f; // Pad0
|
||||
volumeCBData[30] = 0.0f; // Pad1
|
||||
volumeCBData[31] = 0.0f; // Pad2
|
||||
volumeCBData[32] = 0.5f; // LightDir X
|
||||
volumeCBData[33] = 0.8f; // LightDir Y
|
||||
volumeCBData[34] = 0.3f; // LightDir Z
|
||||
volumeCBData[35] = 8.0f; // LightSamples as float
|
||||
UpdateConstantBuffer(volumeCB, volumeCBData, sizeof(float) * 36);
|
||||
if (frameCount == 1) {
|
||||
printf("Volume BBox: [%.2f, %.2f, %.2f] - [%.2f, %.2f, %.2f]\n",
|
||||
volumeCBData[20], volumeCBData[21], volumeCBData[22],
|
||||
|
||||
Reference in New Issue
Block a user