DDSLoader::LoadResult DDSLoader::Load( const char* path, int cubeMapFace, int& outWidth, int& outHeight, bool& outOpaque ) { assert( cubeMapFace >= 0 && cubeMapFace < 7 ); DDSHeader hdr; unsigned x = 0; unsigned y = 0; int mipMapCount = 0; std::ifstream ifs( path, std::ios::binary ); if (!ifs) { outWidth = 512; outHeight = 512; return LoadResult::FileNotFound; } ifs.read((char*) &hdr, sizeof( hdr ) ); assert( hdr.sHeader.dwMagic == DDS_MAGIC ); assert( hdr.sHeader.dwSize == 124 ); if (!(hdr.sHeader.dwFlags & DDSD_PIXELFORMAT) || !(hdr.sHeader.dwFlags & DDSD_CAPS) ) { std::cerr << "Error! Texture " << path << " doesn't have pixelformat or caps." << std::endl; outWidth = 32; outHeight = 32; outOpaque = true; return LoadResult::UnknownPixelFormat; } const uint32_t xSize = hdr.sHeader.dwWidth; const uint32_t ySize = hdr.sHeader.dwHeight; assert( !( xSize & (xSize - 1) ) ); assert( !( ySize & (ySize - 1) ) ); outWidth = xSize; outHeight = ySize; DDSInfo* li = nullptr; if (PF_IS_DXT1( hdr.sHeader.sPixelFormat )) { li = &loadInfoDXT1; outOpaque = true; } else if (PF_IS_DXT3( hdr.sHeader.sPixelFormat )) { li = &loadInfoDXT3; outOpaque = false; } else if (PF_IS_DXT5( hdr.sHeader.sPixelFormat )) { li = &loadInfoDXT5; outOpaque = false; } else if (PF_IS_BGRA8( hdr.sHeader.sPixelFormat )) { li = &loadInfoBGRA8; outOpaque = false; } else if (PF_IS_BGR8( hdr.sHeader.sPixelFormat )) { li = &loadInfoBGR8; outOpaque = true; } else if (PF_IS_BGR5A1( hdr.sHeader.sPixelFormat )) { li = &loadInfoBGR5A1; outOpaque = false; } else if (PF_IS_BGR565( hdr.sHeader.sPixelFormat )) { li = &loadInfoBGR565; outOpaque = true; } else if (PF_IS_INDEX8( hdr.sHeader.sPixelFormat )) { li = &loadInfoIndex8; outOpaque = true; } else { std::cerr << "Error! Texture " << path << " has unknown pixel format." << std::endl; outWidth = 32; outHeight = 32; outOpaque = true; return LoadResult::UnknownPixelFormat; } x = xSize; y = ySize; std::size_t size; mipMapCount = (hdr.sHeader.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.sHeader.dwMipMapCount : 1; if (mipMapCount == 0) { glTexParameteri( cubeMapFace > 0 ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); } if (li->isCompressed) { size = max( li->divSize, x ) / li->divSize * max( li->divSize, y ) / li->divSize * li->blockBytes; assert( size == hdr.sHeader.dwPitchOrLinearSize ); assert( hdr.sHeader.dwFlags & DDSD_LINEARSIZE ); std::vector< unsigned char > data( size ); if (data.empty()) { std::cerr << "Error loading texture " << path << std::endl; outWidth = 32; outHeight = 32; outOpaque = true; return LoadResult::FileNotFound; } for (int ix = 0; ix < mipMapCount; ++ix) { ifs.read( (char*) &data[0], size ); glCompressedTexImage2D( cubeMapFace > 0 ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeMapFace - 1 : GL_TEXTURE_2D, ix, li->internalFormat, x, y, 0, (GLsizei)size, &data[0] ); x = (x + 1) >> 1; y = (y + 1) >> 1; size = max( li->divSize, x ) / li->divSize * max( li->divSize, y ) / li->divSize * li->blockBytes; } }
texture* dds_load_file( char* filename ) { DdsLoadInfo loadInfoDXT1 = { true, false, false, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1 }; DdsLoadInfo loadInfoDXT3 = { true, false, false, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3 }; DdsLoadInfo loadInfoDXT5 = { true, false, false, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5 }; DdsLoadInfo loadInfoBGRA8 = { false, false, false, 1, 4, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR8 = { false, false, false, 1, 3, GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR5A1 = { false, true, false, 1, 2, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }; DdsLoadInfo loadInfoBGR565 = { false, true, false, 1, 2, GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }; DdsLoadInfo loadInfoIndex8 = { false, false, true, 1, 1, GL_RGB8, GL_BGRA, GL_UNSIGNED_BYTE }; SDL_RWops* f = SDL_RWFromFile(filename, "rb"); if (f == NULL) { error("Cannot load file %s", filename); } DDS_header hdr; SDL_RWread(f, &hdr, 1, sizeof(DDS_header)); if( hdr.dwMagic != DDS_MAGIC || hdr.dwSize != 124 || !(hdr.dwFlags & DDSD_PIXELFORMAT) || !(hdr.dwFlags & DDSD_CAPS) ) { error("Cannot Load File %s: Does not appear to be a .dds file.\n", filename); } int x = hdr.dwWidth; int y = hdr.dwHeight; int mip_map_num = (hdr.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.dwMipMapCount : 1; if (!is_power_of_two(x)) { error("Texture %s with is %i pixels which is not a power of two!", filename, x); } if (!is_power_of_two(y)) { error("Texture %s height is %i pixels which is not a power of two!", filename, y); } DdsLoadInfo* li = &loadInfoDXT1; if (PF_IS_DXT1(hdr.sPixelFormat )) { li = &loadInfoDXT1; } else if (PF_IS_DXT3(hdr.sPixelFormat )) { li = &loadInfoDXT3; } else if (PF_IS_DXT5(hdr.sPixelFormat )) { li = &loadInfoDXT5; } else if (PF_IS_BGRA8(hdr.sPixelFormat )) { li = &loadInfoBGRA8; } else if (PF_IS_BGR8(hdr.sPixelFormat )) { li = &loadInfoBGR8; } else if (PF_IS_BGR5A1(hdr.sPixelFormat)) { li = &loadInfoBGR5A1; } else if (PF_IS_BGR565(hdr.sPixelFormat)) { li = &loadInfoBGR565; } else if (PF_IS_INDEX8(hdr.sPixelFormat)) { li = &loadInfoIndex8; } else { error("Cannot Load File %s: Unknown DDS File format type.", filename); } texture* t = texture_new(); if (hdr.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) { t->type = GL_TEXTURE_CUBE_MAP; glBindTexture(GL_TEXTURE_CUBE_MAP, texture_handle(t)); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_FALSE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, mip_map_num-1); } else { t->type = GL_TEXTURE_2D; glBindTexture(GL_TEXTURE_2D, texture_handle(t)); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mip_map_num-1); texture_set_filtering_anisotropic(t); } for (int i = 0; i < (t->type == GL_TEXTURE_CUBE_MAP ? 6 : 1); i++) { GLenum target = t->type; if (t->type == GL_TEXTURE_CUBE_MAP) { target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; } int x = hdr.dwWidth; int y = hdr.dwHeight; int mip_map_num = (hdr.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.dwMipMapCount : 1; if ( li->compressed ) { size_t size = max(li->div_size, x) / li->div_size * max(li->div_size, y) / li->div_size * li->block_bytes; char* data = malloc(size); for(int ix = 0; ix < mip_map_num; ix++) { SDL_RWread(f, data, 1, size); glCompressedTexImage2D(target, ix, li->internal_format, x, y, 0, size, data); x = (x+1)>>1; y = (y+1)>>1; size = max(li->div_size, x) / li->div_size * max(li->div_size, y) / li->div_size * li->block_bytes; } free(data); } else if ( li->palette ) {
bool CDDSLoader::loadDDS( FILE * f ) { DDS_header hdr; size_t s = 0; unsigned int x = 0; unsigned int y = 0; unsigned int mipMapCount = 0; // DDS is so simple to read, too fread( &hdr, sizeof( hdr ), 1, f ); assert( hdr.dwMagic == DDS_MAGIC ); assert( hdr.dwSize == 124 ); if( hdr.dwMagic != DDS_MAGIC || hdr.dwSize != 124 || !(hdr.dwFlags & DDSD_PIXELFORMAT) || !(hdr.dwFlags & DDSD_CAPS) ) { goto failure; } unsigned int xSize = hdr.dwWidth; unsigned int ySize = hdr.dwHeight; assert( !(xSize & (xSize-1)) ); assert( !(ySize & (ySize-1)) ); DdsLoadInfo * li; if( PF_IS_DXT1( hdr.sPixelFormat ) ) { li = &loadInfoDXT1; } else if( PF_IS_DXT3( hdr.sPixelFormat ) ) { li = &loadInfoDXT3; } else if( PF_IS_DXT5( hdr.sPixelFormat ) ) { li = &loadInfoDXT5; } else if( PF_IS_BGRA8( hdr.sPixelFormat ) ) { li = &loadInfoBGRA8; } else if( PF_IS_BGR8( hdr.sPixelFormat ) ) { li = &loadInfoBGR8; } else if( PF_IS_BGR5A1( hdr.sPixelFormat ) ) { li = &loadInfoBGR5A1; } else if( PF_IS_BGR565( hdr.sPixelFormat ) ) { li = &loadInfoBGR565; } else if( PF_IS_INDEX8( hdr.sPixelFormat ) ) { li = &loadInfoIndex8; } else { goto failure; } //fixme: do cube maps later //fixme: do 3d later bool hasMipmaps_=false; GLenum format,cFormat; unsigned int size; x = xSize; y = ySize; // glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE ); // glGenerateMipmap( GL_TEXTURE_2D ); mipMapCount = (hdr.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.dwMipMapCount : 1; if( mipMapCount > 1 ) { hasMipmaps_ = true; } if( li->compressed ) { //1 block store 16pixel(4pixel by 4pixel), ie divSize=4 //each block = 16Byte //therefore x/4 * y/4 * 16 = size of image size_t size = max( li->divSize, x )/li->divSize * max( li->divSize, y )/li->divSize * li->blockBytes; assert( size == hdr.dwPitchOrLinearSize ); assert( hdr.dwFlags & DDSD_LINEARSIZE ); unsigned char * data = (unsigned char *)malloc( size ); if( !data ) { goto failure; } format = cFormat = li->internalFormat; for( unsigned int ix = 0; ix < mipMapCount; ++ix ) { fread( data, 1, size, f ); glCompressedTexImage2D( GL_TEXTURE_2D, ix, li->internalFormat, x, y, 0, size, data ); x = (x+1)>>1; y = (y+1)>>1; size = max( li->divSize, x )/li->divSize * max( li->divSize, y )/li->divSize * li->blockBytes; } free( data ); }
texture* dds_load_file( char* filename ){ DdsLoadInfo loadInfoDXT1 = { 1, 0, 0, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1 }; DdsLoadInfo loadInfoDXT3 = { 1, 0, 0, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3 }; DdsLoadInfo loadInfoDXT5 = { 1, 0, 0, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5 }; DdsLoadInfo loadInfoBGRA8 = { 0, 0, 0, 1, 4, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR8 = { 0, 0, 0, 1, 3, GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR5A1 = { 0, 1, 0, 1, 2, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }; DdsLoadInfo loadInfoBGR565 = { 0, 1, 0, 1, 2, GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }; DdsLoadInfo loadInfoIndex8 = { 0, 0, 1, 1, 1, GL_RGB8, GL_BGRA, GL_UNSIGNED_BYTE }; texture my_texture; glGenTextures(1, &my_texture); glBindTexture(GL_TEXTURE_2D, my_texture); DDS_header hdr; int x = 0; int y = 0; int mipMapCount = 0; SDL_RWops* f = SDL_RWFromFile(filename, "rb"); if (f == NULL) { error("Cannot load file %s", filename); } SDL_RWread(f, &hdr, 1, sizeof(hdr)); if( hdr.dwMagic != DDS_MAGIC || hdr.dwSize != 124 || !(hdr.dwFlags & DDSD_PIXELFORMAT) || !(hdr.dwFlags & DDSD_CAPS) ) { error("Cannot Load File %s: Does not appear to be a .dds file.\n", filename); } x = hdr.dwWidth; y = hdr.dwHeight; if (!is_power_of_two(x)) { warning("Texture %s with is %i pixels which is not a power of two!", filename, x); } if (!is_power_of_two(y)) { warning("Texture %s height is %i pixels which is not a power of two!", filename, y); } DdsLoadInfo* li = &loadInfoDXT1; if( PF_IS_DXT1( hdr.sPixelFormat ) ) { li = &loadInfoDXT1; } else if( PF_IS_DXT3( hdr.sPixelFormat ) ) { li = &loadInfoDXT3; } else if( PF_IS_DXT5( hdr.sPixelFormat ) ) { li = &loadInfoDXT5; } else if( PF_IS_BGRA8( hdr.sPixelFormat ) ) { li = &loadInfoBGRA8; } else if( PF_IS_BGR8( hdr.sPixelFormat ) ) { li = &loadInfoBGR8; } else if( PF_IS_BGR5A1( hdr.sPixelFormat ) ) { li = &loadInfoBGR5A1; } else if( PF_IS_BGR565( hdr.sPixelFormat ) ) { li = &loadInfoBGR565; } else if( PF_IS_INDEX8( hdr.sPixelFormat ) ) { li = &loadInfoIndex8; } else { error("Cannot Load File %s: Unknown DDS File format type.", filename); } glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE ); mipMapCount = (hdr.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.dwMipMapCount : 1; int ix, zz; GLenum cFormat, format; if( li->compressed ) { size_t size = max( li->divSize, x )/li->divSize * max( li->divSize, y )/li->divSize * li->blockBytes; char* data = malloc( size ); if( !data ) { error("Cannot Load File %s: Does not appear to contain any data.", filename); } cFormat = li->internalFormat; format = li->internalFormat; for( ix = 0; ix < mipMapCount; ++ix ) { SDL_RWread(f, data, 1, size); glCompressedTexImage2D( GL_TEXTURE_2D, ix, li->internalFormat, x, y, 0, size, data ); x = (x+1)>>1; y = (y+1)>>1; size = max( li->divSize, x )/li->divSize * max( li->divSize, y )/li->divSize * li->blockBytes; } free( data ); } else if( li->palette ) {
NEOERR* mast_dds_load(char *dir, char *name, RendAsset **a) { char fname[PATH_MAX], *buf, *pos; NEOERR *err; DdsLoadInfo loadInfoDXT1 = { 1, 0, 0, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1 }; DdsLoadInfo loadInfoDXT3 = { 1, 0, 0, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3 }; DdsLoadInfo loadInfoDXT5 = { 1, 0, 0, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5 }; DdsLoadInfo loadInfoBGRA8 = { 0, 0, 0, 1, 4, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR8 = { 0, 0, 0, 1, 3, GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE }; DdsLoadInfo loadInfoBGR5A1 = { 0, 1, 0, 1, 2, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }; DdsLoadInfo loadInfoBGR565 = { 0, 1, 0, 1, 2, GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }; DdsLoadInfo loadInfoIndex8 = { 0, 0, 1, 1, 1, GL_RGB8, GL_BGRA, GL_UNSIGNED_BYTE }; if (dir) snprintf(fname, sizeof(fname), "%s%s", dir, name); else strncpy(fname, name, sizeof(fname)); TexAsset *tnode = mtex_node_new(); if (!tnode) return nerr_raise(NERR_NOMEM, "alloc texture"); DDS_header hdr; int x = 0; int y = 0; int mipMapCount = 0; int totallen = 0; err = ne_load_file_len(fname, &buf, &totallen); if (err != STATUS_OK) return nerr_pass(err); glEnable(GL_TEXTURE_2D); glGenTextures(1, &tnode->tex); glBindTexture(GL_TEXTURE_2D, tnode->tex); pos = buf; memcpy(&hdr, buf, sizeof(hdr)); pos += sizeof(hdr); if (pos - buf > totallen) return nerr_raise(NERR_ASSERT, "file too short"); if (hdr.dwMagic != DDS_MAGIC || hdr.dwSize != 124 || !(hdr.dwFlags & DDSD_PIXELFORMAT) || !(hdr.dwFlags & DDSD_CAPS) ) return nerr_raise(NERR_ASSERT, "%s Does not appear to be a .dds file", fname); x = hdr.dwWidth; y = hdr.dwHeight; if (!is_power_of_two(x)) { mtc_warn("Texture %s with is %i pixels which is not a power of two!", fname, x); } if (!is_power_of_two(y)) { mtc_warn("Texture %s height is %i pixels which is not a power of two!", fname, y); } DdsLoadInfo* li = &loadInfoDXT1; if (PF_IS_DXT1(hdr.sPixelFormat)) { li = &loadInfoDXT1; } else if (PF_IS_DXT3(hdr.sPixelFormat)) { li = &loadInfoDXT3; } else if (PF_IS_DXT5(hdr.sPixelFormat)) { li = &loadInfoDXT5; } else if (PF_IS_BGRA8(hdr.sPixelFormat)) { li = &loadInfoBGRA8; } else if (PF_IS_BGR8(hdr.sPixelFormat)) { li = &loadInfoBGR8; } else if (PF_IS_BGR5A1(hdr.sPixelFormat)) { li = &loadInfoBGR5A1; } else if (PF_IS_BGR565(hdr.sPixelFormat)) { li = &loadInfoBGR565; } else if (PF_IS_INDEX8(hdr.sPixelFormat)) { li = &loadInfoIndex8; } else { return nerr_raise(NERR_ASSERT, "%s: Unknown DDS File format type.", fname); } glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); mipMapCount = (hdr.dwFlags & DDSD_MIPMAPCOUNT) ? hdr.dwMipMapCount : 1; int ix, zz; GLenum cFormat, format; if (li->compressed) { size_t size = max(li->divSize, x) / li->divSize * max(li->divSize, y) / li->divSize * li->blockBytes; char *data = malloc(size); if (!data ) { return nerr_raise(NERR_ASSERT, "%s: not contain any data.", fname); } cFormat = li->internalFormat; format = li->internalFormat; for( ix = 0; ix < mipMapCount; ++ix ) { memcpy(data, pos, size); pos += size; if (pos - buf > totallen) return nerr_raise(NERR_ASSERT, "file too short"); glCompressedTexImage2D(GL_TEXTURE_2D, ix, li->internalFormat, x, y, 0, size, data); x = (x+1)>>1; y = (y+1)>>1; size = max(li->divSize, x) / li->divSize * max(li->divSize, y) / li->divSize * li->blockBytes; } free(data); } else if (li->palette) {