Skip to content

Commit c8e681c

Browse files
committed
feat: implement light volumes #77
1 parent ca70eab commit c8e681c

File tree

7 files changed

+556
-238
lines changed

7 files changed

+556
-238
lines changed

extensions/pl_renderer_ext.c

Lines changed: 174 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,26 @@ pl_renderer_create_scene(plSceneInit tInit)
707707
ptScene->tProbeMesh = gptMesh->create_sphere_mesh(ptScene->ptComponentLibrary, "environment probe mesh", 0.25f, 32, 32, &ptMesh);
708708
ptMesh->tMaterial = tMaterial;
709709

710+
ptMesh = NULL;
711+
ptScene->tUnitSphereMesh = gptMesh->create_sphere_mesh(ptScene->ptComponentLibrary, "unit sphere mesh", 1.0f, 16, 16, &ptMesh);
712+
713+
const uint32_t uStartIndex = pl_sb_size(ptScene->sbtVertexPosBuffer);
714+
const uint32_t uIndexStart = pl_sb_size(ptScene->sbuIndexBuffer);
715+
716+
const plDrawable tDrawable = {
717+
.uIndexCount = (uint32_t)ptMesh->szIndexCount,
718+
.uVertexCount = (uint32_t)ptMesh->szVertexCount,
719+
.uIndexOffset = uIndexStart,
720+
.uVertexOffset = uStartIndex,
721+
.uTransformIndex = ptScene->uNextTransformIndex++,
722+
.uTriangleCount = (uint32_t)ptMesh->szIndexCount / 3
723+
};
724+
ptScene->tUnitSphereDrawable = tDrawable;
725+
pl_sb_resize(ptScene->sbuIndexBuffer, (uint32_t)ptMesh->szIndexCount);
726+
pl_sb_resize(ptScene->sbtVertexPosBuffer, (uint32_t)ptMesh->szVertexCount);
727+
memcpy(&ptScene->sbtVertexPosBuffer[uStartIndex], ptMesh->ptVertexPositions, sizeof(plVec3) * ptMesh->szVertexCount);
728+
memcpy(&ptScene->sbuIndexBuffer[uIndexStart], ptMesh->puIndices, sizeof(uint32_t) * ptMesh->szIndexCount);
729+
710730
// create shadow atlas
711731
ptScene->uShadowAtlasResolution = 1024 * 8;
712732
const plTextureDesc tShadowDepthTextureDesc = {
@@ -759,6 +779,7 @@ pl_renderer_create_scene(plSceneInit tInit)
759779
}
760780
ptScene->tShadowRenderPass = gptGfx->create_render_pass(gptData->ptDevice, &tDepthRenderPassDesc, atShadowAttachmentSets);
761781
ptScene->tFirstShadowRenderPass = gptGfx->create_render_pass(gptData->ptDevice, &tFirstDepthRenderPassDesc, atShadowAttachmentSets);
782+
762783
return ptScene;
763784
}
764785

