📄 video.cpp
字号:
#include "video.h"
bool supportCompression = false;
bool supportMultiTex = false;
bool supportVBO = false;
bool supportDrawRangeElements = false;
//bool supportAntiAlias = false;
//int arbMultisampleFormat = 0;
TextureManager texturemanager;
int gXres, gYres;
// multitex
#ifdef _WIN32 PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL;
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB= NULL; #else // linux void (*wglGetProcAddress(const char *function_name))(void) { return glXGetProcAddress((GLubyte*)function_name); }#endif// compression
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB = NULL;
PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB = NULL;
// VBO
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
// Map / UnmapPFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
bool isExtensionSupported(const char *search)
{
char *exts = (char*)glGetString(GL_EXTENSIONS);
if (exts != NULL) {
string str(exts);
return (str.find(search) != string::npos);
}
return false;
}
/*
// InitMultisample: Used To Query The Multisample Frequencies
bool InitMultisample(HDC hDC)
{
const char *supported = NULL;
PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtString)
supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());
if (supported)
{
string str(supported);
supportAntiAlias = (str.find("WGL_ARB_multisample") != string::npos);
if (supportAntiAlias == false)
return false;
}
// Get Our Pixel Format
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
if (!wglChoosePixelFormatARB)
{
supportAntiAlias = false;
return false;
}
int pixelFormat;
int valid;
UINT numFormats;
float fAttributes[] = {0,0};
// These Attributes Are The Bits We Want To Test For In Our Sample
// Everything Is Pretty Standard, The Only One We Want To
// Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
// These Two Are Going To Do The Main Testing For Whether Or Not
// We Support Multisampling On This Hardware.
int iAttributes[] =
{
WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB,24,
WGL_ALPHA_BITS_ARB,8,
WGL_DEPTH_BITS_ARB,16,
WGL_STENCIL_BITS_ARB,0,
WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
WGL_SAMPLES_ARB,6,
0,0
};
// First We Check To See If We Can Get A Pixel Format For 6 Samples
valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes,1, &pixelFormat, &numFormats);
// If We Returned True, And Our Format Count Is Greater Than 1
if (valid && numFormats >= 1)
{
supportAntiAlias = true;
arbMultisampleFormat = pixelFormat;
return true;
}
// Our Pixel Format With 6 Samples Failed, Test For 4 Samples
iAttributes[19] = 4;
valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
if (valid && numFormats >= 1)
{
supportAntiAlias = true;
arbMultisampleFormat = pixelFormat;
return true;
}
// Our Pixel Format With 4 Samples Failed, Test For 2 Samples
iAttributes[19] = 2;
valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
if (valid && numFormats >= 1)
{
supportAntiAlias = true;
arbMultisampleFormat = pixelFormat;
return true;
}
// Return The Valid Format
supportAntiAlias = false;
return false;
}
*/
void InitExtensions()
{
char *exts = (char*)glGetString(GL_EXTENSIONS);
if (exts != NULL) {
wxLogMessage("Supported Video Extensions:\n%s\n", exts);
#ifdef _WIN32
if (isExtensionSupported("GL_EXT_draw_range_elements")) {
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) wglGetProcAddress("glDrawRangeElements");
supportDrawRangeElements = true;
} else supportDrawRangeElements = false;
#else
if (isExtensionSupported("GL_EXT_draw_range_elements")) {
supportDrawRangeElements = true;
} else supportDrawRangeElements = false;
#endif
if (isExtensionSupported("GL_ARB_multitexture")) {
supportMultiTex = true;
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
glClientActiveTextureARB= (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
} else supportMultiTex = false;
if (isExtensionSupported("GL_ARB_vertex_buffer_object"))
{
supportVBO = true;
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) wglGetProcAddress("glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC) wglGetProcAddress("glBindBufferARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC) wglGetProcAddress("glBufferDataARB");
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) wglGetProcAddress("glDeleteBuffersARB");
glMapBufferARB = (PFNGLMAPBUFFERARBPROC) wglGetProcAddress("glMapBufferARB");
glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) wglGetProcAddress("glUnmapBufferARB");
} else supportVBO = false;
if (isExtensionSupported("GL_ARB_texture_compression") && isExtensionSupported("GL_ARB_texture_cube_map")) {
glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) wglGetProcAddress("glCompressedTexImage2DARB");
supportCompression = isExtensionSupported("GL_EXT_texture_compression_s3tc");
} else supportCompression = false;
} else
wxLogMessage("No video extensions supported!\n");
wxLogMessage("Support Texture Compression: %s", supportCompression ? "true" : "false");
wxLogMessage("Support MultiTextures: %s", supportMultiTex ? "true" : "false");
wxLogMessage("Support DrawRangeElements: %s", supportDrawRangeElements ? "true" : "false");
wxLogMessage("Support Vertex Buffer Object: %s\n", supportVBO ? "true" : "false");
}
GLuint TextureManager::add(std::string name){ GLuint id = 0; if (names.find(name) != names.end()) { id = names[name]; items[id]->addref(); return id; } Texture *tex = new Texture(name); if (tex != NULL) { glGenTextures(1, &id); tex->id = id; LoadBLP(id, tex); do_add(name, id, tex); return id; } return 0;}
void TextureManager::LoadBLP(GLuint id, Texture *tex){ // load BLP texture glBindTexture(GL_TEXTURE_2D, id); int offsets[16], sizes[16], w, h; GLint format; char attr[4]; MPQFile f(tex->name.c_str()); if (f.isEof()) { tex->id = 0; return; } f.seek(8); f.read(attr,4); f.read(&w,4); f.read(&h,4); f.read(offsets,4*16); f.read(sizes,4*16); tex->w = w; tex->h = h; bool hasmipmaps = attr[4]>0; int mipmax = hasmipmaps ? 16 : 1; if (attr[0] == 2) { // compressed unsigned char *ucbuf = NULL; if (!supportCompression) ucbuf = new unsigned char[w*h*4]; format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; int blocksize = 8; // guesswork here :( if (attr[1]==8) { format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; blocksize = 16; } else { if (!attr[3]) format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } tex->compressed = true; unsigned char *buf = new unsigned char[sizes[0]]; // do every mipmap level for (int i=0; i<mipmax; i++) { if (w==0) w = 1; if (h==0) h = 1; if (offsets[i] && sizes[i]) { f.seek(offsets[i]); f.read(buf,sizes[i]); int size = ((w+3)/4) * ((h+3)/4) * blocksize; if (supportCompression) { glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0, size, buf); } else { decompressDXTC(format, w, h, size, buf, ucbuf); glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ucbuf); } } else break; w >>= 1; h >>= 1; } delete[] buf; if (!supportCompression) delete[] ucbuf; } else if (attr[0]==1) { // uncompressed unsigned int pal[256]; f.read(pal,1024); unsigned char *buf = new unsigned char[sizes[0]]; unsigned int *buf2 = new unsigned int[w*h]; unsigned int *p = NULL; unsigned char *c = NULL, *a = NULL; int alphabits = attr[1]; bool hasalpha = alphabits!=0; tex->compressed = false; for (int i=0; i<mipmax; i++) { if (w==0) w = 1; if (h==0) h = 1; if (offsets[i] && sizes[i]) { f.seek(offsets[i]); f.read(buf,sizes[i]); int cnt = 0; int alpha = 0; p = buf2; c = buf; a = buf + w*h; for (int y=0; y<h; y++) { for (int x=0; x<w; x++) { unsigned int k = pal[*c++]; k = ((k&0x00FF0000)>>16) | ((k&0x0000FF00)) | ((k& 0x000000FF)<<16); if (hasalpha) { if (alphabits == 8) { alpha = (*a++); } else if (alphabits == 1) { //alpha = (*a & (128 >> cnt++)) ? 0xff : 0; alpha = (*a & (1 << cnt++)) ? 0xff : 0; if (cnt == 8) { cnt = 0; a++; } } } else alpha = 0xff; k |= alpha << 24; *p++ = k; } } glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf2); } else break; w >>= 1; h >>= 1; } delete[] buf2; delete[] buf; } f.close(); if (hasmipmaps) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } // some models require texture wrapping though glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);}
void TextureManager::doDelete(GLuint id){ glDeleteTextures(1, &id);}void Texture::getPixels(unsigned char* buf){ glBindTexture(GL_TEXTURE_2D, id); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);}struct Color {
unsigned char r, g, b;
};
void decompressDXTC(GLint format, int w, int h, size_t size, unsigned char *src, unsigned char *dest)
{
// sort of copied from linghuye
int bsx = (w<4) ? w : 4;
int bsy = (h<4) ? h : 4;
/*
if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
DDSDecompressDXT1(src, w, h, dest);
return;
}
*/
if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
DDSDecompressDXT3(src, w, h, dest);
return;
}
/*
if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) {
DXT5UnpackAlphaValues(src, w, h, dest);
return;
}
*/
for(int y=0; y<h; y += bsy) {
for(int x=0; x<w; x += bsx) {
//unsigned long alpha = 0;
//unsigned int a0 = 0, a1 = 0;
unsigned int c0 = *(unsigned short*)(src + 0);
unsigned int c1 = *(unsigned short*)(src + 2);
src += 4;
Color color[4];
color[0].b = (unsigned char) ((c0 >> 11) & 0x1f) << 3;
color[0].g = (unsigned char) ((c0 >> 5) & 0x3f) << 2;
color[0].r = (unsigned char) ((c0 ) & 0x1f) << 3;
color[1].b = (unsigned char) ((c1 >> 11) & 0x1f) << 3;
color[1].g = (unsigned char) ((c1 >> 5) & 0x3f) << 2;
color[1].r = (unsigned char) ((c1 ) & 0x1f) << 3;
if(c0 > c1 || format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
color[2].r = (color[0].r * 2 + color[1].r) / 3;
color[2].g = (color[0].g * 2 + color[1].g) / 3;
color[2].b = (color[0].b * 2 + color[1].b) / 3;
color[3].r = (color[0].r + color[1].r * 2) / 3;
color[3].g = (color[0].g + color[1].g * 2) / 3;
color[3].b = (color[0].b + color[1].b * 2) / 3;
} else {
color[2].r = (color[0].r + color[1].r) / 2;
color[2].g = (color[0].g + color[1].g) / 2;
color[2].b = (color[0].b + color[1].b) / 2;
color[3].r = 0;
color[3].g = 0;
color[3].b = 0;
}
for (int j=0; j<bsy; j++) {
unsigned int index = *src++;
unsigned char* dd = dest + (w*(y+j)+x)*4;
for (int i=0; i<bsx; i++) {
*dd++ = color[index & 0x03].b;
*dd++ = color[index & 0x03].g;
*dd++ = color[index & 0x03].r;
//if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
*dd++ = ((index & 0x03) == 3 && c0 <= c1) ? 0 : 255;
//}
index >>= 2;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -