nv_dds.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,363 行 · 第 1/3 页

CPP
1,363
字号
        unsigned int size = (this->*sizefunc)(width, height)*depth;

        // load surface
        unsigned char *pixels = SAFE_NEW unsigned char[size];
        //fread(pixels, 1, size, fp);
		file.Read(pixels, size);

        img.create(width, height, depth, size, pixels);
        
        delete [] pixels;

        if (flipImage) flip(img);
        
        unsigned int w = clamp_size(width >> 1);
        unsigned int h = clamp_size(height >> 1);
        unsigned int d = clamp_size(depth >> 1); 

        // store number of mipmaps
        unsigned int numMipmaps = ddsh.dwMipMapCount;

        // number of mipmaps in file includes main surface so decrease count 
        // by one
        if (numMipmaps != 0)
            numMipmaps--;

        // load all mipmaps for current surface
        for (unsigned int i = 0; i < numMipmaps && (w || h); i++)
        {
            // add empty surface
            img.add_mipmap(CSurface());

            // get reference to newly added mipmap
            CSurface &mipmap = img.get_mipmap(i);

            // calculate mipmap size
            size = (this->*sizefunc)(w, h)*d;

            unsigned char *pixels = SAFE_NEW unsigned char[size];
            //fread(pixels, 1, size, fp);
			file.Read(pixels, size);

            mipmap.create(w, h, d, size, pixels);
            
            delete [] pixels;

            if (flipImage) flip(mipmap);

            // shrink to next power of 2
            w = clamp_size(w >> 1);
            h = clamp_size(h >> 1);
            d = clamp_size(d >> 1); 
        }
    }

    // swap cubemaps on y axis (since image is flipped in OGL)
    if (m_type == TextureCubemap && flipImage)
    {
        CTexture tmp;
        tmp = m_images[3];
        m_images[3] = m_images[2];
        m_images[2] = tmp;
    }
    
    //fclose(fp);

    m_valid = true;

    return true;
}

void CDDSImage::write_texture(const CTexture &texture, FILE *fp)
{
    assert(get_num_mipmaps() == texture.get_num_mipmaps());
    
    fwrite(texture, 1, texture.get_size(), fp);
    
    for (unsigned int i = 0; i < texture.get_num_mipmaps(); i++)
    {
        const CSurface &mipmap = texture.get_mipmap(i);
        fwrite(mipmap, 1, mipmap.get_size(), fp);
    }
}

