diff --git a/example/Vulkan/texture_rect_array.cpp b/example/Vulkan/texture_rect_array.cpp new file mode 100644 index 00000000..771754dd --- /dev/null +++ b/example/Vulkan/texture_rect_array.cpp @@ -0,0 +1,157 @@ +// texture rect +// 画一个带纹理的矩形,2D模式专用 + +#include"VulkanAppFramework.h" +#include +#include +#include +#include +#include +#include + +using namespace hgl; +using namespace hgl::graph; + +VK_NAMESPACE_BEGIN +//Texture2D *CreateTexture2DFromFile(GPUDevice *device,const OSString &filename); +VK_NAMESPACE_END + +constexpr uint32_t SCREEN_WIDTH=512; +constexpr uint32_t SCREEN_HEIGHT=256; + +constexpr float position_data[4]= +{ + 0, //left + 0, //top + 0.5, //right + 1 //bottom +}; + +constexpr float tex_coord_data[4]= +{ + 0,0, + 1,1 +}; + +class TestApp:public VulkanApplicationFramework +{ +private: + + Texture2DArray * texture =nullptr; + Sampler * sampler =nullptr; + MaterialInstance * material_instance =nullptr; + Renderable * render_obj =nullptr; + Pipeline * pipeline =nullptr; + + DeviceBuffer * tex_id_ubo =nullptr; + +private: + + bool InitMaterial() + { + mtl::Material2DCreateConfig cfg(device->GetDeviceAttribute(),"RectTexture2DArray"); + + cfg.coordinate_system=CoordinateSystem2D::ZeroToOne; + cfg.local_to_world=false; + + AutoDelete mci=mtl::CreateRectTexture2DArray(&cfg); + + material_instance=db->CreateMaterialInstance(mci); + + if(!material_instance) + 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 + + 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)) ///<采样器 + return(false); + + 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() + { + RenderablePrimitiveCreater rpc(db,1); + + 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); + } + +public: + + bool Init() + { + if(!VulkanApplicationFramework::Init(SCREEN_WIDTH,SCREEN_HEIGHT)) + return(false); + + if(!InitMaterial()) + return(false); + + if(!InitUBO()) + return(false); + + if(!InitVBO()) + return(false); + + BuildCommandBuffer(render_obj); + + return(true); + } + + void Resize(int w,int h)override + { + VulkanApplicationFramework::Resize(w,h); + + BuildCommandBuffer(render_obj); + } +};//class TestApp:public VulkanApplicationFramework + +int main(int,char **) +{ +#ifdef _DEBUG + if(!CheckStrideBytesByFormat()) + return 0xff; +#endif// + + TestApp app; + + if(!app.Init()) + return(-1); + + while(app.Run()); + + return 0; +} diff --git a/inc/hgl/graph/VKRenderResource.h b/inc/hgl/graph/VKRenderResource.h index ebacdb14..e13c9327 100644 --- a/inc/hgl/graph/VKRenderResource.h +++ b/inc/hgl/graph/VKRenderResource.h @@ -117,6 +117,8 @@ public: //texture Texture2D * LoadTexture2D(const OSString &,bool auto_mipmaps=false); TextureCube * LoadTextureCube(const OSString &,bool auto_mipmaps=false); + bool LoadTexture2DToArray(Texture2DArray *,const uint32_t layer,const OSString &); + public: //Get Material * GetMaterial (const MaterialID &id){return rm_material.Get(id);} diff --git a/inc/hgl/graph/mtl/2d/Material2DCreateConfig.h b/inc/hgl/graph/mtl/2d/Material2DCreateConfig.h index 8f9c5e3c..0a34a0eb 100644 --- a/inc/hgl/graph/mtl/2d/Material2DCreateConfig.h +++ b/inc/hgl/graph/mtl/2d/Material2DCreateConfig.h @@ -33,5 +33,6 @@ MaterialCreateInfo *CreateVertexColor2D(const Material2DCreateConfig *); MaterialCreateInfo *CreatePureColor2D(const Material2DCreateConfig *); MaterialCreateInfo *CreatePureTexture2D(const Material2DCreateConfig *); MaterialCreateInfo *CreateRectTexture2D(Material2DCreateConfig *); +MaterialCreateInfo *CreateRectTexture2DArray(Material2DCreateConfig *); STD_MTL_NAMESPACE_END #endif//HGL_GRAPH_MTL_2D_CREATE_CONFIG_INCLUDE diff --git a/src/SceneGraph/Vulkan/Texture/BufferImageCopy2D.h b/src/SceneGraph/Vulkan/Texture/BufferImageCopy2D.h index 529c0139..db8e4271 100644 --- a/src/SceneGraph/Vulkan/Texture/BufferImageCopy2D.h +++ b/src/SceneGraph/Vulkan/Texture/BufferImageCopy2D.h @@ -37,9 +37,11 @@ public: } template - BufferImageCopy(const Texture2DArray *tex,const RectScope2 &rs):BufferImageCopy() + BufferImageCopy(const Texture2DArray *tex,const RectScope2 &rs,const uint32_t bl,const uint32_t lc):BufferImageCopy() { - imageSubresource.aspectMask=tex->GetAspect(); + imageSubresource.aspectMask =tex->GetAspect(); + imageSubresource.baseArrayLayer =bl; + imageSubresource.layerCount =lc; SetRectScope(rs); } diff --git a/src/SceneGraph/Vulkan/Texture/VKDeviceTexture2DArray.cpp b/src/SceneGraph/Vulkan/Texture/VKDeviceTexture2DArray.cpp index 2e1fcff5..8bde8b2d 100644 --- a/src/SceneGraph/Vulkan/Texture/VKDeviceTexture2DArray.cpp +++ b/src/SceneGraph/Vulkan/Texture/VKDeviceTexture2DArray.cpp @@ -215,7 +215,7 @@ bool GPUDevice::ChangeTexture2DArray(Texture2DArray *tex,DeviceBuffer *buf,const ||scope.GetBottom()>tex->GetHeight()) return(false); - BufferImageCopy buffer_image_copy(tex,scope); + BufferImageCopy buffer_image_copy(tex,scope,base_layer,layer_count); texture_cmd_buf->Begin(); bool result=CopyBufferToImage(tex,buf,&buffer_image_copy,1,base_layer,layer_count,destinationStage); diff --git a/src/SceneGraph/Vulkan/Texture/VKTexture2DArrayLoader.cpp b/src/SceneGraph/Vulkan/Texture/VKTexture2DArrayLoader.cpp index 695f2aeb..6e118806 100644 --- a/src/SceneGraph/Vulkan/Texture/VKTexture2DArrayLoader.cpp +++ b/src/SceneGraph/Vulkan/Texture/VKTexture2DArrayLoader.cpp @@ -3,25 +3,36 @@ #include VK_NAMESPACE_BEGIN -template<> void VkTextureLoader::OnExtent(VkExtent3D &extent) -{ - extent.width =file_header.width; - extent.height =file_header.height; - extent.depth =file_header.layers; -} +//template<> void VkTextureLoader::OnExtent(VkExtent3D &extent) +//{ +// extent.width =file_header.width; +// extent.height =file_header.height; +// extent.depth =file_header.layers; +//} +// +//template<> Texture2DArray *VkTextureLoader::OnCreateTexture(TextureCreateInfo *tci) +//{ +// return device->CreateTexture2DArray(tci); +//} -template<> Texture2DArray *VkTextureLoader::OnCreateTexture(TextureCreateInfo *tci) +bool LoadTexture2DLayerFromFile(GPUDevice *device,Texture2DArray *ta,const uint32_t layer,const OSString &filename,bool auto_mipmaps) { - return device->CreateTexture2DArray(tci); -} - -Texture2DArray *CreateTexture2DArrayFromFile(GPUDevice *device,const OSString &filename,bool auto_mipmaps) -{ - VkTextureLoader loader(device,auto_mipmaps); + //注:依然是Texture2D,则非Texture2DArray。因为这里LOAD的是2D纹理,并不是2DArray纹理 + VkTextureLoader loader(device,auto_mipmaps); if(!loader.Load(filename)) return(nullptr); - return loader.CreateTexture(); + DeviceBuffer *buf=loader.GetBuffer(); + + if(!buf) + return(false); + + RectScope2ui scope; + + scope.Width=ta->GetWidth(); + scope.Height=ta->GetHeight(); + + return device->ChangeTexture2DArray(ta,buf,scope,layer,1); } VK_NAMESPACE_END diff --git a/src/SceneGraph/Vulkan/Texture/VKTextureLoader.h b/src/SceneGraph/Vulkan/Texture/VKTextureLoader.h index e4d55841..05393777 100644 --- a/src/SceneGraph/Vulkan/Texture/VKTextureLoader.h +++ b/src/SceneGraph/Vulkan/Texture/VKTextureLoader.h @@ -59,6 +59,8 @@ public: return(true); } + DeviceBuffer *GetBuffer(){return buf;} + T *CreateTexture() { TextureCreateInfo *tci=new TextureCreateInfo(format); diff --git a/src/SceneGraph/Vulkan/VKRenderResource.cpp b/src/SceneGraph/Vulkan/VKRenderResource.cpp index 0fc528fe..c7f64ecb 100644 --- a/src/SceneGraph/Vulkan/VKRenderResource.cpp +++ b/src/SceneGraph/Vulkan/VKRenderResource.cpp @@ -118,7 +118,6 @@ Sampler *RenderResource::CreateSampler(Texture *tex) } Texture2D *CreateTexture2DFromFile(GPUDevice *device,const OSString &filename,bool auto_mipmaps); -Texture2DArray *CreateTexture2DArrayFromFile(GPUDevice *device,const OSString &filename,bool auto_mipmaps); Texture2D *RenderResource::LoadTexture2D(const OSString &filename,bool auto_mipmaps) { @@ -148,6 +147,18 @@ Texture2D *RenderResource::LoadTexture2D(const OSString &filename,bool auto_mipm return tex; } +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) +{ + if(!ta)return(false); + + if(!LoadTexture2DLayerFromFile(device,ta,layer,filename,false)) + return(false); + + return(true); +} + TextureCube *CreateTextureCubeFromFile(GPUDevice *device,const OSString &filename,bool auto_mipmaps); TextureCube *RenderResource::LoadTextureCube(const OSString &filename,bool auto_mipmaps) diff --git a/src/ShaderGen/2d/M_RectTexture2DArray.cpp b/src/ShaderGen/2d/M_RectTexture2DArray.cpp new file mode 100644 index 00000000..f5743dbd --- /dev/null +++ b/src/ShaderGen/2d/M_RectTexture2DArray.cpp @@ -0,0 +1,120 @@ +#include"Std2DMaterial.h" +#include +#include +#include"common/MFRectPrimitive.h" +#include + +STD_MTL_NAMESPACE_BEGIN +namespace +{ + constexpr const char vs_main[]=R"( +void main() +{ + Output.TexCoord=TexCoord; + + gl_Position=GetPosition2D(); +})"; + + //一个shader中输出的所有数据,会被定义在一个名为Output的结构中。所以编写时要用Output.XXXX来使用。 + //而同时,这个结构在下一个Shader中以Input名称出现,使用时以Input.XXX的形式使用。 + + constexpr const char gs_main[]=R"( +void main() +{ + vec2 vlt=gl_in[0].gl_Position.xy; + vec2 vrb=gl_in[0].gl_Position.zw; + 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(); + + 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)); +})"; + + class MaterialRectTexture2D:public Std2DMaterial + { + public: + + using Std2DMaterial::Std2DMaterial; + ~MaterialRectTexture2D()=default; + + bool CustomVertexShader(ShaderCreateInfoVertex *vsc) override + { + { + RANGE_CHECK_RETURN_FALSE(cfg->coordinate_system) + + vsc->AddInput(VAT_VEC4,VAN::Position); + + 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); + } + } + + vsc->AddInput(VAT_VEC4,VAN::TexCoord); + + vsc->AddOutput(VAT_VEC4,"TexCoord"); + + vsc->SetMain(vs_main); + return(true); + } + + bool CustomGeometryShader(ShaderCreateInfoGeometry *gsc) override + { + gsc->SetGeom(Prim::Points,Prim::TriangleStrip,4); + + gsc->AddOutput(VAT_VEC2,"TexCoord"); + + gsc->SetMain(gs_main); + return(true); + } + + 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了,所以这个名称其实随便起。 + + fsc->SetMain(fs_main); + return(true); + } + };//class MaterialRectTexture2D:public Std2DMaterial +}//namespace + +MaterialCreateInfo *CreateRectTexture2DArray(mtl::Material2DCreateConfig *cfg) +{ + if(!cfg) + return(nullptr); + + cfg->shader_stage_flag_bit|=VK_SHADER_STAGE_GEOMETRY_BIT; + + MaterialRectTexture2D mvc2d(cfg); + + return mvc2d.Create(); +} +STD_MTL_NAMESPACE_END diff --git a/src/ShaderGen/CMakeLists.txt b/src/ShaderGen/CMakeLists.txt index 94adccea..a4b70456 100644 --- a/src/ShaderGen/CMakeLists.txt +++ b/src/ShaderGen/CMakeLists.txt @@ -52,7 +52,9 @@ SET(STD_MTL_2D_SOURCE_FILES ${STD_MTL_2D_HEADER_PATH}/Material2DCreateConfig.h 2d/M_VertexColor2D.cpp 2d/M_PureColor2D.cpp 2d/M_PureTexture2D.cpp - 2d/M_RectTexture2D.cpp) + 2d/M_RectTexture2D.cpp + 2d/M_RectTexture2DArray.cpp +) SET(STD_MTL_SOURCE ${STD_MTL_HEADER_PATH}/MaterialConfig.h ${STD_MTL_HEADER_PATH}/StdMaterial.h