Init
This commit is contained in:
145
DependentExtensions/DXTCompressor/Src/DDSHeader.h
Normal file
145
DependentExtensions/DXTCompressor/Src/DDSHeader.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file was taken from RakNet 4.082 without any modifications.
|
||||
* Please see licenses/RakNet license.txt for the underlying license and related copyright.
|
||||
*/
|
||||
|
||||
#ifndef __DDS_HEADER_H__
|
||||
#define __DDS_HEADER_H__
|
||||
|
||||
// little-endian, of course
|
||||
#define DDS_MAGIC 0x20534444
|
||||
|
||||
|
||||
// DDS_header.dwFlags
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_WIDTH 0x00000004
|
||||
#define DDSD_PITCH 0x00000008
|
||||
#define DDSD_PIXELFORMAT 0x00001000
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_LINEARSIZE 0x00080000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
// DDS_header.sPixelFormat.dwFlags
|
||||
#define DDPF_ALPHAPIXELS 0x00000001
|
||||
#define DDPF_FOURCC 0x00000004
|
||||
#define DDPF_INDEXED 0x00000020
|
||||
#define DDPF_RGB 0x00000040
|
||||
|
||||
// DDS_header.sCaps.dwCaps1
|
||||
#define DDSCAPS_COMPLEX 0x00000008
|
||||
#define DDSCAPS_TEXTURE 0x00001000
|
||||
#define DDSCAPS_MIPMAP 0x00400000
|
||||
|
||||
// DDS_header.sCaps.dwCaps2
|
||||
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||
#define DDSCAPS2_VOLUME 0x00200000
|
||||
|
||||
#define D3DFMT_DXT1 '1TXD' // DXT1 compression texture format
|
||||
#define D3DFMT_DXT2 '2TXD' // DXT2 compression texture format
|
||||
#define D3DFMT_DXT3 '3TXD' // DXT3 compression texture format
|
||||
#define D3DFMT_DXT4 '4TXD' // DXT4 compression texture format
|
||||
#define D3DFMT_DXT5 '5TXD' // DXT5 compression texture format
|
||||
|
||||
#define PF_IS_DXT1(pf) \
|
||||
((pf.dwFlags & DDPF_FOURCC) && \
|
||||
(pf.dwFourCC == D3DFMT_DXT1))
|
||||
|
||||
#define PF_IS_DXT3(pf) \
|
||||
((pf.dwFlags & DDPF_FOURCC) && \
|
||||
(pf.dwFourCC == D3DFMT_DXT3))
|
||||
|
||||
#define PF_IS_DXT5(pf) \
|
||||
((pf.dwFlags & DDPF_FOURCC) && \
|
||||
(pf.dwFourCC == D3DFMT_DXT5))
|
||||
|
||||
#define PF_IS_BGRA8(pf) \
|
||||
((pf.dwFlags & DDPF_RGB) && \
|
||||
(pf.dwFlags & DDPF_ALPHAPIXELS) && \
|
||||
(pf.dwRGBBitCount == 32) && \
|
||||
(pf.dwRBitMask == 0xff0000) && \
|
||||
(pf.dwGBitMask == 0xff00) && \
|
||||
(pf.dwBBitMask == 0xff) && \
|
||||
(pf.dwAlphaBitMask == 0xff000000U))
|
||||
|
||||
#define PF_IS_BGR8(pf) \
|
||||
((pf.dwFlags & DDPF_ALPHAPIXELS) && \
|
||||
!(pf.dwFlags & DDPF_ALPHAPIXELS) && \
|
||||
(pf.dwRGBBitCount == 24) && \
|
||||
(pf.dwRBitMask == 0xff0000) && \
|
||||
(pf.dwGBitMask == 0xff00) && \
|
||||
(pf.dwBBitMask == 0xff))
|
||||
|
||||
#define PF_IS_BGR5A1(pf) \
|
||||
((pf.dwFlags & DDPF_RGB) && \
|
||||
(pf.dwFlags & DDPF_ALPHAPIXELS) && \
|
||||
(pf.dwRGBBitCount == 16) && \
|
||||
(pf.dwRBitMask == 0x00007c00) && \
|
||||
(pf.dwGBitMask == 0x000003e0) && \
|
||||
(pf.dwBBitMask == 0x0000001f) && \
|
||||
(pf.dwAlphaBitMask == 0x00008000))
|
||||
|
||||
#define PF_IS_BGR565(pf) \
|
||||
((pf.dwFlags & DDPF_RGB) && \
|
||||
!(pf.dwFlags & DDPF_ALPHAPIXELS) && \
|
||||
(pf.dwRGBBitCount == 16) && \
|
||||
(pf.dwRBitMask == 0x0000f800) && \
|
||||
(pf.dwGBitMask == 0x000007e0) && \
|
||||
(pf.dwBBitMask == 0x0000001f))
|
||||
|
||||
#define PF_IS_INDEX8(pf) \
|
||||
((pf.dwFlags & DDPF_INDEXED) && \
|
||||
(pf.dwRGBBitCount == 8))
|
||||
|
||||
|
||||
union DDS_header
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int dwMagic;
|
||||
unsigned int dwSize;
|
||||
unsigned int dwFlags;
|
||||
unsigned int dwHeight;
|
||||
unsigned int dwWidth;
|
||||
unsigned int dwPitchOrLinearSize;
|
||||
unsigned int dwDepth;
|
||||
unsigned int dwMipMapCount;
|
||||
unsigned int dwReserved1[ 11 ];
|
||||
|
||||
// DDPIXELFORMAT
|
||||
struct
|
||||
{
|
||||
unsigned int dwSize;
|
||||
unsigned int dwFlags;
|
||||
unsigned int dwFourCC;
|
||||
unsigned int dwRGBBitCount;
|
||||
unsigned int dwRBitMask;
|
||||
unsigned int dwGBitMask;
|
||||
unsigned int dwBBitMask;
|
||||
unsigned int dwAlphaBitMask;
|
||||
} sPixelFormat;
|
||||
|
||||
// DDCAPS2
|
||||
struct
|
||||
{
|
||||
unsigned int dwCaps1;
|
||||
unsigned int dwCaps2;
|
||||
unsigned int dwDDSX;
|
||||
unsigned int dwReserved;
|
||||
} sCaps;
|
||||
unsigned int dwReserved2;
|
||||
};
|
||||
|
||||
char data[ 128 ];
|
||||
};
|
||||
|
||||
#endif // mydds_h
|
||||
|
||||
|
||||
|
||||
813
DependentExtensions/DXTCompressor/Src/DXTCompressor.cpp
Normal file
813
DependentExtensions/DXTCompressor/Src/DXTCompressor.cpp
Normal file
@ -0,0 +1,813 @@
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Portions of this file have been written by using the "Compress YCOCgDXT" sample as a reference.
|
||||
// Please refer to http://developer.download.nvidia.com/SDK/10/opengl/samples.html#compress_YCoCgDXT for more information.
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* This file was taken from RakNet 4.082.
|
||||
* Please see licenses/RakNet license.txt for the underlying license and related copyright.
|
||||
*
|
||||
* Modified work: Copyright (c) 2020, SLikeSoft UG (haftungsbeschr<68>nkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Includes
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include "DXTCompressor.h"
|
||||
#include "FrameBufferRenderBuffer.hpp"
|
||||
#include "ShaderSource.h"
|
||||
#include "OpenGLWindow.hpp"
|
||||
#include <map>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Enable performance timing
|
||||
// #define DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Link with these libraries
|
||||
#pragma comment(lib, "glutstatic")
|
||||
#pragma comment(lib, "glew32")
|
||||
#pragma comment(lib, "cg")
|
||||
#pragma comment(lib, "cgGL")
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Defines
|
||||
#define DXTCOMPRESSOR_WINDOW_WIDTH 640
|
||||
#define DXTCOMPRESSOR_WINDOW_HEIGHT 480
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Static class data
|
||||
int DXTCompressor::m_initRefCount = 0;
|
||||
CGcontext DXTCompressor::m_cgContext;
|
||||
CGprofile DXTCompressor::m_cgVProfile;
|
||||
CGprofile DXTCompressor::m_cgFProfile;
|
||||
CGprogram DXTCompressor::m_compressVProg;
|
||||
CGprogram DXTCompressor::m_compressDXT1RGBAFProg;
|
||||
CGprogram DXTCompressor::m_compressDXT5RGBAFProg;
|
||||
CGprogram DXTCompressor::m_compressDXT1BGRAFProg;
|
||||
CGprogram DXTCompressor::m_compressDXT5BGRAFProg;
|
||||
|
||||
int DXTCompressor::m_numIterations = 0;
|
||||
int DXTCompressor::m_currentImageWidth = 0;
|
||||
int DXTCompressor::m_currentImageHeight = 0;
|
||||
float DXTCompressor::m_lastCompressionTime = 0;
|
||||
float DXTCompressor::m_accumulatedTime = 0;
|
||||
float DXTCompressor::m_timeRunningCompressionShader = 0;
|
||||
float DXTCompressor::m_timeCopyingPixelDataToCPU = 0;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Hash table to store framebuffer objects
|
||||
|
||||
struct FramebufferObjectKeyCompare
|
||||
{
|
||||
bool operator()(int s1, int s2) const
|
||||
{
|
||||
return s1 < s2;
|
||||
}
|
||||
};
|
||||
|
||||
typedef int FramebufferObjectKey;
|
||||
typedef class map< FramebufferObjectKey, FramebufferObject*, FramebufferObjectKeyCompare > FramebufferObjectHashtable;
|
||||
|
||||
// The hashtable
|
||||
FramebufferObjectHashtable s_frameBuffersHash;
|
||||
|
||||
// Hashkey generation
|
||||
FramebufferObjectKey GetHashKey( CompressionType compressionType, int width, int height )
|
||||
{
|
||||
return (int(compressionType) + width + (width*height));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
// Typedef ticks
|
||||
typedef __int64 Ticks;
|
||||
|
||||
inline Ticks GetTicks()
|
||||
{
|
||||
Ticks ticks;
|
||||
QueryPerformanceCounter( (LARGE_INTEGER*) &ticks);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
inline float TicksToMilliseconds( Ticks ticks )
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return float(float(ticks) * 1000.0f / float(freq.QuadPart));
|
||||
}
|
||||
|
||||
const int TIMER_STACK_SIZE = 256;
|
||||
static int g_currentStackId = 0;
|
||||
static Ticks g_startTrack[ TIMER_STACK_SIZE ];
|
||||
static Ticks g_endTrack[ TIMER_STACK_SIZE ];
|
||||
|
||||
// Used for tracking time
|
||||
inline void StartTracking()
|
||||
{
|
||||
g_startTrack[ g_currentStackId++ ] = GetTicks();
|
||||
}
|
||||
|
||||
inline void EndTracking()
|
||||
{
|
||||
g_endTrack[ --g_currentStackId ] = GetTicks();
|
||||
}
|
||||
|
||||
inline float GetDeltaTimeInSeconds()
|
||||
{
|
||||
Ticks delta = g_endTrack[ g_currentStackId ] - g_startTrack[ g_currentStackId ];
|
||||
return TicksToMilliseconds( delta ) / 1000.0f;
|
||||
}
|
||||
|
||||
inline float GetDeltaTimeInMilliseconds()
|
||||
{
|
||||
Ticks delta = g_endTrack[ g_currentStackId ] - g_startTrack[ g_currentStackId ];
|
||||
return TicksToMilliseconds( delta );
|
||||
}
|
||||
|
||||
#endif // #ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
DXTCompressor::DXTCompressor()
|
||||
{
|
||||
m_imageWidth = 0;
|
||||
m_imageHeight = 0;
|
||||
m_compressionType = DXT1;
|
||||
|
||||
m_pCompressFbo = 0;
|
||||
m_compressFboTex = 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::cgErrorCallback()
|
||||
{
|
||||
CGerror lastError = cgGetError();
|
||||
if( lastError )
|
||||
{
|
||||
printf( "%s\n", cgGetErrorString( lastError ) );
|
||||
printf( "%s\n", cgGetLastListing( m_cgContext ) );
|
||||
assert( false );
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
bool DXTCompressor::Initialize()
|
||||
{
|
||||
if( m_initRefCount == 0 )
|
||||
{
|
||||
if( !InitOpenGL() )
|
||||
return false;
|
||||
if( !InitCG() )
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initRefCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::Shutdown()
|
||||
{
|
||||
if( m_initRefCount > 0 )
|
||||
m_initRefCount--;
|
||||
|
||||
if( m_initRefCount == 0 )
|
||||
{
|
||||
// Deallocate buffers
|
||||
DeallocateBuffers();
|
||||
|
||||
// Shutdown cg stuff
|
||||
cgGLDisableProfile(m_cgVProfile);
|
||||
cgGLDisableProfile(m_cgFProfile);
|
||||
cgGLUnloadProgram( m_compressVProg );
|
||||
cgGLUnloadProgram( m_compressDXT1RGBAFProg );
|
||||
cgGLUnloadProgram( m_compressDXT5RGBAFProg );
|
||||
cgGLUnloadProgram( m_compressDXT1BGRAFProg );
|
||||
cgGLUnloadProgram( m_compressDXT5BGRAFProg );
|
||||
cgDestroyContext(m_cgContext);
|
||||
|
||||
// Kill the OpenGL window
|
||||
KillGLWindow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
bool DXTCompressor::InitOpenGL()
|
||||
{
|
||||
bool bFullscreen = false;
|
||||
#if 1
|
||||
// Compute desktop window width and height
|
||||
HWND desktopHwnd = GetDesktopWindow();
|
||||
RECT windowRect;
|
||||
GetWindowRect( desktopHwnd, &windowRect );
|
||||
int windowWidth = windowRect.right - windowRect.left;
|
||||
int windowHeight = windowRect.bottom - windowRect.top;
|
||||
bFullscreen = true;
|
||||
#else
|
||||
int windowWidth = 640;
|
||||
int windowHeight = 480;
|
||||
#endif
|
||||
|
||||
// Create the window; this is needed in order to invoke OpenGL commands
|
||||
BOOL windowCreateSuccess = CreateGLWindow( "Testing", windowWidth, windowHeight, 32, bFullscreen, true );
|
||||
if( !windowCreateSuccess )
|
||||
return false;
|
||||
|
||||
// Int GLEW
|
||||
glewInit();
|
||||
|
||||
// Make sure these extensions are supported
|
||||
if (!glewIsSupported(
|
||||
"GL_VERSION_2_0 "
|
||||
"GL_ARB_vertex_program "
|
||||
"GL_ARB_fragment_program "
|
||||
"GL_NV_gpu_program4 "
|
||||
"GL_ARB_pixel_buffer_object "
|
||||
"GL_EXT_framebuffer_object "
|
||||
"GL_ARB_texture_compression "
|
||||
"GL_EXT_texture_compression_s3tc "
|
||||
"GL_EXT_texture_integer "
|
||||
))
|
||||
{
|
||||
printf("Unable to load required OpenGL extension!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable depth testing
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClearColor(0.2, 0.2, 0.2, 1.0);
|
||||
|
||||
// Report any errors to the console screen
|
||||
glutReportErrors();
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
bool DXTCompressor::InitCG()
|
||||
{
|
||||
// Create Cg Context
|
||||
m_cgContext = cgCreateContext();
|
||||
cgSetErrorCallback( cgErrorCallback );
|
||||
|
||||
// Load Cg programs
|
||||
m_cgVProfile = cgGLGetLatestProfile( CG_GL_VERTEX );
|
||||
m_cgFProfile = cgGLGetLatestProfile( CG_GL_FRAGMENT );
|
||||
|
||||
// Shader compile options...
|
||||
const char *args[] =
|
||||
{
|
||||
"-unroll", "all",
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
m_compressVProg = cgCreateProgram( m_cgContext, CG_SOURCE, pDXTCompressorShaderSource, m_cgVProfile, "compress_vp", args );
|
||||
cgGLLoadProgram( m_compressVProg );
|
||||
|
||||
m_compressDXT1RGBAFProg = cgCreateProgram( m_cgContext, CG_SOURCE, pDXTCompressorShaderSource, m_cgFProfile, "compress_DXT1_RGBA_fp", args );
|
||||
cgGLLoadProgram( m_compressDXT1RGBAFProg );
|
||||
|
||||
m_compressDXT1BGRAFProg = cgCreateProgram( m_cgContext, CG_SOURCE, pDXTCompressorShaderSource, m_cgFProfile, "compress_DXT1_BGRA_fp", args );
|
||||
cgGLLoadProgram( m_compressDXT1BGRAFProg );
|
||||
|
||||
m_compressDXT5RGBAFProg = cgCreateProgram( m_cgContext, CG_SOURCE, pDXTCompressorShaderSource, m_cgFProfile, "compress_YCoCgDXT5_RGBA_fp", args );
|
||||
cgGLLoadProgram( m_compressDXT5RGBAFProg );
|
||||
|
||||
m_compressDXT5BGRAFProg = cgCreateProgram( m_cgContext, CG_SOURCE, pDXTCompressorShaderSource, m_cgFProfile, "compress_YCoCgDXT5_BGRA_fp", args );
|
||||
cgGLLoadProgram( m_compressDXT5BGRAFProg );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
bool DXTCompressor::IsInitialized()
|
||||
{
|
||||
return (m_initRefCount != 0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static GLuint CreateTexture( GLenum target, GLint internalformat, GLenum format, GLenum type, int w, int h )
|
||||
{
|
||||
GLuint tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(target, tex);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(target, 0, internalformat, w, h, 0, format, type, 0);
|
||||
return tex;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
FramebufferObject* DXTCompressor::RequestFBO( CompressionType compressionType, int width, int height )
|
||||
{
|
||||
// Get hash key
|
||||
FramebufferObjectKey hashKey = GetHashKey( compressionType, width, height );
|
||||
|
||||
// See if we have it in the hash
|
||||
if( s_frameBuffersHash.find( hashKey ) != s_frameBuffersHash.end() )
|
||||
{
|
||||
return s_frameBuffersHash[ hashKey ];
|
||||
}
|
||||
|
||||
// Create the texture
|
||||
GLuint newTextureID = 0;
|
||||
FramebufferObject* pNewFrameBufferObject = new FramebufferObject();
|
||||
if( compressionType == DXT1 )
|
||||
{
|
||||
newTextureID = CreateTexture(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_INT, width/4, height/4);
|
||||
}
|
||||
else if( compressionType == DXT5_YCOCG )
|
||||
{
|
||||
newTextureID = CreateTexture(GL_TEXTURE_2D, GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_INT, width/4, height/4);
|
||||
}
|
||||
|
||||
// Attach texture to framebuffer object
|
||||
pNewFrameBufferObject->Bind();
|
||||
pNewFrameBufferObject->AttachTexture(GL_TEXTURE_2D, newTextureID, GL_COLOR_ATTACHMENT0_EXT);
|
||||
pNewFrameBufferObject->IsValid();
|
||||
FramebufferObject::Disable();
|
||||
|
||||
// Add to hash
|
||||
s_frameBuffersHash[ hashKey ] = pNewFrameBufferObject;
|
||||
|
||||
// Return
|
||||
return pNewFrameBufferObject;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::DeallocateBuffers()
|
||||
{
|
||||
FramebufferObjectHashtable::iterator iter = s_frameBuffersHash.begin();
|
||||
while( iter != s_frameBuffersHash.end() )
|
||||
{
|
||||
// Delete object
|
||||
FramebufferObject* pFrameBufferObject = iter->second;
|
||||
GLuint textureID = pFrameBufferObject->GetAttachedTextureID();
|
||||
glDeleteTextures(1, &textureID);
|
||||
delete pFrameBufferObject;
|
||||
|
||||
// Bump
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static inline void SetParameter( CGprogram prog, char *name, float x, float y=0.0, float z=0.0, float w=0.0 )
|
||||
{
|
||||
CGparameter param = cgGetNamedParameter( prog, name );
|
||||
if( param )
|
||||
{
|
||||
cgGLSetParameter4f( param, x, y, z, w );
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::SetShaderConstants()
|
||||
{
|
||||
SetParameter( m_compressDXT1RGBAFProg, "imageSize", m_imageWidth, m_imageHeight );
|
||||
SetParameter( m_compressDXT5RGBAFProg, "imageSize", m_imageWidth, m_imageHeight );
|
||||
SetParameter( m_compressDXT1BGRAFProg, "imageSize", m_imageWidth, m_imageHeight );
|
||||
SetParameter( m_compressDXT5BGRAFProg, "imageSize", m_imageWidth, m_imageHeight );
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static inline void DrawQuad()
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::CompressInternal(bool sourceFormatIsBGRA)
|
||||
{
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
StartTracking();
|
||||
#endif
|
||||
|
||||
glViewport(0, 0, m_imageWidth/4, m_imageHeight/4);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
cgGLBindProgram(m_compressVProg);
|
||||
cgGLEnableProfile(m_cgVProfile);
|
||||
|
||||
if( m_compressionType == DXT5_YCOCG )
|
||||
{
|
||||
if (sourceFormatIsBGRA==false)
|
||||
cgGLBindProgram(m_compressDXT5RGBAFProg);
|
||||
else
|
||||
cgGLBindProgram(m_compressDXT5BGRAFProg);
|
||||
}
|
||||
else if( m_compressionType == DXT1 )
|
||||
{
|
||||
if (sourceFormatIsBGRA==false)
|
||||
cgGLBindProgram(m_compressDXT1RGBAFProg);
|
||||
else
|
||||
cgGLBindProgram(m_compressDXT1BGRAFProg);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false );
|
||||
}
|
||||
|
||||
cgGLEnableProfile(m_cgFProfile);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_imageTexId);
|
||||
SetShaderConstants();
|
||||
|
||||
DrawQuad();
|
||||
|
||||
cgGLDisableProfile(m_cgVProfile);
|
||||
cgGLDisableProfile(m_cgFProfile);
|
||||
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
glFinish();
|
||||
EndTracking();
|
||||
m_timeRunningCompressionShader += GetDeltaTimeInMilliseconds();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
int DXTCompressor::GetBufferSize( CompressionType compressionType, int inputWidth, int inputHeight )
|
||||
{
|
||||
if( compressionType == DXT5_YCOCG )
|
||||
{
|
||||
int size = (inputWidth/4)*(inputHeight/4)*8;
|
||||
return sizeof(GLushort)*size;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = (inputWidth/4)*(inputHeight/4)*4;
|
||||
return sizeof(GLushort)*size;
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
void DXTCompressor::DoCompression( void* ppOutputData, bool sourceFormatIsBGRA )
|
||||
{
|
||||
if( m_compressionType == DXT5_YCOCG )
|
||||
{
|
||||
// Render to integer fbo
|
||||
m_pCompressFbo->Bind();
|
||||
CompressInternal(sourceFormatIsBGRA);
|
||||
|
||||
// Readback data to host
|
||||
int size = (m_imageWidth/4)*(m_imageHeight/4)*8;
|
||||
GLushort *data = (GLushort *) ppOutputData;
|
||||
|
||||
// Copy pixel data
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
StartTracking();
|
||||
#endif
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
glReadPixels(0, 0, m_imageWidth/4, m_imageHeight/4, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, data);
|
||||
FramebufferObject::Disable();
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
EndTracking();
|
||||
m_timeCopyingPixelDataToCPU += GetDeltaTimeInMilliseconds();
|
||||
#endif
|
||||
}
|
||||
else if( m_compressionType == DXT1 )
|
||||
{
|
||||
// Render to integer fbo
|
||||
m_pCompressFbo->Bind();
|
||||
CompressInternal(sourceFormatIsBGRA);
|
||||
|
||||
// Readback data to host
|
||||
int size = (m_imageWidth/4)*(m_imageHeight/4)*4;
|
||||
GLushort *data = (GLushort *) ppOutputData;
|
||||
|
||||
// Copy pixel data
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
StartTracking();
|
||||
#endif
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
glReadPixels(0, 0, m_imageWidth/4, m_imageHeight/4, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT, data);
|
||||
FramebufferObject::Disable();
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
EndTracking();
|
||||
m_timeCopyingPixelDataToCPU += GetDeltaTimeInMilliseconds();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
bool DXTCompressor::CompressImageData( CompressionType compressionType, const void *inputRGBA, int inputWidth, int inputHeight, void *outputData, bool bDisplayResults, bool sourceFormatIsBGRA )
|
||||
{
|
||||
// Make sure we're initialized
|
||||
if( !IsInitialized() )
|
||||
{
|
||||
printf( "You need to initialize DXTCompressor before calling compress!\n " );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the source width and height are divisible by 4
|
||||
// This is a requirement by the DXT compression algorithm
|
||||
if( !( (inputWidth%4)==0 && (inputHeight%4)==0 ) )
|
||||
{
|
||||
printf( "Error! Input image width and height must be multiple of 4, as required by DXT compression rules. You have passed in an image of %dx%d", inputWidth, inputHeight );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Accumulate width and heights
|
||||
m_numIterations++;
|
||||
m_currentImageWidth = inputWidth;
|
||||
m_currentImageHeight = inputHeight;
|
||||
|
||||
// Instantiate the compressor
|
||||
DXTCompressor compressor;
|
||||
compressor.m_imageWidth = inputWidth;
|
||||
compressor.m_imageHeight = inputHeight;
|
||||
compressor.m_compressionType = compressionType;
|
||||
|
||||
// Make a copy of the source data and flip the Y. OpenGL rendering has Y going down
|
||||
/*
|
||||
char* pFlippedData = new char[ inputWidth*inputHeight*4 ];
|
||||
{
|
||||
const int rowSize = inputWidth*4;
|
||||
char* pRunnerDest = pFlippedData + (rowSize*(inputHeight-1));
|
||||
const char* pRunnerSrc = (const char*)inputRGBA;
|
||||
for( int row = inputHeight-1; row >=0; row-- )
|
||||
{
|
||||
memcpy( pRunnerDest, pRunnerSrc, rowSize );
|
||||
pRunnerSrc += rowSize;
|
||||
pRunnerDest -= rowSize;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Generate a texture and bind it to the input source data
|
||||
glGenTextures(1, &compressor.m_imageTexId);
|
||||
glBindTexture(GL_TEXTURE_2D, compressor.m_imageTexId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, inputWidth, inputHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)pFlippedData );
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, inputWidth, inputHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)inputRGBA );
|
||||
|
||||
// Request FBO
|
||||
compressor.m_pCompressFbo = RequestFBO( compressionType, inputWidth, inputHeight );
|
||||
compressor.m_compressFboTex = compressor.m_pCompressFbo->GetAttachedTextureID();
|
||||
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
// Start the clock
|
||||
StartTracking();
|
||||
#endif
|
||||
|
||||
// Do the compression
|
||||
compressor.DoCompression( outputData, sourceFormatIsBGRA );
|
||||
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
// Stop the clock
|
||||
EndTracking();
|
||||
m_lastCompressionTime = GetDeltaTimeInMilliseconds();
|
||||
m_accumulatedTime += m_lastCompressionTime;
|
||||
printf( "Compression time: %f ms\n", m_lastCompressionTime );
|
||||
#endif
|
||||
|
||||
// Display texture? Only DXT1 supported here.
|
||||
if( bDisplayResults && compressionType == DXT1 )
|
||||
{
|
||||
// Create empty dxt1 compressed texture
|
||||
GLuint tempDisplayTexture;
|
||||
int dxt1Size = (inputWidth/4)*(inputHeight/4)*8;
|
||||
GLubyte * tempPadData = new GLubyte [dxt1Size];
|
||||
memset(tempPadData, 0, dxt1Size);
|
||||
glGenTextures(1, &tempDisplayTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, tempDisplayTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, inputWidth, inputHeight, 0, dxt1Size, tempPadData);
|
||||
delete [] tempPadData;
|
||||
|
||||
// Re-upload the texture to VRAM for display
|
||||
int size = (inputWidth/4)*(inputHeight/4);
|
||||
glBindTexture(GL_TEXTURE_2D, tempDisplayTexture);
|
||||
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, inputWidth, inputHeight, 0, size*8, outputData);
|
||||
|
||||
// Display the texture
|
||||
DisplayTexture( tempDisplayTexture, inputWidth, inputHeight );
|
||||
|
||||
// Get rid of the texture
|
||||
glDeleteTextures(1, &tempDisplayTexture);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
// delete [] pFlippedData;
|
||||
// pFlippedData = nullptr;
|
||||
glDeleteTextures( 1, &compressor.m_imageTexId );
|
||||
|
||||
// Done
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "DDSHeader.h"
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
int DXTCompressor::GetDDSHeaderSize(void)
|
||||
{
|
||||
return sizeof(DDS_header);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::WriteDDSHeader( CompressionType compressionType, int width, int height, int compresedDataLength, void *outputData )
|
||||
{
|
||||
DDS_header* pHdr = (DDS_header*)outputData;
|
||||
memset( pHdr, 0, sizeof(DDS_header) );
|
||||
|
||||
pHdr->dwMagic = DDS_MAGIC;
|
||||
pHdr->dwSize = 124;
|
||||
pHdr->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
||||
pHdr->dwWidth = width;
|
||||
pHdr->dwHeight = height;
|
||||
|
||||
pHdr->sCaps.dwCaps1 = DDSCAPS_TEXTURE | DDSD_CAPS;
|
||||
|
||||
pHdr->sPixelFormat.dwSize = 32;
|
||||
pHdr->sPixelFormat.dwFlags = DDPF_FOURCC;
|
||||
|
||||
if( compressionType == DXT1 )
|
||||
pHdr->sPixelFormat.dwFourCC = D3DFMT_DXT1;
|
||||
else if( compressionType == DXT5_YCOCG )
|
||||
pHdr->sPixelFormat.dwFourCC = D3DFMT_DXT5;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::WriteDDSMemoryFile( CompressionType compressionType, int width, int height, const void* pCompressedData, int compresedDataLength, void **outputData, int *outputLength )
|
||||
{
|
||||
// Allocate the header + data
|
||||
int totalSize = sizeof(DDS_header) + compresedDataLength;
|
||||
void* pMemFile = new char[ totalSize ];
|
||||
|
||||
// Write the header
|
||||
WriteDDSHeader(compressionType, width, height, compresedDataLength, pMemFile );
|
||||
|
||||
// Write the data
|
||||
void* pData = ((char*)pMemFile + sizeof(DDS_header));
|
||||
memcpy( pData, pCompressedData, compresedDataLength );
|
||||
|
||||
// Return data to user
|
||||
*outputData = pMemFile;
|
||||
*outputLength = totalSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
void DXTCompressor::PrintPerformanceLog()
|
||||
{
|
||||
#ifdef DXTCOMPRESSOR_ENABLE_PERFORMANCE_TIMING
|
||||
// Compute
|
||||
float mPixelsPerSec = (m_currentImageWidth*m_currentImageHeight*m_numIterations) / (m_accumulatedTime*1e6/1000.0f);
|
||||
printf( "For %dx%d image, compression took %f ms, Average of %f mPixelsPerSec (mPixels/sec)\n", m_currentImageWidth, m_currentImageHeight, m_accumulatedTime/m_numIterations, mPixelsPerSec );
|
||||
printf( "%f ms was spent in running compression shader, %f ms was spent copying pixel data to main memory for the cpu\n", m_timeRunningCompressionShader/m_numIterations, m_timeCopyingPixelDataToCPU/m_numIterations );
|
||||
|
||||
// Reset stats
|
||||
m_currentImageWidth = 0;
|
||||
m_currentImageHeight = 0;
|
||||
m_numIterations = 0;
|
||||
m_accumulatedTime = 0;
|
||||
m_timeCopyingPixelDataToCPU = 0;
|
||||
m_timeRunningCompressionShader = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
static void glutPrint(float x, float y, const char *s, void *font)
|
||||
{
|
||||
int i, len;
|
||||
|
||||
glRasterPos2f(x, y);
|
||||
len = (int) strlen(s);
|
||||
for (i = 0; i < len; i++) {
|
||||
glutBitmapCharacter(font, s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool DrawTexture( GLuint textureID )
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glViewport(0,0,windowWidth,windowHeight);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
||||
DrawQuad();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
glutPrint(-0.95, -0.95, "DXT1 compressed (push ESC to close)", GLUT_BITMAP_9_BY_15);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientResize(HWND hWnd, int nWidth, int nHeight)
|
||||
{
|
||||
RECT rcClient, rcWindow;
|
||||
POINT ptDiff;
|
||||
GetClientRect(hWnd, &rcClient);
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
|
||||
ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
|
||||
MoveWindow(hWnd,rcWindow.left, rcWindow.top, nWidth + ptDiff.x, nHeight + ptDiff.y, TRUE);
|
||||
}
|
||||
|
||||
|
||||
void DXTCompressor::DisplayTexture( GLuint textureID, int texW, int texH )
|
||||
{
|
||||
// Show the window
|
||||
ShowWindow(hWnd,SW_SHOW);
|
||||
|
||||
// Resize the window to match the size of the texture
|
||||
ClientResize( hWnd, texW, texH );
|
||||
|
||||
// Windows message pump
|
||||
MSG msg;
|
||||
BOOL done=FALSE;
|
||||
while(!done)
|
||||
{
|
||||
if (PeekMessage(&msg, nullptr,0,0,PM_REMOVE))
|
||||
{
|
||||
if (msg.message==WM_QUIT)
|
||||
{
|
||||
done=TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((active && !DrawTexture( textureID )) || keys[VK_ESCAPE])
|
||||
{
|
||||
keys[VK_ESCAPE] = FALSE;
|
||||
done=TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the window
|
||||
ShowWindow(hWnd,SW_HIDE);
|
||||
}
|
||||
|
||||
98
DependentExtensions/DXTCompressor/Src/DXTCompressor.h
Normal file
98
DependentExtensions/DXTCompressor/Src/DXTCompressor.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This file was taken from RakNet 4.082 without any modifications.
|
||||
* Please see licenses/RakNet license.txt for the underlying license and related copyright.
|
||||
*/
|
||||
|
||||
#ifndef __DXT_COMPRESSOR_H__
|
||||
#define __DXT_COMPRESSOR_H__
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Includes
|
||||
#include <GL/glew.h>
|
||||
#include <GL/glut.h>
|
||||
#include <Cg/cg.h>
|
||||
#include <Cg/cgGL.h>
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
// Forward decls.
|
||||
class FramebufferObject;
|
||||
class Renderbuffer;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
enum CompressionType
|
||||
{
|
||||
DXT1,
|
||||
DXT5_YCOCG,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
class DXTCompressor
|
||||
{
|
||||
public:
|
||||
|
||||
DXTCompressor();
|
||||
|
||||
public:
|
||||
|
||||
// These need to be called before using the compressor, and shutdown after using the compressor
|
||||
static bool Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
// Compresses input data into the desired compressed format.
|
||||
// The input data is assumed to be 32-bit RGBA (1 byte per channel).
|
||||
// outputData should be allocated to at least GetBufferSize()
|
||||
// This will return true if the compression is successful.
|
||||
static bool CompressImageData( CompressionType compressionType, const void *inputRGBA, int inputWidth, int inputHeight, void *outputData, bool bDisplayResults, bool sourceFormatIsBGRA );
|
||||
static int GetBufferSize(CompressionType compressionType, int inputWidth, int inputHeight );
|
||||
|
||||
// Saves the compressed data into a Microsoft DDS file.
|
||||
static int GetDDSHeaderSize(void);
|
||||
static void WriteDDSHeader( CompressionType compressionType, int width, int height, int compresedDataLength, void *outputData );
|
||||
static void WriteDDSMemoryFile( CompressionType compressionType, int width, int height, const void* pCompressedData, int compresedDataLength, void **outputData, int *outputLength );
|
||||
|
||||
// Prints out the accumulated performance of the compressor
|
||||
static void PrintPerformanceLog();
|
||||
|
||||
private:
|
||||
|
||||
void SetShaderConstants();
|
||||
void CompressInternal( bool sourceFormatIsBGRA);
|
||||
void DoCompression( void* ppOutputData, bool sourceFormatIsBGRA );
|
||||
|
||||
static bool InitOpenGL();
|
||||
static bool InitCG();
|
||||
static void cgErrorCallback();
|
||||
static bool IsInitialized();
|
||||
static void DisplayTexture( GLuint textureID, int texW, int texH );
|
||||
static FramebufferObject* RequestFBO( CompressionType compressionType, int width, int height );
|
||||
static void DeallocateBuffers();
|
||||
|
||||
private:
|
||||
|
||||
// Image related data
|
||||
int m_imageWidth;
|
||||
int m_imageHeight;
|
||||
CompressionType m_compressionType;
|
||||
GLuint m_imageTexId;
|
||||
|
||||
FramebufferObject* m_pCompressFbo;
|
||||
GLuint m_compressFboTex;
|
||||
|
||||
// CG related data
|
||||
static int m_initRefCount;
|
||||
static CGcontext m_cgContext;
|
||||
static CGprofile m_cgVProfile, m_cgFProfile;
|
||||
static CGprogram m_compressVProg, m_compressDXT1RGBAFProg, m_compressDXT5RGBAFProg, m_compressDXT1BGRAFProg, m_compressDXT5BGRAFProg;
|
||||
|
||||
// Used to collect stats
|
||||
static int m_numIterations;
|
||||
static int m_currentImageWidth, m_currentImageHeight;
|
||||
static float m_lastCompressionTime;
|
||||
static float m_accumulatedTime;
|
||||
static float m_timeRunningCompressionShader;
|
||||
static float m_timeCopyingPixelDataToCPU;
|
||||
};
|
||||
|
||||
#endif // __DXT_COMPRESSOR_H__
|
||||
@ -0,0 +1,639 @@
|
||||
/*
|
||||
Copyright (c) 2005,
|
||||
Aaron Lefohn (lefohn@cs.ucdavis.edu)
|
||||
Adam Moerschell (atmoerschell@ucdavis.edu)
|
||||
All rights reserved.
|
||||
|
||||
This software is licensed under the BSD open-source license. See
|
||||
http://www.opensource.org/licenses/bsd-license.php for more detail.
|
||||
|
||||
*************************************************************
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the University of Californa, Davis nor the names of
|
||||
the contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __FRAMEBUFFERRENDERBUFFER_HPP__
|
||||
#define __FRAMEBUFFERRENDERBUFFER_HPP__
|
||||
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <iostream>
|
||||
|
||||
/*!
|
||||
FramebufferObject Class. This class encapsulates the FramebufferObject
|
||||
(FBO) OpenGL spec. See the official spec at:
|
||||
http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
|
||||
|
||||
for details.
|
||||
|
||||
A framebuffer object (FBO) is conceptually a structure containing pointers
|
||||
to GPU memory. The memory pointed to is either an OpenGL texture or an
|
||||
OpenGL RenderBuffer. FBOs can be used to render to one or more textures,
|
||||
share depth buffers between multiple sets of color buffers/textures and
|
||||
are a complete replacement for pbuffers.
|
||||
|
||||
Performance Notes:
|
||||
1) It is more efficient (but not required) to call Bind()
|
||||
on an FBO before making multiple method calls. For example:
|
||||
|
||||
FramebufferObject fbo;
|
||||
fbo.Bind();
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
|
||||
fbo.IsValid();
|
||||
|
||||
To provide a complete encapsulation, the following usage
|
||||
pattern works correctly but is less efficient:
|
||||
|
||||
FramebufferObject fbo;
|
||||
// NOTE : No Bind() call
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
|
||||
fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
|
||||
fbo.IsValid();
|
||||
|
||||
The first usage pattern binds the FBO only once, whereas
|
||||
the second usage binds/unbinds the FBO for each method call.
|
||||
|
||||
2) Use FramebufferObject::Disable() sparingly. We have intentionally
|
||||
left out an "Unbind()" method because it is largely unnecessary
|
||||
and encourages rendundant Bind/Unbind coding. Binding an FBO is
|
||||
usually much faster than enabling/disabling a pbuffer, but is
|
||||
still a costly operation. When switching between multiple FBOs
|
||||
and a visible OpenGL framebuffer, the following usage pattern
|
||||
is recommended:
|
||||
|
||||
FramebufferObject fbo1, fbo2;
|
||||
fbo1.Bind();
|
||||
... Render ...
|
||||
// NOTE : No Unbind/Disable here...
|
||||
|
||||
fbo2.Bind();
|
||||
... Render ...
|
||||
|
||||
// Disable FBO rendering and return to visible window
|
||||
// OpenGL framebuffer.
|
||||
FramebufferObject::Disable();
|
||||
*/
|
||||
class FramebufferObject
|
||||
{
|
||||
public:
|
||||
/// Ctor/Dtor
|
||||
FramebufferObject();
|
||||
virtual ~FramebufferObject();
|
||||
|
||||
/// Bind this FBO as current render target
|
||||
void Bind();
|
||||
|
||||
/// Bind a texture to the "attachment" point of this FBO
|
||||
virtual void AttachTexture( GLenum texTarget,
|
||||
GLuint texId,
|
||||
GLenum attachment = GL_COLOR_ATTACHMENT0_EXT,
|
||||
int mipLevel = 0,
|
||||
int zSlice = 0 );
|
||||
|
||||
/// Bind an array of textures to multiple "attachment" points of this FBO
|
||||
/// - By default, the first 'numTextures' attachments are used,
|
||||
/// starting with GL_COLOR_ATTACHMENT0_EXT
|
||||
virtual void AttachTextures( int numTextures,
|
||||
GLenum texTarget[],
|
||||
GLuint texId[],
|
||||
GLenum attachment[] = NULL,
|
||||
int mipLevel[] = NULL,
|
||||
int zSlice[] = NULL );
|
||||
|
||||
/// Bind a render buffer to the "attachment" point of this FBO
|
||||
virtual void AttachRenderBuffer( GLuint buffId,
|
||||
GLenum attachment = GL_COLOR_ATTACHMENT0_EXT );
|
||||
|
||||
/// Bind an array of render buffers to corresponding "attachment" points
|
||||
/// of this FBO.
|
||||
/// - By default, the first 'numBuffers' attachments are used,
|
||||
/// starting with GL_COLOR_ATTACHMENT0_EXT
|
||||
virtual void AttachRenderBuffers( int numBuffers, GLuint buffId[],
|
||||
GLenum attachment[] = NULL );
|
||||
|
||||
/// Free any resource bound to the "attachment" point of this FBO
|
||||
void Unattach( GLenum attachment );
|
||||
|
||||
/// Free any resources bound to any attachment points of this FBO
|
||||
void UnattachAll();
|
||||
|
||||
/// Is this FBO currently a valid render target?
|
||||
/// - Sends output to std::cerr by default but can
|
||||
/// be a user-defined C++ stream
|
||||
///
|
||||
/// NOTE : This function works correctly in debug build
|
||||
/// mode but always returns "true" if NDEBUG is
|
||||
/// is defined (optimized builds)
|
||||
#ifndef NDEBUG
|
||||
bool IsValid( std::ostream& ostr = std::cerr );
|
||||
#else
|
||||
bool IsValid( std::ostream& ostr = std::cerr ) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// BEGIN : Accessors
|
||||
/// Is attached type GL_RENDERBUFFER_EXT or GL_TEXTURE?
|
||||
GLenum GetAttachedType( GLenum attachment );
|
||||
|
||||
/// What is the Id of Renderbuffer/texture currently
|
||||
/// attached to "attachement?"
|
||||
GLuint GetAttachedId( GLenum attachment );
|
||||
|
||||
/// Which mipmap level is currently attached to "attachement?"
|
||||
GLint GetAttachedMipLevel( GLenum attachment );
|
||||
|
||||
/// Which cube face is currently attached to "attachment?"
|
||||
GLint GetAttachedCubeFace( GLenum attachment );
|
||||
|
||||
/// Which z-slice is currently attached to "attachment?"
|
||||
GLint GetAttachedZSlice( GLenum attachment );
|
||||
/// END : Accessors
|
||||
|
||||
GLuint GetAttachedTextureID() const { return m_attachedTexture; }
|
||||
|
||||
|
||||
/// BEGIN : Static methods global to all FBOs
|
||||
/// Return number of color attachments permitted
|
||||
static int GetMaxColorAttachments();
|
||||
|
||||
/// Disable all FBO rendering and return to traditional,
|
||||
/// windowing-system controlled framebuffer
|
||||
/// NOTE:
|
||||
/// This is NOT an "unbind" for this specific FBO, but rather
|
||||
/// disables all FBO rendering. This call is intentionally "static"
|
||||
/// and named "Disable" instead of "Unbind" for this reason. The
|
||||
/// motivation for this strange semantic is performance. Providing
|
||||
/// "Unbind" would likely lead to a large number of unnecessary
|
||||
/// FBO enablings/disabling.
|
||||
static void Disable();
|
||||
/// END : Static methods global to all FBOs
|
||||
|
||||
protected:
|
||||
void _GuardedBind();
|
||||
void _GuardedUnbind();
|
||||
void _FramebufferTextureND( GLenum attachment, GLenum texTarget,
|
||||
GLuint texId, int mipLevel, int zSlice );
|
||||
static GLuint _GenerateFboId();
|
||||
|
||||
private:
|
||||
GLuint m_fboId;
|
||||
GLint m_savedFboId;
|
||||
GLuint m_attachedTexture;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
FramebufferObject::FramebufferObject()
|
||||
: m_fboId(_GenerateFboId()),
|
||||
m_savedFboId(0)
|
||||
{
|
||||
// Bind this FBO so that it actually gets created now
|
||||
_GuardedBind();
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
FramebufferObject::~FramebufferObject()
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, &m_fboId);
|
||||
}
|
||||
|
||||
void FramebufferObject::Bind()
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
|
||||
}
|
||||
|
||||
void FramebufferObject::Disable()
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::AttachTexture( GLenum texTarget, GLuint texId,
|
||||
GLenum attachment, int mipLevel, int zSlice )
|
||||
{
|
||||
_GuardedBind();
|
||||
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
if( GetAttachedId(attachment) != texId ) {
|
||||
#endif
|
||||
*/
|
||||
|
||||
_FramebufferTextureND( attachment, texTarget,
|
||||
texId, mipLevel, zSlice );
|
||||
|
||||
m_attachedTexture = texId;
|
||||
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
else {
|
||||
cerr << "FramebufferObject::AttachTexture PERFORMANCE WARNING:\n"
|
||||
<< "\tRedundant bind of texture (id = " << texId << ").\n"
|
||||
<< "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[],
|
||||
GLenum attachment[], int mipLevel[], int zSlice[] )
|
||||
{
|
||||
for(int i = 0; i < numTextures; ++i) {
|
||||
AttachTexture( texTarget[i], texId[i],
|
||||
attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i),
|
||||
mipLevel ? mipLevel[i] : 0,
|
||||
zSlice ? zSlice[i] : 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::AttachRenderBuffer( GLuint buffId, GLenum attachment )
|
||||
{
|
||||
_GuardedBind();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if( GetAttachedId(attachment) != buffId ) {
|
||||
#endif
|
||||
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_RENDERBUFFER_EXT, buffId);
|
||||
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
else {
|
||||
cerr << "FramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n"
|
||||
<< "\tRedundant bind of Renderbuffer (id = " << buffId << ")\n"
|
||||
<< "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::AttachRenderBuffers( int numBuffers, GLuint buffId[], GLenum attachment[] )
|
||||
{
|
||||
for(int i = 0; i < numBuffers; ++i) {
|
||||
AttachRenderBuffer( buffId[i],
|
||||
attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i) );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::Unattach( GLenum attachment )
|
||||
{
|
||||
_GuardedBind();
|
||||
GLenum type = GetAttachedType(attachment);
|
||||
|
||||
switch(type) {
|
||||
case GL_NONE:
|
||||
break;
|
||||
case GL_RENDERBUFFER_EXT:
|
||||
AttachRenderBuffer( 0, attachment );
|
||||
break;
|
||||
case GL_TEXTURE:
|
||||
AttachTexture( GL_TEXTURE_2D, 0, attachment );
|
||||
break;
|
||||
default:
|
||||
cerr << "FramebufferObject::unbind_attachment ERROR: Unknown attached resource type\n";
|
||||
}
|
||||
_GuardedUnbind();
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::UnattachAll()
|
||||
{
|
||||
int numAttachments = GetMaxColorAttachments();
|
||||
for(int i = 0; i < numAttachments; ++i) {
|
||||
Unattach( GL_COLOR_ATTACHMENT0_EXT + i );
|
||||
}
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetMaxColorAttachments()
|
||||
{
|
||||
GLint maxAttach = 0;
|
||||
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach );
|
||||
return maxAttach;
|
||||
}
|
||||
|
||||
GLuint FramebufferObject::_GenerateFboId()
|
||||
{
|
||||
GLuint id = 0;
|
||||
glGenFramebuffersEXT(1, &id);
|
||||
return id;
|
||||
}
|
||||
|
||||
void FramebufferObject::_GuardedBind()
|
||||
{
|
||||
// Only binds if m_fboId is different than the currently bound FBO
|
||||
glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId );
|
||||
if (m_fboId != (GLuint)m_savedFboId) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferObject::_GuardedUnbind()
|
||||
{
|
||||
// Returns FBO binding to the previously enabled FBO
|
||||
if (m_fboId != (GLuint)m_savedFboId) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)m_savedFboId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FramebufferObject::_FramebufferTextureND( GLenum attachment, GLenum texTarget,
|
||||
GLuint texId, int mipLevel,
|
||||
int zSlice )
|
||||
{
|
||||
if (texTarget == GL_TEXTURE_1D) {
|
||||
glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_TEXTURE_1D, texId, mipLevel );
|
||||
}
|
||||
else if (texTarget == GL_TEXTURE_3D) {
|
||||
glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_TEXTURE_3D, texId, mipLevel, zSlice );
|
||||
}
|
||||
else {
|
||||
// Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
|
||||
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment,
|
||||
texTarget, texId, mipLevel );
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool FramebufferObject::IsValid( ostream& ostr )
|
||||
{
|
||||
_GuardedBind();
|
||||
|
||||
bool isOK = false;
|
||||
|
||||
GLenum status;
|
||||
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch(status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
|
||||
isOK = true;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n";
|
||||
isOK = false;
|
||||
break;
|
||||
default:
|
||||
ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
|
||||
<< "Unknown ERROR\n";
|
||||
isOK = false;
|
||||
}
|
||||
|
||||
_GuardedUnbind();
|
||||
return isOK;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
/// Accessors
|
||||
GLenum FramebufferObject::GetAttachedType( GLenum attachment )
|
||||
{
|
||||
// Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
|
||||
_GuardedBind();
|
||||
GLint type = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
|
||||
&type);
|
||||
_GuardedUnbind();
|
||||
return GLenum(type);
|
||||
}
|
||||
|
||||
GLuint FramebufferObject::GetAttachedId( GLenum attachment )
|
||||
{
|
||||
_GuardedBind();
|
||||
GLint id = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
|
||||
&id);
|
||||
_GuardedUnbind();
|
||||
return GLuint(id);
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetAttachedMipLevel( GLenum attachment )
|
||||
{
|
||||
_GuardedBind();
|
||||
GLint level = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
|
||||
&level);
|
||||
_GuardedUnbind();
|
||||
return level;
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetAttachedCubeFace( GLenum attachment )
|
||||
{
|
||||
_GuardedBind();
|
||||
GLint level = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
|
||||
&level);
|
||||
_GuardedUnbind();
|
||||
return level;
|
||||
}
|
||||
|
||||
GLint FramebufferObject::GetAttachedZSlice( GLenum attachment )
|
||||
{
|
||||
_GuardedBind();
|
||||
GLint slice = 0;
|
||||
glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
|
||||
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
|
||||
&slice);
|
||||
_GuardedUnbind();
|
||||
return slice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
Renderbuffer Class. This class encapsulates the Renderbuffer OpenGL
|
||||
object described in the FramebufferObject (FBO) OpenGL spec.
|
||||
See the official spec at:
|
||||
http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
|
||||
for complete details.
|
||||
|
||||
A "Renderbuffer" is a chunk of GPU memory used by FramebufferObjects to
|
||||
represent "traditional" framebuffer memory (depth, stencil, and color buffers).
|
||||
By "traditional," we mean that the memory cannot be bound as a texture.
|
||||
With respect to GPU shaders, Renderbuffer memory is "write-only." Framebuffer
|
||||
operations such as alpha blending, depth test, alpha test, stencil test, etc.
|
||||
read from this memory in post-fragement-shader (ROP) operations.
|
||||
|
||||
The most common use of Renderbuffers is to create depth and stencil buffers.
|
||||
Note that as of 7/1/05, NVIDIA drivers to do not support stencil Renderbuffers.
|
||||
|
||||
Usage Notes:
|
||||
1) "internalFormat" can be any of the following:
|
||||
Valid OpenGL internal formats beginning with:
|
||||
RGB, RGBA, DEPTH_COMPONENT
|
||||
|
||||
or a stencil buffer format (not currently supported
|
||||
in NVIDIA drivers as of 7/1/05).
|
||||
STENCIL_INDEX1_EXT
|
||||
STENCIL_INDEX4_EXT
|
||||
STENCIL_INDEX8_EXT
|
||||
STENCIL_INDEX16_EXT
|
||||
*/
|
||||
class Renderbuffer
|
||||
{
|
||||
public:
|
||||
/// Ctors/Dtors
|
||||
Renderbuffer();
|
||||
Renderbuffer(GLenum internalFormat, int width, int height);
|
||||
~Renderbuffer();
|
||||
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void Set(GLenum internalFormat, int width, int height);
|
||||
GLuint GetId() const;
|
||||
|
||||
static GLint GetMaxSize();
|
||||
|
||||
private:
|
||||
GLuint m_bufId;
|
||||
static GLuint _CreateBufferId();
|
||||
};
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
Renderbuffer::Renderbuffer()
|
||||
: m_bufId(_CreateBufferId())
|
||||
{}
|
||||
|
||||
Renderbuffer::Renderbuffer(GLenum internalFormat, int width, int height)
|
||||
: m_bufId(_CreateBufferId())
|
||||
{
|
||||
Set(internalFormat, width, height);
|
||||
}
|
||||
|
||||
Renderbuffer::~Renderbuffer()
|
||||
{
|
||||
glDeleteRenderbuffersEXT(1, &m_bufId);
|
||||
}
|
||||
|
||||
void Renderbuffer::Bind()
|
||||
{
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufId);
|
||||
}
|
||||
|
||||
void Renderbuffer::Unbind()
|
||||
{
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void Renderbuffer::Set(GLenum internalFormat, int width, int height)
|
||||
{
|
||||
int maxSize = Renderbuffer::GetMaxSize();
|
||||
if (width > maxSize || height > maxSize ) {
|
||||
cerr << "Renderbuffer::Renderbuffer() ERROR:\n\t"
|
||||
<< "Size too big (" << width << ", " << height << ")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Guarded bind
|
||||
GLint savedId = 0;
|
||||
glGetIntegerv( GL_RENDERBUFFER_BINDING_EXT, &savedId );
|
||||
if (savedId != (GLint)m_bufId) {
|
||||
Bind();
|
||||
}
|
||||
|
||||
// Allocate memory for renderBuffer
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, width, height );
|
||||
|
||||
// Guarded unbind
|
||||
if (savedId != (GLint)m_bufId) {
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, savedId);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::GetId() const
|
||||
{
|
||||
return m_bufId;
|
||||
}
|
||||
|
||||
GLint Renderbuffer::GetMaxSize()
|
||||
{
|
||||
GLint maxAttach = 0;
|
||||
glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach );
|
||||
return maxAttach;
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::_CreateBufferId()
|
||||
{
|
||||
GLuint id = 0;
|
||||
glGenRenderbuffersEXT(1, &id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
#endif // __FRAMEBUFFERRENDERBUFFER_HPP__
|
||||
|
||||
358
DependentExtensions/DXTCompressor/Src/OpenGLWindow.hpp
Normal file
358
DependentExtensions/DXTCompressor/Src/OpenGLWindow.hpp
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* This Code Was Created By Jeff Molofee 2000
|
||||
* A HUGE Thanks To Fredric Echols For Cleaning Up
|
||||
* And Optimizing This Code, Making It More Flexible!
|
||||
* If You've Found This Code Useful, Please Let Me Know.
|
||||
* Visit My Site At nehe.gamedev.net
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was taken from RakNet 4.082.
|
||||
* Please see licenses/RakNet license.txt for the underlying license and related copyright.
|
||||
*
|
||||
* Modified work: Copyright (c) 2015-2020, SLikeSoft UG (haftungsbeschr<68>nkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <windows.h> // Header File For Windows
|
||||
#include <tchar.h> // Header File For Unicode conversion support
|
||||
#include <gl\gl.h> // Header File For The OpenGL32 Library
|
||||
#include <gl\glu.h> // Header File For The GLu32 Library
|
||||
|
||||
HDC hDC= nullptr; // Private GDI Device Context
|
||||
HGLRC hRC= nullptr; // Permanent Rendering Context
|
||||
HWND hWnd= nullptr; // Holds Our Window Handle
|
||||
HINSTANCE hInstance; // Holds The Instance Of The Application
|
||||
int windowWidth = 0, windowHeight = 0;
|
||||
|
||||
bool keys[256]; // Array Used For The Keyboard Routine
|
||||
bool active=TRUE; // Window Active Flag Set To TRUE By Default
|
||||
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
|
||||
|
||||
static void MessageBoxPrivate( HWND hWnd, const char* pMessage, const char* pTitle, int flags )
|
||||
{
|
||||
printf( "%s: %s\n", pTitle, pMessage );
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
|
||||
|
||||
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
|
||||
{
|
||||
if (height==0) // Prevent A Divide By Zero By
|
||||
{
|
||||
height=1; // Making Height Equal One
|
||||
}
|
||||
|
||||
glViewport(0,0,width,height); // Reset The Current Viewport
|
||||
|
||||
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
|
||||
glLoadIdentity(); // Reset The Projection Matrix
|
||||
|
||||
// Calculate The Aspect Ratio Of The Window
|
||||
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
|
||||
glLoadIdentity(); // Reset The Modelview Matrix
|
||||
}
|
||||
|
||||
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
|
||||
{
|
||||
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
|
||||
glClearDepth(1.0f); // Depth Buffer Setup
|
||||
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
|
||||
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
|
||||
return TRUE; // Initialization Went OK
|
||||
}
|
||||
|
||||
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
|
||||
glLoadIdentity(); // Reset The Current Modelview Matrix
|
||||
return TRUE; // Everything Went OK
|
||||
}
|
||||
|
||||
GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
|
||||
{
|
||||
if (fullscreen) // Are We In Fullscreen Mode?
|
||||
{
|
||||
ChangeDisplaySettings(nullptr,0); // If So Switch Back To The Desktop
|
||||
ShowCursor(TRUE); // Show Mouse Pointer
|
||||
}
|
||||
|
||||
if (hRC) // Do We Have A Rendering Context?
|
||||
{
|
||||
if (!wglMakeCurrent(nullptr, nullptr)) // Are We Able To Release The DC And RC Contexts?
|
||||
{
|
||||
MessageBoxPrivate(nullptr,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
|
||||
{
|
||||
MessageBoxPrivate(nullptr,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
hRC= nullptr; // Set RC To nullptr
|
||||
}
|
||||
|
||||
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
|
||||
{
|
||||
MessageBoxPrivate(nullptr,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
||||
hDC= nullptr; // Set DC To nullptr
|
||||
}
|
||||
|
||||
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
|
||||
{
|
||||
MessageBoxPrivate(nullptr,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
||||
hWnd= nullptr; // Set hWnd To nullptr
|
||||
}
|
||||
|
||||
if (!UnregisterClass(_T("OpenGL"),hInstance)) // Are We Able To Unregister Class
|
||||
{
|
||||
MessageBoxPrivate(nullptr,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
|
||||
hInstance= nullptr; // Set hInstance To nullptr
|
||||
}
|
||||
}
|
||||
|
||||
/* This Code Creates Our OpenGL Window. Parameters Are: *
|
||||
* title - Title To Appear At The Top Of The Window *
|
||||
* width - Width Of The GL Window Or Fullscreen Mode *
|
||||
* height - Height Of The GL Window Or Fullscreen Mode *
|
||||
* bits - Number Of Bits To Use For Color (8/16/24/32) *
|
||||
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
|
||||
|
||||
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag, bool hideWindow=true)
|
||||
{
|
||||
GLuint PixelFormat; // Holds The Results After Searching For A Match
|
||||
WNDCLASS wc; // Windows Class Structure
|
||||
DWORD dwExStyle; // Window Extended Style
|
||||
DWORD dwStyle; // Window Style
|
||||
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
|
||||
WindowRect.left=(long)0; // Set Left Value To 0
|
||||
WindowRect.right=(long)width; // Set Right Value To Requested Width
|
||||
WindowRect.top=(long)0; // Set Top Value To 0
|
||||
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
|
||||
|
||||
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
|
||||
|
||||
hInstance = GetModuleHandle(nullptr); // Grab An Instance For Our Window
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
|
||||
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
|
||||
wc.cbClsExtra = 0; // No Extra Window Data
|
||||
wc.cbWndExtra = 0; // No Extra Window Data
|
||||
wc.hInstance = hInstance; // Set The Instance
|
||||
wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO); // Load The Default Icon
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW); // Load The Arrow Pointer
|
||||
wc.hbrBackground = nullptr; // No Background Required For GL
|
||||
wc.lpszMenuName = nullptr; // We Don't Want A Menu
|
||||
wc.lpszClassName = _T("OpenGL"); // Set The Class Name
|
||||
|
||||
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
|
||||
{
|
||||
MessageBoxPrivate(nullptr,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
if (fullscreen) // Attempt Fullscreen Mode?
|
||||
{
|
||||
DEVMODE dmScreenSettings; // Device Mode
|
||||
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
|
||||
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
|
||||
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
|
||||
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
|
||||
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
|
||||
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
|
||||
|
||||
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
|
||||
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
|
||||
{
|
||||
/*
|
||||
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
|
||||
if (MessageBoxPrivate(nullptr,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
|
||||
{
|
||||
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pop Up A Message Box Letting User Know The Program Is Closing.
|
||||
MessageBoxPrivate(nullptr,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
*/
|
||||
fullscreen=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (fullscreen) // Are We Still In Fullscreen Mode?
|
||||
{
|
||||
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
|
||||
dwStyle=WS_POPUP; // Windows Style
|
||||
ShowCursor(FALSE); // Hide Mouse Pointer
|
||||
}
|
||||
else
|
||||
{
|
||||
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
|
||||
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
|
||||
}
|
||||
|
||||
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
|
||||
|
||||
// Create The Window
|
||||
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
|
||||
_T("OpenGL"), // Class Name
|
||||
_T("DXTCompress"), // Window Title
|
||||
dwStyle | // Defined Window Style
|
||||
WS_CLIPSIBLINGS | // Required Window Style
|
||||
WS_CLIPCHILDREN, // Required Window Style
|
||||
0, 0, // Window Position
|
||||
WindowRect.right-WindowRect.left, // Calculate Window Width
|
||||
WindowRect.bottom-WindowRect.top, // Calculate Window Height
|
||||
nullptr, // No Parent Window
|
||||
nullptr, // No Menu
|
||||
hInstance, // Instance
|
||||
nullptr))) // Dont Pass Anything To WM_CREATE
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||
1, // Version Number
|
||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||
static_cast<BYTE>(bits), // Select Our Color Depth
|
||||
0, 0, 0, 0, 0, 0, // Color Bits Ignored
|
||||
0, // No Alpha Buffer
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
16, // 16Bit Z-Buffer (Depth Buffer)
|
||||
0, // No Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 // Layer Masks Ignored
|
||||
};
|
||||
|
||||
if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
if( hideWindow )
|
||||
ShowWindow(hWnd,SW_HIDE); // Show The Window
|
||||
else
|
||||
ShowWindow(hWnd,SW_SHOW); // Show The Window
|
||||
SetForegroundWindow(hWnd); // Slightly Higher Priority
|
||||
SetFocus(hWnd); // Sets Keyboard Focus To The Window
|
||||
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
|
||||
|
||||
if (!InitGL()) // Initialize Our Newly Created GL Window
|
||||
{
|
||||
KillGLWindow(); // Reset The Display
|
||||
MessageBoxPrivate(nullptr,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return FALSE; // Return FALSE
|
||||
}
|
||||
|
||||
return TRUE; // Success
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
|
||||
UINT uMsg, // Message For This Window
|
||||
WPARAM wParam, // Additional Message Information
|
||||
LPARAM lParam) // Additional Message Information
|
||||
{
|
||||
switch (uMsg) // Check For Windows Messages
|
||||
{
|
||||
case WM_ACTIVATE: // Watch For Window Activate Message
|
||||
{
|
||||
if (!HIWORD(wParam)) // Check Minimization State
|
||||
{
|
||||
active=TRUE; // Program Is Active
|
||||
}
|
||||
else
|
||||
{
|
||||
active=FALSE; // Program Is No Longer Active
|
||||
}
|
||||
|
||||
return 0; // Return To The Message Loop
|
||||
}
|
||||
|
||||
case WM_SYSCOMMAND: // Intercept System Commands
|
||||
{
|
||||
switch (wParam) // Check System Calls
|
||||
{
|
||||
case SC_SCREENSAVE: // Screensaver Trying To Start?
|
||||
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
|
||||
return 0; // Prevent From Happening
|
||||
}
|
||||
break; // Exit
|
||||
}
|
||||
|
||||
case WM_CLOSE: // Did We Receive A Close Message?
|
||||
{
|
||||
PostQuitMessage(0); // Send A Quit Message
|
||||
return 0; // Jump Back
|
||||
}
|
||||
|
||||
case WM_KEYDOWN: // Is A Key Being Held Down?
|
||||
{
|
||||
keys[wParam] = TRUE; // If So, Mark It As TRUE
|
||||
return 0; // Jump Back
|
||||
}
|
||||
|
||||
case WM_KEYUP: // Has A Key Been Released?
|
||||
{
|
||||
keys[wParam] = FALSE; // If So, Mark It As FALSE
|
||||
return 0; // Jump Back
|
||||
}
|
||||
|
||||
case WM_SIZE: // Resize The OpenGL Window
|
||||
{
|
||||
windowWidth = LOWORD(lParam);
|
||||
windowHeight = HIWORD(lParam);
|
||||
ReSizeGLScene(windowWidth, windowHeight); // LoWord=Width, HiWord=Height
|
||||
return 0; // Jump Back
|
||||
}
|
||||
}
|
||||
|
||||
// Pass All Unhandled Messages To DefWindowProc
|
||||
return DefWindowProc(hWnd,uMsg,wParam,lParam);
|
||||
}
|
||||
571
DependentExtensions/DXTCompressor/Src/ShaderSource.h
Normal file
571
DependentExtensions/DXTCompressor/Src/ShaderSource.h
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
Real-time DXT1 & YCoCg DXT5 compression (Cg 2.0)
|
||||
Copyright (c) NVIDIA Corporation.
|
||||
Written by: Ignacio Castano <icastano@nvidia.com>
|
||||
|
||||
Thanks to JMP van Waveren, Simon Green, Eric Werness, Simon Brown
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
const char* pDXTCompressorShaderSource =
|
||||
" \n"
|
||||
"// vertex program \n"
|
||||
"void compress_vp(float4 pos : POSITION, \n"
|
||||
" float2 texcoord : TEXCOORD0, \n"
|
||||
" out float4 hpos : POSITION, \n"
|
||||
" out float2 o_texcoord : TEXCOORD0 \n"
|
||||
" ) \n"
|
||||
"{ \n"
|
||||
" o_texcoord = texcoord; \n"
|
||||
" hpos = pos; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"typedef unsigned int uint; \n"
|
||||
"typedef unsigned int2 uint2; \n"
|
||||
"typedef unsigned int3 uint3; \n"
|
||||
"typedef unsigned int4 uint4; \n"
|
||||
" \n"
|
||||
"const float offset = 128.0 / 255.0; \n"
|
||||
" \n"
|
||||
"// Use dot product to minimize RMS instead absolute distance like in the CPU compressor. \n"
|
||||
"float colorDistance(float3 c0, float3 c1) \n"
|
||||
"{ \n"
|
||||
" return dot(c0-c1, c0-c1); \n"
|
||||
"} \n"
|
||||
"float colorDistance(float2 c0, float2 c1) \n"
|
||||
"{ \n"
|
||||
" return dot(c0-c1, c0-c1); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
" \n"
|
||||
"void ExtractColorBlockRGB(out float3 col[16], sampler2D image, float2 texcoord, float2 imageSize) \n"
|
||||
"{ \n"
|
||||
" // use TXF instruction (integer coordinates with offset) \n"
|
||||
" // note offsets must be constant \n"
|
||||
" //int4 base = int4(wpos*4-2, 0, 0); \n"
|
||||
" int4 base = int4(texcoord * imageSize - 1.5, 0, 0); \n"
|
||||
" col[0] = tex2Dfetch(image, base, int2(0, 0)).rgb; \n"
|
||||
" col[1] = tex2Dfetch(image, base, int2(1, 0)).rgb; \n"
|
||||
" col[2] = tex2Dfetch(image, base, int2(2, 0)).rgb; \n"
|
||||
" col[3] = tex2Dfetch(image, base, int2(3, 0)).rgb; \n"
|
||||
" col[4] = tex2Dfetch(image, base, int2(0, 1)).rgb; \n"
|
||||
" col[5] = tex2Dfetch(image, base, int2(1, 1)).rgb; \n"
|
||||
" col[6] = tex2Dfetch(image, base, int2(2, 1)).rgb; \n"
|
||||
" col[7] = tex2Dfetch(image, base, int2(3, 1)).rgb; \n"
|
||||
" col[8] = tex2Dfetch(image, base, int2(0, 2)).rgb; \n"
|
||||
" col[9] = tex2Dfetch(image, base, int2(1, 2)).rgb; \n"
|
||||
" col[10] = tex2Dfetch(image, base, int2(2, 2)).rgb; \n"
|
||||
" col[11] = tex2Dfetch(image, base, int2(3, 2)).rgb; \n"
|
||||
" col[12] = tex2Dfetch(image, base, int2(0, 3)).rgb; \n"
|
||||
" col[13] = tex2Dfetch(image, base, int2(1, 3)).rgb; \n"
|
||||
" col[14] = tex2Dfetch(image, base, int2(2, 3)).rgb; \n"
|
||||
" col[15] = tex2Dfetch(image, base, int2(3, 3)).rgb; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"void ExtractColorBlockBGR(out float3 col[16], sampler2D image, float2 texcoord, float2 imageSize) \n"
|
||||
"{ \n"
|
||||
" // use TXF instruction (integer coordinates with offset) \n"
|
||||
" // note offsets must be constant \n"
|
||||
" //int4 base = int4(wpos*4-2, 0, 0); \n"
|
||||
" int4 base = int4(texcoord * imageSize - 1.5, 0, 0); \n"
|
||||
" col[0] = tex2Dfetch(image, base, int2(0, 0)).bgr; \n"
|
||||
" col[1] = tex2Dfetch(image, base, int2(1, 0)).bgr; \n"
|
||||
" col[2] = tex2Dfetch(image, base, int2(2, 0)).bgr; \n"
|
||||
" col[3] = tex2Dfetch(image, base, int2(3, 0)).bgr; \n"
|
||||
" col[4] = tex2Dfetch(image, base, int2(0, 1)).bgr; \n"
|
||||
" col[5] = tex2Dfetch(image, base, int2(1, 1)).bgr; \n"
|
||||
" col[6] = tex2Dfetch(image, base, int2(2, 1)).bgr; \n"
|
||||
" col[7] = tex2Dfetch(image, base, int2(3, 1)).bgr; \n"
|
||||
" col[8] = tex2Dfetch(image, base, int2(0, 2)).bgr; \n"
|
||||
" col[9] = tex2Dfetch(image, base, int2(1, 2)).bgr; \n"
|
||||
" col[10] = tex2Dfetch(image, base, int2(2, 2)).bgr; \n"
|
||||
" col[11] = tex2Dfetch(image, base, int2(3, 2)).bgr; \n"
|
||||
" col[12] = tex2Dfetch(image, base, int2(0, 3)).bgr; \n"
|
||||
" col[13] = tex2Dfetch(image, base, int2(1, 3)).bgr; \n"
|
||||
" col[14] = tex2Dfetch(image, base, int2(2, 3)).bgr; \n"
|
||||
" col[15] = tex2Dfetch(image, base, int2(3, 3)).bgr; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"float3 toYCoCg(float3 c) \n"
|
||||
"{ \n"
|
||||
" float Y = (c.r + 2 * c.g + c.b) * 0.25; \n"
|
||||
" float Co = ( ( 2 * c.r - 2 * c.b ) * 0.25 + offset ); \n"
|
||||
" float Cg = ( ( -c.r + 2 * c.g - c.b) * 0.25 + offset ); \n"
|
||||
" \n"
|
||||
" return float3(Y, Co, Cg); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"void ExtractColorBlockYCoCg_RGB(out float3 col[16], sampler2D image, float2 texcoord, float2 imageSize) \n"
|
||||
"{ \n"
|
||||
" // use TXF instruction (integer coordinates with offset) \n"
|
||||
" // note offsets must be constant \n"
|
||||
" //int4 base = int4(wpos*4-2, 0, 0); \n"
|
||||
" int4 base = int4(texcoord * imageSize - 1.5, 0, 0); \n"
|
||||
" col[0] = toYCoCg(tex2Dfetch(image, base, int2(0, 0)).rgb); \n"
|
||||
" col[1] = toYCoCg(tex2Dfetch(image, base, int2(1, 0)).rgb); \n"
|
||||
" col[2] = toYCoCg(tex2Dfetch(image, base, int2(2, 0)).rgb); \n"
|
||||
" col[3] = toYCoCg(tex2Dfetch(image, base, int2(3, 0)).rgb); \n"
|
||||
" col[4] = toYCoCg(tex2Dfetch(image, base, int2(0, 1)).rgb); \n"
|
||||
" col[5] = toYCoCg(tex2Dfetch(image, base, int2(1, 1)).rgb); \n"
|
||||
" col[6] = toYCoCg(tex2Dfetch(image, base, int2(2, 1)).rgb); \n"
|
||||
" col[7] = toYCoCg(tex2Dfetch(image, base, int2(3, 1)).rgb); \n"
|
||||
" col[8] = toYCoCg(tex2Dfetch(image, base, int2(0, 2)).rgb); \n"
|
||||
" col[9] = toYCoCg(tex2Dfetch(image, base, int2(1, 2)).rgb); \n"
|
||||
" col[10] = toYCoCg(tex2Dfetch(image, base, int2(2, 2)).rgb); \n"
|
||||
" col[11] = toYCoCg(tex2Dfetch(image, base, int2(3, 2)).rgb); \n"
|
||||
" col[12] = toYCoCg(tex2Dfetch(image, base, int2(0, 3)).rgb); \n"
|
||||
" col[13] = toYCoCg(tex2Dfetch(image, base, int2(1, 3)).rgb); \n"
|
||||
" col[14] = toYCoCg(tex2Dfetch(image, base, int2(2, 3)).rgb); \n"
|
||||
" col[15] = toYCoCg(tex2Dfetch(image, base, int2(3, 3)).rgb); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"void ExtractColorBlockYCoCg_BGR(out float3 col[16], sampler2D image, float2 texcoord, float2 imageSize) \n"
|
||||
"{ \n"
|
||||
" // use TXF instruction (integer coordinates with offset) \n"
|
||||
" // note offsets must be constant \n"
|
||||
" //int4 base = int4(wpos*4-2, 0, 0); \n"
|
||||
" int4 base = int4(texcoord * imageSize - 1.5, 0, 0); \n"
|
||||
" col[0] = toYCoCg(tex2Dfetch(image, base, int2(0, 0)).bgr); \n"
|
||||
" col[1] = toYCoCg(tex2Dfetch(image, base, int2(1, 0)).bgr); \n"
|
||||
" col[2] = toYCoCg(tex2Dfetch(image, base, int2(2, 0)).bgr); \n"
|
||||
" col[3] = toYCoCg(tex2Dfetch(image, base, int2(3, 0)).bgr); \n"
|
||||
" col[4] = toYCoCg(tex2Dfetch(image, base, int2(0, 1)).bgr); \n"
|
||||
" col[5] = toYCoCg(tex2Dfetch(image, base, int2(1, 1)).bgr); \n"
|
||||
" col[6] = toYCoCg(tex2Dfetch(image, base, int2(2, 1)).bgr); \n"
|
||||
" col[7] = toYCoCg(tex2Dfetch(image, base, int2(3, 1)).bgr); \n"
|
||||
" col[8] = toYCoCg(tex2Dfetch(image, base, int2(0, 2)).bgr); \n"
|
||||
" col[9] = toYCoCg(tex2Dfetch(image, base, int2(1, 2)).bgr); \n"
|
||||
" col[10] = toYCoCg(tex2Dfetch(image, base, int2(2, 2)).bgr); \n"
|
||||
" col[11] = toYCoCg(tex2Dfetch(image, base, int2(3, 2)).bgr); \n"
|
||||
" col[12] = toYCoCg(tex2Dfetch(image, base, int2(0, 3)).bgr); \n"
|
||||
" col[13] = toYCoCg(tex2Dfetch(image, base, int2(1, 3)).bgr); \n"
|
||||
" col[14] = toYCoCg(tex2Dfetch(image, base, int2(2, 3)).bgr); \n"
|
||||
" col[15] = toYCoCg(tex2Dfetch(image, base, int2(3, 3)).bgr); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"// find minimum and maximum colors based on bounding box in color space \n"
|
||||
"void FindMinMaxColorsBox(float3 block[16], out float3 mincol, out float3 maxcol) \n"
|
||||
"{ \n"
|
||||
" mincol = block[0]; \n"
|
||||
" maxcol = block[0]; \n"
|
||||
" \n"
|
||||
" for (int i = 1; i < 16; i++) { \n"
|
||||
" mincol = min(mincol, block[i]); \n"
|
||||
" maxcol = max(maxcol, block[i]); \n"
|
||||
" } \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"void InsetBBox(in out float3 mincol, in out float3 maxcol) \n"
|
||||
"{ \n"
|
||||
" float3 inset = (maxcol - mincol) / 16.0 - (8.0 / 255.0) / 16; \n"
|
||||
" mincol = saturate(mincol + inset); \n"
|
||||
" maxcol = saturate(maxcol - inset); \n"
|
||||
"} \n"
|
||||
"void InsetYBBox(in out float mincol, in out float maxcol) \n"
|
||||
"{ \n"
|
||||
" float inset = (maxcol - mincol) / 32.0 - (16.0 / 255.0) / 32.0; \n"
|
||||
" mincol = saturate(mincol + inset); \n"
|
||||
" maxcol = saturate(maxcol - inset); \n"
|
||||
"} \n"
|
||||
"void InsetCoCgBBox(in out float2 mincol, in out float2 maxcol) \n"
|
||||
"{ \n"
|
||||
" float2 inset = (maxcol - mincol) / 16.0 - (8.0 / 255.0) / 16; \n"
|
||||
" mincol = saturate(mincol + inset); \n"
|
||||
" maxcol = saturate(maxcol - inset); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"void SelectDiagonal(float3 block[16], in out float3 mincol, in out float3 maxcol) \n"
|
||||
"{ \n"
|
||||
" float3 center = (mincol + maxcol) * 0.5; \n"
|
||||
" \n"
|
||||
" float2 cov = 0; \n"
|
||||
" for (int i = 0; i < 16; i++) \n"
|
||||
" { \n"
|
||||
" float3 t = block[i] - center; \n"
|
||||
" cov.x += t.x * t.z; \n"
|
||||
" cov.y += t.y * t.z; \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" if (cov.x < 0) { \n"
|
||||
" float temp = maxcol.x; \n"
|
||||
" maxcol.x = mincol.x; \n"
|
||||
" mincol.x = temp; \n"
|
||||
" } \n"
|
||||
" if (cov.y < 0) { \n"
|
||||
" float temp = maxcol.y; \n"
|
||||
" maxcol.y = mincol.y; \n"
|
||||
" mincol.y = temp; \n"
|
||||
" } \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"float3 RoundAndExpand(float3 v, out uint w) \n"
|
||||
"{ \n"
|
||||
" int3 c = round(v * float3(31, 63, 31)); \n"
|
||||
" w = (c.r << 11) | (c.g << 5) | c.b; \n"
|
||||
" \n"
|
||||
" c.rb = (c.rb << 3) | (c.rb >> 2); \n"
|
||||
" c.g = (c.g << 2) | (c.g >> 4); \n"
|
||||
" \n"
|
||||
" return (float3)c * (1.0 / 255.0); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uint EmitEndPointsDXT1(in out float3 mincol, in out float3 maxcol) \n"
|
||||
"{ \n"
|
||||
" uint2 output; \n"
|
||||
" maxcol = RoundAndExpand(maxcol, output.x); \n"
|
||||
" mincol = RoundAndExpand(mincol, output.y); \n"
|
||||
" \n"
|
||||
" // We have to do this in case we select an alternate diagonal. \n"
|
||||
" if (output.x < output.y) \n"
|
||||
" { \n"
|
||||
" float3 tmp = mincol; \n"
|
||||
" mincol = maxcol; \n"
|
||||
" maxcol = tmp; \n"
|
||||
" return output.y | (output.x << 16); \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" return output.x | (output.y << 16); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uint EmitIndicesDXT1(float3 block[16], float3 mincol, float3 maxcol) \n"
|
||||
"{ \n"
|
||||
" const float RGB_RANGE = 3; \n"
|
||||
" \n"
|
||||
" float3 dir = (maxcol - mincol); \n"
|
||||
" float3 origin = maxcol + dir / (2.0 * RGB_RANGE); \n"
|
||||
" dir /= dot(dir, dir); \n"
|
||||
" \n"
|
||||
" // Compute indices \n"
|
||||
" uint indices = 0; \n"
|
||||
" for (int i = 0; i < 16; i++) \n"
|
||||
" { \n"
|
||||
" uint index = saturate(dot(origin - block[i], dir)) * RGB_RANGE; \n"
|
||||
" indices |= index << (i * 2); \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" uint i0 = (indices & 0x55555555); \n"
|
||||
" uint i1 = (indices & 0xAAAAAAAA) >> 1; \n"
|
||||
" indices = ((i0 ^ i1) << 1) | i1; \n"
|
||||
" \n"
|
||||
" // Output indices \n"
|
||||
" return indices; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"int ScaleYCoCg(float2 minColor, float2 maxColor) \n"
|
||||
"{ \n"
|
||||
" float2 m0 = abs(minColor - offset); \n"
|
||||
" float2 m1 = abs(maxColor - offset); \n"
|
||||
" \n"
|
||||
" float m = max(max(m0.x, m0.y), max(m1.x, m1.y)); \n"
|
||||
" \n"
|
||||
" const float s0 = 64.0 / 255.0; \n"
|
||||
" const float s1 = 32.0 / 255.0; \n"
|
||||
" \n"
|
||||
" int scale = 1; \n"
|
||||
" if (m < s0) scale = 2; \n"
|
||||
" if (m < s1) scale = 4; \n"
|
||||
" \n"
|
||||
" return scale; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"void SelectYCoCgDiagonal(const float3 block[16], in out float2 minColor, in out float2 maxColor) \n"
|
||||
"{ \n"
|
||||
" float2 mid = (maxColor + minColor) * 0.5; \n"
|
||||
" \n"
|
||||
" float cov = 0; \n"
|
||||
" for (int i = 0; i < 16; i++) \n"
|
||||
" { \n"
|
||||
" float2 t = block[i].yz - mid; \n"
|
||||
" cov += t.x * t.y; \n"
|
||||
" } \n"
|
||||
" if (cov < 0) { \n"
|
||||
" float tmp = maxColor.y; \n"
|
||||
" maxColor.y = minColor.y; \n"
|
||||
" minColor.y = tmp; \n"
|
||||
" } \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
" \n"
|
||||
"uint EmitEndPointsYCoCgDXT5(in out float2 mincol, in out float2 maxcol, int scale) \n"
|
||||
"{ \n"
|
||||
" maxcol = (maxcol - offset) * scale + offset; \n"
|
||||
" mincol = (mincol - offset) * scale + offset; \n"
|
||||
" \n"
|
||||
" InsetCoCgBBox(mincol, maxcol); \n"
|
||||
" \n"
|
||||
" maxcol = round(maxcol * float2(31, 63)); \n"
|
||||
" mincol = round(mincol * float2(31, 63)); \n"
|
||||
" \n"
|
||||
" int2 imaxcol = maxcol; \n"
|
||||
" int2 imincol = mincol; \n"
|
||||
" \n"
|
||||
" uint2 output; \n"
|
||||
" output.x = (imaxcol.r << 11) | (imaxcol.g << 5) | (scale - 1); \n"
|
||||
" output.y = (imincol.r << 11) | (imincol.g << 5) | (scale - 1); \n"
|
||||
" \n"
|
||||
" imaxcol.r = (imaxcol.r << 3) | (imaxcol.r >> 2); \n"
|
||||
" imaxcol.g = (imaxcol.g << 2) | (imaxcol.g >> 4); \n"
|
||||
" imincol.r = (imincol.r << 3) | (imincol.r >> 2); \n"
|
||||
" imincol.g = (imincol.g << 2) | (imincol.g >> 4); \n"
|
||||
" \n"
|
||||
" maxcol = (float2)imaxcol * (1.0 / 255.0); \n"
|
||||
" mincol = (float2)imincol * (1.0 / 255.0); \n"
|
||||
" \n"
|
||||
" // Undo rescale. \n"
|
||||
" maxcol = (maxcol - offset) / scale + offset; \n"
|
||||
" mincol = (mincol - offset) / scale + offset; \n"
|
||||
" \n"
|
||||
" return output.x | (output.y << 16); \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uint EmitIndicesYCoCgDXT5(float3 block[16], float2 mincol, float2 maxcol) \n"
|
||||
"{ \n"
|
||||
" const float COCG_RANGE = 3; \n"
|
||||
" \n"
|
||||
" float2 dir = (maxcol - mincol); \n"
|
||||
" float2 origin = maxcol + dir / (2.0 * COCG_RANGE); \n"
|
||||
" dir /= dot(dir, dir); \n"
|
||||
" \n"
|
||||
" // Compute indices \n"
|
||||
" uint indices = 0; \n"
|
||||
" for (int i = 0; i < 16; i++) \n"
|
||||
" { \n"
|
||||
" uint index = saturate(dot(origin - block[i].yz, dir)) * COCG_RANGE; \n"
|
||||
" indices |= index << (i * 2); \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" uint i0 = (indices & 0x55555555); \n"
|
||||
" uint i1 = (indices & 0xAAAAAAAA) >> 1; \n"
|
||||
" indices = ((i0 ^ i1) << 1) | i1; \n"
|
||||
" \n"
|
||||
" // Output indices \n"
|
||||
" return indices; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uint EmitAlphaEndPointsYCoCgDXT5(float mincol, float maxcol) \n"
|
||||
"{ \n"
|
||||
" uint c0 = round(mincol * 255); \n"
|
||||
" uint c1 = round(maxcol * 255); \n"
|
||||
" \n"
|
||||
" return (c0 << 8) | c1; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"// Optimized index selection. \n"
|
||||
"uint2 EmitAlphaIndicesYCoCgDXT5(float3 block[16], float minAlpha, float maxAlpha) \n"
|
||||
"{ \n"
|
||||
" const int ALPHA_RANGE = 7; \n"
|
||||
" \n"
|
||||
" float bias = maxAlpha + (maxAlpha - minAlpha) / (2.0 * ALPHA_RANGE); \n"
|
||||
" float scale = 1.0f / (maxAlpha - minAlpha); \n"
|
||||
" \n"
|
||||
" uint2 indices = 0; \n"
|
||||
" \n"
|
||||
" for (int i = 0; i < 6; i++) \n"
|
||||
" { \n"
|
||||
" uint index = saturate((bias - block[i].x) * scale) * ALPHA_RANGE; \n"
|
||||
" indices.x |= index << (3 * i); \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" for (int i = 6; i < 16; i++) \n"
|
||||
" { \n"
|
||||
" uint index = saturate((bias - block[i].x) * scale) * ALPHA_RANGE; \n"
|
||||
" indices.y |= index << (3 * i - 18); \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" uint2 i0 = (indices >> 0) & 0x09249249; \n"
|
||||
" uint2 i1 = (indices >> 1) & 0x09249249; \n"
|
||||
" uint2 i2 = (indices >> 2) & 0x09249249; \n"
|
||||
" \n"
|
||||
" i2 ^= i0 & i1; \n"
|
||||
" i1 ^= i0; \n"
|
||||
" i0 ^= (i1 | i2); \n"
|
||||
" \n"
|
||||
" indices.x = (i2.x << 2) | (i1.x << 1) | i0.x; \n"
|
||||
" indices.y = (((i2.y << 2) | (i1.y << 1) | i0.y) << 2) | (indices.x >> 16); \n"
|
||||
" indices.x <<= 16; \n"
|
||||
" \n"
|
||||
" return indices; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"// compress a 4x4 block to DXT1 format \n"
|
||||
"// integer version, renders to 2 x int32 buffer \n"
|
||||
"uint4 compress_DXT1_RGBA_fp(float2 texcoord : TEXCOORD0, \n"
|
||||
" uniform sampler2D image, \n"
|
||||
" uniform float2 imageSize = { 512.0, 512.0 } \n"
|
||||
" ) : COLOR \n"
|
||||
"{ \n"
|
||||
" // read block \n"
|
||||
" float3 block[16]; \n"
|
||||
" ExtractColorBlockRGB(block, image, texcoord, imageSize); \n"
|
||||
" \n"
|
||||
" // find min and max colors \n"
|
||||
" float3 mincol, maxcol; \n"
|
||||
" FindMinMaxColorsBox(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" SelectDiagonal(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" InsetBBox(mincol, maxcol); \n"
|
||||
" \n"
|
||||
" uint4 output; \n"
|
||||
" output.x = EmitEndPointsDXT1(mincol, maxcol); \n"
|
||||
" output.w = EmitIndicesDXT1(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" return output; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uint4 compress_DXT1_BGRA_fp(float2 texcoord : TEXCOORD0, \n"
|
||||
" uniform sampler2D image, \n"
|
||||
" uniform float2 imageSize = { 512.0, 512.0 } \n"
|
||||
" ) : COLOR \n"
|
||||
"{ \n"
|
||||
" // read block \n"
|
||||
" float3 block[16]; \n"
|
||||
" ExtractColorBlockBGR(block, image, texcoord, imageSize); \n"
|
||||
" \n"
|
||||
" // find min and max colors \n"
|
||||
" float3 mincol, maxcol; \n"
|
||||
" FindMinMaxColorsBox(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" SelectDiagonal(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" InsetBBox(mincol, maxcol); \n"
|
||||
" \n"
|
||||
" uint4 output; \n"
|
||||
" output.x = EmitEndPointsDXT1(mincol, maxcol); \n"
|
||||
" output.w = EmitIndicesDXT1(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" return output; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
" \n"
|
||||
"// compress a 4x4 block to YCoCg DXT5 format \n"
|
||||
"// integer version, renders to 4 x int32 buffer \n"
|
||||
"uint4 compress_YCoCgDXT5_RGBA_fp(float2 texcoord : TEXCOORD0, \n"
|
||||
" uniform sampler2D image, \n"
|
||||
" uniform float2 imageSize = { 512.0, 512.0 } \n"
|
||||
" ) : COLOR \n"
|
||||
"{ \n"
|
||||
" //imageSize = tex2Dsize(image, texcoord); \n"
|
||||
" \n"
|
||||
" // read block \n"
|
||||
" float3 block[16]; \n"
|
||||
" ExtractColorBlockYCoCg_RGB(block, image, texcoord, imageSize); \n"
|
||||
" \n"
|
||||
" // find min and max colors \n"
|
||||
" float3 mincol, maxcol; \n"
|
||||
" FindMinMaxColorsBox(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" SelectYCoCgDiagonal(block, mincol.yz, maxcol.yz); \n"
|
||||
" \n"
|
||||
" int scale = ScaleYCoCg(mincol.yz, maxcol.yz); \n"
|
||||
" \n"
|
||||
" // Output CoCg in DXT1 block. \n"
|
||||
" uint4 output; \n"
|
||||
" output.z = EmitEndPointsYCoCgDXT5(mincol.yz, maxcol.yz, scale); \n"
|
||||
" output.w = EmitIndicesYCoCgDXT5(block, mincol.yz, maxcol.yz); \n"
|
||||
" \n"
|
||||
" InsetYBBox(mincol.x, maxcol.x); \n"
|
||||
" \n"
|
||||
" // Output Y in DXT5 alpha block. \n"
|
||||
" output.x = EmitAlphaEndPointsYCoCgDXT5(mincol.x, maxcol.x); \n"
|
||||
" \n"
|
||||
" uint2 indices = EmitAlphaIndicesYCoCgDXT5(block, mincol.x, maxcol.x); \n"
|
||||
" output.x |= indices.x; \n"
|
||||
" output.y = indices.y; \n"
|
||||
" \n"
|
||||
" return output; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uint4 compress_YCoCgDXT5_BGRA_fp(float2 texcoord : TEXCOORD0, \n"
|
||||
" uniform sampler2D image, \n"
|
||||
" uniform float2 imageSize = { 512.0, 512.0 } \n"
|
||||
" ) : COLOR \n"
|
||||
"{ \n"
|
||||
" //imageSize = tex2Dsize(image, texcoord); \n"
|
||||
" \n"
|
||||
" // read block \n"
|
||||
" float3 block[16]; \n"
|
||||
" ExtractColorBlockYCoCg_BGR(block, image, texcoord, imageSize); \n"
|
||||
" \n"
|
||||
" // find min and max colors \n"
|
||||
" float3 mincol, maxcol; \n"
|
||||
" FindMinMaxColorsBox(block, mincol, maxcol); \n"
|
||||
" \n"
|
||||
" SelectYCoCgDiagonal(block, mincol.yz, maxcol.yz); \n"
|
||||
" \n"
|
||||
" int scale = ScaleYCoCg(mincol.yz, maxcol.yz); \n"
|
||||
" \n"
|
||||
" // Output CoCg in DXT1 block. \n"
|
||||
" uint4 output; \n"
|
||||
" output.z = EmitEndPointsYCoCgDXT5(mincol.yz, maxcol.yz, scale); \n"
|
||||
" output.w = EmitIndicesYCoCgDXT5(block, mincol.yz, maxcol.yz); \n"
|
||||
" \n"
|
||||
" InsetYBBox(mincol.x, maxcol.x); \n"
|
||||
" \n"
|
||||
" // Output Y in DXT5 alpha block. \n"
|
||||
" output.x = EmitAlphaEndPointsYCoCgDXT5(mincol.x, maxcol.x); \n"
|
||||
" \n"
|
||||
" uint2 indices = EmitAlphaIndicesYCoCgDXT5(block, mincol.x, maxcol.x); \n"
|
||||
" output.x |= indices.x; \n"
|
||||
" output.y = indices.y; \n"
|
||||
" \n"
|
||||
" return output; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"uniform bool reconstructColor = false; \n"
|
||||
"uniform bool displayError = false; \n"
|
||||
"uniform float errorScale = 4.0f; \n"
|
||||
" \n"
|
||||
"uniform sampler2D image : TEXUNIT0; \n"
|
||||
"uniform sampler2D originalImage : TEXUNIT1; \n"
|
||||
" \n"
|
||||
"float4 display_fp(float2 texcoord : TEXCOORD0) : COLOR \n"
|
||||
"{ \n"
|
||||
" float4 rgba = tex2D(image, texcoord); \n"
|
||||
" \n"
|
||||
" if (reconstructColor) \n"
|
||||
" { \n"
|
||||
" float Y = rgba.a; \n"
|
||||
" float scale = 1.0 / ((255.0 / 8.0) * rgba.b + 1); \n"
|
||||
" float Co = (rgba.r - offset) * scale; \n"
|
||||
" float Cg = (rgba.g - offset) * scale; \n"
|
||||
" \n"
|
||||
" float R = Y + Co - Cg; \n"
|
||||
" float G = Y + Cg; \n"
|
||||
" float B = Y - Co - Cg; \n"
|
||||
" \n"
|
||||
" rgba = float4(R, G, B, 1); \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" if (displayError) \n"
|
||||
" { \n"
|
||||
" float3 originalColor = tex2D(originalImage, texcoord).rgb; \n"
|
||||
" float3 diff = abs(rgba.rgb - originalColor) * errorScale; \n"
|
||||
" return float4(diff, 1); \n"
|
||||
" } \n"
|
||||
" else \n"
|
||||
" { \n"
|
||||
" return rgba; \n"
|
||||
" } \n"
|
||||
"} \n"
|
||||
" \n";
|
||||
194
DependentExtensions/DXTCompressor/Src/main.cpp
Normal file
194
DependentExtensions/DXTCompressor/Src/main.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* This file was taken from RakNet 4.082 without any modifications.
|
||||
* Please see licenses/RakNet license.txt for the underlying license and related copyright.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "DXTCompressor.h"
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
bool LoadTGAFromFile( const char* pFilename, void **image, int* width, int* height )
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
char identsize;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
unsigned short colourmapstart;
|
||||
unsigned short colourmaplength;
|
||||
char colourmapbits;
|
||||
unsigned short xstart;
|
||||
unsigned short ystart;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
char bits;
|
||||
char descriptor;
|
||||
|
||||
} TGA_HEADER;
|
||||
|
||||
// Open the file
|
||||
FILE* pic;
|
||||
if((pic=fopen( pFilename, "rb"))==NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Zero out the header
|
||||
TGA_HEADER TGAheader;
|
||||
memset(&TGAheader,0,sizeof(TGA_HEADER));
|
||||
|
||||
// Read the header
|
||||
fread(&TGAheader.identsize,sizeof(char),1,pic);
|
||||
fread(&TGAheader.colourmaptype,sizeof(char),1,pic);
|
||||
fread(&TGAheader.imagetype,sizeof(char),1,pic);
|
||||
fread(&TGAheader.colourmapstart,sizeof(unsigned short),1,pic);
|
||||
fread(&TGAheader.colourmaplength,sizeof(unsigned short),1,pic);
|
||||
fread(&TGAheader.colourmapbits,sizeof(char),1,pic);
|
||||
fread(&TGAheader.xstart,sizeof(unsigned short),1,pic);
|
||||
fread(&TGAheader.ystart,sizeof(unsigned short),1,pic);
|
||||
fread(&TGAheader.width,sizeof(unsigned short),1,pic);
|
||||
fread(&TGAheader.height,sizeof(unsigned short),1,pic);
|
||||
fread(&TGAheader.bits,sizeof(char),1,pic);
|
||||
fread(&TGAheader.descriptor,sizeof(char),1,pic);
|
||||
|
||||
*width = TGAheader.width;
|
||||
*height = TGAheader.height;
|
||||
int DataSize = TGAheader.width*TGAheader.height*4;
|
||||
|
||||
// Read the pixels
|
||||
*image = new char[DataSize];
|
||||
if ((TGAheader.descriptor>>5) & 1)
|
||||
{
|
||||
// Right side up
|
||||
fread(*image, sizeof(char),DataSize, pic);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Upside down
|
||||
for (int row=TGAheader.height-1; row >=0; row--)
|
||||
{
|
||||
fread(((char*) (*image))+row*TGAheader.width*TGAheader.bits/8, TGAheader.bits/8, TGAheader.width, pic);
|
||||
}
|
||||
|
||||
}
|
||||
// Close the file
|
||||
fclose(pic);
|
||||
|
||||
// TGA is stored on disk BGRA
|
||||
// Endian swap bits so that the image is actually in RGBA format
|
||||
if( TGAheader.bits == 32 )
|
||||
{
|
||||
unsigned char* pRunner = (unsigned char*)*image;
|
||||
for( int i = 0; i < DataSize; i+=4 )
|
||||
{
|
||||
char color[4] =
|
||||
{
|
||||
pRunner[ 0 ],
|
||||
pRunner[ 1 ],
|
||||
pRunner[ 2 ],
|
||||
pRunner[ 3 ],
|
||||
};
|
||||
|
||||
pRunner[ 0 ] = color[ 2 ];
|
||||
pRunner[ 1 ] = color[ 1 ];
|
||||
pRunner[ 2 ] = color[ 0 ];
|
||||
pRunner[ 3 ] = color[ 3 ];
|
||||
|
||||
pRunner += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
int main( int argc, const char* argv[] )
|
||||
{
|
||||
// Initialize the compressor
|
||||
DXTCompressor::Initialize();
|
||||
|
||||
// Load sample .tga
|
||||
void* pSourceData;
|
||||
int w, h;
|
||||
//bool bFileLoaded = LoadTGAFromFile( "1600x1200.tga", &pSourceData, &w, &h );
|
||||
bool bFileLoaded = LoadTGAFromFile( "320x200.tga", &pSourceData, &w, &h );
|
||||
|
||||
if( bFileLoaded )
|
||||
{
|
||||
|
||||
// Test performance
|
||||
// const int numIterations = 100;
|
||||
// for( int i = 0; i < numIterations; i++ )
|
||||
// {
|
||||
// // Compress the data
|
||||
// void* pOutputData;
|
||||
// int outputLength;
|
||||
// bool bCompressSuccess = DXTCompressor::CompressRGBAImageData( DXT1, pSourceData, w, h, &pOutputData, &outputLength, false );
|
||||
//
|
||||
// // Clean up
|
||||
// delete [] pOutputData;
|
||||
// pOutputData = NULL;
|
||||
// }
|
||||
|
||||
// Print total stats
|
||||
// printf( "\n\n****Total stats on %d iterations****\n", numIterations );
|
||||
// DXTCompressor::PrintPerformanceLog();
|
||||
|
||||
// Now test saving to DDS memory file
|
||||
{
|
||||
// Compress the data
|
||||
// void* pCompressedOutput;
|
||||
// int compressedOutputLength;
|
||||
// bool bCompressSuccess = DXTCompressor::CompressRGBAImageData( DXT1, pSourceData, w, h, &pCompressedOutput, &compressedOutputLength, false );
|
||||
|
||||
char *outputData;
|
||||
int bufferSize = DXTCompressor::GetBufferSize(DXT1,
|
||||
w,
|
||||
h);
|
||||
int ddsHeaderSize = DXTCompressor::GetDDSHeaderSize();
|
||||
outputData = (char*) malloc(bufferSize + ddsHeaderSize );
|
||||
bool bCompressSuccess = DXTCompressor::CompressRGBAImageData(
|
||||
DXT1,
|
||||
pSourceData,
|
||||
w,
|
||||
h,
|
||||
outputData+ddsHeaderSize, false );
|
||||
|
||||
|
||||
if( bCompressSuccess )
|
||||
{
|
||||
// Save DDS file
|
||||
// void* pOutputDDSFile;
|
||||
// int outputDDSFileLength;
|
||||
// DXTCompressor::WriteDDSMemoryFile( DXT1, w, h, pCompressedOutput, compressedOutputLength, &pOutputDDSFile, &outputDDSFileLength );
|
||||
|
||||
// Clean up
|
||||
// delete [] pCompressedOutput;
|
||||
// pCompressedOutput = NULL;
|
||||
// delete [] pOutputDDSFile;
|
||||
// pOutputDDSFile = NULL;
|
||||
|
||||
DXTCompressor::WriteDDSHeader(DXT1,
|
||||
w,
|
||||
h,
|
||||
bufferSize,
|
||||
outputData);
|
||||
|
||||
FILE *fp = fopen("DXTCompressorTGAtoDDS.dds", "wb");
|
||||
fwrite(outputData,1,bufferSize + ddsHeaderSize,fp);
|
||||
fclose(fp);
|
||||
|
||||
free(outputData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown the compressor
|
||||
DXTCompressor::Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user