Depth Culling works??
This commit is contained in:
@@ -6,8 +6,14 @@ groupshared uint head;
|
||||
groupshared MeshData mesh;
|
||||
groupshared InstanceData instance;
|
||||
groupshared Frustum viewFrustum;
|
||||
groupshared float4x4 modelViewProjection;
|
||||
|
||||
ParameterBlock<Texture2D> pDepthAttachment;
|
||||
struct DepthData
|
||||
{
|
||||
Texture2D<float> texture;
|
||||
}
|
||||
|
||||
ParameterBlock<DepthData> pDepthAttachment;
|
||||
|
||||
[numthreads(TASK_GROUP_SIZE, 1, 1)]
|
||||
[shader("amplification")]
|
||||
@@ -15,6 +21,7 @@ void taskMain(
|
||||
uint threadID: SV_GroupThreadID,
|
||||
uint groupID: SV_GroupID, )
|
||||
{
|
||||
const uint mipLevels = uint(log2(max(pViewParams.screenDimensions.x, pViewParams.screenDimensions.y)));
|
||||
if (threadID == 0)
|
||||
{
|
||||
head = 0;
|
||||
@@ -23,6 +30,7 @@ void taskMain(
|
||||
p.instanceId = pOffsets.instanceOffset + groupID;
|
||||
p.meshletOffset = mesh.meshletOffset;
|
||||
p.cullingOffset = pScene.cullingOffsets[p.instanceId];
|
||||
modelViewProjection = mul(mul(pViewParams.projectionMatrix, pViewParams.viewMatrix), instance.transformMatrix);
|
||||
float3 origin = viewToModel(instance.inverseTransformMatrix, float4(0, 0, 0, 1)).xyz;
|
||||
const float offset = 0.0f;
|
||||
float3 corners[4] = {
|
||||
@@ -46,13 +54,60 @@ void taskMain(
|
||||
// if any triangle was visible last frame, it was drawn by the cached pass already
|
||||
if(!culling.anyVisible())
|
||||
{
|
||||
#ifdef VIEW_CULLING
|
||||
// if the meshlet is outside of the frustum, we skip it since we cant do depth culling anyways
|
||||
if(meshlet.bounding.insideFrustum(viewFrustum))
|
||||
#endif
|
||||
{
|
||||
uint index;
|
||||
InterlockedAdd(head, 1, index);
|
||||
p.culledMeshlets[index] = i;
|
||||
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
|
||||
uint2 screenCornerMin = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y));
|
||||
uint2 screenCornerMax = uint2(0, 0);
|
||||
// we use reverse depth, so higher values are closer
|
||||
float maxDepth = 0;
|
||||
{
|
||||
float4 corners[8];
|
||||
corners[0] = float4(meshlet.bounding.min.x, meshlet.bounding.min.y, meshlet.bounding.min.z, 1.0f);
|
||||
corners[1] = float4(meshlet.bounding.min.x, meshlet.bounding.min.y, meshlet.bounding.max.z, 1.0f);
|
||||
corners[2] = float4(meshlet.bounding.min.x, meshlet.bounding.max.y, meshlet.bounding.min.z, 1.0f);
|
||||
corners[3] = float4(meshlet.bounding.min.x, meshlet.bounding.max.y, meshlet.bounding.max.z, 1.0f);
|
||||
corners[4] = float4(meshlet.bounding.max.x, meshlet.bounding.min.y, meshlet.bounding.min.z, 1.0f);
|
||||
corners[5] = float4(meshlet.bounding.max.x, meshlet.bounding.min.y, meshlet.bounding.max.z, 1.0f);
|
||||
corners[6] = float4(meshlet.bounding.max.x, meshlet.bounding.max.y, meshlet.bounding.min.z, 1.0f);
|
||||
corners[7] = float4(meshlet.bounding.max.x, meshlet.bounding.max.y, meshlet.bounding.max.z, 1.0f);
|
||||
for(uint i = 0; i < 8; ++i)
|
||||
{
|
||||
float4 clipCorner = mul(modelViewProjection, corners[i]);
|
||||
float4 screenCorner = clipToScreen(clipCorner);
|
||||
screenCornerMin = uint2(min(screenCornerMin.x, uint(screenCorner.x)), min(screenCornerMin.y, uint(screenCorner.y)));
|
||||
screenCornerMax = uint2(max(screenCornerMax.x, uint(screenCorner.x)), max(screenCornerMax.y, uint(screenCorner.y)));
|
||||
maxDepth = max(maxDepth, screenCorner.z);
|
||||
}
|
||||
}
|
||||
uint mipLevel = 0;
|
||||
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
|
||||
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
|
||||
{
|
||||
mipLevel++;
|
||||
screenCornerMin /= 2;
|
||||
screenCornerMax /= 2;
|
||||
}
|
||||
|
||||
// now we sample 4 texels from the depth at the calculated mip level, this should give us the
|
||||
float d1 = pDepthAttachment.texture.Load(int3(screenCornerMin.x, screenCornerMin.y, mipLevel)).r;
|
||||
float d2 = pDepthAttachment.texture.Load(int3(screenCornerMin.x, screenCornerMax.y, mipLevel)).r;
|
||||
float d3 = pDepthAttachment.texture.Load(int3(screenCornerMax.x, screenCornerMin.y, mipLevel)).r;
|
||||
float d4 = pDepthAttachment.texture.Load(int3(screenCornerMax.x, screenCornerMax.y, mipLevel)).r;
|
||||
|
||||
// we want to check if the minimum depth (the value farthest away) is smaller than the maximum bounding box depth
|
||||
// otherwise, there is no way for the meshlet to be visible
|
||||
float d = min(min(d1, d2), min(d3, d4));
|
||||
|
||||
// this is technically not correct, as the mipmap is generated with a linear filter, but we actually would need a min filter, but whatever
|
||||
if(d < maxDepth)
|
||||
{
|
||||
uint index;
|
||||
InterlockedAdd(head, 1, index);
|
||||
p.culledMeshlets[index] = i;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ float4 screenToModel(float4x4 inverseTransform, float4 screen)
|
||||
return worldToModel(inverseTransform, world);
|
||||
}
|
||||
|
||||
float4 clipToScreen(float4 clip)
|
||||
{
|
||||
float2 texCoord = float2(clip.x, 1.0f-clip.y) / 2.0f + 0.5f;
|
||||
|
||||
return float4(texCoord * pViewParams.screenDimensions, clip.z, clip.w);
|
||||
}
|
||||
|
||||
struct Plane
|
||||
{
|
||||
float3 n;
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Window/Window.h"
|
||||
|
||||
#include "Graphics/RenderPass/BasePass.h"
|
||||
#include "Graphics/RenderPass/DepthCullingPass.h"
|
||||
#include "Graphics/RenderPass/LightCullingPass.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Editor;
|
||||
@@ -16,7 +18,7 @@ using namespace Seele::Editor;
|
||||
SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo& createInfo)
|
||||
: View(graphics, owner, createInfo, "SceneView"), scene(new Scene(graphics)), cameraSystem(createInfo.dimensions, Vector(0, 0, 10)) {
|
||||
cameraSystem.update(viewportCamera, static_cast<float>(Gfx::getCurrentFrameDelta()));
|
||||
renderGraph.addPass(new DepthPrepass(graphics, scene));
|
||||
renderGraph.addPass(new DepthCullingPass(graphics, scene));
|
||||
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||
renderGraph.addPass(new BasePass(graphics, scene));
|
||||
renderGraph.setViewport(viewport);
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
#pragma once
|
||||
#include "Graphics/RenderPass/BasePass.h"
|
||||
#include "Graphics/RenderPass/DepthPrepass.h"
|
||||
#include "Graphics/RenderPass/LightCullingPass.h"
|
||||
#include "ThreadPool.h"
|
||||
#include "ViewportControl.h"
|
||||
#include "Window/View.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "Window/PlayView.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include <fmt/core.h>
|
||||
#include <random>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Editor;
|
||||
|
||||
@@ -79,7 +79,8 @@ class Graphics {
|
||||
|
||||
virtual OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) = 0;
|
||||
|
||||
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) = 0;
|
||||
virtual void resolveTexture(PTexture source, PTexture destination) = 0;
|
||||
virtual void copyTexture(PTexture src, PTexture dst) = 0;
|
||||
|
||||
bool supportMeshShading() const { return meshShadingEnabled; }
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "RenderGraph.h"
|
||||
#include "Window/Window.h"
|
||||
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
extern bool useViewCulling;
|
||||
@@ -164,13 +163,10 @@ void BasePass::render() {
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet());
|
||||
command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet());
|
||||
command->bindDescriptor(opaqueCulling);
|
||||
for (const auto& drawCall : materialData.instances) {
|
||||
command->bindDescriptor(drawCall.materialInstance->getDescriptorSet());
|
||||
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
|
||||
scene->getLightEnvironment()->getDescriptorSet(), drawCall.materialInstance->getDescriptorSet(),
|
||||
opaqueCulling});
|
||||
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0,
|
||||
sizeof(VertexData::DrawCallOffsets), &drawCall.offsets);
|
||||
if (graphics->supportMeshShading()) {
|
||||
@@ -190,37 +186,32 @@ void BasePass::render() {
|
||||
|
||||
graphics->executeCommands(std::move(commands));
|
||||
graphics->endRenderPass();
|
||||
// Sync color write with next pass/swapchain present
|
||||
// colorAttachment.getTexture()->pipelineBarrier(
|
||||
// Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
// Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
||||
//);
|
||||
// Sync depth with next pass/next frame
|
||||
// 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_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||
//);
|
||||
}
|
||||
|
||||
void BasePass::endFrame() {}
|
||||
|
||||
void BasePass::publishOutputs() {
|
||||
TextureCreateInfo depthBufferInfo = {
|
||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||
.width = viewport->getOwner()->getFramebufferWidth(),
|
||||
.height = viewport->getOwner()->getFramebufferHeight(),
|
||||
.samples = viewport->getSamples(),
|
||||
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
};
|
||||
basePassDepth = graphics->createTexture2D(depthBufferInfo);
|
||||
|
||||
colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||
resources->registerRenderPassOutput("BASEPASS_COLOR", colorAttachment);
|
||||
depthAttachment =
|
||||
Gfx::RenderTargetAttachment(basePassDepth, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||
resources->registerRenderPassOutput("BASEPASS_DEPTH", depthAttachment);
|
||||
}
|
||||
|
||||
void BasePass::createRenderPass() {
|
||||
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
|
||||
|
||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
||||
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
|
||||
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
.colorAttachments = {colorAttachment},
|
||||
.depthAttachment = depthAttachment,
|
||||
|
||||
@@ -28,6 +28,9 @@ class BasePass : public RenderPass {
|
||||
Gfx::PDescriptorSet opaqueCulling;
|
||||
Gfx::PDescriptorSet transparentCulling;
|
||||
|
||||
// use a different texture here so we can do multisampling
|
||||
Gfx::OTexture2D basePassDepth;
|
||||
|
||||
PCameraActor source;
|
||||
Gfx::OPipelineLayout basePassLayout;
|
||||
Gfx::ODescriptorLayout lightCullingLayout;
|
||||
|
||||
@@ -6,8 +6,8 @@ target_sources(Engine
|
||||
CachedDepthPass.cpp
|
||||
DebugPass.h
|
||||
DebugPass.cpp
|
||||
DepthPrepass.h
|
||||
DepthPrepass.cpp
|
||||
DepthCullingPass.h
|
||||
DepthCullingPass.cpp
|
||||
LightCullingPass.h
|
||||
LightCullingPass.cpp
|
||||
RayTracingPass.h
|
||||
@@ -32,7 +32,7 @@ target_sources(Engine
|
||||
BasePass.h
|
||||
CachedDepthPass.h
|
||||
DebugPass.h
|
||||
DepthPrepass.h
|
||||
DepthCullingPass.h
|
||||
LightCullingPass.h
|
||||
RayTracingPass.h
|
||||
RenderGraph.h
|
||||
|
||||
@@ -113,9 +113,7 @@ void CachedDepthPass::render() {
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet());
|
||||
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()});
|
||||
uint32 offset = 0;
|
||||
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets),
|
||||
&offset);
|
||||
@@ -143,18 +141,6 @@ void CachedDepthPass::render() {
|
||||
|
||||
graphics->executeCommands(std::move(commands));
|
||||
graphics->endRenderPass();
|
||||
// Sync depth read/write with depth pass depth read
|
||||
// depthBuffer->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_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
|
||||
// sync visibility write with depth pass visibility write
|
||||
// visibilityBuffer->pipelineBarrier(
|
||||
// Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
// Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
}
|
||||
|
||||
void CachedDepthPass::endFrame() {}
|
||||
|
||||
@@ -74,7 +74,7 @@ void DebugPass::createRenderPass() {
|
||||
colorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
colorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
depthAttachment = resources->requestRenderTarget("BASEPASS_DEPTH");
|
||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
||||
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
+46
-18
@@ -1,4 +1,4 @@
|
||||
#include "DepthPrepass.h"
|
||||
#include "DepthCullingPass.h"
|
||||
#include "Graphics/Shader.h"
|
||||
|
||||
using namespace Seele;
|
||||
@@ -6,9 +6,18 @@ using namespace Seele;
|
||||
extern bool usePositionOnly;
|
||||
extern bool useViewCulling;
|
||||
|
||||
DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
||||
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
||||
depthTextureLayout = graphics->createDescriptorLayout("pDepthAttachment");
|
||||
depthTextureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_MESH_BIT_EXT,
|
||||
});
|
||||
depthTextureLayout->create();
|
||||
|
||||
depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout");
|
||||
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
|
||||
depthPrepassLayout->addDescriptorLayout(depthTextureLayout);
|
||||
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
|
||||
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = 0,
|
||||
@@ -41,11 +50,32 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene) : RenderPass(g
|
||||
}
|
||||
}
|
||||
|
||||
DepthPrepass::~DepthPrepass() {}
|
||||
DepthCullingPass::~DepthCullingPass() {}
|
||||
|
||||
void DepthPrepass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); }
|
||||
void DepthCullingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); }
|
||||
|
||||
void DepthCullingPass::render() {
|
||||
depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_TRANSFER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
depthMipTexture->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
graphics->copyTexture(depthAttachment.getTexture(), Gfx::PTexture2D(depthMipTexture));
|
||||
depthMipTexture->generateMipmaps();
|
||||
|
||||
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);
|
||||
depthMipTexture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
|
||||
|
||||
Gfx::PDescriptorSet set = depthTextureLayout->allocateDescriptorSet();
|
||||
set->updateTexture(0, Gfx::PTexture2D(depthMipTexture));
|
||||
set->writeChanges();
|
||||
|
||||
void DepthPrepass::render() {
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::ORenderCommand> commands;
|
||||
|
||||
@@ -112,9 +142,7 @@ void DepthPrepass::render() {
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet());
|
||||
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set});
|
||||
uint32 offset = 0;
|
||||
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets),
|
||||
&offset);
|
||||
@@ -146,24 +174,24 @@ void DepthPrepass::render() {
|
||||
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 depth read/write with base pass 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_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||
// Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_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);
|
||||
}
|
||||
|
||||
void DepthPrepass::endFrame() {}
|
||||
void DepthCullingPass::endFrame() {}
|
||||
|
||||
void DepthPrepass::publishOutputs() {}
|
||||
void DepthCullingPass::publishOutputs() {
|
||||
uint32 width = viewport->getOwner()->getFramebufferWidth();
|
||||
uint32 height = viewport->getOwner()->getFramebufferHeight();
|
||||
uint32 mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
|
||||
TextureCreateInfo depthMipInfo = {
|
||||
.format = Gfx::SE_FORMAT_D32_SFLOAT, .width = width, .height = height, .mipLevels = mipLevels, .name = "DepthMipTexture"};
|
||||
depthMipTexture = graphics->createTexture2D(depthMipInfo);
|
||||
}
|
||||
|
||||
void DepthPrepass::createRenderPass() {
|
||||
void DepthCullingPass::createRenderPass() {
|
||||
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
|
||||
|
||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
+8
-6
@@ -3,12 +3,12 @@
|
||||
#include "RenderPass.h"
|
||||
|
||||
namespace Seele {
|
||||
class DepthPrepass : public RenderPass {
|
||||
class DepthCullingPass : public RenderPass {
|
||||
public:
|
||||
DepthPrepass(Gfx::PGraphics graphics, PScene scene);
|
||||
DepthPrepass(DepthPrepass&&) = default;
|
||||
DepthPrepass& operator=(DepthPrepass&&) = default;
|
||||
virtual ~DepthPrepass();
|
||||
DepthCullingPass(Gfx::PGraphics graphics, PScene scene);
|
||||
DepthCullingPass(DepthCullingPass&&) = default;
|
||||
DepthCullingPass& operator=(DepthCullingPass&&) = default;
|
||||
virtual ~DepthCullingPass();
|
||||
virtual void beginFrame(const Component::Camera& cam) override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
@@ -16,11 +16,13 @@ class DepthPrepass : public RenderPass {
|
||||
virtual void createRenderPass() override;
|
||||
|
||||
private:
|
||||
Gfx::OTexture2D depthMipTexture;
|
||||
Gfx::RenderTargetAttachment depthAttachment;
|
||||
Gfx::RenderTargetAttachment visibilityAttachment;
|
||||
Gfx::ODescriptorLayout depthTextureLayout;
|
||||
Gfx::OPipelineLayout depthPrepassLayout;
|
||||
|
||||
Gfx::PShaderBuffer cullingBuffer;
|
||||
};
|
||||
DEFINE_REF(DepthPrepass)
|
||||
DEFINE_REF(DepthCullingPass)
|
||||
} // namespace Seele
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "Resources.h"
|
||||
#include "Graphics.h"
|
||||
#include "Material/Material.h"
|
||||
#include "RenderPass/BasePass.h"
|
||||
#include "RenderPass/DepthPrepass.h"
|
||||
#include "Resources.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "Shader.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/RenderPass/BasePass.h"
|
||||
#include "Graphics/RenderPass/DepthPrepass.h"
|
||||
#include "Material/Material.h"
|
||||
#include "ThreadPool.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class Texture : public QueueOwnedResource {
|
||||
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
|
||||
SePipelineStageFlags dstStage) = 0;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) = 0;
|
||||
|
||||
virtual void generateMipmaps() = 0;
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
@@ -40,6 +40,7 @@ class Texture2D : public Texture {
|
||||
virtual uint32 getMipLevels() const = 0;
|
||||
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
|
||||
SePipelineStageFlags dstStage) = 0;
|
||||
virtual void generateMipmaps() = 0;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
@@ -62,6 +63,7 @@ class Texture3D : public Texture {
|
||||
virtual uint32 getMipLevels() const = 0;
|
||||
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
|
||||
SePipelineStageFlags dstStage) = 0;
|
||||
virtual void generateMipmaps() = 0;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
@@ -85,6 +87,7 @@ class TextureCube : public Texture {
|
||||
virtual uint32 getMipLevels() const = 0;
|
||||
virtual void changeLayout(SeImageLayout newLayout, SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
|
||||
SePipelineStageFlags dstStage) = 0;
|
||||
virtual void generateMipmaps() = 0;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
|
||||
@@ -248,6 +248,7 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint
|
||||
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> dynamicOffsets) {
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
|
||||
std::memset(sets, 0, sizeof(VkDescriptorSet) * descriptorSets.size());
|
||||
for (uint32 i = 0; i < descriptorSets.size(); ++i) {
|
||||
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
|
||||
assert(descriptorSet->writeDescriptors.size() == 0);
|
||||
|
||||
@@ -236,6 +236,26 @@ void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) {
|
||||
destinationTex->getImage(), cast(destinationTex->getLayout()), 1, &resolve);
|
||||
}
|
||||
|
||||
void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) {
|
||||
PTextureBase src = source.cast<TextureBase>();
|
||||
PTextureBase dst = destination.cast<TextureBase>();
|
||||
VkImageBlit blit = {.srcSubresource = {.aspectMask = src->getAspect(), .mipLevel = 0, .baseArrayLayer = 0, .layerCount = 1},
|
||||
.srcOffsets =
|
||||
{
|
||||
{0, 0, 0},
|
||||
{(int32)src->getWidth(), (int32)src->getHeight(), (int32)src->getDepth()},
|
||||
},
|
||||
.dstSubresource = {.aspectMask = dst->aspect, .mipLevel = 0, .baseArrayLayer = 0, .layerCount = 1},
|
||||
.dstOffsets = {
|
||||
{0, 0, 0},
|
||||
{(int32)dst->getWidth(), (int32)dst->getHeight(), (int32)dst->getDepth()},
|
||||
}};
|
||||
PCommand command = getGraphicsCommands()->getCommands();
|
||||
vkCmdBlitImage(command->getHandle(), src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst->getImage(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
|
||||
src->aspect & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) {
|
||||
return new BottomLevelAS(this, createInfo);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ class Graphics : public Gfx::Graphics {
|
||||
virtual Gfx::OVertexInput createVertexInput(VertexInputStateCreateInfo createInfo) override;
|
||||
|
||||
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
|
||||
virtual void copyTexture(Gfx::PTexture src, Gfx::PTexture dst) override;
|
||||
|
||||
// Ray Tracing
|
||||
virtual Gfx::OBottomLevelAS createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) override;
|
||||
|
||||
@@ -146,6 +146,7 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc));
|
||||
generateMipmaps();
|
||||
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
@@ -270,6 +271,69 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
|
||||
graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc));
|
||||
}
|
||||
|
||||
void TextureBase::generateMipmaps() {
|
||||
PCommandPool commandPool = graphics->getQueueCommands(currentOwner);
|
||||
VkImageMemoryBarrier barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = handle->image,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = aspect,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
int32 mipWidth = width;
|
||||
int32 mipHeight = height;
|
||||
for (uint32 i = 1; i < mipLevels; ++i) {
|
||||
barrier.subresourceRange.baseMipLevel = i - 1;
|
||||
|
||||
vkCmdPipelineBarrier(commandPool->getCommands()->getHandle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
|
||||
nullptr, 0, nullptr, 1, &barrier);
|
||||
|
||||
VkImageBlit blit = {
|
||||
.srcSubresource =
|
||||
{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = i - 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.srcOffsets =
|
||||
{
|
||||
{0, 0, 0},
|
||||
{mipWidth, mipHeight, 1},
|
||||
},
|
||||
.dstSubresource = {.aspectMask = aspect, .mipLevel = i, .baseArrayLayer = 0, .layerCount = 1},
|
||||
.dstOffsets =
|
||||
{
|
||||
{0, 0, 0},
|
||||
{mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1},
|
||||
},
|
||||
};
|
||||
vkCmdBlitImage(commandPool->getCommands()->getHandle(), handle->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, handle->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, aspect & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
||||
|
||||
if (mipWidth > 1)
|
||||
mipWidth /= 2;
|
||||
if (mipHeight)
|
||||
mipHeight /= 2;
|
||||
}
|
||||
barrier.subresourceRange.baseMipLevel = mipLevels - 1;
|
||||
|
||||
// just so that all levels are in the same layout and we can transition them as one
|
||||
vkCmdPipelineBarrier(commandPool->getCommands()->getHandle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
|
||||
nullptr, 0, nullptr, 1, &barrier);
|
||||
layout = Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
}
|
||||
|
||||
void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) {
|
||||
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||
VkImageMemoryBarrier imageBarrier = {
|
||||
@@ -343,7 +407,7 @@ void TextureBase::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag
|
||||
{
|
||||
.aspectMask = aspect,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.levelCount = mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
@@ -369,6 +433,8 @@ void Texture2D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<
|
||||
TextureBase::download(mipLevel, arrayLayer, face, buffer);
|
||||
}
|
||||
|
||||
void Texture2D::generateMipmaps() { TextureBase::generateMipmaps(); }
|
||||
|
||||
void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::executeOwnershipBarrier(newOwner); }
|
||||
|
||||
void Texture2D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
|
||||
@@ -390,6 +456,9 @@ void Texture3D::changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags sr
|
||||
void Texture3D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) {
|
||||
TextureBase::download(mipLevel, arrayLayer, face, buffer);
|
||||
}
|
||||
|
||||
void Texture3D::generateMipmaps() { TextureBase::generateMipmaps(); }
|
||||
|
||||
void Texture3D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::executeOwnershipBarrier(newOwner); }
|
||||
|
||||
void Texture3D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
|
||||
@@ -412,6 +481,9 @@ void TextureCube::changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags
|
||||
void TextureCube::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) {
|
||||
TextureBase::download(mipLevel, arrayLayer, face, buffer);
|
||||
}
|
||||
|
||||
void TextureCube::generateMipmaps() { TextureBase::generateMipmaps(); }
|
||||
|
||||
void TextureCube::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::executeOwnershipBarrier(newOwner); }
|
||||
|
||||
void TextureCube::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
|
||||
|
||||
@@ -41,6 +41,7 @@ class TextureBase {
|
||||
void changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
|
||||
VkPipelineStageFlags dstStage);
|
||||
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
|
||||
void generateMipmaps();
|
||||
|
||||
protected:
|
||||
OTextureHandle handle;
|
||||
@@ -75,6 +76,7 @@ class Texture2D : public Gfx::Texture2D, public TextureBase {
|
||||
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
@@ -97,6 +99,7 @@ class Texture3D : public Gfx::Texture3D, public TextureBase {
|
||||
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
@@ -119,6 +122,7 @@ class TextureCube : public Gfx::TextureCube, public TextureBase {
|
||||
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
|
||||
virtual void generateMipmaps() override;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Component/KeyboardInput.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/RenderPass/BasePass.h"
|
||||
#include "Graphics/RenderPass/CachedDepthPass.h"
|
||||
#include "Graphics/RenderPass/DebugPass.h"
|
||||
#include "Graphics/RenderPass/DepthPrepass.h"
|
||||
#include "Graphics/RenderPass/LightCullingPass.h"
|
||||
#include "Graphics/RenderPass/SkyboxRenderPass.h"
|
||||
#include "Graphics/RenderPass/DepthCullingPass.h"
|
||||
#include "Graphics/RenderPass/VisibilityPass.h"
|
||||
#include "Graphics/RenderPass/LightCullingPass.h"
|
||||
#include "Graphics/RenderPass/BasePass.h"
|
||||
#include "Graphics/RenderPass/SkyboxRenderPass.h"
|
||||
#include "Graphics/RenderPass/DebugPass.h"
|
||||
#include "System/CameraUpdater.h"
|
||||
#include "System/LightGather.h"
|
||||
#include "System/MeshUpdater.h"
|
||||
@@ -26,7 +26,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
||||
: View(graphics, window, createInfo, "Game"), scene(new Scene(graphics)), gameInterface(dllPath) {
|
||||
reloadGame();
|
||||
renderGraph.addPass(new CachedDepthPass(graphics, scene));
|
||||
renderGraph.addPass(new DepthPrepass(graphics, scene));
|
||||
renderGraph.addPass(new DepthCullingPass(graphics, scene));
|
||||
renderGraph.addPass(new VisibilityPass(graphics, scene));
|
||||
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||
renderGraph.addPass(new BasePass(graphics, scene));
|
||||
|
||||
Reference in New Issue
Block a user