Basic shadow mapping rendering

This commit is contained in:
Dynamitos
2025-05-06 19:36:43 +02:00
parent ee412201e6
commit 3e36340b02
40 changed files with 607 additions and 275 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ void taskMain(
uint cull = p.cullingOffset + i;
MeshletDescription meshlet = pScene.meshletInfos[m];
MeshletCullingInfo culling = pScene.cullingInfos[cull];
if(culling.wasVisible())
//if(culling.wasVisible())
{
uint index;
InterlockedAdd(head, 1, index);
+8
View File
@@ -0,0 +1,8 @@
{
"slang.predefinedMacros": [
],
"slang.additionalSearchPaths": [
"res/shaders/lib",
"c:\\Program Files\\Seele\\res\\shaders\\lib"
]
}
+15 -11
View File
@@ -129,18 +129,22 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
});
Gfx::ORenderPass cubeRenderPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
.colorAttachments = {Gfx::RenderTargetAttachment(cubeMap, Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE)},
.colorAttachments =
{
Gfx::RenderTargetAttachment(cubeMap, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE),
},
},
{
Gfx::SubPassDependency{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
},
},
{Gfx::SubPassDependency{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
}},
{
.size = {SOURCE_RESOLUTION, SOURCE_RESOLUTION},
.offset = {0, 0},
-1
View File
@@ -155,7 +155,6 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
if (material->GetTexture(type, index, &texPath, &mapping, &uvIndex, &blend, &op, &mapMode) != AI_SUCCESS) {
std::cout << "fuck" << std::endl;
}
uvIndex = 1;
std::string textureKey = fmt::format("{0}Texture{1}", paramKey, index);
auto texFilename = std::filesystem::path(texPath.C_Str());
PTextureAsset texture;
+1 -1
View File
@@ -5,7 +5,7 @@ using namespace Seele;
DirectionalLightActor::DirectionalLightActor(PScene scene) : Actor(scene) { attachComponent<Component::DirectionalLight>(); }
DirectionalLightActor::DirectionalLightActor(PScene scene, Vector color, float intensity, Vector direction) : Actor(scene) {
attachComponent<Component::DirectionalLight>(Vector4(color, intensity), Vector4(direction, 0));
attachComponent<Component::DirectionalLight>(Vector4(color, intensity), Vector4(glm::normalize(direction), 0));
}
DirectionalLightActor::~DirectionalLightActor() {}
+2 -1
View File
@@ -6,7 +6,8 @@
namespace Seele {
namespace Component {
struct Camera {
Matrix4 viewMatrix;
float nearPlane = 0.001f;
float farPlane = 10000.0f;
bool mainCamera = false;
};
} // namespace Component
+5
View File
@@ -35,6 +35,11 @@ struct WindowCreateInfo {
struct ViewportCreateInfo {
URect dimensions;
float fieldOfView = glm::radians(70.0f);
// ortho params
float left = 0;
float right = 0;
float top = 0;
float bottom = 0;
};
// doesnt own the data, only proxy it
struct DataSource {
+92 -79
View File
@@ -89,7 +89,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
BasePass::~BasePass() {}
void BasePass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
RenderPass::beginFrame(cam, transform);
viewParamsSet = createViewParamsSet(cam, transform);
cameraPos = transform.getPosition();
cameraForward = transform.getForward();
@@ -136,6 +136,7 @@ void BasePass::beginFrame(const Component::Camera& cam, const Component::Transfo
}
void BasePass::render() {
graphics->beginDebugRegion("BasePass");
opaqueCulling->updateBuffer(LIGHTINDEX_NAME, 0, oLightIndexList);
opaqueCulling->updateTexture(LIGHTGRID_NAME, 0, oLightGrid);
transparentCulling->updateBuffer(LIGHTINDEX_NAME, 0, tLightIndexList);
@@ -151,110 +152,118 @@ void BasePass::render() {
permutation.setDepthCulling(true); // always use the culling info
permutation.setPositionOnly(false);
Array<VertexData::TransparentDraw> transparentData;
// Base Rendering
for (VertexData* vertexData : VertexData::getList()) {
transparentData.addAll(vertexData->getTransparentData());
permutation.setVertexData(vertexData->getTypeName());
for (const auto& materialData : vertexData->getMaterialData()) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
// Create Pipeline(Material, VertexData)
// Descriptors:
// ViewData => global, static
// VertexData => per meshtype
// SceneData => per material instance
// LightEnv => provided by scene
// Material => per material
// LightCulling => calculated by pass
permutation.setMaterial(materialData.material->getName(), materialData.material->getProfile());
Gfx::PermutationId id(permutation);
{
graphics->beginDebugRegion("Opaque");
// Base Rendering
for (VertexData* vertexData : VertexData::getList()) {
transparentData.addAll(vertexData->getTransparentData());
permutation.setVertexData(vertexData->getTypeName());
for (const auto& materialData : vertexData->getMaterialData()) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
// Create Pipeline(Material, VertexData)
// Descriptors:
// ViewData => global, static
// VertexData => per meshtype
// SceneData => per material instance
// LightEnv => provided by scene
// Material => per material
// LightCulling => calculated by pass
permutation.setMaterial(materialData.material->getName(), materialData.material->getProfile());
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender");
command->setViewport(viewport);
Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender");
command->setViewport(viewport);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
bool twoSided = materialData.material->isTwoSided();
bool twoSided = materialData.material->isTwoSided();
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState =
{
.samples = msColorAttachment.getNumSamples(),
},
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
} else {
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState =
{
.samples = msColorAttachment.getNumSamples(),
},
.rasterizationState =
{
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
},
.colorBlend =
{
.attachmentCount = 1,
},
};
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
}
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), opaqueCulling});
for (const auto& drawCall : materialData.instances) {
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)drawCall.instanceMeshData.size(), 1, 1);
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState =
{
.samples = msColorAttachment.getNumSamples(),
},
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
} else {
command->bindIndexBuffer(vertexData->getIndexBuffer());
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), 0);
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState =
{
.samples = msColorAttachment.getNumSamples(),
},
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
}
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), opaqueCulling});
for (const auto& drawCall : materialData.instances) {
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)drawCall.instanceMeshData.size(), 1, 1);
} else {
command->bindIndexBuffer(vertexData->getIndexBuffer());
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), 0);
}
}
}
commands.add(std::move(command));
}
commands.add(std::move(command));
}
graphics->endDebugRegion();
}
//commands.add(waterRenderer->render(viewParamsSet));
//commands.add(terrainRenderer->render(viewParamsSet));
// Skybox
{
graphics->beginDebugRegion("Skybox");
Gfx::ORenderCommand skyboxCommand = graphics->createRenderCommand("SkyboxRender");
skyboxCommand->setViewport(viewport);
skyboxCommand->bindPipeline(skyboxPipeline);
skyboxCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet});
skyboxCommand->draw(36, 1, 0, 0);
graphics->executeCommands(std::move(skyboxCommand));
graphics->endDebugRegion();
}
// Transparent rendering
{
graphics->beginDebugRegion("Transparent");
permutation.setDepthCulling(false); // ignore visibility infos for transparency
Map<float, VertexData::TransparentDraw> sortedDraws;
for (const auto& t : transparentData) {
@@ -352,9 +361,11 @@ void BasePass::render() {
}
}
commands.add(std::move(transparentCommand));
graphics->endDebugRegion();
}
// Debug vertices
if (gDebugVertices.size() > 0) {
graphics->beginDebugRegion("Debug");
Gfx::ORenderCommand debugCommand = graphics->createRenderCommand("DebugRender");
debugCommand->setViewport(viewport);
debugCommand->bindPipeline(debugPipeline);
@@ -362,6 +373,7 @@ void BasePass::render() {
debugCommand->bindVertexBuffer({debugVertices});
debugCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0);
commands.add(std::move(debugCommand));
graphics->endDebugRegion();
}
graphics->executeCommands(std::move(commands));
@@ -369,6 +381,7 @@ void BasePass::render() {
query->endQuery();
timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "BaseEnd");
gDebugVertices.clear();
graphics->endDebugRegion();
}
void BasePass::endFrame() {}
@@ -44,6 +44,7 @@ class BasePass : public RenderPass {
// used for transparency sorting
Vector cameraPos;
Vector cameraForward;
Gfx::PDescriptorSet viewParamsSet;
PCameraActor source;
Gfx::OPipelineLayout basePassLayout;
@@ -15,6 +15,8 @@ target_sources(Engine
RenderGraphResources.cpp
RenderPass.h
RenderPass.cpp
ShadowPass.h
ShadowPass.cpp
#TerrainRenderer.h
#TerrainRenderer.cpp
ToneMappingPass.h
@@ -38,6 +40,7 @@ target_sources(Engine
RenderGraph.h
RenderGraphResources.h
RenderPass.h
ShadowPass.h
#TerrainRenderer.h
UIPass.h
VisibilityPass.h)
@@ -1,6 +1,6 @@
#include "CachedDepthPass.h"
#include "Graphics/Shader.h"
#include "Graphics/Pipeline.h"
#include "Graphics/Shader.h"
using namespace Seele;
@@ -41,9 +41,12 @@ CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : Render
CachedDepthPass::~CachedDepthPass() {}
void CachedDepthPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { RenderPass::beginFrame(cam, transform); }
void CachedDepthPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
}
void CachedDepthPass::render() {
graphics->beginDebugRegion("CachedDepth");
query->beginQuery();
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CachedBegin");
graphics->beginRenderPass(renderPass);
@@ -78,7 +81,7 @@ void CachedDepthPass::render() {
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
@@ -95,7 +98,7 @@ void CachedDepthPass::render() {
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
@@ -125,7 +128,7 @@ void CachedDepthPass::render() {
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
}
}
}
@@ -137,6 +140,7 @@ void CachedDepthPass::render() {
graphics->endRenderPass();
timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CachedEnd");
query->endQuery();
graphics->endDebugRegion();
}
void CachedDepthPass::endFrame() {}
@@ -24,6 +24,7 @@ class CachedDepthPass : public RenderPass {
Gfx::OPipelineStatisticsQuery query;
Gfx::OTimestampQuery timestamps;
Gfx::PDescriptorSet viewParamsSet;
Gfx::PShaderBuffer cullingBuffer;
PScene scene;
};
@@ -65,157 +65,171 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
DepthCullingPass::~DepthCullingPass() {}
void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { RenderPass::beginFrame(cam, transform); }
void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
}
void DepthCullingPass::render() {
query->beginQuery();
depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
depthMipBuffer->rotateBuffer(depthMipBuffer->getNumElements() * sizeof(uint32));
Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet();
set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture());
set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer);
set->writeChanges();
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin");
// First we generate a pixel value per thread, while using a whole threadgroup
// for a single one would be a waste
Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("MipGen");
computeCommand->bindPipeline(depthSourceCopy);
computeCommand->bindDescriptor({viewParamsSet, set});
computeCommand->dispatch((viewport->getWidth() + BLOCK_SIZE - 1) / BLOCK_SIZE, (viewport->getHeight() + BLOCK_SIZE - 1) / BLOCK_SIZE,
1);
graphics->executeCommands(std::move(computeCommand));
for (uint32 i = 0; i < mipOffsets.size() - 1; ++i)
graphics->beginDebugRegion("DepthCullingPass");
{
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
MipParam param = {
.sourceOffset = mipOffsets[i],
.destOffset = mipOffsets[i + 1],
.sourceDim = mipDims[i],
.destDim = mipDims[i + 1],
};
Gfx::OComputeCommand reduceCommand = graphics->createComputeCommand("ReduceCommand");
reduceCommand->bindPipeline(depthReduceLevel);
reduceCommand->bindDescriptor({viewParamsSet, set});
reduceCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), &param);
auto dispatchDim = (mipDims[i + 1] + uint32(BLOCK_SIZE) - 1u) / uint32(BLOCK_SIZE);
reduceCommand->dispatch(dispatchDim.x, dispatchDim.y, 1);
graphics->executeCommands(std::move(reduceCommand));
}
graphics->beginDebugRegion("MipGeneration");
query->beginQuery();
depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
depthMipBuffer->rotateBuffer(depthMipBuffer->getNumElements() * sizeof(uint32));
Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet();
set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture());
set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer);
set->writeChanges();
depthAttachment.getTexture()->changeLayout(
Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CullingBegin");
graphics->beginRenderPass(renderPass);
Array<Gfx::ORenderCommand> commands;
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass");
permutation.setPositionOnly(true);
permutation.setDepthCulling(getGlobals().useDepthCulling);
for (VertexData* vertexData : VertexData::getList()) {
permutation.setVertexData(vertexData->getTypeName());
// Create Pipeline(VertexData)
// Descriptors:
// ViewData => global, static
// VertexData => per meshtype
// SceneData => per meshtype
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
command->setViewport(viewport);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
.attachmentCount = 1,
},
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin");
// First we generate a pixel value per thread, while using a whole threadgroup
// for a single one would be a waste
Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("MipGen");
computeCommand->bindPipeline(depthSourceCopy);
computeCommand->bindDescriptor({viewParamsSet, set});
computeCommand->dispatch((viewport->getWidth() + BLOCK_SIZE - 1) / BLOCK_SIZE,
(viewport->getHeight() + BLOCK_SIZE - 1) / BLOCK_SIZE, 1);
graphics->executeCommands(std::move(computeCommand));
for (uint32 i = 0; i < mipOffsets.size() - 1; ++i) {
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
MipParam param = {
.sourceOffset = mipOffsets[i],
.destOffset = mipOffsets[i + 1],
.sourceDim = mipDims[i],
.destDim = mipDims[i + 1],
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} else {
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
Gfx::OComputeCommand reduceCommand = graphics->createComputeCommand("ReduceCommand");
reduceCommand->bindPipeline(depthReduceLevel);
reduceCommand->bindDescriptor({viewParamsSet, set});
reduceCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), &param);
auto dispatchDim = (mipDims[i + 1] + uint32(BLOCK_SIZE) - 1u) / uint32(BLOCK_SIZE);
reduceCommand->dispatch(dispatchDim.x, dispatchDim.y, 1);
graphics->executeCommands(std::move(reduceCommand));
}
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set});
VertexData::DrawCallOffsets offsets = {
.instanceOffset = 0,
.textureOffset = 0,
.samplerOffset = 0,
.floatOffset = 0,
};
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets),
&offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1);
} else {
const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials) {
for (const auto& drawCall : materialData.instances) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
depthAttachment.getTexture()->changeLayout(
Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CullingBegin");
graphics->endDebugRegion();
}
{
graphics->beginDebugRegion("DepthCulling");
graphics->beginRenderPass(renderPass);
Array<Gfx::ORenderCommand> commands;
Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet();
set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture());
set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer);
set->writeChanges();
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass");
permutation.setPositionOnly(true);
permutation.setDepthCulling(getGlobals().useDepthCulling);
for (VertexData* vertexData : VertexData::getList()) {
permutation.setVertexData(vertexData->getTypeName());
// Create Pipeline(VertexData)
// Descriptors:
// ViewData => global, static
// VertexData => per meshtype
// SceneData => per meshtype
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
command->setViewport(viewport);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} else {
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set});
VertexData::DrawCallOffsets offsets = {
.instanceOffset = 0,
.textureOffset = 0,
.samplerOffset = 0,
.floatOffset = 0,
};
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0,
sizeof(VertexData::DrawCallOffsets), &offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1);
} else {
const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials) {
for (const auto& drawCall : materialData.instances) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
}
}
}
}
commands.add(std::move(command));
}
commands.add(std::move(command));
}
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CullingEnd");
query->endQuery();
// Sync depth read/write with compute read
depthAttachment.getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
// Sync visibility write with compute read
visibilityAttachment.getTexture()->pipelineBarrier(Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CullingEnd");
query->endQuery();
// Sync depth read/write with compute read
depthAttachment.getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
// Sync visibility write with compute read
visibilityAttachment.getTexture()->pipelineBarrier(Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
graphics->endDebugRegion();
}
graphics->endDebugRegion();
}
void DepthCullingPass::endFrame() {}
@@ -44,6 +44,7 @@ class DepthCullingPass : public RenderPass {
Gfx::PComputePipeline depthSourceCopy;
Gfx::OComputeShader depthReduceLevelShader;
Gfx::PComputePipeline depthReduceLevel;
Gfx::PDescriptorSet viewParamsSet;
Gfx::PShaderBuffer cullingBuffer;
PScene scene;
@@ -15,7 +15,7 @@ LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
LightCullingPass::~LightCullingPass() {}
void LightCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
RenderPass::beginFrame(cam, transform);
viewParamsSet = createViewParamsSet(cam, transform);
oLightIndexCounter->pipelineBarrier(Gfx::SE_ACCESS_MEMORY_WRITE_BIT | Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_MEMORY_WRITE_BIT,
@@ -38,6 +38,7 @@ void LightCullingPass::beginFrame(const Component::Camera& cam, const Component:
}
void LightCullingPass::render() {
graphics->beginDebugRegion("LightCulling");
query->beginQuery();
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "LightCullBegin");
oLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT,
@@ -74,6 +75,7 @@ void LightCullingPass::render() {
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
tLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
graphics->endDebugRegion();
}
void LightCullingPass::endFrame() {}
@@ -223,13 +225,14 @@ void LightCullingPass::createRenderPass() {
}
void LightCullingPass::setupFrustums() {
graphics->beginDebugRegion("SetupFrustums");
uint32_t viewportWidth = viewport->getWidth();
uint32_t viewportHeight = viewport->getHeight();
numThreads = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0));
numThreadGroups = glm::ceil(glm::vec4(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1, 0));
RenderPass::beginFrame(Component::Camera(), Component::Transform());
viewParamsSet = createViewParamsSet(Component::Camera(), Component::Transform());
dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams");
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
@@ -294,4 +297,5 @@ void LightCullingPass::setupFrustums() {
graphics->executeCommands(std::move(commands));
frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
graphics->endDebugRegion();
}
@@ -33,6 +33,7 @@ class LightCullingPass : public RenderPass {
Gfx::OComputeShader frustumShader;
Gfx::PComputePipeline frustumPipeline;
Gfx::OPipelineLayout frustumLayout;
Gfx::PDescriptorSet viewParamsSet;
PLightEnvironment lightEnv;
Gfx::PTexture2D depthAttachment;
@@ -67,7 +67,7 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa
static uint32 pass = 0;
static Component::Transform lastCam;
void RayTracingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
RenderPass::beginFrame(cam, transform);
viewParamsSet = createViewParamsSet(cam, transform);
if (lastCam.getPosition() != transform.getPosition() || lastCam.getForward() != transform.getForward()) {
lastCam = transform;
pass = 0;
@@ -75,6 +75,7 @@ void RayTracingPass::beginFrame(const Component::Camera& cam, const Component::T
}
void RayTracingPass::render() {
graphics->beginDebugRegion("RayTracingPass");
texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
Array<Gfx::RayTracingHitGroup> callableGroups;
@@ -185,6 +186,7 @@ void RayTracingPass::render() {
Array<Gfx::ORenderCommand> commands;
commands.add(std::move(command));
graphics->executeCommands(std::move(commands));
graphics->endDebugRegion();
}
void RayTracingPass::endFrame() {}
@@ -32,6 +32,7 @@ class RayTracingPass : public RenderPass {
Gfx::OAnyHitShader anyhit;
Gfx::OMissShader miss;
Gfx::PRayTracingPipeline pipeline;
Gfx::PDescriptorSet viewParamsSet;
PScene scene;
};
} // namespace Seele
+13 -9
View File
@@ -23,10 +23,17 @@ RenderPass::RenderPass(Gfx::PGraphics graphics) : graphics(graphics) {
RenderPass::~RenderPass() {}
void RenderPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
void RenderPass::setResources(PRenderGraphResources _resources) { resources = _resources; }
void RenderPass::setViewport(Gfx::PViewport _viewport) { viewport = _viewport; }
Gfx::PDescriptorSet RenderPass::createViewParamsSet(const Component::Camera& cam, const Component::Transform& transform)
{
auto screenDim = Vector2(static_cast<float>(viewport->getWidth()), static_cast<float>(viewport->getHeight()));
Matrix4 cameraMatrix = cam.viewMatrix;
Matrix4 projectionMatrix = viewport->getProjectionMatrix();
Vector eyePos = transform.getPosition();
Vector lookAt = eyePos + transform.getForward();
Matrix4 cameraMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
Matrix4 projectionMatrix = viewport->getProjectionMatrix(cam.nearPlane, cam.farPlane);
viewParams = {
.viewMatrix = cameraMatrix,
.inverseViewMatrix = glm::inverse(cameraMatrix),
@@ -60,10 +67,10 @@ void RenderPass::beginFrame(const Component::Camera& cam, const Component::Trans
corners[i] = world / world.w;
}
//extract_planes_from_view_projection_matrix(viewParams.viewProjectionMatrix, viewParams.viewFrustum);
// extract_planes_from_view_projection_matrix(viewParams.viewProjectionMatrix, viewParams.viewFrustum);
viewParamsLayout->reset();
viewParamsSet = viewParamsLayout->allocateDescriptorSet();
Gfx::PDescriptorSet viewParamsSet = viewParamsLayout->allocateDescriptorSet();
viewParamsSet->updateConstants("viewMatrix", 0, &viewParams.viewMatrix);
viewParamsSet->updateConstants("inverseViewMatrix", 0, &viewParams.inverseViewMatrix);
viewParamsSet->updateConstants("projectionMatrix", 0, &viewParams.projectionMatrix);
@@ -79,12 +86,9 @@ void RenderPass::beginFrame(const Component::Camera& cam, const Component::Trans
viewParamsSet->updateConstants("pad0", 0, &viewParams.pad0);
viewParamsSet->updateConstants("pad1", 0, &viewParams.pad1);
viewParamsSet->writeChanges();
return viewParamsSet;
}
void RenderPass::setResources(PRenderGraphResources _resources) { resources = _resources; }
void RenderPass::setViewport(Gfx::PViewport _viewport) { viewport = _viewport; }
void RenderPass::normalize_plane(Plane& plane) {
float l = sqrtf(plane.n.x * plane.n.x + plane.n.y * plane.n.y + plane.n.z * plane.n.z);
plane.n.x /= l;
+2 -2
View File
@@ -18,7 +18,7 @@ class RenderPass {
RenderPass(RenderPass&&) = default;
RenderPass& operator=(RenderPass&&) = default;
virtual ~RenderPass();
virtual void beginFrame(const Component::Camera& cam, const Component::Transform& transform);
virtual void beginFrame(const Component::Camera& cam, const Component::Transform& transform) = 0;
virtual void render() = 0;
virtual void endFrame() = 0;
virtual void publishOutputs() = 0;
@@ -27,6 +27,7 @@ class RenderPass {
void setViewport(Gfx::PViewport _viewport);
protected:
Gfx::PDescriptorSet createViewParamsSet(const Component::Camera& cam, const Component::Transform& transform);
struct Plane {
Vector n;
float d;
@@ -67,7 +68,6 @@ class RenderPass {
} viewParams;
PRenderGraphResources resources;
Gfx::ODescriptorLayout viewParamsLayout;
Gfx::PDescriptorSet viewParamsSet;
Gfx::ORenderPass renderPass;
Gfx::PGraphics graphics;
Gfx::PViewport viewport;
@@ -0,0 +1,202 @@
#include "ShadowPass.h"
#include "Graphics/Graphics.h"
#include "Graphics/Shader.h"
using namespace Seele;
ShadowPass::ShadowPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
shadowLayout = graphics->createPipelineLayout("ShadowLayout");
shadowLayout->addDescriptorLayout(viewParamsLayout);
shadowLayout->addPushConstants(Gfx::SePushConstantRange{
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(VertexData::DrawCallOffsets),
});
if (graphics->supportMeshShading()) {
graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{
.baseLayout = shadowLayout,
.taskFile = "DrawListTask",
.mainFile = "DrawListMesh",
.hasFragmentShader = false,
.useMeshShading = true,
.hasTaskShader = true,
.useMaterial = false,
.useVisibility = false,
});
} else {
graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{
.baseLayout = shadowLayout,
.taskFile = "",
.mainFile = "LegacyPass",
.hasFragmentShader = false,
.useMeshShading = false,
.hasTaskShader = false,
.useMaterial = false,
.useVisibility = false,
});
}
}
ShadowPass::~ShadowPass() {}
void ShadowPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {}
void ShadowPass::render() {
graphics->beginDebugRegion("ShadowPass");
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("ShadowPass");
permutation.setDepthCulling(true);
permutation.setPositionOnly(true);
const auto& shadowMaps = scene->getLightEnvironment()->getShadowMaps();
for (uint32 shadowIndex = 0; shadowIndex < scene->getLightEnvironment()->getNumDirectionalLights(); ++shadowIndex) {
Array<Gfx::ORenderCommand> commands;
renderPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
.depthAttachment = Gfx::RenderTargetAttachment(shadowMaps[shadowIndex], Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE),
},
{
Gfx::SubPassDependency{
.srcSubpass = ~0U,
.dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
Gfx::SubPassDependency{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
},
{
.size = {shadowMaps[shadowIndex]->getWidth(), shadowMaps[shadowIndex]->getHeight()},
.offset = {0, 0},
},
"Shadow");
graphics->beginRenderPass(renderPass);
auto light = scene->getLightEnvironment()->getDirectionalLight(shadowIndex);
Vector lightDirection = Vector(light.direction);
Vector lightPosition = -light.direction * 100.0f;
float dot = glm::dot(lightDirection, Math::Transform::FORWARD);
Quaternion rotation = Quaternion(1, 0, 0, 0);
// Handle the edge cases first
if (glm::epsilonEqual(dot, 1.0f, 0.00001f)) {
// Vectors are the same, no rotation
} else if (glm::epsilonEqual(dot, -1.0f, 0.00001f)) {
// Vectors are opposite need 180-degree rotation around any perpendicular axis
rotation = glm::angleAxis(glm::pi<float>(), Vector(0, 1, 0));
} else {
// Normal case
Vector axis = glm::normalize(glm::cross(lightDirection, Math::Transform::FORWARD));
float angle = std::acos(dot); // angle between vectors
rotation = glm::angleAxis(angle, axis);
}
Component::Transform lightTransform = Component::Transform{
.transform = Math::Transform(lightPosition, rotation),
};
Component::Camera lightCamera = Component::Camera{
.nearPlane = -1000.f,
.farPlane = 1000.0f,
};
Gfx::PDescriptorSet viewParamsSet = createViewParamsSet(lightCamera, lightTransform);
for (VertexData* vertexData : VertexData::getList()) {
permutation.setVertexData(vertexData->getTypeName());
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("ShadowRender");
command->setViewport(shadowViewport);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} else {
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()});
VertexData::DrawCallOffsets offsets = {
.instanceOffset = 0,
};
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0,
sizeof(VertexData::DrawCallOffsets), &offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1);
} else {
const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
for (const auto& drawCall : materialData.instances) {
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
}
}
}
}
commands.add(std::move(command));
}
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
}
graphics->endDebugRegion();
}
void ShadowPass::endFrame() {}
void ShadowPass::publishOutputs() {
shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{.dimensions =
{
.size = {2048, 2048},
.offset = {0, 0},
},
.fieldOfView = 0,
.left = -10,
.right = 10,
.top = -10,
.bottom = 10});
viewport = shadowViewport;
}
void ShadowPass::createRenderPass() { cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); }
@@ -0,0 +1,24 @@
#pragma once
#include "RenderPass.h"
namespace Seele {
class ShadowPass : public RenderPass {
public:
ShadowPass(Gfx::PGraphics graphics, PScene scene);
ShadowPass(ShadowPass&& other) = default;
ShadowPass& operator=(ShadowPass&& other) = default;
virtual ~ShadowPass();
virtual void beginFrame(const Component::Camera& cam, const Component::Transform& transform) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
AABB cameraFrustumBox;
Gfx::OPipelineLayout shadowLayout;
Gfx::PShaderBuffer cullingBuffer;
Gfx::OViewport shadowViewport;
PScene scene;
};
DEFINE_REF(ShadowPass)
} // namespace Seele
@@ -123,9 +123,12 @@ ToneMappingPass::ToneMappingPass(Gfx::PGraphics graphics) : RenderPass(graphics)
ToneMappingPass::~ToneMappingPass() {}
void ToneMappingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) { RenderPass::beginFrame(cam, transform); }
void ToneMappingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
}
void ToneMappingPass::render() {
graphics->beginDebugRegion("ToneMapping");
hdrInputTexture.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
@@ -181,6 +184,7 @@ void ToneMappingPass::render() {
command->draw(3, 1, 0, 0);
graphics->executeCommands(std::move(command));
graphics->endRenderPass();
graphics->endDebugRegion();
}
void ToneMappingPass::endFrame() {}
@@ -47,5 +47,7 @@ class ToneMappingPass : public RenderPass {
Gfx::OVertexShader vert;
Gfx::OFragmentShader frag;
Gfx::PGraphicsPipeline pipeline;
Gfx::PDescriptorSet viewParamsSet;
};
}
+1 -1
View File
@@ -54,7 +54,7 @@ UIPass::UIPass(Gfx::PGraphics graphics, UI::PSystem system) : RenderPass(graphic
UIPass::~UIPass() {}
void UIPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
RenderPass::beginFrame(cam, transform);
viewParamsSet = createViewParamsSet(cam, transform);
glyphs.clear();
usedTextures.clear();
elements.clear();
+2
View File
@@ -62,6 +62,8 @@ class UIPass : public RenderPass {
Gfx::ODescriptorLayout uiDescriptorLayout;
Gfx::PDescriptorSet uiDescriptorSet;
Gfx::PDescriptorSet viewParamsSet;
Gfx::OVertexShader uiVertexShader;
Gfx::OFragmentShader uiFragmentShader;
Gfx::OPipelineLayout uiPipelineLayout;
@@ -8,11 +8,12 @@ VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {
VisibilityPass::~VisibilityPass() {}
void VisibilityPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
RenderPass::beginFrame(cam, transform);
viewParamsSet = createViewParamsSet(cam, transform);
cullingBuffer->rotateBuffer(VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo), true);
}
void VisibilityPass::render() {
graphics->beginDebugRegion("VisibilityPass");
cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT,
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
cullingBuffer->clear();
@@ -40,6 +41,7 @@ void VisibilityPass::render() {
cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT | Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT);
graphics->endDebugRegion();
}
void VisibilityPass::endFrame() {}
@@ -26,6 +26,7 @@ class VisibilityPass : public RenderPass {
Gfx::PComputePipeline visibilityPipeline;
Gfx::OPipelineStatisticsQuery query;
Gfx::PTimestampQuery timestamps;
Gfx::PDescriptorSet viewParamsSet;
constexpr static const char* VISIBILITY_NAME = "visibilityTexture";
// Holds culling information for every meshlet for each instance
+4 -3
View File
@@ -6,19 +6,20 @@ using namespace Seele::Gfx;
RenderTargetAttachment::RenderTargetAttachment(PTexture2D texture, SeImageLayout initialLayout, SeImageLayout finalLayout,
SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, SeAttachmentLoadOp stencilLoadOp,
SeAttachmentStoreOp stencilStoreOp)
: clear(), componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp),
: componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout),
loadOp(loadOp),
storeOp(storeOp), stencilLoadOp(stencilLoadOp), stencilStoreOp(stencilStoreOp) {}
RenderTargetAttachment::RenderTargetAttachment(PTextureCube texture, SeImageLayout initialLayout, SeImageLayout finalLayout,
SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, SeAttachmentLoadOp stencilLoadOp,
SeAttachmentStoreOp stencilStoreOp)
: clear(), componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp),
: componentFlags(0), texture(texture), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp),
storeOp(storeOp), stencilLoadOp(stencilLoadOp), stencilStoreOp(stencilStoreOp) {}
RenderTargetAttachment::RenderTargetAttachment(PViewport viewport, SeImageLayout initialLayout, SeImageLayout finalLayout,
SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, SeAttachmentLoadOp stencilLoadOp,
SeAttachmentStoreOp stencilStoreOp)
: clear(), componentFlags(0), viewport(viewport), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp),
: componentFlags(0), viewport(viewport), initialLayout(initialLayout), finalLayout(finalLayout), loadOp(loadOp),
storeOp(storeOp), stencilLoadOp(stencilLoadOp), stencilStoreOp(stencilStoreOp) {}
RenderTargetAttachment::~RenderTargetAttachment() {}
+3 -2
View File
@@ -12,7 +12,6 @@ class Texture : public QueueOwnedResource {
virtual uint32 getWidth() const = 0;
virtual uint32 getHeight() const = 0;
virtual uint32 getDepth() const = 0;
virtual uint32 getNumFaces() const { return 1; }
virtual SeSampleCountFlags getNumSamples() const = 0;
virtual uint32 getMipLevels() const = 0;
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
@@ -36,6 +35,7 @@ class Texture2D : public Texture {
virtual uint32 getWidth() const = 0;
virtual uint32 getHeight() const = 0;
virtual uint32 getDepth() const = 0;
virtual uint32 getNumLayers() const = 0;
virtual SeSampleCountFlags getNumSamples() const = 0;
virtual uint32 getMipLevels() const = 0;
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
@@ -59,6 +59,7 @@ class Texture3D : public Texture {
virtual uint32 getWidth() const = 0;
virtual uint32 getHeight() const = 0;
virtual uint32 getDepth() const = 0;
virtual uint32 getNumLayers() const = 0;
virtual SeSampleCountFlags getNumSamples() const = 0;
virtual uint32 getMipLevels() const = 0;
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
@@ -82,7 +83,7 @@ class TextureCube : public Texture {
virtual uint32 getWidth() const = 0;
virtual uint32 getHeight() const = 0;
virtual uint32 getDepth() const = 0;
virtual uint32 getNumFaces() const { return 6; }
virtual uint32 getNumLayers() const = 0;
virtual SeSampleCountFlags getNumSamples() const = 0;
virtual uint32 getMipLevels() const = 0;
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
+3 -3
View File
@@ -9,9 +9,9 @@
using namespace Seele;
using namespace Seele::Vulkan;
RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array<Gfx::SubPassDependency> _dependencies,
std::string name, Array<uint32> viewMasks, Array<uint32> correlationMasks)
: Gfx::RenderPass(std::move(_layout), std::move(_dependencies)), graphics(graphics) {
RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array<Gfx::SubPassDependency> _dependencies, std::string name,
Array<uint32> viewMasks, Array<uint32> correlationMasks)
: Gfx::RenderPass(std::move(_layout), std::move(_dependencies)), name(name), graphics(graphics) {
subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
Array<VkAttachmentDescription2> attachments;
Array<VkAttachmentReference2> inputRefs;
+2
View File
@@ -15,8 +15,10 @@ class RenderPass : public Gfx::RenderPass {
constexpr size_t getClearValueCount() const { return clearValues.size(); }
constexpr VkClearValue* getClearValues() const { return clearValues.data(); }
constexpr VkSubpassContents getSubpassContents() const { return subpassContents; }
constexpr const std::string& getName() const { return name; }
private:
std::string name;
PGraphics graphics;
VkRenderPass renderPass;
Array<VkClearValue> clearValues;
+3
View File
@@ -83,6 +83,7 @@ class Texture2D : public Gfx::Texture2D, public TextureBase {
virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return handle->depth; }
virtual uint32 getNumLayers() const override { return handle->layerCount; }
virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return handle->mipLevels; }
@@ -106,6 +107,7 @@ class Texture3D : public Gfx::Texture3D, public TextureBase {
virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return handle->depth; }
virtual uint32 getNumLayers() const override { return handle->layerCount; }
virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return handle->mipLevels; }
@@ -129,6 +131,7 @@ class TextureCube : public Gfx::TextureCube, public TextureBase {
virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return handle->depth; }
virtual uint32 getNumLayers() const override { return handle->layerCount; }
virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return handle->mipLevels; }
+7 -9
View File
@@ -9,7 +9,9 @@ Window::~Window() {}
Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo)
: sizeX(viewportInfo.dimensions.size.x), sizeY(viewportInfo.dimensions.size.y), offsetX(viewportInfo.dimensions.offset.x),
offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), owner(owner) {
offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), orthoLeft(viewportInfo.left),
orthoRight(viewportInfo.right), orthoTop(viewportInfo.top), orthoBottom(viewportInfo.bottom),
owner(owner) {
if (owner != nullptr) {
sizeX = std::min(owner->getFramebufferWidth(), sizeX);
sizeY = std::min(owner->getFramebufferHeight(), sizeY);
@@ -18,16 +20,12 @@ Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo)
Viewport::~Viewport() {}
Matrix4 Viewport::getProjectionMatrix() const {
Matrix4 Viewport::getProjectionMatrix(float nearPlane, float farPlane) const {
if (fieldOfView > 0.0f) {
Matrix4 projectionMatrix = glm::perspective(fieldOfView, sizeX / static_cast<float>(sizeY), 0.1f, 1000.0f);
Matrix4 correctionMatrix = Matrix4(
1, 0, 0, 0,
0, -1, 0, 0,
0, 0, 1 / 2.f, 0,
0, 0, 1 / 2.f, 1);
Matrix4 projectionMatrix = glm::perspective(fieldOfView, sizeX / static_cast<float>(sizeY), nearPlane, farPlane);
Matrix4 correctionMatrix = Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 / 2.f, 0, 0, 0, 1 / 2.f, 1);
return correctionMatrix * projectionMatrix;
} else {
return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f);
return glm::ortho(orthoLeft, orthoRight, orthoTop, orthoBottom, nearPlane, farPlane);
}
}
+5 -1
View File
@@ -52,7 +52,7 @@ class Viewport {
constexpr uint32 getOffsetY() const { return offsetY; }
constexpr float getContentScaleX() const { return owner->getContentScaleX(); }
constexpr float getContentScaleY() const { return owner->getContentScaleY(); }
Matrix4 getProjectionMatrix() const;
Matrix4 getProjectionMatrix(float nearPlane, float farPlane) const;
URect getRenderArea() const {
return URect{
.size = {sizeX, sizeY},
@@ -66,6 +66,10 @@ class Viewport {
uint32 offsetX;
uint32 offsetY;
float fieldOfView;
float orthoLeft;
float orthoRight;
float orthoTop;
float orthoBottom;
PWindow owner;
};
DEFINE_REF(Viewport)
+4
View File
@@ -30,6 +30,10 @@ class Transform {
Vector getRight() const;
Vector getUp() const;
constexpr static Vector FORWARD = Vector(0, 0, 1);
constexpr static Vector RIGHT = Vector(-1, 0, 0);
constexpr static Vector UP = Vector(0, 1, 0);
bool equals(const Transform& other, float tolerance = 0.000000001f);
static void multiply(Transform* outTransform, const Transform* a, const Transform* b);
static void add(Transform* outTransform, const Transform* a, const Transform* b);
+12 -1
View File
@@ -1,7 +1,7 @@
#include "LightEnvironment.h"
#include "Asset/AssetRegistry.h"
#include "Asset/EnvironmentMapAsset.h"
#include "Graphics/Graphics.h"
#include "Asset/AssetRegistry.h"
using namespace Seele;
@@ -84,6 +84,17 @@ void LightEnvironment::commit() {
set->updateTexture("irradianceMap", 0, environment->getIrradianceMap());
set->updateSampler("irradianceSampler", 0, environmentSampler);
set->writeChanges();
while (shadowMapArray.size() < dirs.size()) {
shadowMapArray.add(graphics->createTexture2D(TextureCreateInfo{
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = 2048,
.height = 2048,
.elements = (uint32)dirs.size(),
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
.name = "ShadowMap",
}));
}
}
const Gfx::PDescriptorLayout LightEnvironment::getDescriptorLayout() const { return layout; }
+4
View File
@@ -15,11 +15,15 @@ class LightEnvironment {
void addPointLight(Component::PointLight pointLight);
void commit();
const Gfx::PDescriptorLayout getDescriptorLayout() const;
const Component::DirectionalLight& getDirectionalLight(uint32 lightIndex) const { return dirs[lightIndex]; }
Gfx::PDescriptorSet getDescriptorSet();
PEnvironmentMapAsset getEnvironmentMap() { return environment; }
uint64 getNumDirectionalLights() const { return dirs.size(); }
const Array<Gfx::OTexture2D>& getShadowMaps() const { return shadowMapArray; }
private:
Gfx::OShaderBuffer directionalLights;
Array<Gfx::OTexture2D> shadowMapArray;
Gfx::OShaderBuffer pointLights;
Array<Component::DirectionalLight> dirs;
Array<Component::PointLight> points;
-1
View File
@@ -10,5 +10,4 @@ CameraUpdater::~CameraUpdater() {}
void CameraUpdater::update(Component::Camera& camera, Component::Transform& transform) {
Vector eyePos = transform.getPosition();
Vector lookAt = eyePos + transform.getForward();
camera.viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
}
+2
View File
@@ -12,6 +12,7 @@
#include "Graphics/RenderPass/RenderGraphResources.h"
#include "Graphics/RenderPass/ToneMappingPass.h"
#include "Graphics/RenderPass/VisibilityPass.h"
#include "Graphics/RenderPass/ShadowPass.h"
#include "System/CameraUpdater.h"
#include "System/LightGather.h"
#include "System/MeshUpdater.h"
@@ -26,6 +27,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
renderGraph.addPass(new DepthCullingPass(graphics, scene));
renderGraph.addPass(new VisibilityPass(graphics));
renderGraph.addPass(new LightCullingPass(graphics, scene));
renderGraph.addPass(new ShadowPass(graphics, scene));
renderGraph.addPass(new BasePass(graphics, scene));
renderGraph.addPass(new ToneMappingPass(graphics));
renderGraph.setViewport(viewport);