diff --git a/apps/app.c b/apps/app.c index acec5bda..37ff27dd 100644 --- a/apps/app.c +++ b/apps/app.c @@ -76,9 +76,6 @@ typedef struct plAppData_t plEntity tMainCamera; plEntity tSunlight; - // CSM TESTING - plEntity tTestCamera; - // views uint32_t uSceneHandle0; uint32_t uViewHandle0; @@ -244,7 +241,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) // create main camera - ptAppData->tMainCamera = gptEcs->create_perspective_camera(ptMainComponentLibrary, "main camera", (plVec3){0, 2.0f, 5.0f}, PL_PI_3, ptIO->afMainViewportSize[0] / ptIO->afMainViewportSize[1], 0.01f, 400.0f); + ptAppData->tMainCamera = gptEcs->create_perspective_camera(ptMainComponentLibrary, "main camera", (plVec3){0, 2.0f, 5.0f}, PL_PI_3, ptIO->afMainViewportSize[0] / ptIO->afMainViewportSize[1], 0.01f, 100.0f); gptCamera->set_pitch_yaw(gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera), 0.0f, PL_PI); gptCamera->update(gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera)); @@ -253,15 +250,10 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) gptCamera->set_pitch_yaw(gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tCullCamera), 0.0f, PL_PI); gptCamera->update(gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tCullCamera)); - ptAppData->tTestCamera = gptEcs->create_perspective_camera(ptMainComponentLibrary, "test camera", (plVec3){0.0f, 2.0f, 10.0f}, PL_PI_3, 1.0f, 0.01f, 25.0f); - gptCamera->set_pitch_yaw(gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tTestCamera), 0.0f, PL_PI); - gptCamera->update(gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tTestCamera)); - - // create lights ptAppData->tSunlight = gptEcs->create_directional_light(ptMainComponentLibrary, "sunlight", (plVec3){-1.0f, -1.0f, 0.0f}); plLightComponent* ptLight = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_LIGHT, ptAppData->tSunlight); - gptEcs->set_light_shadows(ptMainComponentLibrary, ptAppData->tSunlight, ptAppData->tTestCamera, PL_MAX_SHADOW_CASCADES); + gptEcs->set_light_shadows(ptMainComponentLibrary, ptAppData->tSunlight, ptAppData->tMainCamera, 3); // load models @@ -394,7 +386,9 @@ pl_app_update(plAppData* ptAppData) plCameraComponent* ptCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera); plCameraComponent* ptCullCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tCullCamera); - plCameraComponent* ptTestCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tTestCamera); + + plLightComponent* ptLight = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_LIGHT, ptAppData->tSunlight); + plCameraComponent* ptShadowCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptLight->atShadowCameras[0]); static const float fCameraTravelSpeed = 4.0f; static const float fCameraRotationSpeed = 0.005f; @@ -423,7 +417,6 @@ pl_app_update(plAppData* ptAppData) gptCamera->update(ptCamera); gptCamera->update(ptCullCamera); - gptCamera->update(ptTestCamera); // run ecs system gptRenderer->run_ecs(ptAppData->uSceneHandle0); @@ -436,7 +429,8 @@ pl_app_update(plAppData* ptAppData) uint64_t ulValue2 = ulValue0 + 2; uint64_t ulValue3 = ulValue0 + 3; uint64_t ulValue4 = ulValue0 + 4; - ptAppData->aulNextTimelineValue[ptGraphics->uCurrentFrameIndex] = ulValue4; + uint64_t ulValue5 = ulValue0 + 5; + ptAppData->aulNextTimelineValue[ptGraphics->uCurrentFrameIndex] = ulValue5; // first set of work @@ -476,6 +470,32 @@ pl_app_update(plAppData* ptAppData) }; gptGfx->submit_command_buffer(ptGraphics, &tCommandBuffer, &tSubmitInfo00); + plViewOptions tShadowViewOptions = { + .bShowAllBoundingBoxes = false, + .bShowVisibleBoundingBoxes = false, + .bShowOrigin = false, + .bCullStats = false, + .ptViewCamera = ptShadowCamera, + .ptCullCamera = NULL + }; + + const plBeginCommandInfo tBeginInfo11 = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {ptAppData->atSempahore[ptGraphics->uCurrentFrameIndex]}, + .auWaitSemaphoreValues = {ulValue2} + }; + tCommandBuffer = gptGfx->begin_command_recording(ptGraphics, &tBeginInfo11); + gptRenderer->do_shadows(tCommandBuffer, ptAppData->uSceneHandle0, ptAppData->uViewHandle0, tShadowViewOptions); + + gptGfx->end_command_recording(ptGraphics, &tCommandBuffer); + + const plSubmitInfo tSubmitInfo11 = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {ptAppData->atSempahore[ptGraphics->uCurrentFrameIndex]}, + .auSignalSemaphoreValues = {ulValue3} + }; + gptGfx->submit_command_buffer(ptGraphics, &tCommandBuffer, &tSubmitInfo11); + plViewOptions tViewOptions = { .bShowAllBoundingBoxes = ptAppData->bDrawAllBoundingBoxes, .bShowVisibleBoundingBoxes = ptAppData->bDrawVisibleBoundingBoxes, @@ -494,7 +514,7 @@ pl_app_update(plAppData* ptAppData) const plBeginCommandInfo tBeginInfo1 = { .uWaitSemaphoreCount = 1, .atWaitSempahores = {ptAppData->atSempahore[ptGraphics->uCurrentFrameIndex]}, - .auWaitSemaphoreValues = {ulValue2} + .auWaitSemaphoreValues = {ulValue3} }; tCommandBuffer = gptGfx->begin_command_recording(ptGraphics, &tBeginInfo1); gptRenderer->render_scene(tCommandBuffer, ptAppData->uSceneHandle0, ptAppData->uViewHandle0, tViewOptions); @@ -504,7 +524,7 @@ pl_app_update(plAppData* ptAppData) const plSubmitInfo tSubmitInfo1 = { .uSignalSemaphoreCount = 1, .atSignalSempahores = {ptAppData->atSempahore[ptGraphics->uCurrentFrameIndex]}, - .auSignalSemaphoreValues = {ulValue3} + .auSignalSemaphoreValues = {ulValue4} }; gptGfx->submit_command_buffer(ptGraphics, &tCommandBuffer, &tSubmitInfo1); @@ -513,7 +533,7 @@ pl_app_update(plAppData* ptAppData) const plBeginCommandInfo tBeginInfo2 = { .uWaitSemaphoreCount = 1, .atWaitSempahores = {ptAppData->atSempahore[ptGraphics->uCurrentFrameIndex]}, - .auWaitSemaphoreValues = {ulValue3}, + .auWaitSemaphoreValues = {ulValue4}, }; tCommandBuffer = gptGfx->begin_command_recording(ptGraphics, &tBeginInfo2); @@ -570,17 +590,6 @@ pl_app_update(plAppData* ptAppData) ptAppData->bResize = true; pl_checkbox("Always Resize", &ptAppData->bAlwaysResize); - - pl_slider_float("Light X Dir", &ptLight->tDirection.x, -1.0f, 1.0f); - pl_slider_float("Light Y Dir", &ptLight->tDirection.y, -1.0f, 1.0f); - pl_slider_float("Light Z Dir", &ptLight->tDirection.z, -1.0f, 1.0f); - - pl_slider_float("Camera Pos X", &ptTestCamera->tPos.x, -100.0f, 100.0f); - pl_slider_float("Camera Pos Y", &ptTestCamera->tPos.y, -100.0f, 100.0f); - pl_slider_float("Camera Pos Z", &ptTestCamera->tPos.z, -100.0f, 100.0f); - pl_slider_float("Camera Yaw", &ptTestCamera->fYaw, -PL_PI, PL_PI); - pl_slider_float("Camera Pitch", &ptTestCamera->fPitch, -PL_PI_2, PL_PI_2); - pl_end_collapsing_header(); } @@ -635,7 +644,7 @@ pl_app_update(plAppData* ptAppData) const plSubmitInfo tSubmitInfo2 = { .uSignalSemaphoreCount = 1, .atSignalSempahores = {ptAppData->atSempahore[ptGraphics->uCurrentFrameIndex]}, - .auSignalSemaphoreValues = {ulValue4}, + .auSignalSemaphoreValues = {ulValue5}, }; gptGfx->end_command_recording(ptGraphics, &tCommandBuffer); if(!gptGfx->present(ptGraphics, &tCommandBuffer, &tSubmitInfo2)) diff --git a/extensions/pl_ecs_ext.c b/extensions/pl_ecs_ext.c index 9f4bf9d1..847d6ff2 100644 --- a/extensions/pl_ecs_ext.c +++ b/extensions/pl_ecs_ext.c @@ -1273,7 +1273,7 @@ pl_run_light_update_system(plComponentLibrary* ptLibrary) for(uint32_t i = 0; i < ptLight->uCascadeCount; i++) { - const float p = (i + 1) / (float)PL_MAX_SHADOW_CASCADES; + const float p = (i + 1) / (float)ptLight->uCascadeCount; const float fLog = fMinZ * powf(fRatio, p); const float fUniform = fMinZ + fRange * p; const float fD = ptLight->fCascadeSplitLambda * (fLog - fUniform) + fUniform; @@ -1281,7 +1281,7 @@ pl_run_light_update_system(plComponentLibrary* ptLibrary) } float fLastSplitDist = 0.0; - for(uint32_t j = 0; j < PL_MAX_SHADOW_CASCADES; j++) + for(uint32_t j = 0; j < ptLight->uCascadeCount; j++) { const float fSplitDist = afCascadeSplits[j]; diff --git a/extensions/pl_ref_renderer_ext.c b/extensions/pl_ref_renderer_ext.c index 7319a468..7ba97989 100644 --- a/extensions/pl_ref_renderer_ext.c +++ b/extensions/pl_ref_renderer_ext.c @@ -164,6 +164,13 @@ typedef struct _DynamicData plMat4 tModel; } DynamicData; +typedef struct _plShadowData +{ + plRenderPassHandle tRenderPass; + plVec2 tResolution; + plTextureHandle tDepthTexture0[PL_FRAMES_IN_FLIGHT]; +} plShadowData; + typedef struct _plRefView { // main renderpass @@ -195,6 +202,9 @@ typedef struct _plRefView // drawing api plDrawList3D t3DDrawList; plDrawList3D t3DSelectionDrawList; + + // shadows + plShadowData tShadowData; } plRefView; typedef struct _plRefScene @@ -259,8 +269,10 @@ typedef struct _plRefRendererData // main renderpass layout (used as a template for views) plRenderPassLayoutHandle tRenderPassLayout; + plRenderPassLayoutHandle tDepthRenderPassLayout; // shader templates (variants are made from these) + plShaderHandle tShadowShader; plShaderHandle tOpaqueShader; plShaderHandle tTransparentShader; plShaderHandle tSkyboxShader; @@ -484,6 +496,21 @@ pl_refr_initialize(plWindow* ptWindow) }; gptData->tRenderPassLayout = gptDevice->create_render_pass_layout(&gptData->tGraphics.tDevice, &tRenderPassLayoutDesc); + // create main render pass layout + const plRenderPassLayoutDescription tDepthRenderPassLayoutDesc = { + .atRenderTargets = { + { .tFormat = PL_FORMAT_D32_FLOAT_S8_UINT }, // depth buffer + }, + .uSubpassCount = 1, + .atSubpasses = { + { + .uRenderTargetCount = 1, + .auRenderTargets = {0}, + } + } + }; + gptData->tDepthRenderPassLayout = gptDevice->create_render_pass_layout(&gptData->tGraphics.tDevice, &tDepthRenderPassLayoutDesc); + // create template shaders int aiConstantData[6] = {0, 0, 0, 0, 0, 1}; @@ -739,6 +766,50 @@ pl_refr_initialize(plWindow* ptWindow) tOutlineShaderDescription.atConstants[i].tType = PL_DATA_TYPE_INT; } gptData->tOutlineShader = gptDevice->create_shader(&gptData->tGraphics.tDevice, &tOutlineShaderDescription); + + const plShaderDescription tShadowShaderDescription = { + + #ifdef PL_METAL_BACKEND + .pcVertexShader = "../shaders/metal/outline.metal", + .pcPixelShader = "../shaders/metal/outline.metal", + #else + .pcVertexShader = "shadow.vert.spv", + .pcPixelShader = "shadow.frag.spv", + #endif + .tGraphicsState = { + .ulDepthWriteEnabled = 1, + .ulDepthMode = PL_COMPARE_MODE_LESS, + .ulCullMode = PL_CULL_MODE_CULL_BACK, + .ulWireframe = 0, + .ulStencilMode = PL_COMPARE_MODE_ALWAYS, + .ulStencilRef = 0xff, + .ulStencilMask = 0xff, + .ulStencilOpFail = PL_STENCIL_OP_KEEP, + .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, + .ulStencilOpPass = PL_STENCIL_OP_KEEP + }, + .tVertexBufferBinding = { + .uByteStride = sizeof(float) * 3, + .atAttributes = { {.uByteOffset = 0, .tFormat = PL_FORMAT_R32G32B32_FLOAT}} + }, + .uConstantCount = 0, + .atBlendStates = { + pl__get_blend_state(PL_BLEND_MODE_ALPHA) + }, + .uBlendStateCount = 1, + .tRenderPassLayout = gptData->tDepthRenderPassLayout, + .uSubpassIndex = 0, + .uBindGroupLayoutCount = 1, + .atBindGroupLayouts = { + { + .uBufferBindingCount = 1, + .aBufferBindings = { + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + }, + } + } + }; + gptData->tShadowShader = gptDevice->create_shader(&gptData->tGraphics.tDevice, &tShadowShaderDescription); } static uint32_t @@ -785,6 +856,8 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) plRefView* ptView = &ptScene->atViews[uViewHandle]; ptView->tTargetSize = tDimensions; + ptView->tShadowData.tResolution.x = 1024.0f; + ptView->tShadowData.tResolution.y = 1024.0f; // create offscreen per-frame resources const plTextureDesc tFinalTextureDesc = { @@ -817,6 +890,16 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) .tInitialUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT }; + const plTextureDesc tShadowDepthTextureDesc = { + .tDimensions = {ptView->tShadowData.tResolution.x, ptView->tShadowData.tResolution.y, 1}, + .tFormat = PL_FORMAT_D32_FLOAT_S8_UINT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT | PL_TEXTURE_USAGE_SAMPLED, + .tInitialUsage = PL_TEXTURE_USAGE_SAMPLED + }; + const plBufferDescription atGlobalBuffersDesc = { .tUsage = PL_BUFFER_USAGE_UNIFORM | PL_BUFFER_USAGE_STAGING, .uByteSize = PL_DEVICE_ALLOCATION_BLOCK_SIZE @@ -836,6 +919,7 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) // create offscreen render pass plRenderPassAttachments atAttachmentSets[PL_FRAMES_IN_FLIGHT] = {0}; + plRenderPassAttachments atShadowAttachmentSets[PL_FRAMES_IN_FLIGHT] = {0}; for(uint32_t i = 0; i < PL_FRAMES_IN_FLIGHT; i++) { @@ -847,7 +931,7 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) ptView->tEmissiveTexture[i] = pl__refr_create_texture(&tAttachmentTextureDesc, "emissive original", i); ptView->tAOMetalRoughnessTexture[i] = pl__refr_create_texture(&tAttachmentTextureDesc, "metalroughness original", i); ptView->tDepthTexture[i] = pl__refr_create_texture(&tDepthTextureDesc, "offscreen depth original", i); - + // texture IDs ptView->tFinalTextureID[i] = gptGfx->get_ui_texture_handle(ptGraphics, ptView->tFinalTexture[i], gptData->tDefaultSampler); @@ -905,6 +989,9 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) atAttachmentSets[i].atViewAttachments[4] = ptView->tPositionTexture[i]; atAttachmentSets[i].atViewAttachments[5] = ptView->tEmissiveTexture[i]; atAttachmentSets[i].atViewAttachments[6] = ptView->tAOMetalRoughnessTexture[i]; + + ptView->tShadowData.tDepthTexture0[i] = pl__refr_create_texture(&tShadowDepthTextureDesc, "shadow map", i); + atShadowAttachmentSets[i].atViewAttachments[0] = ptView->tShadowData.tDepthTexture0[i]; } const plRenderPassDescription tRenderPassDesc = { @@ -998,6 +1085,21 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) pl_sb_push(ptScene->sbtVertexDataBuffer, ((plVec4){ 1.0f, 1.0f})); pl_sb_push(ptScene->sbtVertexDataBuffer, ((plVec4){ 1.0f, 0.0f})); + const plRenderPassDescription tDepthRenderPassDesc = { + .tLayout = gptData->tDepthRenderPassLayout, + .tDepthTarget = { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tStencilLoadOp = PL_LOAD_OP_CLEAR, + .tStencilStoreOp = PL_STORE_OP_DONT_CARE, + .tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED, + .tNextUsage = PL_TEXTURE_USAGE_SAMPLED, + .fClearZ = 1.0f + }, + .tDimensions = {.x = ptView->tShadowData.tResolution.x, .y = ptView->tShadowData.tResolution.y} + }; + ptView->tShadowData.tRenderPass = gptDevice->create_render_pass(&ptGraphics->tDevice, &tDepthRenderPassDesc, atShadowAttachmentSets); + return uViewHandle; } @@ -2603,6 +2705,153 @@ pl__refr_cull_job(uint32_t uJobIndex, void* pData) } } +static void +pl_refr_do_shadows(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint32_t uViewHandle, plViewOptions tOptions) +{ + pl_begin_profile_sample(__FUNCTION__); + + // for convience + plGraphics* ptGraphics = &gptData->tGraphics; + plDevice* ptDevice = &ptGraphics->tDevice; + plDrawStream* ptStream = &gptData->tDrawStream; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + plRefView* ptView = &ptScene->atViews[uViewHandle]; + plCameraComponent* ptCamera = tOptions.ptViewCamera; + + gptGfx->reset_draw_stream(ptStream); + + const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtOpaqueDrawables); + const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtTransparentDrawables); + + if(pl_sb_size(ptView->sbtVisibleOpaqueDrawables) != uOpaqueDrawableCount) + { + pl_sb_resize(ptView->sbtVisibleOpaqueDrawables, uOpaqueDrawableCount); + memcpy(ptView->sbtVisibleOpaqueDrawables, ptScene->sbtOpaqueDrawables, sizeof(plDrawable) * uOpaqueDrawableCount); + } + if(pl_sb_size(ptView->sbtVisibleTransparentDrawables) != uTransparentDrawableCount) + { + pl_sb_resize(ptView->sbtVisibleTransparentDrawables, uTransparentDrawableCount); + memcpy(ptView->sbtVisibleTransparentDrawables, ptScene->sbtTransparentDrawables, sizeof(plDrawable) * uTransparentDrawableCount); + } + + // update global buffers & bind groups + const BindGroup_0 tBindGroupBuffer = { + .tCameraPos = ptCamera->tPos, + .tCameraProjection = ptCamera->tProjMat, + .tCameraView = ptCamera->tViewMat, + .tCameraViewProjection = pl_mul_mat4(&ptCamera->tProjMat, &ptCamera->tViewMat) + }; + memcpy(ptGraphics->sbtBuffersCold[ptView->atGlobalBuffers[ptGraphics->uCurrentFrameIndex].uIndex].tMemoryAllocation.pHostMapped, &tBindGroupBuffer, sizeof(BindGroup_0)); + + plBindGroupLayout tBindGroupLayout0 = { + .uBufferBindingCount = 1, + .aBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } + }, + }; + plBindGroupHandle tGlobalBG = gptDevice->get_temporary_bind_group(ptDevice, &tBindGroupLayout0, "temporary global bind group"); + + const plBindGroupUpdateBufferData atBufferData[] = + { + { + .tBuffer = ptView->atGlobalBuffers[ptGraphics->uCurrentFrameIndex], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0) + } + }; + + plBindGroupUpdateData tBGData0 = { + .uBufferCount = 1, + .atBuffers = atBufferData + }; + + gptDevice->update_bind_group(&ptGraphics->tDevice, tGlobalBG, &tBGData0); + + + const plVec2 tDimensions = ptGraphics->sbtRenderPassesCold[ptView->tShadowData.tRenderPass.uIndex].tDesc.tDimensions; + + plDrawArea tArea = { + .ptDrawStream = ptStream, + .tScissor = { + .uWidth = (uint32_t)tDimensions.x, + .uHeight = (uint32_t)tDimensions.y, + }, + .tViewport = { + .fWidth = tDimensions.x, + .fHeight = tDimensions.y, + .fMaxDepth = 1.0f + } + }; + + plRenderEncoder tEncoder = gptGfx->begin_render_pass(ptGraphics, &tCommandBuffer, ptView->tShadowData.tRenderPass); + + for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) + { + const plDrawable tDrawable = ptView->sbtVisibleOpaqueDrawables[i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = gptDevice->allocate_dynamic_data(ptDevice, sizeof(plMat4)); + + plMat4* ptDynamicData = (plMat4*)tDynamicBinding.pcData; + *ptDynamicData = ptTransform->tWorld; + + gptGfx->add_to_stream(ptStream, (plStreamDraw) + { + .uShaderVariant = gptData->tShadowShader.uIndex, + .uDynamicBuffer = tDynamicBinding.uBufferHandle, + .uVertexBuffer = ptScene->tVertexBuffer.uIndex, + .uIndexBuffer = tDrawable.uIndexCount == 0 ? UINT32_MAX : ptScene->tIndexBuffer.uIndex, + .uIndexOffset = tDrawable.uIndexOffset, + .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, + .uBindGroup0 = tGlobalBG.uIndex, + .uBindGroup1 = UINT32_MAX, + .uBindGroup2 = UINT32_MAX, + .uDynamicBufferOffset = tDynamicBinding.uByteOffset, + .uInstanceStart = 0, + .uInstanceCount = 1 + }); + } + + for(uint32_t i = 0; i < uTransparentDrawableCount; i++) + { + const plDrawable tDrawable = ptView->sbtVisibleTransparentDrawables[i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = gptDevice->allocate_dynamic_data(ptDevice, sizeof(plMat4)); + + plMat4* ptDynamicData = (plMat4*)tDynamicBinding.pcData; + *ptDynamicData = ptTransform->tWorld; + + gptGfx->add_to_stream(ptStream, (plStreamDraw) + { + .uShaderVariant = gptData->tShadowShader.uIndex, + .uDynamicBuffer = tDynamicBinding.uBufferHandle, + .uVertexBuffer = ptScene->tVertexBuffer.uIndex, + .uIndexBuffer = tDrawable.uIndexCount == 0 ? UINT32_MAX : ptScene->tIndexBuffer.uIndex, + .uIndexOffset = tDrawable.uIndexOffset, + .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, + .uBindGroup0 = tGlobalBG.uIndex, + .uBindGroup1 = UINT32_MAX, + .uBindGroup2 = UINT32_MAX, + .uDynamicBufferOffset = tDynamicBinding.uByteOffset, + .uInstanceStart = 0, + .uInstanceCount = 1 + }); + } + + gptGfx->draw_stream(&tEncoder, 1, &tArea); + gptGfx->reset_draw_stream(ptStream); + gptGfx->end_render_pass(&tEncoder); + + pl_end_profile_sample(); +} + static void pl_refr_render_scene(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint32_t uViewHandle, plViewOptions tOptions) { @@ -4203,6 +4452,7 @@ pl_load_ref_renderer_api(void) .get_view_texture_id = pl_refr_get_view_texture_id, .resize_view = pl_refr_resize_view, .get_debug_drawlist = pl_refr_get_debug_drawlist, + .do_shadows = pl_refr_do_shadows, }; return &tApi; } diff --git a/extensions/pl_ref_renderer_ext.h b/extensions/pl_ref_renderer_ext.h index 82327b01..4cdf182b 100644 --- a/extensions/pl_ref_renderer_ext.h +++ b/extensions/pl_ref_renderer_ext.h @@ -84,6 +84,9 @@ typedef struct _plRefRendererI void (*update_skin_textures)(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle); void (*perform_skinning)(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle); void (*render_scene)(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint32_t uViewHandle, plViewOptions tOptions); + + + void (*do_shadows)(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint32_t uViewHandle, plViewOptions tOptions); // misc void (*select_entities)(uint32_t uSceneHandle, uint32_t uCount, plEntity*); diff --git a/scripts/gen_build.py b/scripts/gen_build.py index eb39126a..e5e49570 100644 --- a/scripts/gen_build.py +++ b/scripts/gen_build.py @@ -161,6 +161,8 @@ def add_plugin_to_metal_app(name, reloadable, objc = False, binary_name = None): "skinning.comp", "outline.vert", "outline.frag", + "shadow.vert", + "shadow.frag", ] metal_shaders = [ diff --git a/shaders/glsl/shadow.frag b/shaders/glsl/shadow.frag new file mode 100644 index 00000000..0d691563 --- /dev/null +++ b/shaders/glsl/shadow.frag @@ -0,0 +1,44 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + + +//----------------------------------------------------------------------------- +// [SECTION] bind group 0 +//----------------------------------------------------------------------------- + +layout(set = 0, binding = 0) uniform _plGlobalInfo +{ + vec4 tCameraPos; + mat4 tCameraView; + mat4 tCameraProjection; + mat4 tCameraViewProjection; +} tGlobalInfo; + +//----------------------------------------------------------------------------- +// [SECTION] dynamic bind group +//----------------------------------------------------------------------------- + +layout(set = 1, binding = 0) uniform _plObjectInfo +{ + mat4 tModel; +} tObjectInfo; + +//----------------------------------------------------------------------------- +// [SECTION] input & output +//----------------------------------------------------------------------------- + +// layout(location = 0) out vec4 outColor; + +// output +layout(location = 0) in struct plShaderIn { + vec3 tPosition; +} tShaderIn; + +//----------------------------------------------------------------------------- +// [SECTION] entry +//----------------------------------------------------------------------------- + +void main() +{ + // outColor = vec4(1.0, 1.0, 1.0, 1.0); +} \ No newline at end of file diff --git a/shaders/glsl/shadow.vert b/shaders/glsl/shadow.vert new file mode 100644 index 00000000..91e32f4a --- /dev/null +++ b/shaders/glsl/shadow.vert @@ -0,0 +1,48 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +//----------------------------------------------------------------------------- +// [SECTION] bind group 0 +//----------------------------------------------------------------------------- + +layout(set = 0, binding = 0) uniform _plGlobalInfo +{ + vec4 tCameraPos; + mat4 tCameraView; + mat4 tCameraProjection; + mat4 tCameraViewProjection; +} tGlobalInfo; + +//----------------------------------------------------------------------------- +// [SECTION] dynamic bind group +//----------------------------------------------------------------------------- + +layout(set = 1, binding = 0) uniform _plObjectInfo +{ + mat4 tModel; +} tObjectInfo; + +//----------------------------------------------------------------------------- +// [SECTION] input & output +//----------------------------------------------------------------------------- + +// input +layout(location = 0) in vec3 inPos; + +// output +layout(location = 0) out struct plShaderOut { + vec3 tPosition; +} tShaderIn; + +//----------------------------------------------------------------------------- +// [SECTION] entry +//----------------------------------------------------------------------------- + +void main() +{ + + vec4 inPosition = vec4(inPos, 1.0); + vec4 pos = tObjectInfo.tModel * inPosition; + tShaderIn.tPosition = pos.xyz / pos.w; + gl_Position = tGlobalInfo.tCameraViewProjection * pos; +} \ No newline at end of file