support texture file with mipmaps data.

This commit is contained in:
hyzboy 2020-10-25 21:29:18 +08:00
parent 7f71b50316
commit e13d442ee1
11 changed files with 247 additions and 102 deletions

2
CMCore

@ -1 +1 @@
Subproject commit 0f3ef7ff3fad57b6a61d9700fe707ad0a97c844e
Subproject commit 5d75e138b58826b635db09f0dd325b4e6f2d2052

@ -1 +1 @@
Subproject commit 7bceaf2f9c5fbe1630e3a8b0e78eac5f4846f22e
Subproject commit 3d644e9550395a0635332ce044a4b6453cf694f8

View File

@ -42,7 +42,7 @@ private:
MaterialInstance * material_instance =nullptr;
Renderable * render_obj =nullptr;
RenderableInstance *render_instance =nullptr;
GPUBuffer * ubo_world_matrix =nullptr;
GPUBuffer * ubo_world_matrix =nullptr;
Pipeline * pipeline =nullptr;

View File

@ -9,10 +9,6 @@
using namespace hgl;
using namespace hgl::graph;
VK_NAMESPACE_BEGIN
Texture2D *CreateTextureFromFile(GPUDevice *device,const OSString &filename);
VK_NAMESPACE_END
constexpr uint32_t SCREEN_SIZE=512;
constexpr uint32_t VERTEX_COUNT=4;
@ -79,7 +75,6 @@ public:
SAFE_CLEAR(vertex_buffer);
SAFE_CLEAR(sampler_nearest);
SAFE_CLEAR(sampler_linear);
SAFE_CLEAR(texture);
}
private:
@ -135,7 +130,7 @@ private:
bool InitTexture()
{
texture=CreateTextureFromFile(device,OS_TEXT("res/image/heightmap.Tex2D"));
texture=db->LoadTexture2D(OS_TEXT("res/image/heightmap.Tex2D"));
return texture;
}

View File

@ -41,7 +41,7 @@ private:
MaterialInstance * material_instance =nullptr;
Renderable * render_obj =nullptr;
RenderableInstance *render_instance =nullptr;
GPUBuffer * ubo_world_matrix =nullptr;
GPUBuffer * ubo_world_matrix =nullptr;
Pipeline * pipeline =nullptr;
@ -55,7 +55,7 @@ private:
pipeline=CreatePipeline(material_instance,InlinePipeline::Solid2D,Prim::Rectangles);
if(!pipeline)return(false);
texture=CreateTextureFromFile(device,OS_TEXT("res/image/lena.Tex2D"));
texture=db->LoadTexture2D(OS_TEXT("res/image/lena.Tex2D"));
if(!texture)return(false);
sampler=db->CreateSampler();

View File

@ -4,10 +4,28 @@
#include<hgl/io/InputStream.h>
#include<hgl/type/String.h>
#include<hgl/graph/Bitmap.h>
#include<hgl/graph/VKFormat.h>
namespace hgl
{
namespace graph
{
constexpr VkFormat CompressFormatList[]=
{
FMT_BC1_RGBUN,
FMT_BC1_RGBAUN,
FMT_BC2UN,
FMT_BC3UN,
FMT_BC4UN,
FMT_BC5UN,
FMT_BC6UF,
FMT_BC6SF,
FMT_BC7UN
};
constexpr uint32 CompressFormatBits[]={4,4,8,8,4,8,8,8,8};
constexpr uint32 CompressFormatCount=sizeof(CompressFormatList)/sizeof(VkFormat);
#pragma pack(push,1)
struct Tex2DFileHeader
{
@ -31,7 +49,8 @@ namespace hgl
public:
const uint pixel_bytes()const{return (bits[0]+bits[1]+bits[2]+bits[3])>>3;}
const uint pixel_bits()const{return bits[0]+bits[1]+bits[2]+bits[3];}
const uint pixel_bytes()const{return pixel_bits()>>3;}
};//struct TexPixelFormat
#pragma pack(pop)
@ -50,10 +69,12 @@ namespace hgl
uint16 compress_format;
};
uint32 total_bytes;
protected:
protected:
uint32 mipmap_zero_total_bytes;
uint32 ComputeTotalBytes();
virtual void *OnBegin(uint32)=0;
virtual void OnEnd()=0;
virtual void OnError(){}

View File

@ -120,6 +120,11 @@ public: //Image
VkImage CreateImage (VkImageCreateInfo *);
void DestoryImage (VkImage);
private: //texture
bool CommitTexture2D(Texture2D *,GPUBuffer *buf,uint32_t width,uint32_t height,const uint32_t miplevel,VkPipelineStageFlags stage);
bool CommitTexture2DMipmaps(Texture2D *,GPUBuffer *buf,uint32_t width,uint32_t height,uint32_t miplevel,uint32_t);
public: //Texture
bool CheckFormatSupport(const VkFormat,const uint32_t bits,ImageTiling tiling=ImageTiling::Optimal)const;
@ -131,11 +136,10 @@ public: //Texture
void Clear(TextureCreateInfo *);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count, const uint32_t miplevel=1);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List<ImageRegion> &, const uint32_t miplevel=1);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height, const uint32_t miplevel=1);
bool ChangeTexture2D(Texture2D *,void *data, uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size,const uint32_t miplevel=1);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List<ImageRegion> &, const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count, const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height, const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
bool ChangeTexture2D(Texture2D *,void *data, uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size,const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
template<typename T>
bool ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const RectScope2<T> &rs)

View File

@ -9,7 +9,7 @@ struct TextureData
VkImage image =VK_NULL_HANDLE;
VkImageLayout image_layout=VK_IMAGE_LAYOUT_UNDEFINED;
ImageView * image_view =nullptr;
uint32 miplevel =0;
uint32 miplevel =0;
VkImageTiling tiling =VK_IMAGE_TILING_OPTIMAL;
};//struct TextureData
@ -18,7 +18,9 @@ struct TextureCreateInfo
VkExtent3D extent;
VkFormat format;
uint32_t usage;
uint32_t mipmap; ///<如果值>0表示提供的数据已有mipmaps如果为0表示自动生成mipmaps
uint32_t mipmap_zero_total_bytes;
uint32_t origin_mipmaps; //原始mipmaps0/1
uint32_t target_mipmaps; //目标mipmaps如果和origin_mipmaps不相等则证明希望自动生成mipmaps
VkImageAspectFlags aspect;
ImageTiling tiling;
@ -30,19 +32,16 @@ struct TextureCreateInfo
ImageView * image_view; //如果没有imageview则创建
void * pixels; //如果没有buffer但有pixels则根据pixels和以上条件创建buffer
VkDeviceSize pixel_bytes;
VkDeviceSize total_bytes;
GPUBuffer * buffer; //如果pixels也没有则代表不会立即写入图像数据
public:
TextureCreateInfo()
{
hgl_zero(*this);
mipmap=1;
hgl_zero(*this);
}
void SetAutoMipmaps(){mipmap=0;}
TextureCreateInfo(const uint32_t aspect_bit,const VkExtent2D &ext,const VkFormat &fmt,VkImage img):TextureCreateInfo()
{
aspect=aspect_bit;
@ -172,6 +171,11 @@ public:
return(true);
}
void SetAutoMipmaps()
{
target_mipmaps=hgl::GetMipLevel(extent.width,extent.height,extent.depth);
}
};//struct TextureCreateInfo
struct ColorTextureCreateInfo:public TextureCreateInfo

View File

