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 + -
显示快捷键?