ULRE/example/Vulkan/DeferredRenderMultiCmdBuffer.cpp

455 lines
12 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/VKRenderableInstance.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(GPUSemaphore *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;
GPUBuffer *ubo_lights;
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
2020-10-22 18:57:02 +08:00
Renderable *ro_plane,
*ro_cube,
*ro_sphere,
*ro_torus,
*ro_cylinder,
2021-09-28 20:26:36 +08:00
*ro_cone,
*ro_gbc_plane,
*ro_axis;
2020-10-22 18:57:02 +08:00
RenderableInstance *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);
}
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);
gbuffer.rt=device->CreateRenderTarget(&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();
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);
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
}
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)
{
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"));
texture.normal =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Normal.Tex2D"));
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(DescriptorSetsType::Value);
if(!mp)
return(false);
mp->BindSampler("TexColor" ,texture.color, texture.color_sampler);
mp->BindSampler("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(DescriptorSetsType::Value);
if(!mp)
return(false);
2019-12-02 22:14:00 +08:00
mp->BindUBO("lights",ubo_lights);
mp->BindSampler("GB_Color" ,gbuffer.rt->GetColorTexture((uint)GBufferAttachment::Color),gbuffer.sampler);
mp->BindSampler("GB_Normal" ,gbuffer.rt->GetColorTexture((uint)GBufferAttachment::Normal),gbuffer.sampler);
mp->BindSampler("GB_Depth" ,gbuffer.rt->GetDepthTexture(),gbuffer.sampler);
mp->Update();
}
2019-12-02 22:14:00 +08:00
return(true);
}
void CreateRenderObject(const VAB *vab)
2019-12-02 22:14:00 +08:00
{
{
struct PlaneCreateInfo pci;
ro_plane=CreateRenderablePlane(db,vab,&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=CreateRenderableCube(db,vab,&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=CreateRenderableSphere(db,vab,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=CreateRenderableTorus(db,vab,&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=CreateRenderableCylinder(db,vab,&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=CreateRenderableCone(db,vab,&cci);
2019-12-02 22:14:00 +08:00
}
}
bool InitCompositionRenderable()
{
ro_gbc_plane=CreateRenderableGBufferComposition(db,sp_composition.material_instance->GetVAB());
2020-10-22 18:57:02 +08:00
if(!ro_gbc_plane)return(false);
ro_gbc_plane_ri=db->CreateRenderableInstance(ro_gbc_plane,sp_composition.material_instance,sp_composition.pipeline_fan);
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->GetVAB());
render_root.CreateSubNode( scale(100,100,1), db->CreateRenderableInstance(ro_plane ,sp->material_instance,sp->pipeline_fan ));
2021-09-28 20:26:36 +08:00
render_root.CreateSubNode( db->CreateRenderableInstance(ro_torus ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode( scale(20,20,20), db->CreateRenderableInstance(ro_sphere ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode(translate(-30, 0,10)*scale(10,10,10), db->CreateRenderableInstance(ro_cube ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode(translate( 30, 30,10)*scale(1,1,2), db->CreateRenderableInstance(ro_cylinder ,sp->material_instance,sp->pipeline_triangles));
render_root.CreateSubNode(translate( 0,-30, 0)*scale(1,1,2), db->CreateRenderableInstance(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);
if(!gbuffer.cmd->BeginRenderPass())
return(false);
render_list->Render(gbuffer.cmd);
2019-12-02 22:14:00 +08:00
gbuffer.cmd->EndRenderPass();
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();
// White
2021-09-28 20:26:36 +08:00
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-01-26 11:00:47 +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);
2020-10-22 18:57:02 +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;
}