@ -10,6 +10,46 @@
VK_NAMESPACE_BEGIN
namespace
{
struct BufferImageCopy:public VkBufferImageCopy
{
public:
BufferImageCopy()
{
hgl_zero(*this);
imageSubresource.layerCount=1;
}
BufferImageCopy(const VkImageAspectFlags aspect_mask):BufferImageCopy()
{
imageSubresource.aspectMask=aspect_mask;
}
void Set(const VkImageAspectFlags aspect_mask,const uint32_t layer_count)
{
imageSubresource.aspectMask=aspect_mask;
imageSubresource.layerCount=layer_count;
}
void Set(ImageRegion *ir)
{
imageOffset.x=ir->left;
imageOffset.y=ir->top;
imageExtent.width=ir->width;
imageExtent.height=ir->height;
imageExtent.depth=1;
}
void SetRectScope(int32_t left,int32_t top,uint32_t width,uint32_t height)
{
imageOffset.x=left;
imageOffset.y=top;
imageExtent.width=width;
imageExtent.height=height;
imageExtent.depth=1;
}
};//
void GenerateMipmaps(GPUCmdBuffer *texture_cmd_buf,VkImage image,VkImageAspectFlags aspect_mask,const int32_t width,const int32_t height,const uint32_t mipLevels)
{
//VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
@ -126,11 +166,12 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci)
if(tci->extent.width*tci->extent.height*tci->extent.depth<=0)return(nullptr);
const uint32_t miplevels=((tci->mipmap==0)?GetMipLevel(tci->extent):tci->mipmap);
if(tci->target_mipmaps==0)
tci->target_mipmaps=(tci->origin_mipmaps>1?tci->origin_mipmaps:1);
if(!tci->image)
{
Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,miplevels);
Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,tci->target_mipmaps);
tci->image=CreateImage(&ici);
if(!tci->image)
@ -143,7 +184,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci)
}
if(!tci->image_view)
tci->image_view=CreateImageView2D(attr->device,tci->format,tci->extent,miplevels,tci->aspect,tci->image);
tci->image_view=CreateImageView2D(attr->device,tci->format,tci->extent,tci->target_mipmaps,tci->aspect,tci->image);
TextureData *tex_data=new TextureData;
@ -151,7 +192,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci)
tex_data->image_layout = tci->image_layout;
tex_data->image = tci->image;
tex_data->image_view = tci->image_view;
tex_data->miplevel = miplevels;
tex_data->miplevel = tci->target_mipmaps;
tex_data->tiling = VkImageTiling(tci->tiling);
Texture2D *tex=CreateTexture2D(tex_data);
@ -162,12 +203,33 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci)
return(nullptr);
}
if((!tci->buffer)&&tci->pixels&&tci->pixel_bytes>0)
tci->buffer=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,tci->pixel_bytes,tci->pixels);
if((!tci->buffer)&&tci->pixels&&tci->total_bytes>0)
tci->buffer=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,tci->total_bytes,tci->pixels);
if(tci->buffer)
{
ChangeTexture2D(tex,tci->buffer,0,0,tci->extent.width,tci->extent.height,tex_data->miplevel);
texture_cmd_buf->Begin();
if(tci->target_mipmaps==tci->origin_mipmaps)
{
if(tci->target_mipmaps<=1) //本身不含mipmaps但也不要mipmaps
{
CommitTexture2D(tex,tci->buffer,tci->extent.width,tci->extent.height,tex_data->miplevel,VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
else //本身有mipmaps数据
{
CommitTexture2DMipmaps(tex,tci->buffer,tci->extent.width,tci->extent.height,tex_data->miplevel,tci->mipmap_zero_total_bytes);
}
}
else
if(tci->origin_mipmaps<=1) //本身不含mipmaps数据,又想要mipmaps
{
CommitTexture2D(tex,tci->buffer,tci->extent.width,tci->extent.height,tex_data->miplevel,VK_PIPELINE_STAGE_TRANSFER_BIT);
GenerateMipmaps(texture_cmd_buf,tex->GetImage(),tex->GetAspect(),tex->GetWidth(),tex->GetHeight(),tex_data->miplevel);
}
texture_cmd_buf->End();
SubmitTexture(*texture_cmd_buf);
delete tci->buffer;
}
@ -175,7 +237,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci)
return tex;
}
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImageCopy *buffer_image_copy,const int count,const uint32_t miplevel)
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImageCopy *buffer_image_copy,const int count,const uint32_t miplevel,VkPipelineStageFlags destinationStage)
{
if(!tex||!buf)
return(false);
@ -196,7 +258,6 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.subresourceRange = subresourceRange;
texture_cmd_buf->Begin();
texture_cmd_buf->PipelineBarrier(
VK_PIPELINE_STAGE_HOST_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -215,21 +276,15 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
VkPipelineStageFlags destinationStage;
if(miplevel>1)
if(destinationStage==VK_PIPELINE_STAGE_TRANSFER_BIT)
{
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else
else// if(destinationStage==VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
{
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
texture_cmd_buf->PipelineBarrier(
@ -240,16 +295,10 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag
0, nullptr,
1, &imageMemoryBarrier);
if(miplevel>1)
GenerateMipmaps(texture_cmd_buf,tex->GetImage(),tex->GetAspect(),tex->GetWidth(),tex->GetHeight(),miplevel);
texture_cmd_buf->End();
SubmitTexture(*texture_cmd_buf);
return(true);
}
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List<ImageRegion> &ir_list,const uint32_t miplevel)
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List<ImageRegion> &ir_list,const uint32_t miplevel,VkPipelineStageFlags destinationStage)
{
if(!tex||!buf||ir_list.GetCount()<=0)
return(false);
@ -259,11 +308,10 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List<ImageRe
AutoDeleteArray<VkBufferImageCopy> buffer_image_copy(ir_count);
VkBufferImageCopy *tp=buffer_image_copy;
const ImageRegion *sp=ir_list.GetData();
VkDeviceSize offset=0;
for(int i=0;i<ir_list.GetCount();i++)
for(const ImageRegion &sp:ir_list)
{
tp->bufferOffset = offset;
tp->bufferRowLength = 0;
@ -272,22 +320,21 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List<ImageRe
tp->imageSubresource.mipLevel = 0;
tp->imageSubresource.baseArrayLayer = 0;
tp->imageSubresource.layerCount = 1;
tp->imageOffset.x = sp->left;
tp->imageOffset.y = sp->top;
tp->imageOffset.x = sp.left;
tp->imageOffset.y = sp.top;
tp->imageOffset.z = 0;
tp->imageExtent.width = sp->width;
tp->imageExtent.height= sp->height;
tp->imageExtent.width = sp.width;
tp->imageExtent.height= sp.height;
tp->imageExtent.depth = 1;
offset+=sp->bytes;
++sp;
offset+=sp.bytes;
++tp;
}
return ChangeTexture2D(tex,buf,buffer_image_copy,ir_count,miplevel);
return ChangeTexture2D(tex,buf,buffer_image_copy,ir_count,miplevel,destinationStage);
}
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height,const uint32_t miplevel)
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height,const uint32_t miplevel,VkPipelineStageFlags destinationStage)
{
if(!tex||!buf
||left<0||left+width>tex->GetWidth()
@ -295,25 +342,66 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint
||width<=0||height<=0)
return(false);
VkBufferImageCopy buffer_image_copy;
buffer_image_copy.bufferOffset = 0;
buffer_image_copy.bufferRowLength = 0;
buffer_image_copy.bufferImageHeight = 0;
buffer_image_copy.imageSubresource.aspectMask = tex->GetAspect();
buffer_image_copy.imageSubresource.mipLevel = 0;
buffer_image_copy.imageSubresource.baseArrayLayer = 0;
buffer_image_copy.imageSubresource.layerCount = 1;
buffer_image_copy.imageOffset.x = left;
buffer_image_copy.imageOffset.y = top;
buffer_image_copy.imageOffset.z = 0;
buffer_image_copy.imageExtent.width = width;
buffer_image_copy.imageExtent.height= height;
buffer_image_copy.imageExtent.depth = 1;
BufferImageCopy buffer_image_copy(tex->GetAspect());
buffer_image_copy.SetRectScope(left,top,width,height);
return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel);
return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel,destinationStage);
}
bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size,const uint32_t miplevel)
bool GPUDevice::CommitTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t width,uint32_t height,const uint32_t miplevel,VkPipelineStageFlags destinationStage)
{
if(!tex||!buf)return(false);
BufferImageCopy buffer_image_copy(tex->GetAspect());
buffer_image_copy.SetRectScope(0,0,width,height);
return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel,destinationStage);
}
bool GPUDevice::CommitTexture2DMipmaps(Texture2D *tex,GPUBuffer *buf,uint32_t width,uint32_t height,uint32_t miplevel,uint32_t total_bytes)
{
if(!tex||!buf
||width<=0||height<=0)
return(false);
AutoDeleteArray<VkBufferImageCopy> buffer_image_copy(miplevel);
VkDeviceSize offset=0;
uint32_t level=0;
buffer_image_copy.zero();
for(VkBufferImageCopy &bic:buffer_image_copy)
{
bic.bufferOffset = offset;
bic.bufferRowLength = 0;
bic.bufferImageHeight = 0;
bic.imageSubresource.aspectMask = tex->GetAspect();
bic.imageSubresource.mipLevel = level++;
bic.imageSubresource.baseArrayLayer = 0;
bic.imageSubresource.layerCount = 1;
bic.imageOffset.x = 0;
bic.imageOffset.y = 0;
bic.imageOffset.z = 0;
bic.imageExtent.width = width;
bic.imageExtent.height= height;
bic.imageExtent.depth = 1;
if(total_bytes<8)
offset+=8;
else
offset+=total_bytes;
if(width>1){width>>=1;total_bytes>>=1;}
if(height>1){height>>=1;total_bytes>>=1;}
}
return ChangeTexture2D(tex,buf,buffer_image_copy,miplevel,miplevel,VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size,const uint32_t miplevel,VkPipelineStageFlags destinationStage)
{
if(!tex||!data
||left<0||left+width>tex->GetWidth()
@ -324,7 +412,7 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t
GPUBuffer *buf=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,size,data);
bool result=ChangeTexture2D(tex,buf,left,top,width,height,miplevel);
bool result=ChangeTexture2D(tex,buf,left,top,width,height,miplevel,destinationStage);
delete buf;

View File

@ -117,21 +117,6 @@ namespace
void *OnBegin(uint32 total_bytes) override
{
constexpr VkFormat CompressFormatList[]=
{
FMT_BC1_RGBUN,
FMT_BC1_RGBAUN,
FMT_BC2UN,
FMT_BC3UN,
FMT_BC4UN,
FMT_BC5UN,
FMT_BC6UF,
FMT_BC6SF,
FMT_BC7UN
};
constexpr size_t CompressFormatCount=sizeof(CompressFormatList)/sizeof(VkFormat);
SAFE_CLEAR(buf);
SAFE_CLEAR(tex);
@ -161,8 +146,10 @@ namespace
buf->Unmap();
TextureCreateInfo *tci=new TextureCreateInfo(format);
tci->SetData(buf,file_header.width,file_header.height);
if(auto_mipmaps)
if(auto_mipmaps&&file_header.mipmaps<=1)
{
if(device->CheckFormatSupport(format,VK_FORMAT_FEATURE_BLIT_DST_BIT))
{
@ -170,8 +157,13 @@ namespace
tci->SetAutoMipmaps();
}
}
else
{
tci->origin_mipmaps=
tci->target_mipmaps=file_header.mipmaps;
}
tci->SetData(buf,file_header.width,file_header.height);
tci->mipmap_zero_total_bytes=mipmap_zero_total_bytes;
tex=device->CreateTexture2D(tci);

View File

@ -7,6 +7,51 @@ namespace hgl
{
namespace graph
{
uint32 Texture2DLoader::ComputeTotalBytes()
{
uint32 pixel_bits;
uint32 bytes;
if(file_header.channels==0)
{
if(compress_format<0||compress_format>=CompressFormatCount)
return(0);
pixel_bits=CompressFormatBits[compress_format];
}
else
{
pixel_bits=pixel_format.pixel_bits();
}
bytes=(pixel_bits*file_header.pixel_count())>>3;
mipmap_zero_total_bytes=bytes;
if(file_header.mipmaps<=1)
return bytes;
uint32 total=0;
uint32 w=file_header.width;
uint32 h=file_header.height;
while(w>=1&&h>=1)
{
if(bytes<8)
total+=8;
else
total+=bytes;
if(w==1&&h==1)break;
if(w>1){w>>=1;bytes>>=1;}
if(h>1){h>>=1;bytes>>=1;}
}
return total;
}
bool Texture2DLoader::Load(io::InputStream *is)
{
if(!is)return(false);
@ -14,31 +59,27 @@ namespace hgl
if(is->Read(&file_header,sizeof(Tex2DFileHeader))!=sizeof(Tex2DFileHeader))
return(false);
if(file_header.version!=2)
if(file_header.version!=3)
return(false);
total_bytes=0;
if(file_header.channels==0) //压缩格式
{
if(is->Read(&compress_format,sizeof(uint16))!=sizeof(uint16))
return(false);
if(is->Read(&total_bytes,sizeof(uint32))!=sizeof(uint32))
return(false);
}
else
{
if(is->Read(&pixel_format,sizeof(TexPixelFormat))!=sizeof(TexPixelFormat))
return(false);
total_bytes=file_header.pixel_count()*pixel_format.pixel_bytes();
}
const uint32 total_bytes=ComputeTotalBytes();
if(is->Available()<total_bytes)
return(false);
void *ptr=OnBegin(total_bytes);
if(!ptr)
return(false);