diff --git a/compat/GL.hpp b/compat/GL.hpp index d22f2a7..608b9b5 100644 --- a/compat/GL.hpp +++ b/compat/GL.hpp @@ -89,6 +89,12 @@ void xglGenBuffers(GLsizei num, GLuint* buffers); void xglDeleteBuffers(GLsizei num, GLuint* buffers); void xglOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearpl, GLfloat farpl); void xglSwapIntervalEXT(int interval); +void xglEnableClientState(GLenum _array); +void xglDisableClientState(GLenum _array); +void xglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +void xglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +void xglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +void xglDrawArrays(GLenum mode, GLint first, GLsizei count); // @TODO: not the right place, but er, it's ok void drawArrayVT(GLuint buffer, int count, int stride); diff --git a/compat/GLExt.cpp b/compat/GLExt.cpp index e6b41e6..8ed32ea 100644 --- a/compat/GLExt.cpp +++ b/compat/GLExt.cpp @@ -7,16 +7,20 @@ ********************************************************************/ #include "GL.hpp" +#include HWND GetHWND(); extern LPCTSTR g_GameTitle; -// this sucks... F* you Microsoft for making me do this hacky ass bullsh*t. +// Don't undefine. It will make the game MUCH slower. +#define USE_HARDWARE_GL_BUFFERS +#ifdef USE_HARDWARE_GL_BUFFERS PFNGLBINDBUFFERPROC p_glBindBuffer; PFNGLBUFFERDATAPROC p_glBufferData; PFNGLGENBUFFERSPROC p_glGenBuffers; PFNGLDELETEBUFFERSPROC p_glDeleteBuffers; +#endif // this is stupidly hacky typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC) (int interval); @@ -25,24 +29,31 @@ PFNWGLSWAPINTERVALEXTPROC p_wglSwapIntervalEXT; bool xglInitted() { +#ifdef USE_HARDWARE_GL_BUFFERS return p_glBindBuffer && p_glBufferData && p_glGenBuffers && p_glDeleteBuffers; +#else + return true; +#endif } void xglInit() { +#ifdef USE_HARDWARE_GL_BUFFERS p_glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer"); p_glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData"); p_glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers"); p_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers"); +#endif p_wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); +#ifdef USE_HARDWARE_GL_BUFFERS if (!xglInitted()) - { MessageBox(GetHWND(), TEXT("Error initializing GL extensions. Update your graphics drivers!"), g_GameTitle, MB_OK); - } +#endif } +#ifdef USE_HARDWARE_GL_BUFFERS void xglBindBuffer(GLenum target, GLuint buffer) { p_glBindBuffer(target, buffer); @@ -63,6 +74,37 @@ void xglDeleteBuffers(GLsizei num, GLuint* buffers) p_glDeleteBuffers(num, buffers); } +void xglEnableClientState(GLenum _array) +{ + glEnableClientState(_array); +} + +void xglDisableClientState(GLenum _array) +{ + glDisableClientState(_array); +} + +void xglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + glTexCoordPointer(size, type, stride, pointer); +} + +void xglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + glColorPointer(size, type, stride, pointer); +} + +void xglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + glVertexPointer(size, type, stride, pointer); +} + +void xglDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + glDrawArrays(mode, first, count); +} +#endif + void xglOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearpl, GLfloat farpl) { return glOrtho(GLdouble(left), GLdouble(right), GLdouble(bottom), GLfloat(top), GLdouble(nearpl), GLdouble(farpl)); @@ -75,3 +117,270 @@ void xglSwapIntervalEXT(int interval) p_wglSwapIntervalEXT(interval); } + +#ifndef USE_HARDWARE_GL_BUFFERS + +// ** Incomplete software based emulation of OpenGL vertex buffers. + +struct GLBuffer +{ + GLuint m_id; + GLvoid* m_pBufferData; + GLsizei m_bufferSize; + GLenum m_usage; // as passed into glBufferData + + // vertex pointer + GLint m_vtx_size; + GLenum m_vtx_type; + GLsizei m_vtx_stride; + GLint m_vtx_offset; + + // texture coord pointer + GLint m_tc_size; + GLenum m_tc_type; + GLsizei m_tc_stride; + GLint m_tc_offset; + + // color pointer + GLint m_col_size; + GLenum m_col_type; + GLsizei m_col_stride; + GLint m_col_offset; + + GLBuffer(GLuint id) + { + m_id = id; + m_pBufferData = nullptr; + m_bufferSize = 0; + m_usage = 0; + } + + void SetVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* offset) + { + m_vtx_size = size; + m_vtx_type = type; + m_vtx_stride = stride; + m_vtx_offset = int(size_t(offset)); + } + + void SetTextureCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* offset) + { + m_tc_size = size; + m_tc_type = type; + m_tc_stride = stride; + m_tc_offset = int(size_t(offset)); + } + + void SetColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* offset) + { + m_col_size = size; + m_col_type = type; + m_col_stride = stride; + m_col_offset = int(size_t(offset)); + } +}; + +typedef std::unordered_map GLBufferMap; + +GLBufferMap g_GLBuffers; +GLBuffer* g_pCurrentlyBoundGLBuffer = nullptr; +GLuint g_NextGLBufferID; +bool g_bUseVertexArrays, g_bUseColorArrays, g_bUseTextureCoordArrays; // modified by xgl[En/Dis]ableClientState + +void xglGenBuffers(GLsizei num, GLuint* buffers) +{ + for (GLsizei i = 0; i < num; i++) + { + *buffers++ = ++g_NextGLBufferID; + g_GLBuffers[g_NextGLBufferID] = new GLBuffer(g_NextGLBufferID); + } + + LogMsg("g_NextGLBufferID=%d", g_NextGLBufferID); +} + +void xglAssert2(bool condition, const char* condstr, const char* file, int line) +{ + if (condition) return; + + LogMsg("Error: Assertion failed at %s:%d: %s", file, line, condstr); + +#ifdef _MSC_VER + assert(false); +#endif + + exit(1); +} +#define xglAssert(condition) xglAssert2(condition,#condition,__FILE__,__LINE__) + +void xglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + xglAssert(g_pCurrentlyBoundGLBuffer != nullptr); + g_pCurrentlyBoundGLBuffer->SetVertexPointer(size, type, stride, pointer); +} + +void xglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + xglAssert(g_pCurrentlyBoundGLBuffer != nullptr); + g_pCurrentlyBoundGLBuffer->SetTextureCoordPointer(size, type, stride, pointer); +} + +void xglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + xglAssert(g_pCurrentlyBoundGLBuffer != nullptr); + g_pCurrentlyBoundGLBuffer->SetColorPointer(size, type, stride, pointer); +} + +void xglBindBuffer(GLenum target, GLuint bufferID) +{ + xglAssert(target == GL_ARRAY_BUFFER); + + GLBufferMap::iterator iter = g_GLBuffers.find(bufferID); + if (iter == g_GLBuffers.end()) + return; + + g_pCurrentlyBoundGLBuffer = iter->second; +} + +void xglBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ + xglAssert(target == GL_ARRAY_BUFFER); + xglAssert(g_pCurrentlyBoundGLBuffer != nullptr); + + GLBuffer* pBuf = g_pCurrentlyBoundGLBuffer; + + // free the old data, if there was any + if (pBuf->m_pBufferData) + { + free(pBuf->m_pBufferData); + pBuf->m_pBufferData = nullptr; + } + + pBuf->m_pBufferData = (GLvoid*)malloc(size); + xglAssert(pBuf->m_pBufferData != nullptr); + + memcpy(pBuf->m_pBufferData, data, size); + + pBuf->m_usage = usage; +} + +void xglDeleteBuffer(GLsizei num) +{ + GLBufferMap::iterator iter = g_GLBuffers.find(num); + xglAssert(iter != g_GLBuffers.end()); + + if (iter->second == g_pCurrentlyBoundGLBuffer) + g_pCurrentlyBoundGLBuffer = nullptr; + + delete iter->second; + g_GLBuffers.erase(iter); +} + +void xglDeleteBuffers(GLsizei num, GLuint* buffers) +{ + for (GLsizei i = 0; i < num; i++) + { + xglDeleteBuffer(buffers[i]); + buffers[i] = 0; + } +} + +void xglEnableClientState(GLenum _array) +{ + if (_array == GL_VERTEX_ARRAY) + { + g_bUseVertexArrays = true; + return; + } + if (_array == GL_COLOR_ARRAY) + { + g_bUseColorArrays = true; + return; + } + if (_array == GL_TEXTURE_COORD_ARRAY) + { + g_bUseTextureCoordArrays = true; + return; + } + + glEnableClientState(_array); +} + +void xglDisableClientState(GLenum _array) +{ + if (_array == GL_VERTEX_ARRAY) + { + g_bUseVertexArrays = false; + return; + } + if (_array == GL_COLOR_ARRAY) + { + g_bUseColorArrays = false; + return; + } + if (_array == GL_TEXTURE_COORD_ARRAY) + { + g_bUseTextureCoordArrays = false; + return; + } + + glDisableClientState(_array); +} + +void xglDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + xglAssert(g_pCurrentlyBoundGLBuffer != nullptr); + GLBuffer* pBuf = g_pCurrentlyBoundGLBuffer; + + glBegin(mode); + + for (GLsizeiptr i = first, j = 0; j < count; i++, j++) + { + uintptr_t addr = uintptr_t(pBuf->m_pBufferData); + + void* pVtx = (void*)(addr + pBuf->m_vtx_offset + i * pBuf->m_vtx_stride); + void* pCol = (void*)(addr + pBuf->m_col_offset + i * pBuf->m_col_stride); + void* pTC = (void*)(addr + pBuf->m_tc_offset + i * pBuf->m_tc_stride); + + if (g_bUseTextureCoordArrays) + { + if (pBuf->m_tc_type == GL_FLOAT) + { + float* pfTC = (float*)pTC; + /**/ if (pBuf->m_tc_size == 2) + glTexCoord2fv(pfTC); + else xglAssert(!"Unimplemented texcoord size!"); + } + else xglAssert(!"Unimplemented texcoord type!"); + } + + if (g_bUseColorArrays) + { + if (pBuf->m_col_type == GL_UNSIGNED_BYTE) + { + uint8_t* pfCol = (uint8_t*)pCol; + /**/ if (pBuf->m_col_size == 4) + glColor4f(float(pfCol[0])/255.0f, float(pfCol[1])/255.0f, float(pfCol[2])/255.0f, float(pfCol[3])/255.0f); + else xglAssert(!"Unimplemented color size!"); + } + else xglAssert(!"Unimplemented color type!"); + } + + if (g_bUseVertexArrays) + { + if (pBuf->m_vtx_type == GL_FLOAT) + { + float* pfVtx = (float*)pVtx; + /**/ if (pBuf->m_vtx_size == 3) + glVertex3fv(pfVtx); + else if (pBuf->m_vtx_size == 2) + glVertex2fv(pfVtx); + else xglAssert(!"Unimplemented texcoord size!"); + } + else xglAssert(!"Unimplemented vertex type!"); + } + } + + glEnd(); +} + +#endif diff --git a/source/client/common/Utils.cpp b/source/client/common/Utils.cpp index 9935a59..35f73bf 100644 --- a/source/client/common/Utils.cpp +++ b/source/client/common/Utils.cpp @@ -303,28 +303,28 @@ void sleepMs(int ms) void drawArrayVT(GLuint buffer, int count, int stride) { xglBindBuffer(GL_ARRAY_BUFFER, buffer); - glTexCoordPointer(2, GL_FLOAT, stride, (void*)12); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(3, GL_FLOAT, stride, nullptr); - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_TRIANGLES, 0, count); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + xglTexCoordPointer(2, GL_FLOAT, stride, (void*)12); + xglEnableClientState(GL_TEXTURE_COORD_ARRAY); + xglVertexPointer(3, GL_FLOAT, stride, nullptr); + xglEnableClientState(GL_VERTEX_ARRAY); + xglDrawArrays(GL_TRIANGLES, 0, count); + xglDisableClientState(GL_VERTEX_ARRAY); + xglDisableClientState(GL_TEXTURE_COORD_ARRAY); } void drawArrayVTC(GLuint buffer, int count, int stride) { xglBindBuffer(GL_ARRAY_BUFFER, buffer); - glVertexPointer(3, GL_FLOAT, stride, nullptr); - glTexCoordPointer(2, GL_FLOAT, stride, (void*)12); - glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)20); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glDrawArrays(GL_TRIANGLES, 0, count); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); + xglVertexPointer(3, GL_FLOAT, stride, nullptr); + xglTexCoordPointer(2, GL_FLOAT, stride, (void*)12); + xglColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)20); + xglEnableClientState(GL_VERTEX_ARRAY); + xglEnableClientState(GL_TEXTURE_COORD_ARRAY); + xglEnableClientState(GL_COLOR_ARRAY); + xglDrawArrays(GL_TRIANGLES, 0, count); + xglDisableClientState(GL_VERTEX_ARRAY); + xglDisableClientState(GL_TEXTURE_COORD_ARRAY); + xglDisableClientState(GL_COLOR_ARRAY); } float Max(float a, float b) diff --git a/source/client/model/Cube.cpp b/source/client/model/Cube.cpp index 1e2eb31..5e8ea86 100644 --- a/source/client/model/Cube.cpp +++ b/source/client/model/Cube.cpp @@ -75,7 +75,9 @@ void Cube::addBox(float x, float y, float z, int d, int e, int f, float g) void Cube::compile(float scale) { - xglDeleteBuffers(1, &m_buffer); + if (m_bCompiled) + xglDeleteBuffers(1, &m_buffer); + xglGenBuffers(1, &m_buffer); Tesselator& t = Tesselator::instance; diff --git a/source/client/renderer/RenderList.cpp b/source/client/renderer/RenderList.cpp index a3c840d..1de0d01 100644 --- a/source/client/renderer/RenderList.cpp +++ b/source/client/renderer/RenderList.cpp @@ -108,9 +108,9 @@ void RenderList::render() void RenderList::renderChunks() { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + xglEnableClientState(GL_VERTEX_ARRAY); + xglEnableClientState(GL_COLOR_ARRAY); + xglEnableClientState(GL_TEXTURE_COORD_ARRAY); if (field_1C > 0) { @@ -121,16 +121,16 @@ void RenderList::renderChunks() glTranslatef(chk.field_C, chk.field_10, chk.field_14); xglBindBuffer(GL_ARRAY_BUFFER, chk.field_0); - glVertexPointer (3, GL_FLOAT, sizeof(Tesselator::Vertex), (void*)offsetof(Tesselator::Vertex, m_x)); - glTexCoordPointer(2, GL_FLOAT, sizeof(Tesselator::Vertex), (void*)offsetof(Tesselator::Vertex, m_u)); - glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(Tesselator::Vertex), (void*)offsetof(Tesselator::Vertex, m_color)); - glDrawArrays(GL_TRIANGLES, 0, chk.field_4); + xglVertexPointer (3, GL_FLOAT, sizeof(Tesselator::Vertex), (void*)offsetof(Tesselator::Vertex, m_x)); + xglTexCoordPointer(2, GL_FLOAT, sizeof(Tesselator::Vertex), (void*)offsetof(Tesselator::Vertex, m_u)); + xglColorPointer (4, GL_UNSIGNED_BYTE, sizeof(Tesselator::Vertex), (void*)offsetof(Tesselator::Vertex, m_color)); + xglDrawArrays(GL_TRIANGLES, 0, chk.field_4); glPopMatrix(); } } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + xglDisableClientState(GL_VERTEX_ARRAY); + xglDisableClientState(GL_COLOR_ARRAY); + xglDisableClientState(GL_TEXTURE_COORD_ARRAY); } diff --git a/source/client/renderer/Tesselator.cpp b/source/client/renderer/Tesselator.cpp index 00de01b..e5ad49a 100644 --- a/source/client/renderer/Tesselator.cpp +++ b/source/client/renderer/Tesselator.cpp @@ -162,31 +162,31 @@ void Tesselator::draw() if (m_bHaveTex) { // it won't use address 12, because we've bound a buffer object - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, m_u)); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + xglTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, m_u)); + xglEnableClientState(GL_TEXTURE_COORD_ARRAY); } if (m_bHaveColor) { // it won't use address 12, because we've bound a buffer object - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void*)offsetof(Vertex, m_color)); - glEnableClientState(GL_COLOR_ARRAY); + xglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void*)offsetof(Vertex, m_color)); + xglEnableClientState(GL_COLOR_ARRAY); } - glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, m_x)); - glEnableClientState(GL_VERTEX_ARRAY); + xglVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, m_x)); + xglEnableClientState(GL_VERTEX_ARRAY); // if we want to draw quads, draw triangles actually // otherwise, just pass the mode, it's fine if (m_drawArraysMode == GL_QUADS) - glDrawArrays(GL_TRIANGLES, 0, field_4); + xglDrawArrays(GL_TRIANGLES, 0, field_4); else - glDrawArrays(m_drawArraysMode, 0, field_4); + xglDrawArrays(m_drawArraysMode, 0, field_4); - glDisableClientState(GL_VERTEX_ARRAY); + xglDisableClientState(GL_VERTEX_ARRAY); if (m_bHaveColor) - glDisableClientState(GL_COLOR_ARRAY); + xglDisableClientState(GL_COLOR_ARRAY); if (m_bHaveTex) - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + xglDisableClientState(GL_TEXTURE_COORD_ARRAY); } clear();