New skyboxrenderer + moved meshrenderer inside engine and out from main to clean that up
This commit is contained in:
@@ -231,3 +231,62 @@ graph LR
|
||||
1. **Cubemap source** — **Procedural gradient skybox** chosen because asset loading infrastructure is not yet established.
|
||||
2. **Sampler heap** — Evaluate what exists. However, with a procedural skybox, we won't need a sampler for Phase 3! (The sky color can be procedurally generated from the reconstructed view direction).
|
||||
3. **Specular** — **Blinn-Phong** specular, structured in an agnostic way so PBR (physically based rendering) parameters can be plugged in later.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Forward Rendered Entity Lights
|
||||
|
||||
A simple, fast forward renderer using a Global Structured Buffer for entity-based point lights.
|
||||
|
||||
### Approach: Bindless Global Lights Buffer
|
||||
|
||||
Instead of passing each light via PushConstants, we pass a `StructuredBuffer<PointLight>` index and iterate over the active lights in the fragment shader.
|
||||
|
||||
### New C++ Components
|
||||
|
||||
```cpp
|
||||
struct PointLight
|
||||
{
|
||||
Vector3 Position;
|
||||
float Radius;
|
||||
Vector3 Color;
|
||||
float Intensity;
|
||||
};
|
||||
```
|
||||
|
||||
1. **Lights Buffer Allocation**: Allocate a `StructuredBuffer` large enough for all potential lights (e.g., max 1024).
|
||||
2. **Buffer Upload**: Loop through the active game entity lights every frame and upload them using the TransferBuffer system.
|
||||
3. **PushData Update**:
|
||||
- `uint32 LightsBufferIndex`
|
||||
- `uint32 ActiveLightCount`
|
||||
|
||||
### Shader Design
|
||||
|
||||
**Fragment Shader Expansion** loop over all `ActiveLightCount` to compute the attenuation and diffuse, then accumulate.
|
||||
|
||||
```hlsl
|
||||
StructuredBuffer<PointLight> lights = ResourceDescriptorHeap[LightsBufferIndex];
|
||||
|
||||
float3 totalDiffuse = Color.rgb * LightColor * NdotL; // Include Directional Sun
|
||||
|
||||
for (uint i = 0; i < ActiveLightCount; ++i)
|
||||
{
|
||||
PointLight light = lights[i];
|
||||
|
||||
float3 lightVector = light.Position - WorldPosition;
|
||||
float distance = length(lightVector);
|
||||
|
||||
if (distance > light.Radius) continue;
|
||||
|
||||
float3 L = lightVector / distance;
|
||||
float NdotL = saturate(dot(N, L));
|
||||
|
||||
float attenuation = 1.0 - saturate(distance / light.Radius);
|
||||
attenuation *= attenuation; // inverse square-ish
|
||||
|
||||
totalDiffuse += Color.rgb * light.Color * light.Intensity * NdotL * attenuation;
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Passing `WorldPosition` to the Fragment shader from the Vertex shader is required for positional lighting.
|
||||
|
||||
Reference in New Issue
Block a user