diff --git a/shaders/FSL/ShaderList.fsl b/shaders/FSL/ShaderList.fsl index b4123b9..ae52056 100644 --- a/shaders/FSL/ShaderList.fsl +++ b/shaders/FSL/ShaderList.fsl @@ -2,6 +2,22 @@ #include "basic.frag.fsl" #end -#vert VR_MULTIVIEW basic.vert -#include "basic.vert.fsl" +#frag shadow.frag +#include "shadow.frag.fsl" +#end + +#vert VR_MULTIVIEW sphere.vert +#include "sphere.vert.fsl" +#end + +#vert VR_MULTIVIEW quad.vert +#include "quad.vert.fsl" +#end + +#vert VR_MULTIVIEW sphere_shadow.vert +#include "sphere_shadow.vert.fsl" +#end + +#vert VR_MULTIVIEW quad_shadow.vert +#include "quad_shadow.vert.fsl" #end \ No newline at end of file diff --git a/shaders/FSL/basic.frag.fsl b/shaders/FSL/basic.frag.fsl index e517d81..86d71aa 100644 --- a/shaders/FSL/basic.frag.fsl +++ b/shaders/FSL/basic.frag.fsl @@ -1,38 +1,27 @@ -/* - * Copyright (c) 2017-2022 The Forge Interactive Inc. - * - * This file is part of The-Forge - * (see https://github.com/ConfettiFX/The-Forge). - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. -*/ - -// Shader for simple shading with a point light -// for planets in Unit Test 12 - Transformations +RES(Tex2D(float), lightMap, UPDATE_FREQ_NONE, t0, binding = 0); +RES(SamplerState, uSampler, UPDATE_FREQ_NONE, s0, binding = 1); STRUCT(VSOutput) { DATA(float4, Position, SV_Position); DATA(float4, Color, COLOR); + DATA(float2, LightmapPos, TEXCOORD0); + DATA(float, LightmapHeight, TEXCOORD1); }; -float4 PS_MAIN( VSOutput In ) +float4 PS_MAIN(VSOutput In) { INIT_MAIN; + + float2 coord = (In.LightmapPos + float2(1, 1)) / float2(2, 2); + coord.y = 1 - coord.y; + + float4 litDepth = SampleTex2D(Get(lightMap), Get(uSampler), coord); + + if (litDepth.x > In.LightmapHeight + 0.05) + { + In.Color -= float4(0.8, 0.8, 0.8, 0.0); + } + RETURN(In.Color); } diff --git a/shaders/FSL/basic.vert.fsl b/shaders/FSL/basic.vert.fsl deleted file mode 100644 index f741eed..0000000 --- a/shaders/FSL/basic.vert.fsl +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017-2022 The Forge Interactive Inc. - * - * This file is part of The-Forge - * (see https://github.com/ConfettiFX/The-Forge). - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. -*/ - -#include "resources.h.fsl" - -STRUCT(VSInput) -{ - DATA(float3, Position, POSITION); - DATA(float3, Normal, NORMAL); -}; - -STRUCT(VSOutput) -{ - DATA(float4, Position, SV_Position); - DATA(float4, Color, COLOR); -}; - -VSOutput VS_MAIN( VSInput In, SV_InstanceID(uint) InstanceID ) -{ - INIT_MAIN; - VSOutput Out; - -#if VR_MULTIVIEW_ENABLED - float4x4 tempMat = mul(Get(mvp)[VR_VIEW_ID], Get(toWorld)[InstanceID]); -#else - float4x4 tempMat = mul(Get(mvp), Get(toWorld)[InstanceID]); -#endif - Out.Position = mul(tempMat, float4(In.Position.xyz, 1.0f)); - - float4 normal = normalize(mul(Get(toWorld)[InstanceID], float4(In.Normal.xyz, 0.0f))); // Assume uniform scaling - float4 pos = mul(Get(toWorld)[InstanceID], float4(In.Position.xyz, 1.0f)); - - float lightIntensity = 1.0f; - // float quadraticCoeff = 1.2; - float ambientCoeff = 0.1; - - float3 lightDir; - - if (Get(color)[InstanceID].w < 0.01) // Special case for Sun, so that it is lit from its top - lightDir = float3(0.0f, 1.0f, 0.0f); - else - lightDir = normalize(Get(lightPosition) - pos.xyz); - - // float distance = length(lightDir); - // float attenuation = 1.0 / (quadraticCoeff * distance * distance); - // float intensity = lightIntensity * attenuation; - - float3 baseColor = Get(color)[InstanceID].xyz; - float3 blendedColor = (Get(lightColor) * baseColor) * lightIntensity; - float3 diffuse = blendedColor * max(dot(normal.xyz, lightDir), 0.0); - float3 ambient = baseColor * ambientCoeff; - Out.Color = float4(diffuse + ambient, 1.0); - RETURN(Out); -} diff --git a/shaders/FSL/quad.vert.fsl b/shaders/FSL/quad.vert.fsl new file mode 100644 index 0000000..e6667ec --- /dev/null +++ b/shaders/FSL/quad.vert.fsl @@ -0,0 +1,23 @@ +#include "quad_resource.fsl" + +VSOutput VS_MAIN(VSInput In, SV_InstanceID(uint) InstanceID) +{ + INIT_MAIN; + VSOutput Out; + +#if VR_MULTIVIEW_ENABLED + float4x4 wvp = mul(Get(mvp)[VR_VIEW_ID], Get(toWorld)); +#else + float4x4 wvp = mul(Get(mvp), Get(toWorld)); +#endif + Out.Position = mul(wvp, float4(In.Position.xyz, 1.0f)); + Out.Color = Get(color); + + float4x4 lightWVP = mul(Get(lightProjView), Get(toWorld)); + float4 lightSpacePos = mul(lightWVP, float4(In.Position.xyz, 1.0f)); + + Out.LightmapPos = lightSpacePos.xy; + Out.LightmapHeight = lightSpacePos.z; + + RETURN(Out); +} diff --git a/shaders/FSL/quad_resource.fsl b/shaders/FSL/quad_resource.fsl new file mode 100644 index 0000000..07518cb --- /dev/null +++ b/shaders/FSL/quad_resource.fsl @@ -0,0 +1,30 @@ +#ifndef QUAD_RESOURCE +#define QUAD_RESOURCE + +CBUFFER(uniformBlock, UPDATE_FREQ_PER_FRAME, b0, binding = 0) +{ +#if VR_MULTIVIEW_ENABLED + DATA(float4x4, mvp[VR_MULTIVIEW_COUNT], None); +#else + DATA(float4x4, mvp, None); +#endif + DATA(float4x4, lightProjView, None); + DATA(float4x4, toWorld, None); + DATA(float4, color, None); +}; + +STRUCT(VSInput) +{ + DATA(float3, Position, POSITION); + DATA(float3, Normal, NORMAL); +}; + +STRUCT(VSOutput) +{ + DATA(float4, Position, SV_Position); + DATA(float4, Color, COLOR); + DATA(float2, LightmapPos, TEXCOORD0); + DATA(float, LightmapHeight, TEXCOORD1); +}; + +#endif \ No newline at end of file diff --git a/shaders/FSL/quad_shadow.vert.fsl b/shaders/FSL/quad_shadow.vert.fsl new file mode 100644 index 0000000..3a9587d --- /dev/null +++ b/shaders/FSL/quad_shadow.vert.fsl @@ -0,0 +1,14 @@ +#include "quad_resource.fsl" + +VSOutput VS_MAIN(VSInput In, SV_InstanceID(uint) InstanceID) +{ + INIT_MAIN; + VSOutput Out; + + float4x4 tempMat = mul(Get(lightProjView), Get(toWorld)); + + Out.Position = mul(tempMat, float4(In.Position.xyz, 1.0f)); + Out.Color = Get(color); + + RETURN(Out); +} diff --git a/shaders/FSL/resources.h.fsl b/shaders/FSL/resources.h.fsl deleted file mode 100644 index 71e6ce5..0000000 --- a/shaders/FSL/resources.h.fsl +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017-2022 The Forge Interactive Inc. - * - * This file is part of The-Forge - * (see https://github.com/ConfettiFX/The-Forge). - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. -*/ - -#ifndef RESOURCES_H -#define RESOURCES_H - -// UPDATE_FREQ_NONE -RES(Tex2D(float4), RightText, UPDATE_FREQ_NONE, t1, binding = 1); -RES(Tex2D(float4), LeftText, UPDATE_FREQ_NONE, t2, binding = 2); -RES(Tex2D(float4), TopText, UPDATE_FREQ_NONE, t3, binding = 3); -RES(Tex2D(float4), BotText, UPDATE_FREQ_NONE, t4, binding = 4); -RES(Tex2D(float4), FrontText, UPDATE_FREQ_NONE, t5, binding = 5); -RES(Tex2D(float4), BackText, UPDATE_FREQ_NONE, t6, binding = 6); -RES(SamplerState, uSampler0, UPDATE_FREQ_NONE, s0, binding = 7); - -// UPDATE_FREQ_PER_FRAME -#ifndef MAX_PLANETS - #define MAX_PLANETS 768 -#endif -CBUFFER(uniformBlock, UPDATE_FREQ_PER_FRAME, b0, binding = 0) -{ -#if VR_MULTIVIEW_ENABLED - DATA(float4x4, mvp[VR_MULTIVIEW_COUNT], None); -#else - DATA(float4x4, mvp, None); -#endif - DATA(float4x4, toWorld[MAX_PLANETS], None); - DATA(float4, color[MAX_PLANETS], None); - - // Point Light Information - DATA(float3, lightPosition, None); - DATA(float3, lightColor, None); -}; - -#endif \ No newline at end of file diff --git a/shaders/FSL/shadow.frag.fsl b/shaders/FSL/shadow.frag.fsl new file mode 100644 index 0000000..fcbb826 --- /dev/null +++ b/shaders/FSL/shadow.frag.fsl @@ -0,0 +1,5 @@ +void PS_MAIN() +{ + INIT_MAIN; + RETURN(); +} diff --git a/shaders/FSL/sphere.vert.fsl b/shaders/FSL/sphere.vert.fsl new file mode 100644 index 0000000..02d012e --- /dev/null +++ b/shaders/FSL/sphere.vert.fsl @@ -0,0 +1,23 @@ +#include "sphere_resource.fsl" + +VSOutput VS_MAIN(VSInput In, SV_InstanceID(uint) InstanceID) +{ + INIT_MAIN; + VSOutput Out; + +#if VR_MULTIVIEW_ENABLED + float4x4 wvp = mul(Get(mvp)[VR_VIEW_ID], Get(toWorld)[InstanceID]); +#else + float4x4 wvp = mul(Get(mvp), Get(toWorld)[InstanceID]); +#endif + Out.Position = mul(wvp, float4(In.Position.xyz, 1.0f)); + Out.Color = Get(color)[InstanceID]; + + float4x4 lightWVP = mul(Get(lightProjView), Get(toWorld)[InstanceID]); + float4 lightSpacePos = mul(lightWVP, float4(In.Position.xyz, 1.0f)); + + Out.LightmapPos = lightSpacePos.xy; + Out.LightmapHeight = lightSpacePos.z; + + RETURN(Out); +} diff --git a/shaders/FSL/sphere_resource.fsl b/shaders/FSL/sphere_resource.fsl new file mode 100644 index 0000000..82bf6db --- /dev/null +++ b/shaders/FSL/sphere_resource.fsl @@ -0,0 +1,35 @@ +#ifndef SPHERE_RESOURCE +#define SPHERE_RESOURCE + +#ifndef MAX_PLANETS +#define MAX_PLANETS 768 +#endif + +CBUFFER(uniformBlock, UPDATE_FREQ_PER_FRAME, b0, binding = 0) +{ +#if VR_MULTIVIEW_ENABLED + DATA(float4x4, mvp[VR_MULTIVIEW_COUNT], None); +#else + DATA(float4x4, mvp, None); +#endif + DATA(float4x4, lightProjView, None); + + DATA(float4x4, toWorld[MAX_PLANETS], None); + DATA(float4, color[MAX_PLANETS], None); +}; + +STRUCT(VSInput) +{ + DATA(float3, Position, POSITION); + DATA(float3, Normal, NORMAL); +}; + +STRUCT(VSOutput) +{ + DATA(float4, Position, SV_Position); + DATA(float4, Color, COLOR); + DATA(float2, LightmapPos, TEXCOORD0); + DATA(float, LightmapHeight, TEXCOORD1); +}; + +#endif \ No newline at end of file diff --git a/shaders/FSL/sphere_shadow.vert.fsl b/shaders/FSL/sphere_shadow.vert.fsl new file mode 100644 index 0000000..a150aaf --- /dev/null +++ b/shaders/FSL/sphere_shadow.vert.fsl @@ -0,0 +1,13 @@ +#include "sphere_resource.fsl" + +VSOutput VS_MAIN(VSInput In, SV_InstanceID(uint) InstanceID) +{ + INIT_MAIN; + VSOutput Out; + + float4x4 tempMat = mul(Get(lightProjView), Get(toWorld)[InstanceID]); + Out.Position = mul(tempMat, float4(In.Position.xyz, 1.0f)); + Out.Color = Get(color)[InstanceID]; + + RETURN(Out); +} diff --git a/src/DemoScene.cpp b/src/DemoScene.cpp index 6e5ddc8..d05a876 100644 --- a/src/DemoScene.cpp +++ b/src/DemoScene.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -11,48 +12,87 @@ namespace DemoScene { - int vertexCount{}; + int spherePoints = 0; + int quadPoints = 0; - constexpr size_t MAX_STARS = 768; - std::array position{}; - std::array color{}; - vec3 lightPosition{1.0f, 0, 0}; - vec3 lightColor{0.9f, 0.9f, 0.7f}; + constexpr size_t MAX_SPHERE = 768; + std::array position{}; + std::array size{1.0f}; + std::array color{}; + std::array speed{}; - struct UniformBlock + struct SphereUniform { - CameraMatrix mProjectView; - std::array mToWorldMat; - std::array mColor; + CameraMatrix projectView; + CameraMatrix lightProjectView; + std::array world; + std::array color; + } sphereUniform = {}; - vec3 mLightPosition; - vec3 mLightColor; - } uniform = {}; + struct QuadUniform + { + CameraMatrix projectView; + CameraMatrix lightProjectView; + mat4 world; + vec4 color; + } quadUniform = {}; + + Shader *pShaderInstancing = nullptr; + Shader *pShaderInstancingShadow = nullptr; + RootSignature *pRSInstancing = nullptr; + DescriptorSet *pDSSphereUniform = nullptr; + Buffer *pBufferSphereUniform = nullptr; + Buffer *pBufferSphereVertex = nullptr; + Pipeline *pPipelineSphere = nullptr; + Pipeline *pPipelineSphereShadow = nullptr; + + Shader *pShaderSingle = nullptr; + Shader *pShaderSingleShadow = nullptr; + RootSignature *pRSSingle = nullptr; + DescriptorSet *pDSQuadUniform = nullptr; + Buffer *pBufferQuadVertex = nullptr; + Buffer *pBufferQuadIndex = nullptr; + Buffer *pBufferQuadUniform = nullptr; + Pipeline *pPipelineQuad = nullptr; + Pipeline *pPipelineQuadShadow = nullptr; + + ICameraController *pCameraController = nullptr; + + RenderTarget *pRTDepth = nullptr; + + constexpr int SHADOW_MAP_SIZE = 2048; + RenderTarget *pRTShadowMap = nullptr; + DescriptorSet *pDSShadowMap = nullptr; + + CameraMatrix lightViewProj{}; + + Sampler *pSampler; - Shader *pShader{nullptr}; - RootSignature *pRootSignature{nullptr}; - DescriptorSet *pDSUniform{nullptr}; - Buffer *pProjViewUniformBuffer{nullptr}; - Buffer *pSphereVertexBuffer{nullptr}; - Pipeline *pPLSphere{nullptr}; + TinyImageFormat depthBufferFormat = TinyImageFormat_D32_SFLOAT; - ICameraController *pCameraController{nullptr}; + void AddSphereResources(Renderer *pRenderer); + void RemoveSphereResources(Renderer *pRenderer); - RenderTarget *pDepthBuffer{nullptr}; - TinyImageFormat depthBufferFormat = TinyImageFormat_D32_SFLOAT; + void AddQuadResources(Renderer *pRenderer); + void RemoveQuadResources(Renderer *pRenderer); } // namespace DemoScene -bool DemoScene::Init() +bool DemoScene::Init(Renderer *pRenderer) { - float *vertices{}; - generateSpherePoints(&vertices, &vertexCount, 24, 1.0f); + float *sphereVertices{}; + generateSpherePoints(&sphereVertices, &spherePoints, 12, 1.0f); + + float *quadVertices{}; + generateQuad(&quadVertices, &quadPoints); + + uint16_t quadIndices[6] = {0, 1, 2, 1, 3, 2}; SyncToken token{}; - uint64_t sphereDataSize = vertexCount * sizeof(float); + uint64_t sphereDataSize = spherePoints * sizeof(float); BufferLoadDesc sphereVbDesc{ - .ppBuffer = &pSphereVertexBuffer, - .pData = vertices, + .ppBuffer = &pBufferSphereVertex, + .pData = sphereVertices, .mDesc{ .mSize = sphereDataSize, .mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY, @@ -61,10 +101,33 @@ bool DemoScene::Init() }; addResource(&sphereVbDesc, &token); + uint64_t quadDataSize = quadPoints * sizeof(float); + BufferLoadDesc quadVbDesc{ + .ppBuffer = &pBufferQuadVertex, + .pData = quadVertices, + .mDesc{ + .mSize = quadDataSize, + .mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY, + .mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER, + }, + }; + addResource(&quadVbDesc, &token); + + BufferLoadDesc quadIdDesc{ + .ppBuffer = &pBufferQuadIndex, + .pData = quadIndices, + .mDesc{ + .mSize = sizeof(uint16_t) * 6, + .mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY, + .mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER, + }, + }; + addResource(&quadIdDesc, &token); + BufferLoadDesc ubDesc = { - .ppBuffer = &pProjViewUniformBuffer, + .ppBuffer = &pBufferSphereUniform, .mDesc{ - .mSize = sizeof(UniformBlock), + .mSize = sizeof(SphereUniform), .mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU, .mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT, .mDescriptors = DESCRIPTOR_TYPE_UNIFORM_BUFFER, @@ -72,12 +135,25 @@ bool DemoScene::Init() }; addResource(&ubDesc, &token); - for (size_t i = 0; i < MAX_STARS; i++) + BufferLoadDesc quadUniformDesc = { + .ppBuffer = &pBufferQuadUniform, + .mDesc{ + .mSize = sizeof(QuadUniform), + .mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU, + .mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT, + .mDescriptors = DESCRIPTOR_TYPE_UNIFORM_BUFFER, + }, + }; + addResource(&quadUniformDesc, &token); + + for (size_t i = 0; i < MAX_SPHERE; i++) { - position[i] = {randomFloat(-100, 100), randomFloat(-100, 100), randomFloat(-100, 100)}; + position[i] = {randomFloat(-200, 200), randomFloat(-200, 200), randomFloat(-200, 200)}; color[i] = {randomFloat01(), randomFloat01(), randomFloat01(), 1.0f}; + size[i] = randomFloat(0, 10); + speed[i] = {randomFloat(-10.0f, 10.0f), randomFloat(-10.0f, 10.0f), randomFloat(-10.0f, 10.0f)}; } - + CameraMotionParameters cmp{160.0f, 600.0f, 1000.0f}; vec3 camPos{0.0f, 0.0f, 20.0f}; vec3 lookAt{vec3(0)}; @@ -85,16 +161,86 @@ bool DemoScene::Init() pCameraController = initFpsCameraController(camPos, lookAt); pCameraController->setMotionParameters(cmp); + SamplerDesc samplerDesc = { + .mMinFilter = FILTER_LINEAR, + .mMagFilter = FILTER_LINEAR, + .mAddressU = ADDRESS_MODE_CLAMP_TO_EDGE, + .mAddressV = ADDRESS_MODE_CLAMP_TO_EDGE, + }; + addSampler(pRenderer, &samplerDesc, &pSampler); + + typedef bool (*CameraInputHandler)(InputActionContext *ctx, DefaultInputActions::DefaultInputAction action); + static CameraInputHandler onCameraInput = + [](InputActionContext *ctx, DefaultInputActions::DefaultInputAction action) + { + if (*(ctx->pCaptured)) + { + float2 delta = uiIsFocused() ? float2(0.f, 0.f) : ctx->mFloat2; + switch (action) + { + case DefaultInputActions::ROTATE_CAMERA: + pCameraController->onRotate(delta); + break; + case DefaultInputActions::TRANSLATE_CAMERA: + pCameraController->onMove(delta); + break; + case DefaultInputActions::TRANSLATE_CAMERA_VERTICAL: + pCameraController->onMoveY(delta[0]); + break; + default: + break; + } + } + return true; + }; + InputActionDesc actionDesc = {DefaultInputActions::CAPTURE_INPUT, + [](InputActionContext *ctx) + { + setEnableCaptureInput(!uiIsFocused() && + INPUT_ACTION_PHASE_CANCELED != ctx->mPhase); + return true; + }, + NULL}; + addInputAction(&actionDesc); + actionDesc = {DefaultInputActions::ROTATE_CAMERA, + [](InputActionContext *ctx) { return onCameraInput(ctx, DefaultInputActions::ROTATE_CAMERA); }, NULL}; + addInputAction(&actionDesc); + actionDesc = {DefaultInputActions::TRANSLATE_CAMERA, + [](InputActionContext *ctx) { return onCameraInput(ctx, DefaultInputActions::TRANSLATE_CAMERA); }, + NULL}; + addInputAction(&actionDesc); + actionDesc = {DefaultInputActions::TRANSLATE_CAMERA_VERTICAL, + [](InputActionContext *ctx) + { return onCameraInput(ctx, DefaultInputActions::TRANSLATE_CAMERA_VERTICAL); }, + NULL}; + addInputAction(&actionDesc); + actionDesc = {DefaultInputActions::RESET_CAMERA, + [](InputActionContext *ctx) + { + if (!uiWantTextInput()) + pCameraController->resetView(); + return true; + }}; + addInputAction(&actionDesc); + waitForToken(&token); - tf_free(vertices); + + tf_free(sphereVertices); + tf_free(quadVertices); return true; } -void DemoScene::Exit() +void DemoScene::Exit(Renderer *pRenderer) { - removeResource(pProjViewUniformBuffer); - removeResource(pSphereVertexBuffer); + removeResource(pBufferSphereUniform); + removeResource(pBufferSphereVertex); + + removeResource(pBufferQuadUniform); + removeResource(pBufferQuadVertex); + removeResource(pBufferQuadIndex); + + removeSampler(pRenderer, pSampler); exitCameraController(pCameraController); } @@ -103,32 +249,11 @@ bool DemoScene::Load(ReloadDesc *pReloadDesc, Renderer *pRenderer, RenderTarget { if (pReloadDesc->mType & RELOAD_TYPE_SHADER) { - ShaderLoadDesc basicShader{ - .mStages{ - { - .pFileName = "basic.vert", - }, - { - .pFileName = "basic.frag", - }, - }, - }; - - addShader(pRenderer, &basicShader, &pShader); - ASSERT(pShader); - - RootSignatureDesc rootDesc{ - .ppShaders = &pShader, - .mShaderCount = 1, - }; - - addRootSignature(pRenderer, &rootDesc, &pRootSignature); - ASSERT(pRootSignature); + AddSphereResources(pRenderer); + AddQuadResources(pRenderer); - DescriptorSetDesc desc = {pRootSignature, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, 1}; - addDescriptorSet(pRenderer, &desc, &pDSUniform); - - ASSERT(pDSUniform); + DescriptorSetDesc dsDesc = {pRSInstancing, DESCRIPTOR_UPDATE_FREQ_NONE, 1}; + addDescriptorSet(pRenderer, &dsDesc, &pDSShadowMap); } if (pReloadDesc->mType & (RELOAD_TYPE_RESIZE | RELOAD_TYPE_RENDERTARGET)) @@ -145,8 +270,25 @@ bool DemoScene::Load(ReloadDesc *pReloadDesc, Renderer *pRenderer, RenderTarget .mClearValue = {}, .mSampleQuality = 0, }; - addRenderTarget(pRenderer, &desc, &pDepthBuffer); - ASSERT(pDepthBuffer); + addRenderTarget(pRenderer, &desc, &pRTDepth); + ASSERT(pRTDepth); + + desc = { + .mFlags = TEXTURE_CREATION_FLAG_OWN_MEMORY_BIT, + .mWidth = SHADOW_MAP_SIZE, + .mHeight = SHADOW_MAP_SIZE, + .mDepth = 1, + .mArraySize = 1, + .mSampleCount = SAMPLE_COUNT_1, + .mFormat = depthBufferFormat, + .mStartState = RESOURCE_STATE_SHADER_RESOURCE, + .mClearValue = {}, + .mSampleQuality = 0, + .mDescriptors = DESCRIPTOR_TYPE_TEXTURE, + }; + + addRenderTarget(pRenderer, &desc, &pRTShadowMap); + ASSERT(pRTShadowMap); } if (pReloadDesc->mType & (RELOAD_TYPE_SHADER | RELOAD_TYPE_RENDERTARGET)) @@ -179,7 +321,7 @@ bool DemoScene::Load(ReloadDesc *pReloadDesc, Renderer *pRenderer, RenderTarget }; RasterizerStateDesc sphereRasterizerStateDesc = {}; - sphereRasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + sphereRasterizerStateDesc.mCullMode = CULL_MODE_NONE; DepthStateDesc depthStateDesc{ .mDepthTest = true, @@ -189,8 +331,8 @@ bool DemoScene::Load(ReloadDesc *pReloadDesc, Renderer *pRenderer, RenderTarget PipelineDesc desc = { .mGraphicsDesc{ - .pShaderProgram = pShader, - .pRootSignature = pRootSignature, + .pShaderProgram = pShaderInstancing, + .pRootSignature = pRSInstancing, .pVertexLayout = &vertexLayout, .pDepthState = &depthStateDesc, .pRasterizerState = &sphereRasterizerStateDesc, @@ -205,97 +347,337 @@ bool DemoScene::Load(ReloadDesc *pReloadDesc, Renderer *pRenderer, RenderTarget .mType = PIPELINE_TYPE_GRAPHICS, }; - GraphicsPipelineDesc &pipelineSettings = desc.mGraphicsDesc; + addPipeline(pRenderer, &desc, &pPipelineSphere); + ASSERT(pPipelineSphere); + + desc = { + .mGraphicsDesc{ + .pShaderProgram = pShaderInstancingShadow, + .pRootSignature = pRSInstancing, + .pVertexLayout = &vertexLayout, + .pDepthState = &depthStateDesc, + .pRasterizerState = &sphereRasterizerStateDesc, + .mSampleCount = pRenderTarget->mSampleCount, + .mSampleQuality = pRenderTarget->mSampleQuality, + .mDepthStencilFormat = depthBufferFormat, + .mPrimitiveTopo = PRIMITIVE_TOPO_TRI_LIST, + .mVRFoveatedRendering = true, + }, + .mType = PIPELINE_TYPE_GRAPHICS, + }; + + addPipeline(pRenderer, &desc, &pPipelineSphereShadow); + ASSERT(pPipelineSphereShadow); + + desc = { + .mGraphicsDesc = + { + .pShaderProgram = pShaderSingle, + .pRootSignature = pRSSingle, + .pVertexLayout = &vertexLayout, + .pDepthState = &depthStateDesc, + .pRasterizerState = &sphereRasterizerStateDesc, + .pColorFormats = &pRenderTarget->mFormat, + .mRenderTargetCount = 1, + .mSampleCount = pRenderTarget->mSampleCount, + .mSampleQuality = pRenderTarget->mSampleQuality, + .mDepthStencilFormat = depthBufferFormat, + .mPrimitiveTopo = PRIMITIVE_TOPO_TRI_LIST, + .mVRFoveatedRendering = true, + }, + .mType = PIPELINE_TYPE_GRAPHICS, + }; + + addPipeline(pRenderer, &desc, &pPipelineQuad); + ASSERT(pPipelineQuad); + + desc = { + .mGraphicsDesc = + { + .pShaderProgram = pShaderSingleShadow, + .pRootSignature = pRSSingle, + .pVertexLayout = &vertexLayout, + .pDepthState = &depthStateDesc, + .pRasterizerState = &sphereRasterizerStateDesc, + .mSampleCount = pRenderTarget->mSampleCount, + .mSampleQuality = pRenderTarget->mSampleQuality, + .mDepthStencilFormat = depthBufferFormat, + .mPrimitiveTopo = PRIMITIVE_TOPO_TRI_LIST, + .mVRFoveatedRendering = true, + }, + .mType = PIPELINE_TYPE_GRAPHICS, + }; - addPipeline(pRenderer, &desc, &pPLSphere); - ASSERT(pPLSphere); + addPipeline(pRenderer, &desc, &pPipelineQuadShadow); + ASSERT(pPipelineQuadShadow); } DescriptorData params = { .pName = "uniformBlock", - .ppBuffers = &pProjViewUniformBuffer, + .ppBuffers = &pBufferSphereUniform, }; - updateDescriptorSet(pRenderer, 0, pDSUniform, 1, ¶ms); + updateDescriptorSet(pRenderer, 0, pDSSphereUniform, 1, ¶ms); + + params = { + .pName = "uniformBlock", + .ppBuffers = &pBufferQuadUniform, + }; + updateDescriptorSet(pRenderer, 0, pDSQuadUniform, 1, ¶ms); + + params = { + .pName = "lightMap", + .ppTextures = &pRTShadowMap->pTexture, + }; + updateDescriptorSet(pRenderer, 0, pDSShadowMap, 1, ¶ms); return true; } +void DemoScene::AddSphereResources(Renderer *pRenderer) +{ + ShaderLoadDesc shaderDesc{ + .mStages{ + { + .pFileName = "sphere.vert", + }, + { + .pFileName = "basic.frag", + }, + }, + }; + + addShader(pRenderer, &shaderDesc, &pShaderInstancing); + ASSERT(pShaderInstancing); + + shaderDesc = { + .mStages{ + { + .pFileName = "sphere_shadow.vert", + }, + { + .pFileName = "shadow.frag", + }, + }, + }; + addShader(pRenderer, &shaderDesc, &pShaderInstancingShadow); + ASSERT(pShaderInstancingShadow); + + std::array shaders = {pShaderInstancing, pShaderInstancingShadow}; + RootSignatureDesc rootDesc{ + .ppShaders = shaders.data(), + .mShaderCount = shaders.size(), + }; + addRootSignature(pRenderer, &rootDesc, &pRSInstancing); + ASSERT(pRSInstancing); + + DescriptorSetDesc dsDesc = {pRSInstancing, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, 1}; + addDescriptorSet(pRenderer, &dsDesc, &pDSSphereUniform); + + ASSERT(pDSSphereUniform); +} + +void DemoScene::AddQuadResources(Renderer *pRenderer) +{ + ShaderLoadDesc shaderDesc{ + .mStages{ + { + .pFileName = "quad.vert", + }, + { + .pFileName = "basic.frag", + }, + }, + }; + + addShader(pRenderer, &shaderDesc, &pShaderSingle); + ASSERT(pShaderSingle); + + shaderDesc = { + .mStages{ + { + .pFileName = "quad_shadow.vert", + }, + { + .pFileName = "shadow.frag", + }, + }, + }; + + addShader(pRenderer, &shaderDesc, &pShaderSingleShadow); + ASSERT(pShaderSingleShadow); + + std::array shaders = {pShaderSingle, pShaderSingleShadow}; + RootSignatureDesc rootDesc{ + .ppShaders = shaders.data(), + .mShaderCount = shaders.size(), + }; + + addRootSignature(pRenderer, &rootDesc, &pRSSingle); + ASSERT(pRSSingle); + + DescriptorSetDesc dsDesc = {pRSSingle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, 1}; + addDescriptorSet(pRenderer, &dsDesc, &pDSQuadUniform); + + ASSERT(pDSQuadUniform); +} + void DemoScene::Unload(ReloadDesc *pReloadDesc, Renderer *pRenderer) { if (pReloadDesc->mType & (RELOAD_TYPE_SHADER | RELOAD_TYPE_RENDERTARGET)) { - removePipeline(pRenderer, pPLSphere); + removePipeline(pRenderer, pPipelineSphere); + removePipeline(pRenderer, pPipelineSphereShadow); + removePipeline(pRenderer, pPipelineQuad); + removePipeline(pRenderer, pPipelineQuadShadow); } if (pReloadDesc->mType & RELOAD_TYPE_SHADER) { - removeDescriptorSet(pRenderer, pDSUniform); - removeRootSignature(pRenderer, pRootSignature); - removeShader(pRenderer, pShader); + RemoveSphereResources(pRenderer); + RemoveQuadResources(pRenderer); + + removeDescriptorSet(pRenderer, pDSShadowMap); } if (pReloadDesc->mType & (RELOAD_TYPE_RESIZE | RELOAD_TYPE_RENDERTARGET)) { - removeRenderTarget(pRenderer, pDepthBuffer); + removeRenderTarget(pRenderer, pRTDepth); + removeRenderTarget(pRenderer, pRTShadowMap); } } +void DemoScene::RemoveSphereResources(Renderer *pRenderer) +{ + removeDescriptorSet(pRenderer, pDSSphereUniform); + removeRootSignature(pRenderer, pRSInstancing); + removeShader(pRenderer, pShaderInstancing); + removeShader(pRenderer, pShaderInstancingShadow); +} + +void DemoScene::RemoveQuadResources(Renderer *pRenderer) +{ + removeDescriptorSet(pRenderer, pDSQuadUniform); + removeRootSignature(pRenderer, pRSSingle); + removeShader(pRenderer, pShaderSingle); + removeShader(pRenderer, pShaderSingleShadow); +} + void DemoScene::Update(float deltaTime, uint32_t width, uint32_t height) { - pCameraController->update(deltaTime); const float aspectInverse = (float)height / (float)width; const float horizontal_fov = PI / 2.0f; + + Point3 lightPos{0, 300, 500}; + Point3 lightLookAt{0, -200, 0}; + mat4 lightView = mat4::lookAtLH(lightPos, lightLookAt, {0, 1, 0}); + lightViewProj = CameraMatrix::orthographic(-200, 200, -200, 200, 1000, 0.1) * lightView; + + sphereUniform.lightProjectView = lightViewProj; + quadUniform.lightProjectView = lightViewProj; + + pCameraController->update(deltaTime); CameraMatrix projMat = CameraMatrix::perspective(horizontal_fov, aspectInverse, 1000.0f, 0.1f); CameraMatrix mProjectView = projMat * pCameraController->getViewMatrix(); - uniform.mProjectView = mProjectView; - for (int i = 0; i < MAX_STARS; i++) + sphereUniform.projectView = mProjectView; + + for (int i = 0; i < MAX_SPHERE; i++) { - position[i].setZ(position[i].getZ() + deltaTime * 100.0f); - if (position[i].getZ() > 100) + position[i] = position[i] + (deltaTime * speed[i]); + if (fabs(position[i].getX()) > 200 || fabs(position[i].getY()) > 200 || fabs(position[i].getZ()) > 200) { - position[i].setX(randomFloat(-100, 100)); - position[i].setY(randomFloat(-100, 100)); - position[i].setZ(randomFloat(-100, 100)); + position[i].setX(randomFloat(-200, 200)); + position[i].setY(randomFloat(-200, 200)); + position[i].setZ(randomFloat(-200, 200)); color[i] = {randomFloat01(), randomFloat01(), randomFloat01(), 1.0}; + size[i] = randomFloat(1.0f, 10.0f); } - uniform.mColor[i] = color[i]; - uniform.mToWorldMat[i] = mat4(0).identity().translation(position[i]); + sphereUniform.color[i] = color[i]; + sphereUniform.world[i] = mat4::translation(position[i]) * mat4::scale({size[i], size[i], size[i]}); } - uniform.mLightColor = lightColor; - uniform.mLightPosition = lightPosition; + + quadUniform.projectView = mProjectView; + quadUniform.color = {1.0f, 1.0f, 1.0f, 1.0f}; + quadUniform.world = mat4::translation({0, -200, 0}) * mat4::rotationX(degToRad(-90)) * mat4::scale({200, 200, 200}); } void DemoScene::Draw(Cmd *pCmd, Renderer *pRenderer, RenderTarget *pRenderTarget) { + constexpr uint32_t stride = sizeof(float) * 6; + { + RenderTargetBarrier barriers[]{ + {pRTShadowMap, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE}, + }; + cmdResourceBarrier(pCmd, 0, nullptr, 0, nullptr, 1, barriers); + } + + { + BindRenderTargetsDesc bindRenderTargets = { + .mDepthStencil = {pRTShadowMap, LOAD_ACTION_CLEAR}, + }; + + cmdBindRenderTargets(pCmd, &bindRenderTargets); + } + cmdSetViewport(pCmd, 0.0f, 0.0f, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0.0f, 1.0f); + cmdSetScissor(pCmd, 0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE); + + cmdBindPipeline(pCmd, pPipelineSphereShadow); + cmdBindDescriptorSet(pCmd, 0, pDSSphereUniform); + cmdBindVertexBuffer(pCmd, 1, &pBufferSphereVertex, &stride, nullptr); + cmdDrawInstanced(pCmd, spherePoints / 6, 0, MAX_SPHERE, 0); + + cmdBindPipeline(pCmd, pPipelineQuadShadow); + cmdBindDescriptorSet(pCmd, 0, pDSQuadUniform); + cmdBindVertexBuffer(pCmd, 1, &pBufferQuadVertex, &stride, nullptr); + cmdBindIndexBuffer(pCmd, pBufferQuadIndex, INDEX_TYPE_UINT16, 0); + cmdDrawIndexed(pCmd, 6, 0, 0); + + cmdBindRenderTargets(pCmd, nullptr); + { + RenderTargetBarrier barriers[]{ + {pRTShadowMap, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE}, + }; + cmdResourceBarrier(pCmd, 0, nullptr, 0, nullptr, 1, barriers); + } + BindRenderTargetsDesc bindRenderTargets = { .mRenderTargetCount = 1, .mRenderTargets = { {pRenderTarget, LOAD_ACTION_CLEAR}, }, - .mDepthStencil = {pDepthBuffer, LOAD_ACTION_CLEAR}, + .mDepthStencil = {pRTDepth, LOAD_ACTION_CLEAR}, }; cmdBindRenderTargets(pCmd, &bindRenderTargets); cmdSetViewport(pCmd, 0.0f, 0.0f, (float)pRenderTarget->mWidth, (float)pRenderTarget->mHeight, 0.0f, 1.0f); cmdSetScissor(pCmd, 0, 0, pRenderTarget->mWidth, pRenderTarget->mHeight); - cmdBindPipeline(pCmd, pPLSphere); - cmdBindDescriptorSet(pCmd, 0, pDSUniform); - - constexpr uint32_t sphereVbStride = sizeof(float) * 6; - cmdBindVertexBuffer(pCmd, 1, &pSphereVertexBuffer, &sphereVbStride, nullptr); - - cmdDrawInstanced(pCmd, vertexCount / 6, 0, MAX_STARS, 0); + cmdBindPipeline(pCmd, pPipelineSphere); + cmdBindDescriptorSet(pCmd, 0, pDSSphereUniform); + cmdBindDescriptorSet(pCmd, 0, pDSShadowMap); + cmdBindVertexBuffer(pCmd, 1, &pBufferSphereVertex, &stride, nullptr); + cmdDrawInstanced(pCmd, spherePoints / 6, 0, MAX_SPHERE, 0); + + cmdBindPipeline(pCmd, pPipelineQuad); + cmdBindDescriptorSet(pCmd, 0, pDSQuadUniform); + cmdBindDescriptorSet(pCmd, 0, pDSShadowMap); + cmdBindVertexBuffer(pCmd, 1, &pBufferQuadVertex, &stride, nullptr); + cmdBindIndexBuffer(pCmd, pBufferQuadIndex, INDEX_TYPE_UINT16, 0); + cmdDrawIndexed(pCmd, 6, 0, 0); } void DemoScene::PreDraw() { - BufferUpdateDesc viewProjCbv = {pProjViewUniformBuffer}; - beginUpdateResource(&viewProjCbv); - *(UniformBlock *)viewProjCbv.pMappedData = uniform; - endUpdateResource(&viewProjCbv); + BufferUpdateDesc sphereUniformUpdateDesc = {pBufferSphereUniform}; + beginUpdateResource(&sphereUniformUpdateDesc); + *(SphereUniform *)sphereUniformUpdateDesc.pMappedData = sphereUniform; + endUpdateResource(&sphereUniformUpdateDesc); + + BufferUpdateDesc quadUniformUpdateDesc = {pBufferQuadUniform}; + beginUpdateResource(&quadUniformUpdateDesc); + *(QuadUniform *)quadUniformUpdateDesc.pMappedData = quadUniform; + endUpdateResource(&quadUniformUpdateDesc); } diff --git a/src/DemoScene.h b/src/DemoScene.h index a54ebb7..2573029 100644 --- a/src/DemoScene.h +++ b/src/DemoScene.h @@ -5,8 +5,8 @@ namespace DemoScene { - bool Init(); - void Exit(); + bool Init(Renderer *pRenderer); + void Exit(Renderer *pRenderer); bool Load(ReloadDesc *pReloadDesc, Renderer *pRenderer, RenderTarget *pRenderTarget); void Unload(ReloadDesc *pReloadDesc, Renderer *pRenderer); void Update(float deltaTime, uint32_t width, uint32_t height); diff --git a/src/MainApp.cpp b/src/MainApp.cpp index b072578..e33f5e4 100644 --- a/src/MainApp.cpp +++ b/src/MainApp.cpp @@ -156,7 +156,7 @@ bool MainApp::Init() GlobalInputActionDesc globalInputActionDesc = {GlobalInputActionDesc::ANY_BUTTON_ACTION, onAnyInput, this}; setGlobalInputAction(&globalInputActionDesc); - if (!Scene::Init()) + if (!Scene::Init(pRenderer)) { return false; }; @@ -166,7 +166,7 @@ bool MainApp::Init() void MainApp::Exit() { - Scene::Exit(); + Scene::Exit(pRenderer); exitInputSystem(); exitUserInterface(); exitFontSystem();