ULRE/example/Vulkan/DeferredRender.cpp

530 lines
15 KiB
C++
Raw Normal View History

2021-11-22 16:36:29 +08:00
// 简单传统延迟渲染使用多个RenderPass多个CommandBuffer
2019-12-02 22:14:00 +08:00
#include"VulkanAppFramework.h"
#include<hgl/filesystem/FileSystem.h>
#include<hgl/graph/InlineGeometry.h>
2020-10-21 12:39:22 +08:00
#include<hgl/graph/VKRenderResource.h>
#include<hgl/graph/VKRenderable.h>
2019-12-02 22:14:00 +08:00
#include<hgl/graph/RenderList.h>
#include<hgl/graph/VKTexture.h>
#include<hgl/graph/VKImageView.h>
#include<hgl/graph/VKSampler.h>
#include<hgl/graph/VKFramebuffer.h>
2020-10-22 18:57:02 +08:00
#include<hgl/Time.h>
2019-12-02 22:14:00 +08:00
using namespace hgl;
using namespace hgl::graph;
VK_NAMESPACE_BEGIN
Texture2D *CreateTexture2DFromFile(GPUDevice *device,const OSString &filename);
2019-12-02 22:14:00 +08:00
VK_NAMESPACE_END
2020-10-22 18:57:02 +08:00
constexpr uint32_t SCREEN_WIDTH=1280;
constexpr uint32_t SCREEN_HEIGHT=SCREEN_WIDTH/16*9;
2019-12-02 22:14:00 +08:00
2020-10-21 12:47:06 +08:00
using Texture2DPointer=Texture2D *;
2019-12-02 22:14:00 +08:00
2020-10-22 18:57:02 +08:00
enum class GBufferAttachment
{
Color=0,
2020-10-22 18:57:02 +08:00
Normal,
ENUM_CLASS_RANGE(Color,Normal)
2020-10-22 18:57:02 +08:00
};//
2021-09-28 20:26:36 +08:00
constexpr VkFormat gbuffer_color_format[size_t(GBufferAttachment::RANGE_SIZE)]={UPF_RGB565,UPF_RG8};
2021-06-24 19:25:43 +08:00
constexpr VkFormat gbuffer_depth_format=PF_D16UN;
2020-10-22 18:57:02 +08:00
struct alignas(16) PhongPointLight
{
Vector4f color;
2020-10-22 18:57:02 +08:00
Vector4f position;
float radius;
};//
2019-12-02 22:14:00 +08:00
class TestApp:public CameraAppFramework
{
private:
SceneNode render_root;
RenderList *render_list=nullptr;
2019-12-02 22:14:00 +08:00
struct
{
2020-10-28 17:28:07 +08:00
RenderTarget *rt=nullptr;
2021-09-22 18:36:54 +08:00
RenderPass *rp=nullptr;
RenderCmdBuffer *cmd=nullptr;
Sampler *sampler=nullptr;
public:
bool Submit(Semaphore *sem)
{
return rt->Submit(cmd,sem);
}
}gbuffer;
2019-12-02 22:14:00 +08:00
2020-10-22 18:57:02 +08:00
PhongPointLight lights;
DeviceBuffer *ubo_lights;
2020-10-22 18:57:02 +08:00
2019-12-02 22:14:00 +08:00
struct SubpassParam
{
2020-10-21 12:47:06 +08:00
Material * material;
MaterialInstance * material_instance;
2020-10-21 12:47:06 +08:00
Pipeline * pipeline_fan;
Pipeline * pipeline_triangles;
2019-12-02 22:14:00 +08:00
};//
2020-10-22 18:57:02 +08:00
SubpassParam sp_gbuffer;
SubpassParam sp_composition;
2019-12-02 22:14:00 +08:00
2022-10-14 19:27:29 +08:00
Primitive *ro_plane,
2020-10-22 18:57:02 +08:00
*ro_cube,
*ro_sphere,
*ro_torus,
*ro_cylinder,
2021-09-28 20:26:36 +08:00
*ro_cone,
*ro_gbc_plane,
*ro_axis;
Renderable *ro_gbc_plane_ri;
2019-12-02 22:14:00 +08:00
struct
{
2020-10-22 18:57:02 +08:00
Texture2DPointer color=nullptr;
Texture2DPointer normal=nullptr;
Sampler * color_sampler=nullptr;
Sampler * normal_sampler=nullptr;
2019-12-02 22:14:00 +08:00
}texture;
2020-10-22 19:37:28 +08:00
public:
~TestApp()
{
SAFE_CLEAR(render_list);
2020-10-28 17:28:07 +08:00
SAFE_CLEAR(gbuffer.cmd);
SAFE_CLEAR(gbuffer.rt);
2020-10-22 19:37:28 +08:00
}
2020-10-19 22:26:42 +08:00
private:
2019-12-02 22:14:00 +08:00
void CreateGBufferSampler()
{
VkSamplerCreateInfo sci=
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
nullptr,
0,
VK_FILTER_LINEAR,
VK_FILTER_LINEAR,
VK_SAMPLER_MIPMAP_MODE_NEAREST,
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
0.0f,
false,
1.0f,
false,
VK_COMPARE_OP_NEVER,
0.0f,
0.0f,
VK_BORDER_COLOR_INT_OPAQUE_BLACK,
false
};
gbuffer.sampler=db->CreateSampler(&sci);
2022-09-29 18:29:21 +08:00
#ifdef _DEBUG
{
auto da=device->GetDeviceAttribute();
if(da->debug_maker)
{
da->debug_maker->SetSampler(*(gbuffer.sampler), "[debug maker] GBuffer_Sampler");
}
if(da->debug_utils)
{
da->debug_utils->SetSampler(*(gbuffer.sampler), "[debug utils] GBuffer_Sampler");
}
}
#endif//_DEBUG
}
2019-12-02 22:14:00 +08:00
bool InitGBuffer()
{
FramebufferInfo fbi(gbuffer_color_format,size_t(GBufferAttachment::RANGE_SIZE),gbuffer_depth_format);
fbi.SetExtent(SCREEN_WIDTH,SCREEN_HEIGHT);
2023-03-18 17:58:57 +08:00
gbuffer.rt=device->CreateRT(&fbi);
2019-12-02 22:14:00 +08:00
if(!gbuffer.rt)return(false);
2019-12-02 22:14:00 +08:00
gbuffer.cmd=device->CreateRenderCommandBuffer();
2021-09-22 18:36:54 +08:00
gbuffer.rp=gbuffer.rt->GetRenderPass();
CreateGBufferSampler();
2022-09-27 19:41:28 +08:00
#ifdef _DEBUG
{
auto da=device->GetDeviceAttribute();
VkQueue q=*(gbuffer.rt->GetQueue());
VkFramebuffer fbo= gbuffer.rt->GetFramebuffer()->GetFramebuffer();
VkRenderPass rp= gbuffer.rp->GetVkRenderPass();
VkSemaphore sem=*(gbuffer.rt->GetRenderCompleteSemaphore());
VkCommandBuffer cb=*(gbuffer.cmd);
VkSampler s=*(gbuffer.sampler);
if(da->debug_maker)
{
da->debug_maker->SetQueue( q, "[debug maker] GBufferQueue");
da->debug_maker->SetFramebuffer( fbo,"[debug maker] GBufferFBO");
da->debug_maker->SetRenderPass( rp, "[debug maker] GBufferRenderpass");
da->debug_maker->SetCommandBuffer( cb, "[debug maker] GBufferCommandBuffer");
da->debug_maker->SetSampler( s, "[debug maker] GBufferSampler");
da->debug_maker->SetSemaphore( sem,"[debug maker] GBufferSemaphore");
}
if(da->debug_utils)
{
da->debug_utils->SetQueue( q, "[debug utils] GBufferQueue");
da->debug_utils->SetFramebuffer( fbo,"[debug utils] GBufferFBO");
da->debug_utils->SetRenderPass( rp, "[debug utils] GBufferRenderpass");
da->debug_utils->SetCommandBuffer( cb, "[debug utils] GBufferCommandBuffer");
da->debug_utils->SetSampler( s, "[debug utils] GBufferSampler");
da->debug_utils->SetSemaphore( sem,"[debug utils] GBufferSemaphore");
}
}
#endif//_DEBUG
return(gbuffer.rt);
2019-12-02 22:14:00 +08:00
}
bool InitMaterial(SubpassParam *sp,const OSString &material_filename)
2019-12-02 22:14:00 +08:00
{
2020-10-22 18:57:02 +08:00
sp->material=db->CreateMaterial(material_filename);
2019-12-02 22:14:00 +08:00
if(!sp->material)
return(false);
sp->material_instance=db->CreateMaterialInstance(sp->material);
2019-12-02 22:14:00 +08:00
return(true);
}
bool InitGBufferPipeline(SubpassParam *sp)
{
sp->pipeline_triangles =gbuffer.rp->CreatePipeline(sp->material_instance,InlinePipeline::Solid3D,Prim::Triangles);
2020-10-19 22:26:42 +08:00
if(!sp->pipeline_triangles)
return(false);
2019-12-02 22:14:00 +08:00
sp->pipeline_fan =gbuffer.rp->CreatePipeline(sp->material_instance,InlinePipeline::Solid3D,Prim::Fan);
2022-09-29 18:29:21 +08:00
if(!sp->pipeline_fan)
return(false);
2019-12-02 22:14:00 +08:00
2022-09-29 18:29:21 +08:00
#ifdef _DEBUG
{
auto da=device->GetDeviceAttribute();
if(da->debug_maker)
{
da->debug_maker->SetPipeline(*(sp->pipeline_triangles), "[debug maker] GBuffer_Pipeline_Triangles");
da->debug_maker->SetPipeline(*(sp->pipeline_fan), "[debug maker] GBuffer_Pipeline_Fan");
}
if(da->debug_utils)
{
da->debug_utils->SetPipeline(*(sp->pipeline_triangles), "[debug utils] GBuffer_Pipeline_Triangles");
da->debug_utils->SetPipeline(*(sp->pipeline_fan), "[debug utils] GBuffer_Pipeline_Fan");
}
}
#endif//_DEBUG
return(true);
2019-12-02 22:14:00 +08:00
}
bool InitCompositionPipeline(SubpassParam *sp)
{
sp->pipeline_fan=device_render_pass->CreatePipeline(sp->material_instance,InlinePipeline::Solid2D,Prim::Fan);
2019-12-02 22:14:00 +08:00
2020-10-19 22:26:42 +08:00
return sp->pipeline_fan;
2019-12-02 22:14:00 +08:00
}
2020-10-22 18:57:02 +08:00
bool InitLightsUBO()
{
ubo_lights=db->CreateUBO(sizeof(lights),&lights);
return ubo_lights;
}
Sampler *CreateSampler(Texture *tex)
2022-10-28 17:57:09 +08:00
{
VkSamplerCreateInfo sci=
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
nullptr,
0,
VK_FILTER_LINEAR,
VK_FILTER_LINEAR,
VK_SAMPLER_MIPMAP_MODE_LINEAR,
VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_SAMPLER_ADDRESS_MODE_REPEAT,
0.0f,
false,
1.0f,
false,
VK_COMPARE_OP_NEVER,
0.0f,
0.0f,
VK_BORDER_COLOR_INT_OPAQUE_BLACK,
false
};
sci.maxLod=tex->GetMipLevel();
return db->CreateSampler(&sci);
}
2019-12-02 22:14:00 +08:00
bool InitMaterial()
{
2020-10-22 18:57:02 +08:00
if(!InitLightsUBO())return(false);
if(!InitMaterial(&sp_gbuffer, OS_TEXT("res/material/opaque")))return(false);
if(!InitMaterial(&sp_composition,OS_TEXT("res/material/composition")))return(false);
2019-12-02 22:14:00 +08:00
if(!InitGBufferPipeline(&sp_gbuffer))return(false);
if(!InitCompositionPipeline(&sp_composition))return(false);
2020-10-22 18:57:02 +08:00
texture.color =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Albedo.Tex2D"));
2022-03-31 23:36:34 +08:00
if(!texture.color)return(false);
2020-10-22 18:57:02 +08:00
texture.normal =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Normal.Tex2D"));
2022-03-31 23:36:34 +08:00
if(!texture.normal)return(false);
texture.color_sampler=CreateSampler(texture.color);
texture.normal_sampler=CreateSampler(texture.normal);
2022-01-10 20:31:04 +08:00
BindCameraUBO(sp_gbuffer.material_instance);
{
MaterialParameters *mp=sp_gbuffer.material_instance->GetMP(DescriptorSetType::Value);
if(!mp)
return(false);
2023-02-23 13:25:05 +08:00
mp->BindImageSampler("TexColor" ,texture.color, texture.color_sampler);
mp->BindImageSampler("TexNormal" ,texture.normal, texture.normal_sampler);
mp->Update();
}
2022-01-10 20:31:04 +08:00
BindCameraUBO(sp_composition.material_instance);
{
MaterialParameters *mp=sp_composition.material_instance->GetMP(DescriptorSetType::Value);
if(!mp)
return(false);
2019-12-02 22:14:00 +08:00
mp->BindUBO("lights",ubo_lights);
2023-02-23 13:25:05 +08:00
mp->BindImageSampler("GB_Color" ,gbuffer.rt->GetColorTexture((uint)GBufferAttachment::Color),gbuffer.sampler);
mp->BindImageSampler("GB_Normal" ,gbuffer.rt->GetColorTexture((uint)GBufferAttachment::Normal),gbuffer.sampler);
mp->BindImageSampler("GB_Depth" ,gbuffer.rt->GetDepthTexture(),gbuffer.sampler);
mp->Update();
}
2019-12-02 22:14:00 +08:00
return(true);
}
void CreateRenderObject(const VIL *vil)
2019-12-02 22:14:00 +08:00
{
using namespace inline_geometry;
2019-12-02 22:14:00 +08:00
{
struct PlaneCreateInfo pci;
ro_plane=CreatePlane(db,vil,&pci);
2019-12-02 22:14:00 +08:00
}
2020-11-09 19:00:58 +08:00
2019-12-02 22:14:00 +08:00
{
struct CubeCreateInfo cci;
ro_cube=CreateCube(db,vil,&cci);
2019-12-02 22:14:00 +08:00
}
2020-11-09 19:00:58 +08:00
2019-12-02 22:14:00 +08:00
{
ro_sphere=CreateSphere(db,vil,64);
2019-12-02 22:14:00 +08:00
}
{
TorusCreateInfo tci;
tci.innerRadius=50;
tci.outerRadius=70;
2020-10-22 18:57:02 +08:00
tci.numberSlices=128;
tci.numberStacks=64;
2019-12-02 22:14:00 +08:00
tci.uv_scale.x=4;
tci.uv_scale.y=1;
ro_torus=CreateTorus(db,vil,&tci);
2019-12-02 22:14:00 +08:00
}
{
CylinderCreateInfo cci;
cci.halfExtend=10;
cci.radius=10;
2020-10-22 18:57:02 +08:00
cci.numberSlices=32;
2019-12-02 22:14:00 +08:00
ro_cylinder=CreateCylinder(db,vil,&cci);
2019-12-02 22:14:00 +08:00
}
{
ConeCreateInfo cci;
cci.halfExtend=10;
cci.radius=10;
2020-10-22 18:57:02 +08:00
cci.numberSlices=128;
cci.numberStacks=32;
2019-12-02 22:14:00 +08:00
ro_cone=CreateCone(db,vil,&cci);
2019-12-02 22:14:00 +08:00
}
}
bool InitCompositionRenderable()
{
ro_gbc_plane=inline_geometry::CreateGBufferCompositionRectangle(db,sp_composition.material_instance->GetVIL());
2020-10-22 18:57:02 +08:00
if(!ro_gbc_plane)return(false);
ro_gbc_plane_ri=db->CreateRenderable(ro_gbc_plane,sp_composition.material_instance,sp_composition.pipeline_fan);
2020-10-22 18:57:02 +08:00
if(!ro_gbc_plane_ri)return(false);
2019-12-02 22:14:00 +08:00
2020-10-22 18:57:02 +08:00
return(true);
2019-12-02 22:14:00 +08:00
}
2019-12-02 22:14:00 +08:00
bool InitScene(SubpassParam *sp)
{
CreateRenderObject(sp->material_instance->GetVIL());
render_root.CreateSubNode( scale(100,100,1), db->CreateRenderable(ro_plane ,sp->material_instance,sp->pipeline_fan ));
render_root.CreateSubNode( db->CreateRenderable(ro_torus ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode( scale(20,20,20), db->CreateRenderable(ro_sphere ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode(translate(-30, 0,10)*scale(10,10,10), db->CreateRenderable(ro_cube ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode(translate( 30, 30,10)*scale(1,1,2), db->CreateRenderable(ro_cylinder ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode(translate( 0,-30, 0)*scale(1,1,2), db->CreateRenderable(ro_cone ,sp->material_instance,sp->pipeline_triangles));
2019-12-02 22:14:00 +08:00
render_root.RefreshMatrix();
render_list->Expend(GetCameraInfo(),&render_root);
2019-12-02 22:14:00 +08:00
return(true);
}
bool InitGBufferCommandBuffer()
{
if(!gbuffer.cmd)
2019-12-02 22:14:00 +08:00
return(false);
gbuffer.cmd->Begin();
if(!gbuffer.cmd->BindFramebuffer(gbuffer.rt->GetRenderPass(),gbuffer.rt->GetFramebuffer()))
2019-12-02 22:14:00 +08:00
return(false);
2022-09-27 19:41:28 +08:00
gbuffer.cmd->BeginRegion("GBuffer Begin",Color4f(1,0,0,1));
if(!gbuffer.cmd->BeginRenderPass())
return(false);
render_list->Render(gbuffer.cmd);
2019-12-02 22:14:00 +08:00
gbuffer.cmd->EndRenderPass();
2022-09-26 16:11:42 +08:00
gbuffer.cmd->EndRegion();
gbuffer.cmd->End();
2019-12-02 22:14:00 +08:00
return(true);
}
public:
bool Init()
{
if(!CameraAppFramework::Init(SCREEN_WIDTH,SCREEN_HEIGHT))
return(false);
render_list=new RenderList(device);
2019-12-02 22:14:00 +08:00
if(!InitGBuffer())
return(false);
if(!InitMaterial())
return(false);
if(!InitScene(&sp_gbuffer))
return(false);
if(!InitGBufferCommandBuffer())
return(false);
if(!InitCompositionRenderable())
return(false);
return(true);
}
2020-10-22 18:57:02 +08:00
void UpdateLights()
{
const double timer=GetDoubleTime();
2022-09-27 19:41:28 +08:00
// White
lights.position = Vector4f(0.0f, 0.0f, 25.0f, 0.0f);
lights.color = Vector4f(15.0f);
lights.radius = 155.0f;
2020-10-22 18:57:02 +08:00
2022-09-27 19:41:28 +08:00
lights.position.x = sin(rad2deg(timer/100)) * 100.0f;
lights.position.y = cos(rad2deg(timer/100)) * 100.0f;
2020-10-22 18:57:02 +08:00
ubo_lights->Write(&lights);
}
2019-12-02 22:14:00 +08:00
virtual void SubmitDraw(int index) override
{
gbuffer.Submit(sc_render_target->GetPresentCompleteSemaphore());
2019-12-02 22:14:00 +08:00
VkCommandBuffer cb=*cmd_buf[index];
sc_render_target->Submit(cb,gbuffer.rt->GetRenderCompleteSemaphore());
2020-10-22 18:57:02 +08:00
sc_render_target->PresentBackbuffer();
sc_render_target->WaitQueue();
sc_render_target->WaitFence();
gbuffer.rt->WaitQueue();
gbuffer.rt->WaitFence();
2019-12-02 22:14:00 +08:00
}
void BuildCommandBuffer(uint32_t index) override
{
2020-10-22 18:57:02 +08:00
VulkanApplicationFramework::BuildCommandBuffer(index,ro_gbc_plane_ri);
}
void Draw()override
{
UpdateLights();
render_root.RefreshMatrix();
render_list->Expend(GetCameraInfo(),&render_root);
2022-09-26 16:11:42 +08:00
CameraAppFramework::Draw();
2019-12-02 22:14:00 +08:00
}
};//class TestApp:public CameraAppFramework
int main(int,char **)
{
TestApp app;
if(!app.Init())
return(-1);
while(app.Run());
return 0;
}