@@ -1184,7 +1205,7 @@ pl_renderer_create_view(plScene* ptScene, plVec2 tDimensions)
11841205
.tStoreOp = PL_STORE_OP_STORE,
11851206
.tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED,
11861207
.tNextUsage = PL_TEXTURE_USAGE_SAMPLED,
1187-
.tClearColor = {0.0f, 0.0f, 0.0f, 1.0f}
1208+
.tClearColor = {0.0f, 0.0f, 0.0f, 0.0f}
11881209
},
11891210
{
11901211
.tLoadOp = PL_LOAD_OP_CLEAR,
@@ -1874,8 +1895,29 @@ pl_renderer_reload_scene_shaders(plScene* ptScene)
18741895
const uint32_t uLightCount = gptECS->get_components(ptScene->ptComponentLibrary, gptData->tLightComponentType, (void**)&ptLights, NULL);
18751896
int aiLightingConstantData[] = {iSceneWideRenderingFlags, pl_sb_capacity(ptScene->sbtLightData), pl_sb_size(ptScene->sbtProbeData), gptData->tRuntimeOptions.tShaderDebugMode};
18761897
ptScene->tLightingShader = gptShaderVariant->get_shader("deferred_lighting", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
1898+
ptScene->tDeferredLightingVolumeShader = gptShaderVariant->get_shader("deferred_lighting_volume", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
18771899
aiLightingConstantData[0] = gptData->tRuntimeOptions.bPunctualLighting ? (PL_RENDERING_FLAG_USE_PUNCTUAL | PL_RENDERING_FLAG_SHADOWS) : 0;
18781900
ptScene->tEnvLightingShader = gptShaderVariant->get_shader("deferred_lighting", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
1901+
ptScene->tEnvLightingVolumeShader = gptShaderVariant->get_shader("deferred_lighting_volume", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
1902+
1903+
plMeshComponent* ptMesh = gptECS->get_component(ptScene->ptComponentLibrary, gptMesh->get_ecs_type_key_mesh(), ptScene->tUnitSphereMesh);
1904+
1905+
const uint32_t uStartIndex = pl_sb_size(ptScene->sbtVertexPosBuffer);
1906+
const uint32_t uIndexStart = pl_sb_size(ptScene->sbuIndexBuffer);
1907+
1908+
const plDrawable tDrawable = {
1909+
.uIndexCount = (uint32_t)ptMesh->szIndexCount,
1910+
.uVertexCount = (uint32_t)ptMesh->szVertexCount,
1911+
.uIndexOffset = uIndexStart,
1912+
.uVertexOffset = uStartIndex,
1913+
.uTransformIndex = ptScene->uNextTransformIndex++,
1914+
.uTriangleCount = (uint32_t)ptMesh->szIndexCount / 3
1915+
};
1916+
ptScene->tUnitSphereDrawable = tDrawable;
1917+
pl_sb_resize(ptScene->sbuIndexBuffer, (uint32_t)ptMesh->szIndexCount);
1918+
pl_sb_resize(ptScene->sbtVertexPosBuffer, (uint32_t)ptMesh->szVertexCount);
1919+
memcpy(&ptScene->sbtVertexPosBuffer[uStartIndex], ptMesh->ptVertexPositions, sizeof(plVec3) * ptMesh->szVertexCount);
1920+
memcpy(&ptScene->sbuIndexBuffer[uIndexStart], ptMesh->puIndices, sizeof(uint32_t) * ptMesh->szIndexCount);
18791921

18801922
pl__renderer_unstage_drawables(ptScene);
18811923
pl__renderer_set_drawable_shaders(ptScene);
@@ -1962,8 +2004,10 @@ pl_renderer_finalize_scene(plScene* ptScene)
19622004
// create lighting shader
19632005
int aiLightingConstantData[] = {iSceneWideRenderingFlags, pl_sb_capacity(ptScene->sbtLightData), pl_sb_size(ptScene->sbtProbeData), gptData->tRuntimeOptions.tShaderDebugMode};
19642006
ptScene->tLightingShader = gptShaderVariant->get_shader("deferred_lighting", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
2007+
ptScene->tDeferredLightingVolumeShader = gptShaderVariant->get_shader("deferred_lighting_volume", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
19652008
aiLightingConstantData[0] = gptData->tRuntimeOptions.bPunctualLighting ? (PL_RENDERING_FLAG_USE_PUNCTUAL | PL_RENDERING_FLAG_SHADOWS) : 0;
19662009
ptScene->tEnvLightingShader = gptShaderVariant->get_shader("deferred_lighting", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
2010+
ptScene->tEnvLightingVolumeShader = gptShaderVariant->get_shader("deferred_lighting_volume", NULL, NULL, aiLightingConstantData, &gptData->tRenderPassLayout);
19672011

19682012

19692013
for(uint32_t i = 0; i < gptGfx->get_frames_in_flight(); i++)
@@ -2691,31 +2735,138 @@ pl_renderer_render_view(plView* ptView, plCamera* ptCamera, plCamera* ptCullCame
26912735
gptGfx->update_bind_group(gptData->ptDevice, tViewBG, &tViewBGData);
26922736
gptGfx->queue_bind_group_for_deletion(ptDevice, tViewBG);
26932737

2694-
plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice);
2695-
plGpuDynDeferredLighting* ptLightingDynamicData = (plGpuDynDeferredLighting*)tLightingDynamicData.pcData;
2696-
ptLightingDynamicData->uGlobalIndex = 0;
2738+
if(gptData->tRuntimeOptions.tShaderDebugMode == PL_SHADER_DEBUG_MODE_NONE)
2739+
{
2740+
const uint32_t uProbeCount = pl_sb_size(ptScene->sbtProbeData);
2741+
const uint32_t uLightCount = pl_sb_size(ptScene->sbtLightData);
2742+
2743+
gptGfx->reset_draw_stream(ptStream, uLightCount + uProbeCount);
2744+
for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++)
2745+
{
2746+
plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice);
2747+
plGpuDynDeferredLighting* ptLightingDynamicData = (plGpuDynDeferredLighting*)tLightingDynamicData.pcData;
2748+
ptLightingDynamicData->uGlobalIndex = 0;
2749+
ptLightingDynamicData->iLightIndex = (int)uLightIndex;
2750+
ptLightingDynamicData->iProbeIndex = -1;
2751+
2752+
if(ptScene->sbtLightData[uLightIndex].iType == PL_LIGHT_TYPE_DIRECTIONAL)
2753+
{
2754+
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
2755+
{
2756+
.tShader = ptScene->tLightingShader,
2757+
.auDynamicBuffers = {
2758+
tLightingDynamicData.uBufferHandle
2759+
},
2760+
.uIndexOffset = 0,
2761+
.uTriangleCount = 1,
2762+
.atBindGroups = {
2763+
ptScene->atBindGroups[uFrameIdx],
2764+
tViewBG,
2765+
ptView->tLightingBindGroup
2766+
},
2767+
.auDynamicBufferOffsets = {
2768+
tLightingDynamicData.uByteOffset
2769+
},
2770+
.uInstanceOffset = 0,
2771+
.uInstanceCount = 1
2772+
});
2773+
}
2774+
else
2775+
{
2776+
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
2777+
{
2778+
.tShader = ptScene->tDeferredLightingVolumeShader,
2779+
.auDynamicBuffers = {
2780+
tLightingDynamicData.uBufferHandle
2781+
},
2782+
.atVertexBuffers = {
2783+
ptScene->tVertexBuffer,
2784+
},
2785+
.tIndexBuffer = ptScene->tIndexBuffer,
2786+
.uIndexOffset = ptScene->tUnitSphereDrawable.uIndexOffset,
2787+
.uTriangleCount = ptScene->tUnitSphereDrawable.uTriangleCount,
2788+
.uVertexOffset = ptScene->tUnitSphereDrawable.uVertexOffset,
2789+
.atBindGroups = {
2790+
ptScene->atBindGroups[uFrameIdx],
2791+
tViewBG,
2792+
ptView->tLightingBindGroup
2793+
},
2794+
.auDynamicBufferOffsets = {
2795+
tLightingDynamicData.uByteOffset
2796+
},
2797+
.uInstanceOffset = 0,
2798+
.uInstanceCount = 1
2799+
});
2800+
}
2801+
}
2802+
2803+
for(uint32_t uProbeIndex = 0; uProbeIndex < uProbeCount; uProbeIndex++)
2804+
{
2805+
plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice);
2806+
plGpuDynDeferredLighting* ptLightingDynamicData = (plGpuDynDeferredLighting*)tLightingDynamicData.pcData;
2807+
ptLightingDynamicData->uGlobalIndex = 0;
2808+
ptLightingDynamicData->iLightIndex = -1;
2809+
ptLightingDynamicData->iProbeIndex = (int)uProbeIndex;
26972810

2698-
gptGfx->reset_draw_stream(ptStream, 1);
2699-
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
2811+
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
2812+
{
2813+
.tShader = ptScene->tDeferredLightingVolumeShader,
2814+
.auDynamicBuffers = {
2815+
tLightingDynamicData.uBufferHandle
2816+
},
2817+
.atVertexBuffers = {
2818+
ptScene->tVertexBuffer,
2819+
},
2820+
.tIndexBuffer = ptScene->tIndexBuffer,
2821+
.uIndexOffset = ptScene->tUnitSphereDrawable.uIndexOffset,
2822+
.uTriangleCount = ptScene->tUnitSphereDrawable.uTriangleCount,
2823+
.uVertexOffset = ptScene->tUnitSphereDrawable.uVertexOffset,
2824+
.atBindGroups = {
2825+
ptScene->atBindGroups[uFrameIdx],
2826+
tViewBG,
2827+
ptView->tLightingBindGroup
2828+
},
2829+
.auDynamicBufferOffsets = {
2830+
tLightingDynamicData.uByteOffset
2831+
},
2832+
.uInstanceOffset = 0,
2833+
.uInstanceCount = 1
2834+
});
2835+
}
2836+
}
2837+
else
27002838
{
2701-
.tShader = ptScene->tLightingShader,
2702-
.auDynamicBuffers = {
2703-
tLightingDynamicData.uBufferHandle
2704-
},
2705-
.uIndexOffset = 0,
2706-
.uTriangleCount = 2,
2707-
.atBindGroups = {
2708-
ptScene->atBindGroups[uFrameIdx],
2709-
tViewBG,
2710-
ptView->tLightingBindGroup
2711-
},
2712-
.auDynamicBufferOffsets = {
2713-
tLightingDynamicData.uByteOffset
2714-
},
2715-
.uInstanceOffset = 0,
2716-
.uInstanceCount = 1
2717-
});
2839+
gptGfx->reset_draw_stream(ptStream, 1);
2840+
plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice);
2841+
plGpuDynDeferredLighting* ptLightingDynamicData = (plGpuDynDeferredLighting*)tLightingDynamicData.pcData;
2842+
ptLightingDynamicData->uGlobalIndex = 0;
2843+
ptLightingDynamicData->iLightIndex = -1;
2844+
ptLightingDynamicData->iProbeIndex = -1;
2845+
2846+
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
2847+
{
2848+
.tShader = ptScene->tLightingShader,
2849+
.auDynamicBuffers = {
2850+
tLightingDynamicData.uBufferHandle
2851+
},
2852+
.uIndexOffset = 0,
2853+
.uTriangleCount = 1,
2854+
.atBindGroups = {
2855+
ptScene->atBindGroups[uFrameIdx],
2856+
tViewBG,
2857+
ptView->tLightingBindGroup
2858+
},
2859+
.auDynamicBufferOffsets = {
2860+
tLightingDynamicData.uByteOffset
2861+
},
2862+
.uInstanceOffset = 0,
2863+
.uInstanceCount = 1
2864+
});
2865+
}
2866+
27182867
gptGfx->draw_stream(ptSceneEncoder, 1, &tArea);
2868+
2869+
27192870

