diff --git a/example/Vulkan/texture_rect_array.cpp b/example/Vulkan/texture_rect_array.cpp index 771754dd..dbf4fbf1 100644 --- a/example/Vulkan/texture_rect_array.cpp +++ b/example/Vulkan/texture_rect_array.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace hgl; using namespace hgl::graph; @@ -16,15 +17,15 @@ VK_NAMESPACE_BEGIN //Texture2D *CreateTexture2DFromFile(GPUDevice *device,const OSString &filename); VK_NAMESPACE_END -constexpr uint32_t SCREEN_WIDTH=512; +constexpr uint32_t SCREEN_WIDTH=256; constexpr uint32_t SCREEN_HEIGHT=256; -constexpr float position_data[4]= +float position_data[4]= { - 0, //left - 0, //top - 0.5, //right - 1 //bottom + 0, //left + 0, //top + 1, //right + 1 //bottom }; constexpr float tex_coord_data[4]= @@ -33,100 +34,154 @@ constexpr float tex_coord_data[4]= 1,1 }; +constexpr const os_char *tex_filename[]= +{ + OS_TEXT("001-online resume.Tex2D"), + OS_TEXT("002-salary.Tex2D"), + OS_TEXT("003-application.Tex2D"), + OS_TEXT("004-job interview.Tex2D") +}; + +constexpr const size_t TexCount=sizeof(tex_filename)/sizeof(os_char *); + class TestApp:public VulkanApplicationFramework { private: + SceneNode render_root; + RenderList * render_list =nullptr; + Texture2DArray * texture =nullptr; Sampler * sampler =nullptr; - MaterialInstance * material_instance =nullptr; - Renderable * render_obj =nullptr; - Pipeline * pipeline =nullptr; + Material * material =nullptr; + Pipeline * pipeline =nullptr; DeviceBuffer * tex_id_ubo =nullptr; + struct + { + MaterialInstance * mi; + Renderable * r; + }render_obj[TexCount]{}; + private: + bool InitTexture() + { + texture=db->CreateTexture2DArray( 512,512, ///<纹理尺寸 + TexCount, ///<纹理层数 + PF_BC1_RGBAUN, ///<纹理格式 + false); ///<是否自动产生mipmaps + + if(!texture)return(false); + + OSString filename; + + for(uint i=0;iLoadTexture2DToArray(texture,i,filename)) + return(false); + } + + return(true); + } + bool InitMaterial() { mtl::Material2DCreateConfig cfg(device->GetDeviceAttribute(),"RectTexture2DArray"); cfg.coordinate_system=CoordinateSystem2D::ZeroToOne; - cfg.local_to_world=false; + cfg.local_to_world=true; AutoDelete mci=mtl::CreateRectTexture2DArray(&cfg); - material_instance=db->CreateMaterialInstance(mci); + material=db->CreateMaterial(mci); - if(!material_instance) + if(!material) return(false); -// pipeline=db->CreatePipeline(material_instance,sc_render_target,OS_TEXT("res/pipeline/solid2d")); - pipeline=CreatePipeline(material_instance,InlinePipeline::Solid2D,Prim::SolidRectangles); //等同上一行,为Framework重载,默认使用swapchain的render target + pipeline=CreatePipeline(material,InlinePipeline::Solid2D,Prim::SolidRectangles); //等同上一行,为Framework重载,默认使用swapchain的render target if(!pipeline) return(false); - texture=this->device->CreateTexture2DArray( 512,512, ///<纹理尺寸 - 2, ///<纹理层数 - PF_BC1_RGBAUN, ///<纹理格式 - false); ///<是否自动产生mipmaps - - if(!texture)return(false); - - db->LoadTexture2DToArray(texture,0,OS_TEXT("res/image/icon/freepik/001-online resume.Tex2D")); - db->LoadTexture2DToArray(texture,1,OS_TEXT("res/image/icon/freepik/002-salary.Tex2D")); - sampler=db->CreateSampler(); - if(!material_instance->BindImageSampler(DescriptorSetType::PerMaterial, ///<描述符合集 - mtl::SamplerName::Color, ///<采样器名称 - texture, ///<纹理 - sampler)) ///<采样器 + if(!material->BindImageSampler( DescriptorSetType::PerMaterial, ///<描述符合集 + mtl::SamplerName::Color, ///<采样器名称 + texture, ///<纹理 + sampler)) ///<采样器 return(false); + for(uint32_t i=0;iCreateMaterialInstance(material); + + if(!render_obj[i].mi) + return(false); + + render_obj[i].mi->WriteMIData(i); //设置MaterialInstance的数据 + } + return(true); } - bool InitUBO() - { - tex_id_ubo=db->CreateUBO(sizeof(uint32_t)); - - uint id=0; - - tex_id_ubo->Write(&id,sizeof(uint32_t)); - - return material_instance->BindUBO(DescriptorSetType::Global,"TexID",tex_id_ubo); - } - - bool InitVBO() + bool InitVBOAndRenderList() { RenderablePrimitiveCreater rpc(db,1); + position_data[2]=1.0f/float(TexCount); + if(!rpc.SetVBO(VAN::Position,VF_V4F,position_data))return(false); if(!rpc.SetVBO(VAN::TexCoord,VF_V4F,tex_coord_data))return(false); - render_obj=rpc.Create(material_instance,pipeline); - return(render_obj); + Vector3f offset(1.0f/float(TexCount),0,0); + + for(uint32_t i=0;iExpend(&render_root); + + return(true); } public: + ~TestApp() + { + SAFE_CLEAR(render_list); + } + bool Init() { - if(!VulkanApplicationFramework::Init(SCREEN_WIDTH,SCREEN_HEIGHT)) + if(!VulkanApplicationFramework::Init(SCREEN_WIDTH*TexCount,SCREEN_HEIGHT)) return(false); - + + render_list=new RenderList(device); + + if(!InitTexture()) + return(false); + if(!InitMaterial()) return(false); - if(!InitUBO()) + if(!InitVBOAndRenderList()) return(false); - if(!InitVBO()) - return(false); - - BuildCommandBuffer(render_obj); + BuildCommandBuffer(render_list); return(true); } @@ -135,7 +190,7 @@ public: { VulkanApplicationFramework::Resize(w,h); - BuildCommandBuffer(render_obj); + BuildCommandBuffer(render_list); } };//class TestApp:public VulkanApplicationFramework diff --git a/example/common/VulkanAppFramework.h b/example/common/VulkanAppFramework.h index e409eca4..1f04a591 100644 --- a/example/common/VulkanAppFramework.h +++ b/example/common/VulkanAppFramework.h @@ -510,9 +510,9 @@ public: return ubo_camera_info; } - bool BindCameraUBO(MaterialInstance *mi) + bool BindCameraUBO(Material *mtl) { - return mi->BindUBO(DescriptorSetType::Global,"g_camera",ubo_camera_info); + return mtl->BindUBO(DescriptorSetType::Global,"g_camera",ubo_camera_info); } virtual void BuildCommandBuffer(uint32_t index)=0; diff --git a/inc/hgl/graph/VKMaterial.h b/inc/hgl/graph/VKMaterial.h index b873e84d..78401aa5 100644 --- a/inc/hgl/graph/VKMaterial.h +++ b/inc/hgl/graph/VKMaterial.h @@ -75,6 +75,12 @@ public: bool Release(VIL *); const uint GetVILCount(); +public: + + bool BindUBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic=false); + bool BindSSBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic=false); + bool BindImageSampler(const DescriptorSetType &type,const AnsiString &name,Texture *tex,Sampler *sampler); + public: const bool HasMI ()const{return mi_data_bytes>0;} diff --git a/inc/hgl/graph/VKMaterialInstance.h b/inc/hgl/graph/VKMaterialInstance.h index 40d8b511..2d06dc0c 100644 --- a/inc/hgl/graph/VKMaterialInstance.h +++ b/inc/hgl/graph/VKMaterialInstance.h @@ -77,10 +77,6 @@ public: template void WriteMIData (const T &data){WriteMIData(&data,sizeof(T));} ///<写入材质实例数据 - - bool BindUBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic=false); - bool BindSSBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic=false); - bool BindImageSampler(const DescriptorSetType &type,const AnsiString &name,Texture *tex,Sampler *sampler); };//class MaterialInstance VK_NAMESPACE_END #endif//HGL_GRAPH_VULKAN_MATERIAL_INSTANCE_INCLUDE diff --git a/inc/hgl/graph/VKRenderResource.h b/inc/hgl/graph/VKRenderResource.h index e13c9327..af6a0318 100644 --- a/inc/hgl/graph/VKRenderResource.h +++ b/inc/hgl/graph/VKRenderResource.h @@ -117,6 +117,7 @@ public: //texture Texture2D * LoadTexture2D(const OSString &,bool auto_mipmaps=false); TextureCube * LoadTextureCube(const OSString &,bool auto_mipmaps=false); + Texture2DArray * CreateTexture2DArray(const uint32_t width,const uint32_t height,const uint32_t layer,const VkFormat &fmt,bool auto_mipmaps=false); bool LoadTexture2DToArray(Texture2DArray *,const uint32_t layer,const OSString &); public: //Get diff --git a/src/SceneGraph/RenderAssignBuffer.cpp b/src/SceneGraph/RenderAssignBuffer.cpp index dfb9c2b2..7f04643b 100644 --- a/src/SceneGraph/RenderAssignBuffer.cpp +++ b/src/SceneGraph/RenderAssignBuffer.cpp @@ -33,8 +33,10 @@ void RenderAssignBuffer::Bind(MaterialInstance *mi)const if(assign_binding_count<=0)return; - mi->BindUBO(DescriptorSetType::PerFrame,mtl::SBS_LocalToWorld.name,ubo_l2w); - mi->BindUBO(DescriptorSetType::MaterialInstance,mtl::SBS_MaterialInstance.name,ubo_mi); + Material *mtl=mi->GetMaterial(); + + mtl->BindUBO(DescriptorSetType::PerFrame,mtl::SBS_LocalToWorld.name,ubo_l2w); + mtl->BindUBO(DescriptorSetType::MaterialInstance,mtl::SBS_MaterialInstance.name,ubo_mi); } void RenderAssignBuffer::Clear() diff --git a/src/SceneGraph/Vulkan/VKMaterial.cpp b/src/SceneGraph/Vulkan/VKMaterial.cpp index 7f63642f..2a4e87cb 100644 --- a/src/SceneGraph/Vulkan/VKMaterial.cpp +++ b/src/SceneGraph/Vulkan/VKMaterial.cpp @@ -66,4 +66,43 @@ const uint Material::GetVILCount() { return vertex_input->GetInstanceCount(); } + +bool Material::BindUBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic) +{ + MaterialParameters *mp=GetMP(type); + + if(!mp) + return(false); + + if(!mp->BindUBO(name,ubo,dynamic))return(false); + + mp->Update(); + return(true); +} + +bool Material::BindSSBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic) +{ + MaterialParameters *mp=GetMP(type); + + if(!mp) + return(false); + + if(!mp->BindSSBO(name,ubo,dynamic))return(false); + + mp->Update(); + return(true); +} + +bool Material::BindImageSampler(const DescriptorSetType &type,const AnsiString &name,Texture *tex,Sampler *sampler) +{ + MaterialParameters *mp=GetMP(type); + + if(!mp) + return(false); + + if(!mp->BindImageSampler(name,tex,sampler))return(false); + + mp->Update(); + return(true); +} VK_NAMESPACE_END diff --git a/src/SceneGraph/Vulkan/VKMaterialInstance.cpp b/src/SceneGraph/Vulkan/VKMaterialInstance.cpp index a9dd08ae..d79f4cef 100644 --- a/src/SceneGraph/Vulkan/VKMaterialInstance.cpp +++ b/src/SceneGraph/Vulkan/VKMaterialInstance.cpp @@ -54,43 +54,4 @@ MaterialInstance::MaterialInstance(Material *mtl,VIL *v,const int id) mi_id=id; } - -bool MaterialInstance::BindUBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic) -{ - MaterialParameters *mp=material->GetMP(type); - - if(!mp) - return(false); - - if(!mp->BindUBO(name,ubo,dynamic))return(false); - - mp->Update(); - return(true); -} - -bool MaterialInstance::BindSSBO(const DescriptorSetType &type,const AnsiString &name,DeviceBuffer *ubo,bool dynamic) -{ - MaterialParameters *mp=material->GetMP(type); - - if(!mp) - return(false); - - if(!mp->BindSSBO(name,ubo,dynamic))return(false); - - mp->Update(); - return(true); -} - -bool MaterialInstance::BindImageSampler(const DescriptorSetType &type,const AnsiString &name,Texture *tex,Sampler *sampler) -{ - MaterialParameters *mp=material->GetMP(type); - - if(!mp) - return(false); - - if(!mp->BindImageSampler(name,tex,sampler))return(false); - - mp->Update(); - return(true); -} VK_NAMESPACE_END diff --git a/src/SceneGraph/Vulkan/VKRenderResource.cpp b/src/SceneGraph/Vulkan/VKRenderResource.cpp index c7f64ecb..366ed8f9 100644 --- a/src/SceneGraph/Vulkan/VKRenderResource.cpp +++ b/src/SceneGraph/Vulkan/VKRenderResource.cpp @@ -147,6 +147,16 @@ Texture2D *RenderResource::LoadTexture2D(const OSString &filename,bool auto_mipm return tex; } +Texture2DArray *RenderResource::CreateTexture2DArray(const uint32_t width,const uint32_t height,const uint32_t layer,const VkFormat &fmt,bool auto_mipmaps) +{ + Texture2DArray *ta=device->CreateTexture2DArray(width,height,layer,fmt,auto_mipmaps); + + if(ta) + Add(ta); + + return ta; +} + bool LoadTexture2DLayerFromFile(GPUDevice *device,Texture2DArray *t2d,const uint32_t layer,const OSString &filename,bool auto_mipmaps); bool RenderResource::LoadTexture2DToArray(Texture2DArray *ta,const uint32_t layer,const OSString &filename) diff --git a/src/ShaderGen/2d/M_RectTexture2DArray.cpp b/src/ShaderGen/2d/M_RectTexture2DArray.cpp index f5743dbd..1bc6def7 100644 --- a/src/ShaderGen/2d/M_RectTexture2DArray.cpp +++ b/src/ShaderGen/2d/M_RectTexture2DArray.cpp @@ -7,9 +7,13 @@ STD_MTL_NAMESPACE_BEGIN namespace { + constexpr const char mi_codes[]="uvec4 id;"; //材质实例代码 + constexpr const uint32_t mi_bytes=sizeof(Vector4u); //材质实例数据大小 + constexpr const char vs_main[]=R"( void main() { + HandoverMI(); Output.TexCoord=TexCoord; gl_Position=GetPosition2D(); @@ -26,26 +30,20 @@ void main() vec2 tlt=Input[0].TexCoord.xy; vec2 trb=Input[0].TexCoord.zw; - gl_Position=vec4(vlt, vec2(0,1));Output.TexCoord=tlt; EmitVertex(); - gl_Position=vec4(vlt.x, vrb.y, vec2(0,1));Output.TexCoord=vec2(tlt.x,trb.y); EmitVertex(); - gl_Position=vec4(vrb.x, vlt.y, vec2(0,1));Output.TexCoord=vec2(trb.x,tlt.y); EmitVertex(); - gl_Position=vec4(vrb, vec2(0,1));Output.TexCoord=trb; EmitVertex(); + HandoverMI();gl_Position=vec4(vlt, vec2(0,1));Output.TexCoord=tlt; EmitVertex(); + HandoverMI();gl_Position=vec4(vlt.x, vrb.y, vec2(0,1));Output.TexCoord=vec2(tlt.x,trb.y); EmitVertex(); + HandoverMI();gl_Position=vec4(vrb.x, vlt.y, vec2(0,1));Output.TexCoord=vec2(trb.x,tlt.y); EmitVertex(); + HandoverMI();gl_Position=vec4(vrb, vec2(0,1));Output.TexCoord=trb; EmitVertex(); EndPrimitive(); })"; - constexpr const ShaderBufferSource SBS_TextureID= - { - "TextureID", - "TexID", - - "uint id;" - }; - constexpr const char fs_main[]=R"( void main() { - Color=texture(TextureColor,vec3(Input.TexCoord,TexID.id)); + MaterialInstance mi=GetMI(); + + Color=texture(TextureColor,vec3(Input.TexCoord,mi.id.x)); })"; class MaterialRectTexture2D:public Std2DMaterial @@ -57,19 +55,26 @@ void main() bool CustomVertexShader(ShaderCreateInfoVertex *vsc) override { + RANGE_CHECK_RETURN_FALSE(cfg->coordinate_system) + + vsc->AddInput(VAT_VEC4,VAN::Position); + + if(cfg->local_to_world) { - RANGE_CHECK_RETURN_FALSE(cfg->coordinate_system) + mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS); - vsc->AddInput(VAT_VEC4,VAN::Position); + vsc->AddAssign(); + vsc->AddFunction(func::GetPosition2DRectL2W[size_t(cfg->coordinate_system)]); + } + else vsc->AddFunction(func::GetPosition2DRect[size_t(cfg->coordinate_system)]); - if(cfg->coordinate_system==CoordinateSystem2D::Ortho) - { - mci->AddUBO(VK_SHADER_STAGE_VERTEX_BIT, - DescriptorSetType::Global, - SBS_ViewportInfo); - } + if(cfg->coordinate_system==CoordinateSystem2D::Ortho) + { + mci->AddUBO(VK_SHADER_STAGE_VERTEX_BIT, + DescriptorSetType::Global, + SBS_ViewportInfo); } vsc->AddInput(VAT_VEC4,VAN::TexCoord); @@ -92,10 +97,6 @@ void main() bool CustomFragmentShader(ShaderCreateInfoFragment *fsc) override { - mci->AddUBO(VK_SHADER_STAGE_FRAGMENT_BIT, - DescriptorSetType::Global, - SBS_TextureID); - mci->AddSampler(VK_SHADER_STAGE_FRAGMENT_BIT,DescriptorSetType::PerMaterial,SamplerType::Sampler2DArray,mtl::SamplerName::Color); fsc->AddOutput(VAT_VEC4,"Color"); //Fragment shader的输出等于最终的RT了,所以这个名称其实随便起。 @@ -103,6 +104,16 @@ void main() fsc->SetMain(fs_main); return(true); } + + bool EndCustomShader() override + { + mci->SetMaterialInstance( mi_codes, //材质实例glsl代码 + mi_bytes, //材质实例数据大小 + VK_SHADER_STAGE_FRAGMENT_BIT); //只在Fragment Shader中使用材质实例最终数据 + + return(true); + } + };//class MaterialRectTexture2D:public Std2DMaterial }//namespace diff --git a/src/ShaderGen/MaterialCreateInfo.cpp b/src/ShaderGen/MaterialCreateInfo.cpp index 09cb80ae..a67561dd 100644 --- a/src/ShaderGen/MaterialCreateInfo.cpp +++ b/src/ShaderGen/MaterialCreateInfo.cpp @@ -242,6 +242,9 @@ bool MaterialCreateInfo::CreateShader() if(sc->GetShaderStage()==VK_SHADER_STAGE_VERTEX_BIT) sc->AddFunction(mtl::func::HandoverMI_VS); + else + if(sc->GetShaderStage()==VK_SHADER_STAGE_GEOMETRY_BIT) + sc->AddFunction(mtl::func::HandoverMI_GS); else sc->AddFunction(mtl::func::HandoverMI); } diff --git a/src/ShaderGen/common/MFCommon.h b/src/ShaderGen/common/MFCommon.h index 5026ff02..66f1a8c3 100644 --- a/src/ShaderGen/common/MFCommon.h +++ b/src/ShaderGen/common/MFCommon.h @@ -21,10 +21,17 @@ void HandoverMI() } )"; +constexpr const char HandoverMI_GS[]=R"( +void HandoverMI() +{ + Output.MaterialInstanceID=Input[0].MaterialInstanceID; +} +)"; + constexpr const char HandoverMI[]=R"( void HandoverMI() { - Output.MaterialInstanceID=Assign.y; + Output.MaterialInstanceID=Input.MaterialInstanceID; } )"; diff --git a/src/ShaderGen/common/MFRectPrimitive.h b/src/ShaderGen/common/MFRectPrimitive.h index db04a9a6..faa850c7 100644 --- a/src/ShaderGen/common/MFRectPrimitive.h +++ b/src/ShaderGen/common/MFRectPrimitive.h @@ -29,6 +29,39 @@ vec4 GetPosition2D() return vec4(lt.xy,rb.xy); } +)" + }; + + constexpr const char *GetPosition2DRectL2W[size_t(CoordinateSystem2D::RANGE_SIZE)]= + { + R"( +vec4 GetPosition2D() +{ + vec4 lt=GetLocalToWorld()*vec4(Position.xy,0,1); + vec4 rb=GetLocalToWorld()*vec4(Position.zw,0,1); + + return vec4(lt.xy,rb.xy); +} +)", + +R"( +vec4 GetPosition2D() +{ + vec4 lt=GetLocalToWorld()*vec4(Position.xy,0,1); + vec4 rb=GetLocalToWorld()*vec4(Position.zw,0,1); + + return vec4(lt.xy,rb.xy)*2-1; +} +)", + +R"( +vec4 GetPosition2D() +{ + vec4 lt=viewport.ortho_matrix*GetLocalToWorld()*vec4(Position.xy,0,1); + vec4 rb=viewport.ortho_matrix*GetLocalToWorld()*vec4(Position.zw,0,1); + + return vec4(lt.xy,rb.xy); +} )" }; }//namespace func