This project is entirely implemented using Direct3D (D3D), based on the PrimeEngine Framework provided in USC CSCI 522 Game Engine Development, which demonstrates the ability to simulate ocean surfaces with fluid dynamics and implement atmospheric scattering models within a Direct3D-based rendering framework.
Implementation Details
Infinite Ocean Surface: Projected Grid
- A vertex buffer object (VBO) is generated in screen space and projected into world space to achieve an infinite ocean effect.
Inverse Discrete Fourier Transform (IDFT) Spectrum
- A Compute Shader is used to reconstruct the wave height and normals from the frequency spectrum. The following CG Compute Shader updates the Fourier spectrum over time using the Phillips spectrum model, which is crucial for generating physically realistic ocean wave animations.
[numthreads(16, 16, 1)]
void main(uint3 globalIdx : SV_DispatchThreadID) {
uint index = globalIdx.y * spectrumN + globalIdx.x;
float h0Re = H0Re[index];
float h0Im = H0Im[index];
float time = gGameTimes.x;
float speed = xV_yW_zSpeed_wTiling.z;
float L = xL_yG_zAmp.x;
float g = xL_yG_zAmp.y;
float kx = (float(globalIdx.x) - float(spectrumN) / 2.0) / L;
float ky = (float(globalIdx.y) - float(spectrumN) / 2.0) / L;
float2 k = float2(kx, ky);
float omega = sqrt(g * length(k));
float phase = omega * time;
float hRe = h0Re * cos(phase) - h0Im * sin(phase);
float hIm = h0Re * sin(phase) + h0Im * cos(phase);
HRe[index] = hRe;
HIm[index] = hIm;
}
Atmospheric Scattering
This implementation considers single scattering models, incorporating Rayleigh and Mie scattering physics. The shader performs numerical integration using a ray marching approach to compute the light transport through the atmosphere.
float3 atmosphericScattering(Light sunlight, DETAILED_MESH_SHADOWED_PS_IN pIn) {
float3 ray_o = xyzgEyePosW_wDoMotionBlur.xyz;
float3 ray_d = normalize(pIn.iPosW.xyz - ray_o);
float3 V = -ray_d, L = normalize(sunlight.xyzDir_w.xyz);
float3 p1 = ray_o + float3(0, earthRadius, 0);
float p1Dist2Atmo = getDist2Atmosphere(p1, ray_d);
int numSteps = 16;
float stepSize = p1Dist2Atmo / float(numSteps);
p1 += ray_d * stepSize * 0.5;
float transmittance = 1.0;
float3 accumulatedColor = float3(0.0, 0.0, 0.0);
for (int i = 0; i < 1; i++) {
float p1Dist2p2 = getDist2Atmosphere(p1, L);
float3 p2 = p1 + L * p1Dist2p2;
float3 sunRadiance = sunlight.diffuse.xyz;
float3 t1 = Transmittance(p2, p1);
float3 s = Scattering(p1, L, V) * 1e5;
float3 t2 = Transmittance(p1, ray_o);
accumulatedColor += sunRadiance * t1 * s * t2 * stepSize;
p1 += ray_d * stepSize;
}
return accumulatedColor;
}
The Los Angeles wildfires illustrate how strong Rayleigh scattering effects can persist even at noon.
Beyond the scope of CSCI 522, we have also deepened our understanding of Direct3D rendering pipelines and DXR (DirectX Raytracing).
Potential Improvements
Projected Grid
- Tessellation (Specular highlights appear mosaic-like and not smooth enough, normal map disturbance reduces the effect)
- LOD
IDFT Spectrum
- Offset Spectrum
- FFT
- Subsurface Scattering, Foam, Fresnel
Atmospheric Scattering
- LUT
References
Projected Grid
- Introduction to 3D Game Programming with DirectX 12
- https://www.cnblogs.com/ArenAK/archive/2007/11/07/951713.html
- https://www.nowcoder.com/discuss/472709363229126656
- https://blog.csdn.net/saviollar/article/details/1350583
- https://zhuanlan.zhihu.com/p/558150619
IDFT Spectrum
- https://zhuanlan.zhihu.com/p/95482541
- https://zhuanlan.zhihu.com/p/335946333
- https://www.bilibili.com/video/BV1281hYXE2J
- https://people.computing.clemson.edu/~jtessen/reports/papers_files/coursenotes2004.pdf