nv_dds.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,363 行 · 第 1/3 页
CPP
1,363 行
//This file contains source code provided by NVIDIA Corporation
//Modified DDS reader class from NVIDIA SDK
///////////////////////////////////////////////////////////////////////////////
//
// Description:
//
// Loads DDS images (DXTC1, DXTC3, DXTC5, RGB (888, 888X), and RGBA (8888) are
// supported) for use in OpenGL. Image is flipped when its loaded as DX images
// are stored with different coordinate system. If file has mipmaps and/or
// cubemaps then these are loaded as well. Volume textures can be loaded as
// well but they must be uncompressed.
//
// When multiple textures are loaded (i.e a volume or cubemap texture),
// additional faces can be accessed using the array operator.
//
// The mipmaps for each face are also stored in a list and can be accessed like
// so: image.get_mipmap() (which accesses the first mipmap of the first
// image). To get the number of mipmaps call the get_num_mipmaps function for
// a given texture.
//
// Call the is_volume() or is_cubemap() function to check that a loaded image
// is a volume or cubemap texture respectively. If a volume texture is loaded
// then the get_depth() function should return a number greater than 1.
// Mipmapped volume textures and DXTC compressed volume textures are supported.
//
///////////////////////////////////////////////////////////////////////////////
//
// Update: 9/15/2003
//
// Added functions to create new image from a buffer of pixels. Added function
// to save current image to disk.
//
// Update: 6/11/2002
//
// Added some convenience functions to handle uploading textures to OpenGL. The
// following functions have been added:
//
// bool upload_texture1D();
// bool upload_texture2D(unsigned int imageIndex = 0, GLenum target = GL_TEXTURE_2D);
// bool upload_textureRectangle();
// bool upload_texture3D();
// bool upload_textureCubemap();
//
// See function implementation below for instructions/comments on using each
// function.
//
// The open function has also been updated to take an optional second parameter
// specifying whether the image should be flipped on load. This defaults to
// true.
//
///////////////////////////////////////////////////////////////////////////////
// Sample usage
///////////////////////////////////////////////////////////////////////////////
//
// Loading a compressed texture:
//
// CDDSImage image;
// GLuint texobj;
//
// image.load("compressed.dds");
//
// glGenTextures(1, &texobj);
// glEnable(GL_TEXTURE_2D);
// glBindTexture(GL_TEXTURE_2D, texobj);
//
// glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, image.get_format(),
// image.get_width(), image.get_height(), 0, image.get_size(),
// image);
//
// for (int i = 0; i < image.get_num_mipmaps(); i++)
// {
// CSurface mipmap = image.get_mipmap(i);
//
// glCompressedTexImage2DARB(GL_TEXTURE_2D, i+1, image.get_format(),
// mipmap.get_width(), mipmap.get_height(), 0, mipmap.get_size(),
// mipmap);
// }
///////////////////////////////////////////////////////////////////////////////
//
// Loading an uncompressed texture:
//
// CDDSImage image;
// GLuint texobj;
//
// image.load("uncompressed.dds");
//
// glGenTextures(1, &texobj);
// glEnable(GL_TEXTURE_2D);
// glBindTexture(GL_TEXTURE_2D, texobj);
//
// glTexImage2D(GL_TEXTURE_2D, 0, image.get_components(), image.get_width(),
// image.get_height(), 0, image.get_format(), GL_UNSIGNED_BYTE, image);
//
// for (int i = 0; i < image.get_num_mipmaps(); i++)
// {
// glTexImage2D(GL_TEXTURE_2D, i+1, image.get_components(),
// image.get_mipmap(i).get_width(), image.get_mipmap(i).get_height(),
// 0, image.get_format(), GL_UNSIGNED_BYTE, image.get_mipmap(i));
// }
//
///////////////////////////////////////////////////////////////////////////////
//
// Loading an uncompressed cubemap texture:
//
// CDDSImage image;
// GLuint texobj;
// GLenum target;
//
// image.load("cubemap.dds");
//
// glGenTextures(1, &texobj);
// glEnable(GL_TEXTURE_CUBE_MAP_ARB);
// glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texobj);
//
// for (int n = 0; n < 6; n++)
// {
// target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+n;
//
// glTexImage2D(target, 0, image.get_components(), image[n].get_width(),
// image[n].get_height(), 0, image.get_format(), GL_UNSIGNED_BYTE,
// image[n]);
//
// for (int i = 0; i < image[n].get_num_mipmaps(); i++)
// {
// glTexImage2D(target, i+1, image.get_components(),
// image[n].get_mipmap(i).get_width(),
// image[n].get_mipmap(i).get_height(), 0,
// image.get_format(), GL_UNSIGNED_BYTE, image[n].get_mipmap(i));
// }
// }
//
///////////////////////////////////////////////////////////////////////////////
//
// Loading a volume texture:
//
// CDDSImage image;
// GLuint texobj;
//
// image.load("volume.dds");
//
// glGenTextures(1, &texobj);
// glEnable(GL_TEXTURE_3D);
// glBindTexture(GL_TEXTURE_3D, texobj);
//
// PFNGLTEXIMAGE3DPROC glTexImage3D;
// glTexImage3D(GL_TEXTURE_3D, 0, image.get_components(), image.get_width(),
// image.get_height(), image.get_depth(), 0, image.get_format(),
// GL_UNSIGNED_BYTE, image);
//
// for (int i = 0; i < image.get_num_mipmaps(); i++)
// {
// glTexImage3D(GL_TEXTURE_3D, i+1, image.get_components(),
// image[0].get_mipmap(i).get_width(),
// image[0].get_mipmap(i).get_height(),
// image[0].get_mipmap(i).get_depth(), 0, image.get_format(),
// GL_UNSIGNED_BYTE, image[0].get_mipmap(i));
// }
#include "StdAfx.h"
#if defined(WIN32)
# include <windows.h>
# define GET_EXT_POINTER(name, type) \
name = (type)wglGetProcAddress(#name)
#elif defined(UNIX) || defined(unix)
#define GLX_GLXEXT_PROTOTYPES
//# include <GL/glx.h>
# define GET_EXT_POINTER(name, type) \
name = (type)glXGetProcAddressARB((const GLubyte*)#name)
#elif defined(__APPLE__)
// Mac OpenGL headers are 1.4/1.5 Compatable already!
# define GET_EXT_POINTER(name, type)
#else
# define GET_EXT_POINTER(name, type)
# error unknown platform
#endif
/*#ifdef MACOS
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#define GL_TEXTURE_RECTANGLE_NV GL_TEXTURE_RECTANGLE_EXT
#else*/
//#include <GL/gl.h>
//#include <GL/glext.h>
//#endif
#include <stdio.h>
#include <assert.h>
#include "nv_dds.h"
#include "FileSystem/FileHandler.h"
#include "Platform/byteorder.h"
// Moved because of conflicts with GLEW.
#if defined(UNIX) || defined(unix)
# include <GL/glx.h>
#endif
using namespace std;
using namespace nv_dds;
///////////////////////////////////////////////////////////////////////////////
// static function pointers for uploading 3D textures and compressed 1D, 2D
// and 3D textures.
#ifndef __APPLE__
PFNGLTEXIMAGE3DEXTPROC CDDSImage::glTexImage3D = NULL;
PFNGLCOMPRESSEDTEXIMAGE1DARBPROC CDDSImage::glCompressedTexImage1DARB = NULL;
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC CDDSImage::glCompressedTexImage2DARB = NULL;
PFNGLCOMPRESSEDTEXIMAGE3DARBPROC CDDSImage::glCompressedTexImage3DARB = NULL;
#endif
///////////////////////////////////////////////////////////////////////////////
// CDDSImage public functions
///////////////////////////////////////////////////////////////////////////////
// default constructor
CDDSImage::CDDSImage()
: m_format(0),
m_components(0),
m_type(TextureNone),
m_valid(false)
{
}
CDDSImage::~CDDSImage()
{
}
void CDDSImage::create_textureFlat(unsigned int format, unsigned int components, const CTexture &baseImage)
{
assert(format != 0);
assert(components != 0);
assert(baseImage.get_depth() == 1);
// remove any existing images
clear();
m_format = format;
m_components = components;
m_type = TextureFlat;
m_images.push_back(baseImage);
m_valid = true;
}
void CDDSImage::create_texture3D(unsigned int format, unsigned int components, const CTexture &baseImage)
{
assert(format != 0);
assert(components != 0);
assert(baseImage.get_depth() > 1);
// remove any existing images
clear();
m_format = format;
m_components = components;
m_type = Texture3D;
m_images.push_back(baseImage);
m_valid = true;
}
inline bool same_size(const CTexture &a, const CTexture &b)
{
if (a.get_width() != b.get_width())
return false;
if (a.get_height() != b.get_height())
return false;
if (a.get_depth() != b.get_depth())
return false;
return true;
}
void CDDSImage::create_textureCubemap(unsigned int format, unsigned int components,
const CTexture &positiveX, const CTexture &negativeX,
const CTexture &positiveY, const CTexture &negativeY,
const CTexture &positiveZ, const CTexture &negativeZ)
{
assert(format != 0);
assert(components != 0);
assert(positiveX.get_depth() == 1);
// verify that all dimensions are the same
assert(same_size(positiveX, negativeX));
assert(same_size(positiveX, positiveY));
assert(same_size(positiveX, negativeY));
assert(same_size(positiveX, positiveZ));
assert(same_size(positiveX, negativeZ));
// remove any existing images
clear();
m_format = format;
m_components = components;
m_type = TextureCubemap;
m_images.push_back(positiveX);
m_images.push_back(negativeX);
m_images.push_back(positiveY);
m_images.push_back(negativeY);
m_images.push_back(positiveZ);
m_images.push_back(negativeZ);
m_valid = true;
}
///////////////////////////////////////////////////////////////////////////////
// loads DDS image
//
// filename - fully qualified name of DDS image
// flipImage - specifies whether image is flipped on load, default is true
bool CDDSImage::load(string filename, bool flipImage)
{
assert(filename.length() != 0);
// clear any previously loaded images
clear();
// open file
// FILE *fp = fopen(filename.c_str(), "rb");
CFileHandler file(filename);
if (!file.FileExists())
return false;
// read in file marker, make sure its a DDS file
char filecode[4];
//fread(filecode, 1, 4, fp);
file.Read(filecode, 4);
if (strncmp(filecode, "DDS ", 4) != 0)
{
//fclose(fp);
return false;
}
// read in DDS header
DDS_HEADER ddsh;
//fread(&ddsh, sizeof(DDS_HEADER), 1, fp);
int tmp = sizeof(unsigned int);
file.Read(&ddsh.dwSize, tmp);
file.Read(&ddsh.dwFlags, tmp);
file.Read(&ddsh.dwHeight, tmp);
file.Read(&ddsh.dwWidth, tmp);
file.Read(&ddsh.dwPitchOrLinearSize, tmp);
file.Read(&ddsh.dwDepth, tmp);
file.Read(&ddsh.dwMipMapCount, tmp);
file.Read(&ddsh.dwReserved1, tmp*11);
file.Read(&ddsh.ddspf.dwSize, tmp);
file.Read(&ddsh.ddspf.dwFlags, tmp);
file.Read(&ddsh.ddspf.dwFourCC, tmp);
file.Read(&ddsh.ddspf.dwRGBBitCount, tmp);
file.Read(&ddsh.ddspf.dwRBitMask, tmp);
file.Read(&ddsh.ddspf.dwGBitMask, tmp);
file.Read(&ddsh.ddspf.dwBBitMask, tmp);
file.Read(&ddsh.ddspf.dwABitMask, tmp);
file.Read(&ddsh.dwCaps1, tmp);
file.Read(&ddsh.dwCaps2, tmp);
file.Read(&ddsh.dwReserved2, tmp*3);
ddsh.dwSize = swabdword(ddsh.dwSize);
ddsh.dwFlags = swabdword(ddsh.dwFlags);
ddsh.dwHeight = swabdword(ddsh.dwHeight);
ddsh.dwWidth = swabdword(ddsh.dwWidth);
ddsh.dwPitchOrLinearSize = swabdword(ddsh.dwPitchOrLinearSize);
ddsh.dwMipMapCount = swabdword(ddsh.dwMipMapCount);
ddsh.ddspf.dwSize = swabdword(ddsh.ddspf.dwSize);
ddsh.ddspf.dwFlags = swabdword(ddsh.ddspf.dwFlags);
ddsh.ddspf.dwFourCC = swabdword(ddsh.ddspf.dwFourCC);
ddsh.ddspf.dwRGBBitCount = swabdword(ddsh.ddspf.dwRGBBitCount);
ddsh.dwCaps1 = swabdword(ddsh.dwCaps1);
ddsh.dwCaps2 = swabdword(ddsh.dwCaps2);
// default to flat texture type (1D, 2D, or rectangle)
m_type = TextureFlat;
// check if image is a cubemap
if (ddsh.dwCaps2 & DDSF_CUBEMAP)
m_type = TextureCubemap;
// check if image is a volume texture
if ((ddsh.dwCaps2 & DDSF_VOLUME) && (ddsh.dwDepth > 0))
m_type = Texture3D;
// figure out what the image format is
if (ddsh.ddspf.dwFlags & DDSF_FOURCC)
{
switch(ddsh.ddspf.dwFourCC)
{
case FOURCC_DXT1:
m_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
m_components = 3;
break;
case FOURCC_DXT3:
m_format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
m_components = 4;
break;
case FOURCC_DXT5:
m_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
m_components = 4;
break;
default:
//fclose(fp);
return false;
}
}
else if (ddsh.ddspf.dwFlags == DDSF_RGBA && ddsh.ddspf.dwRGBBitCount == 32)
{
m_format = GL_BGRA_EXT;
m_components = 4;
}
else if (ddsh.ddspf.dwFlags == DDSF_RGB && ddsh.ddspf.dwRGBBitCount == 32)
{
m_format = GL_BGRA_EXT;
m_components = 4;
}
else if (ddsh.ddspf.dwFlags == DDSF_RGB && ddsh.ddspf.dwRGBBitCount == 24)
{
m_format = GL_BGR_EXT;
m_components = 3;
}
else if (ddsh.ddspf.dwRGBBitCount == 8)
{
m_format = GL_LUMINANCE;
m_components = 1;
}
else
{
//fclose(fp);
return false;
}
// store primary surface width/height/depth
unsigned int width, height, depth;
width = ddsh.dwWidth;
height = ddsh.dwHeight;
depth = clamp_size(ddsh.dwDepth); // set to 1 if 0
// use correct size calculation function depending on whether image is
// compressed
unsigned int (CDDSImage::*sizefunc)(unsigned int, unsigned int);
sizefunc = (is_compressed() ? &CDDSImage::size_dxtc : &CDDSImage::size_rgb);
// load all surfaces for the image (6 surfaces for cubemaps)
for (unsigned int n = 0; n < (unsigned int)(m_type == TextureCubemap ? 6 : 1); n++)
{
// add empty texture object
m_images.push_back(CTexture());
// get reference to newly added texture object
CTexture &img = m_images[n];
// calculate surface size
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?