diff --git a/apps/app.c b/apps/app.c index a18c8dea..781db1c2 100644 --- a/apps/app.c +++ b/apps/app.c @@ -72,10 +72,10 @@ typedef struct plAppData_t // views uint32_t uSceneHandle0; - uint32_t uSceneHandle1; + // uint32_t uSceneHandle1; uint32_t uViewHandle0; - uint32_t uViewHandle1; - uint32_t uViewHandle2; + // uint32_t uViewHandle1; + // uint32_t uViewHandle2; // drawing plDrawLayer* ptDrawLayer; @@ -220,10 +220,10 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) // create offscreen view (temporary API) ptAppData->uSceneHandle0 = gptRenderer->create_scene(); - ptAppData->uSceneHandle1 = gptRenderer->create_scene(); + // ptAppData->uSceneHandle1 = gptRenderer->create_scene(); ptAppData->uViewHandle0 = gptRenderer->create_view(ptAppData->uSceneHandle0, (plVec2){ptIO->afMainViewportSize[0] , ptIO->afMainViewportSize[1]}); - ptAppData->uViewHandle1 = gptRenderer->create_view(ptAppData->uSceneHandle0, (plVec2){500.0f, 500.0f}); - ptAppData->uViewHandle2 = gptRenderer->create_view(ptAppData->uSceneHandle1, (plVec2){500.0f, 500.0f}); + // ptAppData->uViewHandle1 = gptRenderer->create_view(ptAppData->uSceneHandle0, (plVec2){500.0f, 500.0f}); + // ptAppData->uViewHandle2 = gptRenderer->create_view(ptAppData->uSceneHandle1, (plVec2){500.0f, 500.0f}); // temporary draw layer for submitting fullscreen quad of offscreen render ptAppData->ptDrawLayer = pl_request_layer(pl_get_draw_list(NULL), "draw layer"); @@ -239,10 +239,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)); - plComponentLibrary* ptSecondaryComponentLibrary = gptRenderer->get_component_library(ptAppData->uSceneHandle1); - ptAppData->tMainCamera2 = gptEcs->create_perspective_camera(ptSecondaryComponentLibrary, "secondary camera", (plVec3){-3.265f, 2.967f, 0.311f}, PL_PI_3, 1.0f, 0.01f, 400.0f); - gptCamera->set_pitch_yaw(gptEcs->get_component(ptSecondaryComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera2), -0.535f, 1.737f); - gptCamera->update(gptEcs->get_component(ptSecondaryComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera2)); + // plComponentLibrary* ptSecondaryComponentLibrary = gptRenderer->get_component_library(ptAppData->uSceneHandle1); + // ptAppData->tMainCamera2 = gptEcs->create_perspective_camera(ptSecondaryComponentLibrary, "secondary camera", (plVec3){-3.265f, 2.967f, 0.311f}, PL_PI_3, 1.0f, 0.01f, 400.0f); + // gptCamera->set_pitch_yaw(gptEcs->get_component(ptSecondaryComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera2), -0.535f, 1.737f); + // gptCamera->update(gptEcs->get_component(ptSecondaryComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera2)); // load models pl_begin_profile_frame(); @@ -250,7 +250,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) pl_begin_profile_sample("load skyboxes"); const plMat4 tTransform0 = pl_mat4_translate_xyz(2.0f, 1.0f, 0.0f); gptRenderer->load_skybox_from_panorama(ptAppData->uSceneHandle0, "../data/glTF-Sample-Environments-main/ennis.jpg", 1024); - gptRenderer->load_skybox_from_panorama(ptAppData->uSceneHandle1, "../data/glTF-Sample-Environments-main/ennis.jpg", 1024); + // gptRenderer->load_skybox_from_panorama(ptAppData->uSceneHandle1, "../data/glTF-Sample-Environments-main/ennis.jpg", 1024); pl_end_profile_sample(); plModelLoaderData tLoaderData0 = {0}; @@ -263,20 +263,20 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) gptModelLoader->free_data(&tLoaderData0); pl_end_profile_sample(); - pl_begin_profile_sample("load models 1"); - gptModelLoader->load_gltf(ptSecondaryComponentLibrary, "../data/glTF-Sample-Assets-main/Models/CesiumMan/glTF/CesiumMan.gltf", NULL, &tLoaderData0); - gptModelLoader->load_stl(ptSecondaryComponentLibrary, "../data/pilotlight-assets-master/meshes/monkey.stl", (plVec4){1.0f, 0.0f, 0.0f, 0.80f}, &tTransform0, &tLoaderData0); - gptRenderer->add_drawable_objects_to_scene(ptAppData->uSceneHandle1, tLoaderData0.uOpaqueCount, tLoaderData0.atOpaqueObjects, tLoaderData0.uTransparentCount, tLoaderData0.atTransparentObjects); - gptModelLoader->free_data(&tLoaderData0); - pl_end_profile_sample(); + // pl_begin_profile_sample("load models 1"); + // gptModelLoader->load_gltf(ptSecondaryComponentLibrary, "../data/glTF-Sample-Assets-main/Models/CesiumMan/glTF/CesiumMan.gltf", NULL, &tLoaderData0); + // gptModelLoader->load_stl(ptSecondaryComponentLibrary, "../data/pilotlight-assets-master/meshes/monkey.stl", (plVec4){1.0f, 0.0f, 0.0f, 0.80f}, &tTransform0, &tLoaderData0); + // gptRenderer->add_drawable_objects_to_scene(ptAppData->uSceneHandle1, tLoaderData0.uOpaqueCount, tLoaderData0.atOpaqueObjects, tLoaderData0.uTransparentCount, tLoaderData0.atTransparentObjects); + // gptModelLoader->free_data(&tLoaderData0); + // pl_end_profile_sample(); pl_begin_profile_sample("finalize scene 0"); gptRenderer->finalize_scene(ptAppData->uSceneHandle0); pl_end_profile_sample(); - pl_begin_profile_sample("finalize scene 1"); - gptRenderer->finalize_scene(ptAppData->uSceneHandle1); - pl_end_profile_sample(); + // pl_begin_profile_sample("finalize scene 1"); + // gptRenderer->finalize_scene(ptAppData->uSceneHandle1); + // pl_end_profile_sample(); pl_end_profile_frame(); @@ -372,10 +372,10 @@ pl_app_update(plAppData* ptAppData) // handle input plComponentLibrary* ptMainComponentLibrary = gptRenderer->get_component_library(ptAppData->uSceneHandle0); - plComponentLibrary* ptSecondaryComponentLibrary = gptRenderer->get_component_library(ptAppData->uSceneHandle1); + // plComponentLibrary* ptSecondaryComponentLibrary = gptRenderer->get_component_library(ptAppData->uSceneHandle1); plCameraComponent* ptCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera); - plCameraComponent* ptCamera2 = gptEcs->get_component(ptSecondaryComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera2); + // plCameraComponent* ptCamera2 = gptEcs->get_component(ptSecondaryComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tMainCamera2); plCameraComponent* ptCullCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptAppData->tCullCamera); static const float fCameraTravelSpeed = 4.0f; @@ -404,12 +404,12 @@ pl_app_update(plAppData* ptAppData) } gptCamera->update(ptCamera); - gptCamera->update(ptCamera2); + // gptCamera->update(ptCamera2); gptCamera->update(ptCullCamera); // run ecs system gptRenderer->run_ecs(ptAppData->uSceneHandle0); - gptRenderer->run_ecs(ptAppData->uSceneHandle1); + // gptRenderer->run_ecs(ptAppData->uSceneHandle1); // new ui frame pl_new_frame(); @@ -432,7 +432,7 @@ pl_app_update(plAppData* ptAppData) plCommandBuffer tCommandBuffer = gptGfx->begin_command_recording(ptGraphics, &tBeginInfo0); gptRenderer->update_scene(tCommandBuffer, ptAppData->uSceneHandle0); - gptRenderer->update_scene(tCommandBuffer, ptAppData->uSceneHandle1); + // gptRenderer->update_scene(tCommandBuffer, ptAppData->uSceneHandle1); gptGfx->end_command_recording(ptGraphics, &tCommandBuffer); const plSubmitInfo tSubmitInfo0 = { @@ -451,14 +451,14 @@ pl_app_update(plAppData* ptAppData) .ptCullCamera = ptAppData->bFrustumCulling ? ptCamera : NULL }; - plViewOptions tViewOptions2 = { - .bShowAllBoundingBoxes = ptAppData->bDrawAllBoundingBoxes, - .bShowVisibleBoundingBoxes = ptAppData->bDrawVisibleBoundingBoxes, - .bShowOrigin = false, - .bCullStats = false, - .ptViewCamera = ptCamera2, - .ptCullCamera = ptCamera2 - }; + // plViewOptions tViewOptions2 = { + // .bShowAllBoundingBoxes = ptAppData->bDrawAllBoundingBoxes, + // .bShowVisibleBoundingBoxes = ptAppData->bDrawVisibleBoundingBoxes, + // .bShowOrigin = false, + // .bCullStats = false, + // .ptViewCamera = ptCamera2, + // .ptCullCamera = ptCamera2 + // }; if(ptAppData->bFrustumCulling && ptAppData->bFreezeCullCamera) tViewOptions.ptCullCamera = ptCullCamera; @@ -473,8 +473,8 @@ pl_app_update(plAppData* ptAppData) }; tCommandBuffer = gptGfx->begin_command_recording(ptGraphics, &tBeginInfo1); gptRenderer->render_scene(tCommandBuffer, ptAppData->uSceneHandle0, ptAppData->uViewHandle0, tViewOptions); - gptRenderer->render_scene(tCommandBuffer, ptAppData->uSceneHandle0, ptAppData->uViewHandle1, tViewOptions2); - gptRenderer->render_scene(tCommandBuffer, ptAppData->uSceneHandle1, ptAppData->uViewHandle2, tViewOptions2); + // gptRenderer->render_scene(tCommandBuffer, ptAppData->uSceneHandle0, ptAppData->uViewHandle1, tViewOptions2); + // gptRenderer->render_scene(tCommandBuffer, ptAppData->uSceneHandle1, ptAppData->uViewHandle2, tViewOptions2); gptGfx->end_command_recording(ptGraphics, &tCommandBuffer); @@ -579,8 +579,8 @@ pl_app_update(plAppData* ptAppData) // add full screen quad for offscreen render pl_add_image(ptAppData->ptDrawLayer, gptRenderer->get_view_texture_id(ptAppData->uSceneHandle0, ptAppData->uViewHandle0), (plVec2){0}, (plVec2){ptIO->afMainViewportSize[0], ptIO->afMainViewportSize[1]}); - pl_add_image(ptAppData->ptDrawLayer, gptRenderer->get_view_texture_id(ptAppData->uSceneHandle0, ptAppData->uViewHandle1), (plVec2){0}, (plVec2){500.0f, 500.0f}); - pl_add_image(ptAppData->ptDrawLayer, gptRenderer->get_view_texture_id(ptAppData->uSceneHandle1, ptAppData->uViewHandle2), (plVec2){0.0f, 500.0f}, (plVec2){500.0f, 1000.0f}); + // pl_add_image(ptAppData->ptDrawLayer, gptRenderer->get_view_texture_id(ptAppData->uSceneHandle0, ptAppData->uViewHandle1), (plVec2){0}, (plVec2){500.0f, 500.0f}); + // pl_add_image(ptAppData->ptDrawLayer, gptRenderer->get_view_texture_id(ptAppData->uSceneHandle1, ptAppData->uViewHandle2), (plVec2){0.0f, 500.0f}, (plVec2){500.0f, 1000.0f}); pl_submit_layer(ptAppData->ptDrawLayer); plRenderEncoder tEncoder = gptGfx->begin_render_pass(ptGraphics, &tCommandBuffer, ptGraphics->tMainRenderPass); diff --git a/extensions/pl_ref_renderer_ext.c b/extensions/pl_ref_renderer_ext.c index 3fa5f135..009ee117 100644 --- a/extensions/pl_ref_renderer_ext.c +++ b/extensions/pl_ref_renderer_ext.c @@ -140,7 +140,8 @@ typedef struct _plRefView plBufferHandle atGlobalBuffers[PL_FRAMES_IN_FLIGHT]; // misc - plDrawable* sbtVisibleDrawables; + plDrawable* sbtVisibleOpaqueDrawables; + plDrawable* sbtVisibleTransparentDrawables; // drawing api plDrawList3D t3DDrawList; @@ -152,7 +153,8 @@ typedef struct _plRefScene plRenderPassLayoutHandle tRenderPassLayout; // shader templates - plShaderHandle tShader; + plShaderHandle tOpaqueShader; + plShaderHandle tTransparentShader; uint32_t uVariantCount; const plShaderVariant* ptVariants; plHashMap tVariantHashmap; @@ -178,9 +180,6 @@ typedef struct _plRefScene plBufferHandle tStorageBuffer; plBufferHandle tMaterialDataBuffer; - // misc - plDrawable* sbtSubmittedDrawables; - uint32_t uViewCount; plRefView atViews[PL_MAX_VIEWS_PER_SCENE]; plSkinData* sbtSkinData; @@ -261,7 +260,7 @@ static const plJobI* gptJob = NULL; //----------------------------------------------------------------------------- // general helpers -static void pl__add_drawable_data_to_global_buffer(plRefScene*, uint32_t uDrawableIndex); +static void pl__add_drawable_data_to_global_buffer(plRefScene*, uint32_t uDrawableIndex, plDrawable* atDrawables); static bool pl__sat_visibility_test(plCameraComponent*, const plAABB*); // shader variants @@ -384,7 +383,7 @@ pl_refr_create_scene(void) gptECS->init_component_library(&ptScene->tComponentLibrary); // shaders default values - ptScene->tShader = (plShaderHandle){UINT32_MAX, UINT32_MAX}; + ptScene->tOpaqueShader = (plShaderHandle){UINT32_MAX, UINT32_MAX}; // buffer default values ptScene->tVertexBuffer = (plBufferHandle){UINT32_MAX, UINT32_MAX}; @@ -417,110 +416,206 @@ pl_refr_create_scene(void) .uSubpassInputCount = 4, .auSubpassInputs = {0, 2, 3, 4}, }, - { // composition + { // transparencies .uRenderTargetCount = 2, .auRenderTargets = {0, 1}, - .uSubpassInputCount = 0 + .uSubpassInputCount = 2, + .auSubpassInputs = {0, 1} }, } }; ptScene->tRenderPassLayout = gptDevice->create_render_pass_layout(&gptData->tGraphics.tDevice, &tRenderPassLayoutDesc); - // create template shader - plShaderDescription tShaderDescription = { + // create template shaders + { + plShaderDescription tOpaqueShaderDescription = { - #ifdef PL_METAL_BACKEND - .pcVertexShader = "../shaders/metal/primitive.metal", - .pcPixelShader = "../shaders/metal/primitive.metal", - #else - .pcVertexShader = "primitive.vert.spv", - .pcPixelShader = "primitive.frag.spv", - #endif - .tGraphicsState = { - .ulDepthWriteEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_LESS_OR_EQUAL, - .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 = 5, - .atBlendStates = { - pl__get_blend_state(PL_BLEND_MODE_ALPHA), - pl__get_blend_state(PL_BLEND_MODE_NONE), - pl__get_blend_state(PL_BLEND_MODE_NONE) - }, - .uBlendStateCount = 3, - .tRenderPassLayout = ptScene->tRenderPassLayout, - .uSubpassIndex = 0, - .uBindGroupLayoutCount = 3, - .atBindGroupLayouts = { - { - .uBufferBindingCount = 3, - .aBufferBindings = { - { - .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, - .uSlot = 0, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL - }, - { - .tType = PL_BUFFER_BINDING_TYPE_STORAGE, - .uSlot = 1, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + #ifdef PL_METAL_BACKEND + .pcVertexShader = "../shaders/metal/primitive.metal", + .pcPixelShader = "../shaders/metal/primitive.metal", + #else + .pcVertexShader = "primitive.vert.spv", + .pcPixelShader = "primitive.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 = 5, + .atBlendStates = { + pl__get_blend_state(PL_BLEND_MODE_NONE), + pl__get_blend_state(PL_BLEND_MODE_NONE), + pl__get_blend_state(PL_BLEND_MODE_NONE) + }, + .uBlendStateCount = 3, + .tRenderPassLayout = ptScene->tRenderPassLayout, + .uSubpassIndex = 0, + .uBindGroupLayoutCount = 3, + .atBindGroupLayouts = { + { + .uBufferBindingCount = 3, + .aBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + }, + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 1, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + }, + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 2, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } }, - { - .tType = PL_BUFFER_BINDING_TYPE_STORAGE, - .uSlot = 2, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + .uSamplerBindingCount = 1, + .atSamplerBindings = { {.uSlot = 3, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}} + }, + { + .uTextureBindingCount = 1, + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 2}, } }, - .uSamplerBindingCount = 1, - .atSamplerBindings = { {.uSlot = 3, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}} - }, - { - .uTextureBindingCount = 1, - .atTextureBindings = { - {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 2}, + { + .uTextureBindingCount = 1, + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} + } } + } + }; + for(uint32_t i = 0; i < tOpaqueShaderDescription.uConstantCount; i++) + { + tOpaqueShaderDescription.atConstants[i].uID = i; + tOpaqueShaderDescription.atConstants[i].uOffset = i * sizeof(int); + tOpaqueShaderDescription.atConstants[i].tType = PL_DATA_TYPE_INT; + } + + int aiConstantData[5] = {0}; + aiConstantData[2] = 0; + aiConstantData[3] = 0; + aiConstantData[4] = 0; + + aiConstantData[0] = (int)PL_MESH_FORMAT_FLAG_HAS_NORMAL; + int iFlagCopy = (int)PL_MESH_FORMAT_FLAG_HAS_NORMAL; + while(iFlagCopy) + { + aiConstantData[1] += iFlagCopy & 1; + iFlagCopy >>= 1; + } + tOpaqueShaderDescription.pTempConstantData = aiConstantData; + ptScene->tOpaqueShader = gptDevice->create_shader(&gptData->tGraphics.tDevice, &tOpaqueShaderDescription); + } + + { + plShaderDescription tTransparentShaderDescription = { + + #ifdef PL_METAL_BACKEND + .pcVertexShader = "../shaders/metal/primitive.metal", + .pcPixelShader = "../shaders/metal/primitive.metal", + #else + .pcVertexShader = "primitive.vert.spv", + .pcPixelShader = "transparent.frag.spv", + #endif + .tGraphicsState = { + .ulDepthWriteEnabled = 0, + .ulDepthMode = PL_COMPARE_MODE_LESS_OR_EQUAL, + .ulCullMode = PL_CULL_MODE_NONE, + .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 }, - { - .uTextureBindingCount = 1, - .atTextureBindings = { - {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} + .tVertexBufferBinding = { + .uByteStride = sizeof(float) * 3, + .atAttributes = { {.uByteOffset = 0, .tFormat = PL_FORMAT_R32G32B32_FLOAT}} + }, + .uConstantCount = 5, + .atBlendStates = { + pl__get_blend_state(PL_BLEND_MODE_ALPHA) + }, + .uBlendStateCount = 1, + .tRenderPassLayout = ptScene->tRenderPassLayout, + .uSubpassIndex = 2, + .uBindGroupLayoutCount = 3, + .atBindGroupLayouts = { + { + .uBufferBindingCount = 3, + .aBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + }, + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 1, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + }, + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 2, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } + }, + .uSamplerBindingCount = 1, + .atSamplerBindings = { {.uSlot = 3, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}} + }, + { + .uTextureBindingCount = 1, + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 2}, + } + }, + { + .uTextureBindingCount = 1, + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} + } } } + }; + for(uint32_t i = 0; i < tTransparentShaderDescription.uConstantCount; i++) + { + tTransparentShaderDescription.atConstants[i].uID = i; + tTransparentShaderDescription.atConstants[i].uOffset = i * sizeof(int); + tTransparentShaderDescription.atConstants[i].tType = PL_DATA_TYPE_INT; } - }; - for(uint32_t i = 0; i < tShaderDescription.uConstantCount; i++) - { - tShaderDescription.atConstants[i].uID = i; - tShaderDescription.atConstants[i].uOffset = i * sizeof(int); - tShaderDescription.atConstants[i].tType = PL_DATA_TYPE_INT; - } - int aiConstantData[5] = {0}; - aiConstantData[2] = 0; - aiConstantData[3] = 0; - aiConstantData[4] = 0; - - aiConstantData[0] = (int)PL_MESH_FORMAT_FLAG_HAS_NORMAL; - int iFlagCopy = (int)PL_MESH_FORMAT_FLAG_HAS_NORMAL; - while(iFlagCopy) - { - aiConstantData[1] += iFlagCopy & 1; - iFlagCopy >>= 1; + int aiConstantData[5] = {0}; + aiConstantData[2] = 0; + aiConstantData[3] = 0; + aiConstantData[4] = 0; + + aiConstantData[0] = (int)PL_MESH_FORMAT_FLAG_HAS_NORMAL; + int iFlagCopy = (int)PL_MESH_FORMAT_FLAG_HAS_NORMAL; + while(iFlagCopy) + { + aiConstantData[1] += iFlagCopy & 1; + iFlagCopy >>= 1; + } + tTransparentShaderDescription.pTempConstantData = aiConstantData; + ptScene->tTransparentShader = gptDevice->create_shader(&gptData->tGraphics.tDevice, &tTransparentShaderDescription); } - tShaderDescription.pTempConstantData = aiConstantData; - ptScene->tShader = gptDevice->create_shader(&gptData->tGraphics.tDevice, &tShaderDescription); - return uSceneHandle; } @@ -931,13 +1026,13 @@ pl_refr_cleanup(void) for(uint32_t j = 0; j < ptScene->uViewCount; j++) { plRefView* ptView = &ptScene->atViews[j]; - pl_sb_free(ptView->sbtVisibleDrawables); + pl_sb_free(ptView->sbtVisibleOpaqueDrawables); + pl_sb_free(ptView->sbtVisibleTransparentDrawables); } pl_sb_free(ptScene->sbtVertexPosBuffer); pl_sb_free(ptScene->sbtVertexDataBuffer); pl_sb_free(ptScene->sbuIndexBuffer); pl_sb_free(ptScene->sbtMaterialBuffer); - pl_sb_free(ptScene->sbtSubmittedDrawables); pl_sb_free(ptScene->sbtOpaqueDrawables); pl_sb_free(ptScene->sbtTransparentDrawables); pl_sb_free(ptScene->sbtSkinData); @@ -1368,16 +1463,6 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) plGraphics* ptGraphics = &gptData->tGraphics; plDevice* ptDevice = &ptGraphics->tDevice; - // add opaque items - const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtOpaqueDrawables); - for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) - pl_sb_push(ptScene->sbtSubmittedDrawables, ptScene->sbtOpaqueDrawables[i]); - - // add transparent items - const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtTransparentDrawables); - for(uint32_t i = 0; i < uTransparentDrawableCount; i++) - pl_sb_push(ptScene->sbtSubmittedDrawables, ptScene->sbtTransparentDrawables[i]); - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pl_begin_profile_sample("load textures"); @@ -1428,13 +1513,95 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~CPU Buffers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // fill CPU buffers & drawable list - pl_begin_profile_sample("fill CPU buffers"); - const uint32_t uDrawableCount = pl_sb_size(ptScene->sbtSubmittedDrawables); - for(uint32_t i = 0; i < uDrawableCount; i++) + pl_begin_profile_sample("fill CPU opaque buffers"); + const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtOpaqueDrawables); + for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) + { + + ptScene->sbtOpaqueDrawables[i].uSkinIndex = UINT32_MAX; + plEntity tEntity = ptScene->sbtOpaqueDrawables[i].tEntity; + + // get actual components + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptObject->tMesh); + plMaterialComponent* ptMaterial = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MATERIAL, ptMesh->tMaterial); + + plBindGroupLayout tMaterialBindGroupLayout = { + .uTextureBindingCount = 2, + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED}, + {.uSlot = 1, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED}, + } + }; + const uint64_t ulMaterialIndex = pl_hm_lookup(&tMaterialBindGroupDict, (uint64_t)ptMaterial); + ptScene->sbtOpaqueDrawables[i].tMaterialBindGroup = sbtMaterialBindGroups[ulMaterialIndex]; + + // add data to global buffers + pl__add_drawable_data_to_global_buffer(ptScene, i, ptScene->sbtOpaqueDrawables); + + // choose shader variant + int aiConstantData0[5] = {0}; + aiConstantData0[0] = (int)ptMesh->ulVertexStreamMask; + aiConstantData0[2] = (int)(ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_BASE_COLOR_MAP].acName[0] != 0); // PL_HAS_BASE_COLOR_MAP; + aiConstantData0[3] = (int)(ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_NORMAL_MAP].acName[0] != 0); // PL_HAS_NORMAL_MAP + aiConstantData0[4] = (int)(ptMesh->tSkinComponent.uIndex != UINT32_MAX); + int iFlagCopy0 = (int)ptMesh->ulVertexStreamMask; + while(iFlagCopy0) + { + aiConstantData0[1] += iFlagCopy0 & 1; + iFlagCopy0 >>= 1; + } + + const plShaderVariant tVariant = { + .pTempConstantData = aiConstantData0, + .tGraphicsState = { + .ulDepthWriteEnabled = 1, + .ulDepthMode = PL_COMPARE_MODE_LESS, + .ulCullMode = PL_CULL_MODE_CULL_BACK, + .ulStencilMode = PL_COMPARE_MODE_ALWAYS, + .ulStencilRef = 0xff, + .ulStencilMask = 0xff, + .ulStencilOpFail = PL_STENCIL_OP_KEEP, + .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, + .ulStencilOpPass = PL_STENCIL_OP_KEEP + } + }; + + ptScene->sbtOpaqueDrawables[i].uShader = pl__get_shader_variant(uSceneHandle, ptScene->tOpaqueShader, &tVariant).uIndex; + + if(ptMesh->tSkinComponent.uIndex != UINT32_MAX) + { + + plSkinData tSkinData = {.tEntity = ptMesh->tSkinComponent}; + + plSkinComponent* ptSkinComponent = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_SKIN, ptMesh->tSkinComponent); + unsigned int textureWidth = (unsigned int)ceilf(sqrtf((float)(pl_sb_size(ptSkinComponent->sbtJoints) * 8))); + pl_sb_resize(ptSkinComponent->sbtTextureData, textureWidth * textureWidth); + const plTextureDesc tSkinTextureDesc = { + .tDimensions = {(float)textureWidth, (float)textureWidth, 1}, + .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED + }; + + for(uint32_t uFrameIndex = 0; uFrameIndex < PL_FRAMES_IN_FLIGHT; uFrameIndex++) + tSkinData.atDynamicTexture[uFrameIndex] = pl__refr_create_texture_with_data(&tSkinTextureDesc, "joint texture", uFrameIndex, ptSkinComponent->sbtTextureData, sizeof(float) * 4 * textureWidth * textureWidth); + + ptScene->sbtOpaqueDrawables[i].uSkinIndex = pl_sb_size(ptScene->sbtSkinData); + pl_sb_push(ptScene->sbtSkinData, tSkinData); + } + } + pl_end_profile_sample(); + + pl_begin_profile_sample("fill CPU transparent buffers"); + const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtTransparentDrawables); + for(uint32_t i = 0; i < uTransparentDrawableCount; i++) { - ptScene->sbtSubmittedDrawables[i].uSkinIndex = UINT32_MAX; - plEntity tEntity = ptScene->sbtSubmittedDrawables[i].tEntity; + ptScene->sbtTransparentDrawables[i].uSkinIndex = UINT32_MAX; + plEntity tEntity = ptScene->sbtTransparentDrawables[i].tEntity; // get actual components plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tEntity); @@ -1449,10 +1616,10 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) } }; const uint64_t ulMaterialIndex = pl_hm_lookup(&tMaterialBindGroupDict, (uint64_t)ptMaterial); - ptScene->sbtSubmittedDrawables[i].tMaterialBindGroup = sbtMaterialBindGroups[ulMaterialIndex]; + ptScene->sbtTransparentDrawables[i].tMaterialBindGroup = sbtMaterialBindGroups[ulMaterialIndex]; // add data to global buffers - pl__add_drawable_data_to_global_buffer(ptScene, i); + pl__add_drawable_data_to_global_buffer(ptScene, i, ptScene->sbtTransparentDrawables); // choose shader variant int aiConstantData0[5] = {0}; @@ -1472,7 +1639,7 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) .tGraphicsState = { .ulDepthWriteEnabled = 1, .ulDepthMode = PL_COMPARE_MODE_LESS_OR_EQUAL, - .ulCullMode = ptMaterial->tBlendMode == PL_MATERIAL_BLEND_MODE_OPAQUE ? PL_CULL_MODE_CULL_BACK : PL_CULL_MODE_NONE, + .ulCullMode = PL_CULL_MODE_NONE, .ulStencilMode = PL_COMPARE_MODE_ALWAYS, .ulStencilRef = 0xff, .ulStencilMask = 0xff, @@ -1482,7 +1649,7 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) } }; - ptScene->sbtSubmittedDrawables[i].uShader = pl__get_shader_variant(uSceneHandle, ptScene->tShader, &tVariant).uIndex; + ptScene->sbtTransparentDrawables[i].uShader = pl__get_shader_variant(uSceneHandle, ptScene->tTransparentShader, &tVariant).uIndex; if(ptMesh->tSkinComponent.uIndex != UINT32_MAX) { @@ -1504,7 +1671,7 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) for(uint32_t uFrameIndex = 0; uFrameIndex < PL_FRAMES_IN_FLIGHT; uFrameIndex++) tSkinData.atDynamicTexture[uFrameIndex] = pl__refr_create_texture_with_data(&tSkinTextureDesc, "joint texture", uFrameIndex, ptSkinComponent->sbtTextureData, sizeof(float) * 4 * textureWidth * textureWidth); - ptScene->sbtSubmittedDrawables[i].uSkinIndex = pl_sb_size(ptScene->sbtSkinData); + ptScene->sbtTransparentDrawables[i].uSkinIndex = pl_sb_size(ptScene->sbtSkinData); pl_sb_push(ptScene->sbtSkinData, tSkinData); } } @@ -1513,7 +1680,6 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) pl_hm_free(&tMaterialBindGroupDict); pl_sb_free(sbtMaterialBindGroups); - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~GPU Buffers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pl_begin_profile_sample("fill GPU buffers"); @@ -1609,6 +1775,7 @@ typedef struct _plCullData { plRefScene* ptScene; plCameraComponent* ptCullCamera; + plDrawable* atDrawables; } plCullData; static void @@ -1616,12 +1783,12 @@ pl__refr_cull_job(uint32_t uJobIndex, void* pData) { plCullData* ptCullData = pData; plRefScene* ptScene = ptCullData->ptScene; - plDrawable tDrawable = ptScene->sbtSubmittedDrawables[uJobIndex]; + plDrawable tDrawable = ptCullData->atDrawables[uJobIndex]; plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, tDrawable.tEntity); - ptScene->sbtSubmittedDrawables[uJobIndex].bCulled = true; + ptCullData->atDrawables[uJobIndex].bCulled = true; if(pl__sat_visibility_test(ptCullData->ptCullCamera, &ptMesh->tAABBFinal)) { - ptScene->sbtSubmittedDrawables[uJobIndex].bCulled = false; + ptCullData->atDrawables[uJobIndex].bCulled = false; } } @@ -1636,35 +1803,67 @@ pl_refr_render_scene(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint // handle culling - const uint32_t uDrawableCount = pl_sb_size(ptScene->sbtSubmittedDrawables); + const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtOpaqueDrawables); + const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtTransparentDrawables); pl_begin_profile_sample("cull operations"); if(tOptions.ptCullCamera) { - plCullData tCullData = { + plCullData tOpaqueCullData = { + .ptScene = ptScene, + .ptCullCamera = tOptions.ptCullCamera, + .atDrawables = ptScene->sbtOpaqueDrawables + }; + plAtomicCounter* ptOpaqueCounter = NULL; + + plJobDesc tOpaqueJobDesc = { + .task = pl__refr_cull_job, + .pData = &tOpaqueCullData + }; + + plCullData tTransparentCullData = { .ptScene = ptScene, - .ptCullCamera = tOptions.ptCullCamera + .ptCullCamera = tOptions.ptCullCamera, + .atDrawables = ptScene->sbtTransparentDrawables }; - plAtomicCounter* ptCounter = NULL; - plJobDesc tJobDesc = { + plAtomicCounter* ptTransparentCounter = NULL; + plJobDesc tTransparentJobDesc = { .task = pl__refr_cull_job, - .pData = &tCullData + .pData = &tTransparentCullData }; - gptJob->dispatch_batch(uDrawableCount, 0, tJobDesc, &ptCounter); - gptJob->wait_for_counter(ptCounter); + gptJob->dispatch_batch(uOpaqueDrawableCount, 0, tOpaqueJobDesc, &ptOpaqueCounter); + gptJob->dispatch_batch(uTransparentDrawableCount, 0, tTransparentJobDesc, &ptTransparentCounter); + gptJob->wait_for_counter(ptOpaqueCounter); + gptJob->wait_for_counter(ptTransparentCounter); - pl_sb_reset(ptView->sbtVisibleDrawables); - for(uint32_t uDrawableIndex = 0; uDrawableIndex < uDrawableCount; uDrawableIndex++) + pl_sb_reset(ptView->sbtVisibleOpaqueDrawables); + for(uint32_t uDrawableIndex = 0; uDrawableIndex < uOpaqueDrawableCount; uDrawableIndex++) { - const plDrawable tDrawable = ptScene->sbtSubmittedDrawables[uDrawableIndex]; + const plDrawable tDrawable = ptScene->sbtOpaqueDrawables[uDrawableIndex]; if(!tDrawable.bCulled) - pl_sb_push(ptView->sbtVisibleDrawables, tDrawable); + pl_sb_push(ptView->sbtVisibleOpaqueDrawables, tDrawable); + } + + pl_sb_reset(ptView->sbtVisibleTransparentDrawables); + for(uint32_t uDrawableIndex = 0; uDrawableIndex < uTransparentDrawableCount; uDrawableIndex++) + { + const plDrawable tDrawable = ptScene->sbtTransparentDrawables[uDrawableIndex]; + if(!tDrawable.bCulled) + pl_sb_push(ptView->sbtVisibleTransparentDrawables, tDrawable); } } - else if(pl_sb_size(ptView->sbtVisibleDrawables) != uDrawableCount) + else { - pl_sb_resize(ptView->sbtVisibleDrawables, uDrawableCount); - memcpy(ptView->sbtVisibleDrawables, ptScene->sbtSubmittedDrawables, sizeof(plDrawable) * uDrawableCount); + 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); + } } pl_end_profile_sample(); @@ -1762,14 +1961,15 @@ pl_refr_render_scene(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint if(!pdVisibleObjects) pdVisibleObjects = gptStats->get_counter("visible objects"); - const uint32_t uVisibleDrawCount = pl_sb_size(ptView->sbtVisibleDrawables); + const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptView->sbtVisibleOpaqueDrawables); + const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptView->sbtVisibleTransparentDrawables); if(tOptions.bCullStats) - *pdVisibleObjects = (double)uVisibleDrawCount; + *pdVisibleObjects = (double)(uVisibleOpaqueDrawCount + uVisibleTransparentDrawCount); - for(uint32_t i = 0; i < uVisibleDrawCount; i++) + for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) { - const plDrawable tDrawable = ptView->sbtVisibleDrawables[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); @@ -1829,6 +2029,8 @@ pl_refr_render_scene(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint gptGfx->draw_stream(&tEncoder, 1, &tArea); gptGfx->reset_draw_stream(ptStream); + + gptGfx->next_subpass(&tEncoder); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~skybox~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(ptScene->tSkyboxTexture.uIndex != UINT32_MAX) @@ -1851,27 +2053,68 @@ pl_refr_render_scene(plCommandBuffer tCommandBuffer, uint32_t uSceneHandle, uint .uInstanceStart = 0, .uInstanceCount = 1 }); - - gptGfx->next_subpass(&tEncoder); gptGfx->draw_stream(&tEncoder, 1, &tArea); } gptGfx->reset_draw_stream(ptStream); + for(uint32_t i = 0; i < uVisibleTransparentDrawCount; 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(DynamicData)); + + DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; + ptDynamicData->iDataOffset = tDrawable.uDataOffset; + ptDynamicData->iVertexOffset = tDrawable.uVertexOffset; + ptDynamicData->tModel = ptTransform->tWorld; + ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; + + gptGfx->add_to_stream(ptStream, (plStreamDraw) + { + .uShaderVariant = tDrawable.uShader, + .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, + .uBindGroup1 = tDrawable.tMaterialBindGroup.uIndex, + .uBindGroup2 = tDrawable.uSkinIndex == UINT32_MAX ? gptData->tNullSkinBindgroup.uIndex : ptScene->sbtSkinData[tDrawable.uSkinIndex].tTempBindGroup.uIndex, + .uDynamicBufferOffset = tDynamicBinding.uByteOffset, + .uInstanceStart = 0, + .uInstanceCount = 1 + }); + } + gptGfx->draw_stream(&tEncoder, 1, &tArea); + if(tOptions.bShowAllBoundingBoxes) { - for(uint32_t i = 0; i < uDrawableCount; i++) + for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) { - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtSubmittedDrawables[i].tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtOpaqueDrawables[i].tEntity); + + gptGfx->add_3d_aabb(&ptView->t3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plVec4){1.0f, 0.0f, 0.0f, 1.0f}, 0.02f); + } + for(uint32_t i = 0; i < uTransparentDrawableCount; i++) + { + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtTransparentDrawables[i].tEntity); gptGfx->add_3d_aabb(&ptView->t3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plVec4){1.0f, 0.0f, 0.0f, 1.0f}, 0.02f); } } else if(tOptions.bShowVisibleBoundingBoxes) { - for(uint32_t i = 0; i < uVisibleDrawCount; i++) + for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) { - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleDrawables[i].tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleOpaqueDrawables[i].tEntity); + + gptGfx->add_3d_aabb(&ptView->t3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plVec4){1.0f, 0.0f, 0.0f, 1.0f}, 0.02f); + } + for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) + { + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleTransparentDrawables[i].tEntity); gptGfx->add_3d_aabb(&ptView->t3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plVec4){1.0f, 0.0f, 0.0f, 1.0f}, 0.02f); } @@ -1926,9 +2169,10 @@ pl_add_drawable_objects_to_scene(uint32_t uSceneHandle, uint32_t uOpaqueCount, c //----------------------------------------------------------------------------- static void -pl__add_drawable_data_to_global_buffer(plRefScene* ptScene, uint32_t uDrawableIndex) +pl__add_drawable_data_to_global_buffer(plRefScene* ptScene, uint32_t uDrawableIndex, plDrawable* atDrawables) { - plEntity tEntity = ptScene->sbtSubmittedDrawables[uDrawableIndex].tEntity; + + plEntity tEntity = atDrawables[uDrawableIndex].tEntity; // get actual components plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tEntity); @@ -2064,12 +2308,12 @@ pl__add_drawable_data_to_global_buffer(plRefScene* ptScene, uint32_t uDrawableIn }; pl_sb_push(ptScene->sbtMaterialBuffer, tMaterial); - ptScene->sbtSubmittedDrawables[uDrawableIndex].uIndexCount = uIndexCount; - ptScene->sbtSubmittedDrawables[uDrawableIndex].uVertexCount = uVertexCount; - ptScene->sbtSubmittedDrawables[uDrawableIndex].uIndexOffset = uIndexBufferStart; - ptScene->sbtSubmittedDrawables[uDrawableIndex].uVertexOffset = uVertexPosStartIndex; - ptScene->sbtSubmittedDrawables[uDrawableIndex].uDataOffset = uVertexDataStartIndex; - ptScene->sbtSubmittedDrawables[uDrawableIndex].uMaterialIndex = uMaterialIndex; + atDrawables[uDrawableIndex].uIndexCount = uIndexCount; + atDrawables[uDrawableIndex].uVertexCount = uVertexCount; + atDrawables[uDrawableIndex].uIndexOffset = uIndexBufferStart; + atDrawables[uDrawableIndex].uVertexOffset = uVertexPosStartIndex; + atDrawables[uDrawableIndex].uDataOffset = uVertexDataStartIndex; + atDrawables[uDrawableIndex].uMaterialIndex = uMaterialIndex; } static bool diff --git a/scripts/gen_build.py b/scripts/gen_build.py index faeab2f4..71c18f35 100644 --- a/scripts/gen_build.py +++ b/scripts/gen_build.py @@ -149,6 +149,7 @@ def add_plugin_to_metal_app(name, reloadable, objc = False, binary_name = None): "skybox.vert", "primitive.frag", "primitive.vert", + "transparent.frag", "lighting.vert", "lighting.frag", "draw_3d.vert", diff --git a/shaders/glsl/primitive.frag b/shaders/glsl/primitive.frag index 21966ba4..db1c1447 100644 --- a/shaders/glsl/primitive.frag +++ b/shaders/glsl/primitive.frag @@ -187,7 +187,6 @@ vec4 getBaseColor(vec4 u_ColorFactor) void main() { vec4 tBaseColor = getBaseColor(tMaterialInfo.atMaterials[tObjectInfo.iMaterialIndex].tColor); - vec3 tSunlightColor = vec3(1.0, 1.0, 1.0); NormalInfo tNormalInfo = pl_get_normal_info(); outAlbedo = tBaseColor; outNormal = vec4(tNormalInfo.n, 1.0); diff --git a/shaders/glsl/transparent.frag b/shaders/glsl/transparent.frag new file mode 100644 index 00000000..e8dda516 --- /dev/null +++ b/shaders/glsl/transparent.frag @@ -0,0 +1,199 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +//----------------------------------------------------------------------------- +// [SECTION] forward declarations +//----------------------------------------------------------------------------- + +const int PL_MESH_FORMAT_FLAG_NONE = 0; +const int PL_MESH_FORMAT_FLAG_HAS_POSITION = 1 << 0; +const int PL_MESH_FORMAT_FLAG_HAS_NORMAL = 1 << 1; +const int PL_MESH_FORMAT_FLAG_HAS_TANGENT = 1 << 2; +const int PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_0 = 1 << 3; +const int PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_1 = 1 << 4; +const int PL_MESH_FORMAT_FLAG_HAS_COLOR_0 = 1 << 5; +const int PL_MESH_FORMAT_FLAG_HAS_COLOR_1 = 1 << 6; +const int PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 = 1 << 7; +const int PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 = 1 << 8; +const int PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 = 1 << 9; +const int PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 = 1 << 10; + +layout(constant_id = 0) const int MeshVariantFlags = PL_MESH_FORMAT_FLAG_NONE; +layout(constant_id = 1) const int PL_DATA_STRIDE = 0; +layout(constant_id = 2) const int PL_HAS_BASE_COLOR_MAP = 0; +layout(constant_id = 3) const int PL_HAS_NORMAL_MAP = 0; +layout(constant_id = 4) const int PL_USE_SKINNING = 0; + +//----------------------------------------------------------------------------- +// [SECTION] global +//----------------------------------------------------------------------------- + +struct tMaterial +{ + vec4 tColor; +}; + +layout(set = 0, binding = 0) uniform _plGlobalInfo +{ + vec4 tCameraPos; + mat4 tCameraView; + mat4 tCameraProjection; + mat4 tCameraViewProjection; +} tGlobalInfo; + +layout(std140, set = 0, binding = 1) readonly buffer _tVertexBuffer +{ + vec4 atVertexData[]; +} tVertexBuffer; + +layout(set = 0, binding = 2) readonly buffer plMaterialInfo +{ + tMaterial atMaterials[]; +} tMaterialInfo; + +layout(set = 0, binding = 3) uniform sampler tDefaultSampler; + +layout(set = 1, binding = 0) uniform texture2D tBaseColorSampler[]; +// layout(set = 1, binding = 1) uniform texture2D tNormalSampler[]; + +layout(set = 2, binding = 0) uniform texture2D tSkinningSampler; + +layout(set = 3, binding = 0) uniform _plObjectInfo +{ + int iDataOffset; + int iVertexOffset; + int iMaterialIndex; + mat4 tModel; +} tObjectInfo; + +const float GAMMA = 2.2; +const float INV_GAMMA = 1.0 / GAMMA; + +// linear to sRGB approximation +// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html +vec3 linearTosRGB(vec3 color) +{ + return pow(color, vec3(INV_GAMMA)); +} + +layout(location = 0) out vec4 outColor; + +// output +layout(location = 0) in struct plShaderIn { + vec3 tPosition; + vec4 tWorldPosition; + vec2 tUV[2]; + vec4 tColor; + vec3 tWorldNormal; + mat3 tTBN; +} tShaderIn; + +struct NormalInfo { + vec3 ng; // Geometry normal + vec3 t; // Geometry tangent + vec3 b; // Geometry bitangent + vec3 n; // Shading normal + vec3 ntex; // Normal from texture, scaling is accounted for. +}; + +NormalInfo pl_get_normal_info() +{ + vec2 UV = tShaderIn.tUV[0]; + vec2 uv_dx = dFdx(UV); + vec2 uv_dy = dFdy(UV); + + if (length(uv_dx) <= 1e-2) { + uv_dx = vec2(1.0, 0.0); + } + + if (length(uv_dy) <= 1e-2) { + uv_dy = vec2(0.0, 1.0); + } + + vec3 t_ = (uv_dy.t * dFdx(tShaderIn.tPosition) - uv_dx.t * dFdy(tShaderIn.tPosition)) / + (uv_dx.s * uv_dy.t - uv_dy.s * uv_dx.t); + + vec3 n, t, b, ng; + + // Compute geometrical TBN: + if(bool(MeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_NORMAL)) + { + + if(bool(MeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TANGENT)) + { + // Trivial TBN computation, present as vertex attribute. + // Normalize eigenvectors as matrix is linearly interpolated. + t = normalize(tShaderIn.tTBN[0]); + b = normalize(tShaderIn.tTBN[1]); + ng = normalize(tShaderIn.tTBN[2]); + } + else + { + // Normals are either present as vertex attributes or approximated. + ng = normalize(tShaderIn.tWorldNormal); + t = normalize(t_ - ng * dot(ng, t_)); + b = cross(ng, t); + } + } + else + { + ng = normalize(cross(dFdx(tShaderIn.tPosition), dFdy(tShaderIn.tPosition))); + t = normalize(t_ - ng * dot(ng, t_)); + b = cross(ng, t); + } + + + // For a back-facing surface, the tangential basis vectors are negated. + if (gl_FrontFacing == false) + { + t *= -1.0; + b *= -1.0; + ng *= -1.0; + } + + // Compute normals: + NormalInfo info; + info.ng = ng; + if(bool(PL_HAS_NORMAL_MAP)) + { + info.ntex = texture(sampler2D(tBaseColorSampler[1], tDefaultSampler), UV).rgb * 2.0 - vec3(1.0); + // info.ntex *= vec3(0.2, 0.2, 1.0); + // info.ntex *= vec3(u_NormalScale, u_NormalScale, 1.0); + info.ntex = normalize(info.ntex); + info.n = normalize(mat3(t, b, ng) * info.ntex); + } + else + { + info.n = ng; + } + info.t = t; + info.b = b; + return info; +} + +vec4 getBaseColor(vec4 u_ColorFactor) +{ + vec4 baseColor = u_ColorFactor; + + if(bool(PL_HAS_BASE_COLOR_MAP)) + { + baseColor *= texture(sampler2D(tBaseColorSampler[0], tDefaultSampler), tShaderIn.tUV[0]); + } + return baseColor; +} + +void main() +{ + vec4 tBaseColor = getBaseColor(tMaterialInfo.atMaterials[tObjectInfo.iMaterialIndex].tColor); + if(tBaseColor.a < 0.1) + { + discard; + } + vec3 tSunlightColor = vec3(1.0, 1.0, 1.0); + NormalInfo tNormalInfo = pl_get_normal_info(); + vec3 tSunLightDirection = vec3(-1.0, -1.0, -1.0); + float fDiffuseIntensity = max(0.0, dot(normalize(tNormalInfo.n), -normalize(tSunLightDirection))); + outColor = tBaseColor * vec4(tSunlightColor * (0.05 + fDiffuseIntensity), 1.0); + + outColor = vec4(linearTosRGB(outColor.rgb), tBaseColor.a); +} \ No newline at end of file