bool CDDSImage::save(std::string filename, bool flipImage)
{
    assert(m_valid);
    assert(m_type != TextureNone);

    DDS_HEADER ddsh;
    unsigned int headerSize = sizeof(DDS_HEADER);
    memset(&ddsh, 0, headerSize);
    ddsh.dwSize = headerSize;
    ddsh.dwFlags = DDSF_CAPS | DDSF_WIDTH | DDSF_HEIGHT | DDSF_PIXELFORMAT;
    ddsh.dwHeight = get_height();
    ddsh.dwWidth = get_width();

    if (is_compressed())
    {
        ddsh.dwFlags |= DDSF_LINEARSIZE;
        ddsh.dwPitchOrLinearSize = get_size();
    }
    else
    {
        ddsh.dwFlags |= DDSF_PITCH;
        ddsh.dwPitchOrLinearSize = get_dword_aligned_linesize(get_width(), m_components * 8);
    }
    
    if (m_type == Texture3D)
    {
        ddsh.dwFlags |= DDSF_DEPTH;
        ddsh.dwDepth = get_depth();
    }

    if (get_num_mipmaps() > 0)
    {
        ddsh.dwFlags |= DDSF_MIPMAPCOUNT;
        ddsh.dwMipMapCount = get_num_mipmaps() + 1;
    }

    ddsh.ddspf.dwSize = sizeof(DDS_PIXELFORMAT);

    if (is_compressed())
    {
        ddsh.ddspf.dwFlags = DDSF_FOURCC;
        
        if (m_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
            ddsh.ddspf.dwFourCC = FOURCC_DXT1;
        if (m_format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
            ddsh.ddspf.dwFourCC = FOURCC_DXT3;
        if (m_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
            ddsh.ddspf.dwFourCC = FOURCC_DXT5;
    }
    else
    {
        ddsh.ddspf.dwFlags = (m_components == 4) ? DDSF_RGBA : DDSF_RGB;
        ddsh.ddspf.dwRGBBitCount = m_components * 8;
        ddsh.ddspf.dwRBitMask = 0x00ff0000;
        ddsh.ddspf.dwGBitMask = 0x0000ff00;
        ddsh.ddspf.dwBBitMask = 0x000000ff;
 
        if (m_components == 4)
        {
            ddsh.ddspf.dwFlags |= DDSF_ALPHAPIXELS;
            ddsh.ddspf.dwABitMask = 0xff000000;
        }
    }
    
    ddsh.dwCaps1 = DDSF_TEXTURE;
    
    if (m_type == TextureCubemap)
    {
        ddsh.dwCaps1 |= DDSF_COMPLEX;
        ddsh.dwCaps2 = DDSF_CUBEMAP | DDSF_CUBEMAP_ALL_FACES;
    }

    if (m_type == Texture3D)
    {
        ddsh.dwCaps1 |= DDSF_COMPLEX;
        ddsh.dwCaps2 = DDSF_VOLUME;
    }

    if (get_num_mipmaps() > 0)
        ddsh.dwCaps1 |= DDSF_COMPLEX | DDSF_MIPMAP;

    // open file
    FILE *fp = fopen(filename.c_str(), "wb");
    if (fp == NULL)
        return false;

    // write file header
    fwrite("DDS ", 1, 4, fp);
    
    // write dds header
    fwrite(&ddsh, 1, sizeof(DDS_HEADER), fp);

    if (m_type != TextureCubemap)
    {
        CTexture tex = m_images[0];
        if (flipImage) flip_texture(tex);
        write_texture(tex, fp);
    }
    else
    {
        assert(m_images.size() == 6);

        for (unsigned int i = 0; i < m_images.size(); i++)
        {
            CTexture cubeFace;

            if (i == 2) 
                cubeFace = m_images[3];
            else if (i == 3) 
                cubeFace = m_images[2];
            else 
                cubeFace = m_images[i];

            if (flipImage) flip_texture(cubeFace);
            write_texture(cubeFace, fp);
        }
    }

    fclose(fp);
    return true;
}

///////////////////////////////////////////////////////////////////////////////
// free image memory
void CDDSImage::clear()
{
    m_components = 0;
    m_format = 0;
    m_type = TextureNone;
    m_valid = false;

    m_images.clear();
}

#ifndef BITMAP_NO_OPENGL

///////////////////////////////////////////////////////////////////////////////
// uploads a compressed/uncompressed 1D texture
bool CDDSImage::upload_texture1D()
{
    assert(m_valid);
    assert(!m_images.empty());

    const CTexture &baseImage = m_images[0];

    assert(baseImage.get_height() == 1);
    assert(baseImage.get_width() > 0);

    if (is_compressed())
    {
        // get function pointer if needed
        if (glCompressedTexImage1DARB == NULL)
        {
            GET_EXT_POINTER(glCompressedTexImage1DARB, 
                            PFNGLCOMPRESSEDTEXIMAGE1DARBPROC);
        }
        
        if (glCompressedTexImage1DARB == NULL)
            return false;
        
        glCompressedTexImage1DARB(GL_TEXTURE_1D, 0, m_format, 
            baseImage.get_width(), 0, baseImage.get_size(), baseImage);
        
        // load all mipmaps
        for (unsigned int i = 0; i < baseImage.get_num_mipmaps(); i++)
        {
            const CSurface &mipmap = baseImage.get_mipmap(i);
            glCompressedTexImage1DARB(GL_TEXTURE_1D, i+1, m_format, 
                mipmap.get_width(), 0, mipmap.get_size(), mipmap);
        }
    }
    else
    {
        GLint alignment = -1;
        if (!is_dword_aligned())
        {
            glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        }

        glTexImage1D(GL_TEXTURE_1D, 0, m_components, baseImage.get_width(), 0,
            m_format, GL_UNSIGNED_BYTE, baseImage);

        // load all mipmaps
        for (unsigned int i = 0; i < baseImage.get_num_mipmaps(); i++)
        {
            const CSurface &mipmap = baseImage.get_mipmap(i);

            glTexImage1D(GL_TEXTURE_1D, i+1, m_components, 
                mipmap.get_width(), 0, m_format, GL_UNSIGNED_BYTE, mipmap);
        }

        if (alignment != -1)
            glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
    }

    return true;
}

///////////////////////////////////////////////////////////////////////////////
// uploads a compressed/uncompressed 2D texture
//
// imageIndex - allows you to optionally specify other loaded surfaces for 2D
//              textures such as a face in a cubemap or a slice in a volume
//
//              default: 0
//
// target     - allows you to optionally specify a different texture target for
//              the 2D texture such as a specific face of a cubemap
//
//              default: GL_TEXTURE_2D
bool CDDSImage::upload_texture2D(unsigned int imageIndex, GLenum target)
{
    assert(m_valid);
    assert(!m_images.empty());
    assert(imageIndex >= 0);
    assert(imageIndex < m_images.size());
    assert(m_images[imageIndex]);

    const CTexture &image = m_images[imageIndex];

    assert(image.get_height() > 0);
    assert(image.get_width() > 0);
    assert(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_NV ||
        (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 
         target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB));
    
    if (is_compressed())
    {
        // load function pointer if needed
        if (glCompressedTexImage2DARB == NULL)
        {
            GET_EXT_POINTER(glCompressedTexImage2DARB, 
                            PFNGLCOMPRESSEDTEXIMAGE2DARBPROC);
        }
        
        if (glCompressedTexImage2DARB == NULL)
            return false;
        
        glCompressedTexImage2DARB(target, 0, m_format, image.get_width(), 
            image.get_height(), 0, image.get_size(), image);
        
        // load all mipmaps
        for (unsigned int i = 0; i < image.get_num_mipmaps(); i++)
        {
            const CSurface &mipmap = image.get_mipmap(i);

            glCompressedTexImage2DARB(target, i+1, m_format, 
                mipmap.get_width(), mipmap.get_height(), 0, 
                mipmap.get_size(), mipmap);
        }
    }
    else
    {
        GLint alignment = -1;
        if (!is_dword_aligned())
        {
            glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        }

        glTexImage2D(target, 0, m_components, image.get_width(), 
            image.get_height(), 0, m_format, GL_UNSIGNED_BYTE, 
            image);

        // load all mipmaps
        for (unsigned int i = 0; i < image.get_num_mipmaps(); i++)
        {
            const CSurface &mipmap = image.get_mipmap(i);
            
            glTexImage2D(target, i+1, m_components, mipmap.get_width(), 
                mipmap.get_height(), 0, m_format, GL_UNSIGNED_BYTE, mipmap); 
        }

        if (alignment != -1)
            glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
    }
    
    return true;
}

///////////////////////////////////////////////////////////////////////////////
// uploads a compressed/uncompressed 3D texture
bool CDDSImage::upload_texture3D()
{
    assert(m_valid);
    assert(!m_images.empty());
    assert(m_type == Texture3D);

    const CTexture &baseImage = m_images[0];
    
    assert(baseImage.get_depth() >= 1);

    if (is_compressed())
    {
        // retrieve function pointer if needed
        if (glCompressedTexImage3DARB == NULL)
        {
            GET_EXT_POINTER(glCompressedTexImage3DARB, 
                            PFNGLCOMPRESSEDTEXIMAGE3DARBPROC);
        }

        if (glCompressedTexImage3DARB == NULL)
            return false;

        glCompressedTexImage3DARB(GL_TEXTURE_3D, 0, m_format,  
            baseImage.get_width(), baseImage.get_height(), baseImage.get_depth(),
            0, baseImage.get_size(), baseImage);
        
        // load all mipmap volumes
        for (unsigned int i = 0; i < baseImage.get_num_mipmaps(); i++)
        {
            const CSurface &mipmap = baseImage.get_mipmap(i);

            glCompressedTexImage3DARB(GL_TEXTURE_3D, i+1, m_format, 
                mipmap.get_width(), mipmap.get_height(), mipmap.get_depth(), 
                0, mipmap.get_size(), mipmap);
        }
    }
    else
    {
        // retrieve function pointer if needed
        if (glTexImage3D == NULL)
        {
            GET_EXT_POINTER(glTexImage3D, PFNGLTEXIMAGE3DEXTPROC);
        }
    
        if (glTexImage3D == NULL)
            return false;
    
        GLint alignment = -1;
        if (!is_dword_aligned())
        {
            glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        }

        glTexImage3D(GL_TEXTURE_3D, 0, m_components, baseImage.get_width(), 
            baseImage.get_height(), baseImage.get_depth(), 0, m_format, 
            GL_UNSIGNED_BYTE, baseImage);
        
        // load all mipmap volumes
        for (unsigned int i = 0; i < baseImage.get_num_mipmaps(); i++)
        {
            const CSurface &mipmap = baseImage.get_mipmap(i);

            glTexImage3D(GL_TEXTURE_3D, i+1, m_components, 
                mipmap.get_width(), mipmap.get_height(), mipmap.get_depth(), 0, 
                m_format, GL_UNSIGNED_BYTE,  mipmap);
        }

        if (alignment != -1)
            glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
    }
    
    return true;
}

bool CDDSImage::upload_textureRectangle()
{
    return upload_texture2D(0, GL_TEXTURE_RECTANGLE_NV);
}

///////////////////////////////////////////////////////////////////////////////
// uploads a compressed/uncompressed cubemap texture
bool CDDSImage::upload_textureCubemap()
{
    assert(m_valid);
    assert(!m_images.empty());
    assert(m_type == TextureCubemap);
    assert(m_images.size() == 6);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?