27202871
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 2 - forward~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27212872

extensions/pl_renderer_internal.c

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,32 +2994,68 @@ pl__renderer_update_probes(plScene* ptScene)
29942994

29952995
// create lighting dynamic bind group
29962996

2997-
plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice);
2998-
plGpuDynDeferredLighting* ptLightingDynamicData = (plGpuDynDeferredLighting*)tLightingDynamicData.pcData;
2999-
ptLightingDynamicData->uGlobalIndex = uFace;
2997+
const uint32_t uLightCount = pl_sb_size(ptScene->sbtLightData);
30002998

3001-
3002-
gptGfx->reset_draw_stream(ptStream, 1);
3003-
*gptData->pdDrawCalls += 1.0;
3004-
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
2999+
gptGfx->reset_draw_stream(ptStream, uLightCount);
3000+
for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++)
30053001
{
3006-
.tShader = ptScene->tEnvLightingShader,
3007-
.auDynamicBuffers = {
3008-
tLightingDynamicData.uBufferHandle
3009-
},
3010-
.uIndexOffset = 0,
3011-
.uTriangleCount = 2,
3012-
.atBindGroups = {
3013-
ptScene->atBindGroups[uFrameIdx],
3014-
tViewBG,
3015-
ptProbe->atLightingBindGroup[uFace]
3016-
},
3017-
.auDynamicBufferOffsets = {
3018-
tLightingDynamicData.uByteOffset
3019-
},
3020-
.uInstanceOffset = 0,
3021-
.uInstanceCount = 1
3022-
});
3002+
plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice);
3003+
plGpuDynDeferredLighting* ptLightingDynamicData = (plGpuDynDeferredLighting*)tLightingDynamicData.pcData;
3004+
ptLightingDynamicData->uGlobalIndex = uFace;
3005+
ptLightingDynamicData->iLightIndex = (int)uLightIndex;
3006+
ptLightingDynamicData->iProbeIndex = -1;
3007+
3008+
if(ptScene->sbtLightData[uLightIndex].iType == PL_LIGHT_TYPE_DIRECTIONAL)
3009+
{
3010+
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
3011+
{
3012+
.tShader = ptScene->tEnvLightingShader,
3013+
.auDynamicBuffers = {
3014+
tLightingDynamicData.uBufferHandle
3015+
},
3016+
.uIndexOffset = 0,
3017+
.uTriangleCount = 1,
3018+
.atBindGroups = {
3019+
ptScene->atBindGroups[uFrameIdx],
3020+
tViewBG,
3021+
ptProbe->atLightingBindGroup[uFace]
3022+
},
3023+
.auDynamicBufferOffsets = {
3024+
tLightingDynamicData.uByteOffset
3025+
},
3026+
.uInstanceOffset = 0,
3027+
.uInstanceCount = 1
3028+
});
3029+
}
3030+
else
3031+
{
3032+
pl_add_to_draw_stream(ptStream, (plDrawStreamData)
3033+
{
3034+
.tShader = ptScene->tEnvLightingVolumeShader,
3035+
.auDynamicBuffers = {
3036+
tLightingDynamicData.uBufferHandle
3037+
},
3038+
.atVertexBuffers = {
3039+
ptScene->tVertexBuffer,
3040+
},
3041+
.tIndexBuffer = ptScene->tIndexBuffer,
3042+
.uIndexOffset = ptScene->tUnitSphereDrawable.uIndexOffset,
3043+
.uTriangleCount = ptScene->tUnitSphereDrawable.uTriangleCount,
3044+
.uVertexOffset = ptScene->tUnitSphereDrawable.uVertexOffset,
3045+
.atBindGroups = {
3046+
ptScene->atBindGroups[uFrameIdx],
3047+
tViewBG,
3048+
ptProbe->atLightingBindGroup[uFace]
3049+
},
3050+
.auDynamicBufferOffsets = {
3051+
tLightingDynamicData.uByteOffset
3052+
},
3053+
.uInstanceOffset = 0,
3054+
.uInstanceCount = 1
3055+
});
3056+
}
3057+
}
3058+
*gptData->pdDrawCalls += (double)uLightCount;
30233059
gptGfx->draw_stream(ptProbeEncoder, 1, &tArea);
30243060

30253061
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 2 - forward~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

extensions/pl_renderer_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,9 @@ typedef struct _plScene
336336
const char* pcName;
337337
bool bActive;
338338
plShaderHandle tLightingShader;
339+
plShaderHandle tDeferredLightingVolumeShader;
339340
plShaderHandle tEnvLightingShader;
341+
plShaderHandle tEnvLightingVolumeShader;
340342
uint64_t uLastSemValueForShadow;
341343

342344
// skybox resources (optional)
@@ -438,6 +440,10 @@ typedef struct _plScene
438440
plBVH tBvh;
439441
plAABB* sbtBvhAABBs;
440442
plBVHNode** sbtNodeStack;
443+
444+
// light volumes
445+
plDrawable tUnitSphereDrawable;
446+
plEntity tUnitSphereMesh;
441447
} plScene;
442448

443449
typedef struct _plRefRendererData

0 commit comments

Comments
 (0)