mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
add experimental and mostly broken modern OpenGL backend
This commit is contained in:
parent
bbcc64a6e1
commit
1f05ebe1af
735
src/Graphics.c
735
src/Graphics.c
@ -970,6 +970,11 @@ void Gfx_OnWindowResize(void) {
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*----------------------------------------------------------OpenGL---------------------------------------------------------*
|
*----------------------------------------------------------OpenGL---------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
|
/* The OpenGL backend is a bit verbose, since it's really 3 backends in one:
|
||||||
|
* - OpenGL 1.1 (completely lacking GPU, fallbacks to say Windows built-in software rasteriser)
|
||||||
|
* - OpenGL 1.5 or OpenGL 1.2 + GL_ARB_vertex_buffer_object (default desktop backend)
|
||||||
|
* - OpenGL ES 2.0 (alternative modern-ish backend)
|
||||||
|
*/
|
||||||
#ifndef CC_BUILD_D3D9
|
#ifndef CC_BUILD_D3D9
|
||||||
#ifdef CC_BUILD_WIN
|
#ifdef CC_BUILD_WIN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -981,20 +986,23 @@ void Gfx_OnWindowResize(void) {
|
|||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Extensions from later than OpenGL 1.1 */
|
|
||||||
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
|
||||||
#define GL_ARRAY_BUFFER 0x8892
|
|
||||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
|
||||||
#define GL_STATIC_DRAW 0x88E4
|
|
||||||
#define GL_DYNAMIC_DRAW 0x88E8
|
|
||||||
#define GL_BGRA_EXT 0x80E1
|
|
||||||
|
|
||||||
#ifdef CC_BUILD_GL11
|
#ifdef CC_BUILD_GL11
|
||||||
static GfxResourceID gl_activeList;
|
static GfxResourceID gl_activeList;
|
||||||
#define gl_DYNAMICLISTID 1234567891
|
#define gl_DYNAMICLISTID 1234567891
|
||||||
static void* gl_dynamicListData;
|
static void* gl_dynamicListData;
|
||||||
|
#elif CC_BUILD_GLMODERN
|
||||||
|
#define _glBindBuffer(t,b) glBindBuffer(t,b)
|
||||||
|
#define _glDeleteBuffers(n,b) glDeleteBuffers(n,b)
|
||||||
|
#define _glGenBuffers(n,b) glGenBuffers(n,b)
|
||||||
|
#define _glBufferData(t,s,d,u) glBufferData(t,s,d,u)
|
||||||
|
#define _glBufferSubData(t,o,s,d) glBufferSubData(t,o,s,d)
|
||||||
#else
|
#else
|
||||||
/* Weak linked on OSX, so we don't need to use GetProcAddress */
|
/* Not present in some gl.h which only have up to OpenGL 1.1 */
|
||||||
|
#define GL_ARRAY_BUFFER 0x8892
|
||||||
|
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||||
|
#define GL_STATIC_DRAW 0x88E4
|
||||||
|
#define GL_DYNAMIC_DRAW 0x88E8
|
||||||
|
|
||||||
typedef void (APIENTRY *FUNC_GLBINDBUFFER) (GLenum target, GLuint buffer);
|
typedef void (APIENTRY *FUNC_GLBINDBUFFER) (GLenum target, GLuint buffer);
|
||||||
typedef void (APIENTRY *FUNC_GLDELETEBUFFERS) (GLsizei n, const GLuint *buffers);
|
typedef void (APIENTRY *FUNC_GLDELETEBUFFERS) (GLsizei n, const GLuint *buffers);
|
||||||
typedef void (APIENTRY *FUNC_GLGENBUFFERS) (GLsizei n, GLuint *buffers);
|
typedef void (APIENTRY *FUNC_GLGENBUFFERS) (GLsizei n, GLuint *buffers);
|
||||||
@ -1007,41 +1015,17 @@ static FUNC_GLBUFFERDATA _glBufferData;
|
|||||||
static FUNC_GLBUFFERSUBDATA _glBufferSubData;
|
static FUNC_GLBUFFERSUBDATA _glBufferSubData;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||||
|
#define GL_BGRA_EXT 0x80E1
|
||||||
static int gl_compare[8] = { GL_ALWAYS, GL_NOTEQUAL, GL_NEVER, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER };
|
static int gl_compare[8] = { GL_ALWAYS, GL_NOTEQUAL, GL_NEVER, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER };
|
||||||
|
|
||||||
typedef void (*GL_SetupVBFunc)(void);
|
typedef void (*GL_SetupVBFunc)(void);
|
||||||
typedef void (*GL_SetupVBRangeFunc)(int startVertex);
|
typedef void (*GL_SetupVBRangeFunc)(int startVertex);
|
||||||
static GL_SetupVBFunc gl_setupVBFunc;
|
static GL_SetupVBFunc gl_setupVBFunc;
|
||||||
static GL_SetupVBRangeFunc gl_setupVBRangeFunc;
|
static GL_SetupVBRangeFunc gl_setupVBRangeFunc;
|
||||||
|
|
||||||
#ifndef CC_BUILD_GL11
|
static void GL_CheckSupport(void);
|
||||||
static void GL_CheckVboSupport(void) {
|
static void GL_InitState(void);
|
||||||
const static String vboExt = String_FromConst("GL_ARB_vertex_buffer_object");
|
|
||||||
String extensions = String_FromReadonly(glGetString(GL_EXTENSIONS));
|
|
||||||
String version = String_FromReadonly(glGetString(GL_VERSION));
|
|
||||||
|
|
||||||
int major = (int)(version.buffer[0] - '0'); /* x.y. (and so forth) */
|
|
||||||
int minor = (int)(version.buffer[2] - '0');
|
|
||||||
|
|
||||||
/* Supported in core since 1.5 */
|
|
||||||
if (major > 1 || (major == 1 && minor >= 5)) {
|
|
||||||
_glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBuffer");
|
|
||||||
_glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffers");
|
|
||||||
_glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffers");
|
|
||||||
_glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferData");
|
|
||||||
_glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubData");
|
|
||||||
} else if (String_CaselessContains(&extensions, &vboExt)) {
|
|
||||||
_glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBufferARB");
|
|
||||||
_glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffersARB");
|
|
||||||
_glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffersARB");
|
|
||||||
_glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferDataARB");
|
|
||||||
_glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubDataARB");
|
|
||||||
} else {
|
|
||||||
Logger_Abort("Only OpenGL 1.1 supported.\n\n" \
|
|
||||||
"Compile the game with CC_BUILD_GL11, or ask on the classicube forums for it");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Gfx_Init(void) {
|
void Gfx_Init(void) {
|
||||||
struct GraphicsMode mode;
|
struct GraphicsMode mode;
|
||||||
GraphicsMode_MakeDefault(&mode);
|
GraphicsMode_MakeDefault(&mode);
|
||||||
@ -1051,15 +1035,9 @@ void Gfx_Init(void) {
|
|||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx.MaxTexWidth);
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx.MaxTexWidth);
|
||||||
Gfx.MaxTexHeight = Gfx.MaxTexWidth;
|
Gfx.MaxTexHeight = Gfx.MaxTexWidth;
|
||||||
|
|
||||||
#ifndef CC_BUILD_GL11
|
GL_CheckSupport();
|
||||||
Gfx.CustomMipmapsLevels = true;
|
GL_InitState();
|
||||||
GL_CheckVboSupport();
|
|
||||||
#endif
|
|
||||||
Gfx_InitDefaultResources();
|
Gfx_InitDefaultResources();
|
||||||
|
|
||||||
glHint(GL_FOG_HINT, GL_NICEST);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_Free(void) {
|
void Gfx_Free(void) {
|
||||||
@ -1142,7 +1120,6 @@ void Gfx_DeleteTexture(GfxResourceID* texId) {
|
|||||||
*texId = GFX_NULL;
|
*texId = GFX_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_SetTexturing(bool enabled) { gl_Toggle(GL_TEXTURE_2D); }
|
|
||||||
void Gfx_EnableMipmaps(void) { }
|
void Gfx_EnableMipmaps(void) { }
|
||||||
void Gfx_DisableMipmaps(void) { }
|
void Gfx_DisableMipmaps(void) { }
|
||||||
|
|
||||||
@ -1150,52 +1127,8 @@ void Gfx_DisableMipmaps(void) { }
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-----------------------------------------------------State management----------------------------------------------------*
|
*-----------------------------------------------------State management----------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
static PackedCol gl_lastFogCol;
|
|
||||||
static float gl_lastFogEnd = -1, gl_lastFogDensity = -1;
|
|
||||||
static int gl_lastFogMode = -1;
|
|
||||||
static PackedCol gl_lastClearCol;
|
static PackedCol gl_lastClearCol;
|
||||||
|
|
||||||
void Gfx_SetFog(bool enabled) {
|
|
||||||
gfx_fogEnabled = enabled;
|
|
||||||
gl_Toggle(GL_FOG);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetFogCol(PackedCol col) {
|
|
||||||
float rgba[4];
|
|
||||||
if (PackedCol_Equals(col, gl_lastFogCol)) return;
|
|
||||||
|
|
||||||
rgba[0] = col.R / 255.0f; rgba[1] = col.G / 255.0f;
|
|
||||||
rgba[2] = col.B / 255.0f; rgba[3] = col.A / 255.0f;
|
|
||||||
|
|
||||||
glFogfv(GL_FOG_COLOR, rgba);
|
|
||||||
gl_lastFogCol = col;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetFogDensity(float value) {
|
|
||||||
if (value == gl_lastFogDensity) return;
|
|
||||||
glFogf(GL_FOG_DENSITY, value);
|
|
||||||
gl_lastFogDensity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetFogEnd(float value) {
|
|
||||||
if (value == gl_lastFogEnd) return;
|
|
||||||
glFogf(GL_FOG_END, value);
|
|
||||||
gl_lastFogEnd = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetFogMode(FogFunc func) {
|
|
||||||
static GLint modes[3] = { GL_LINEAR, GL_EXP, GL_EXP2 };
|
|
||||||
if (func == gl_lastFogMode) return;
|
|
||||||
|
|
||||||
glFogi(GL_FOG_MODE, modes[func]);
|
|
||||||
gl_lastFogMode = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetFaceCulling(bool enabled) { gl_Toggle(GL_CULL_FACE); }
|
void Gfx_SetFaceCulling(bool enabled) { gl_Toggle(GL_CULL_FACE); }
|
||||||
void Gfx_SetAlphaTest(bool enabled) { gl_Toggle(GL_ALPHA_TEST); }
|
|
||||||
void Gfx_SetAlphaTestFunc(CompareFunc func, float value) {
|
|
||||||
glAlphaFunc(gl_compare[func], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetAlphaBlending(bool enabled) { gl_Toggle(GL_BLEND); }
|
void Gfx_SetAlphaBlending(bool enabled) { gl_Toggle(GL_BLEND); }
|
||||||
void Gfx_SetAlphaBlendFunc(BlendFunc srcFunc, BlendFunc dstFunc) {
|
void Gfx_SetAlphaBlendFunc(BlendFunc srcFunc, BlendFunc dstFunc) {
|
||||||
@ -1223,6 +1156,13 @@ void Gfx_SetDepthTestFunc(CompareFunc func) {
|
|||||||
glDepthFunc(gl_compare[func]);
|
glDepthFunc(gl_compare[func]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) {
|
||||||
|
Matrix_OrthographicOffCenter(matrix, 0.0f, width, height, 0.0f, -10000.0f, 10000.0f);
|
||||||
|
}
|
||||||
|
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) {
|
||||||
|
Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*---------------------------------------------------Vertex/Index buffers--------------------------------------------------*
|
*---------------------------------------------------Vertex/Index buffers--------------------------------------------------*
|
||||||
@ -1256,8 +1196,8 @@ GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_BindVb(GfxResourceID vb) { glBindBuffer(GL_ARRAY_BUFFER, vb); }
|
void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(GL_ARRAY_BUFFER, vb); }
|
||||||
void Gfx_BindIb(GfxResourceID ib) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); }
|
void Gfx_BindIb(GfxResourceID ib) { _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); }
|
||||||
|
|
||||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||||
if (!vb || *vb == GFX_NULL) return;
|
if (!vb || *vb == GFX_NULL) return;
|
||||||
@ -1270,212 +1210,15 @@ void Gfx_DeleteIb(GfxResourceID* ib) {
|
|||||||
_glDeleteBuffers(1, ib);
|
_glDeleteBuffers(1, ib);
|
||||||
*ib = GFX_NULL;
|
*ib = GFX_NULL;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { return gl_DYNAMICLISTID; }
|
|
||||||
GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat fmt, int count) {
|
|
||||||
/* We need to setup client state properly when building the list */
|
|
||||||
int curFormat = gfx_batchFormat, stride;
|
|
||||||
Gfx_SetVertexFormat(fmt);
|
|
||||||
|
|
||||||
GLuint list = glGenLists(1);
|
|
||||||
glNewList(list, GL_COMPILE);
|
|
||||||
count &= ~0x01; /* Need to get rid of the 1 extra element, see comment in chunk mesh builder for why */
|
|
||||||
|
|
||||||
uint16_t indices[GFX_MAX_INDICES];
|
|
||||||
Gfx_MakeIndices(indices, ICOUNT(count));
|
|
||||||
stride = gfx_strideSizes[fmt];
|
|
||||||
|
|
||||||
glVertexPointer(3, GL_FLOAT, stride, vertices);
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)((uint8_t*)vertices + 12));
|
|
||||||
if (fmt == VERTEX_FORMAT_P3FT2FC4B) {
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, stride, (void*)((uint8_t*)vertices + 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
glDrawElements(GL_TRIANGLES, ICOUNT(count), GL_UNSIGNED_SHORT, indices);
|
|
||||||
glEndList();
|
|
||||||
Gfx_SetVertexFormat(curFormat);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { return GFX_NULL; }
|
|
||||||
void Gfx_BindVb(GfxResourceID vb) { gl_activeList = vb; }
|
|
||||||
void Gfx_BindIb(GfxResourceID ib) { }
|
|
||||||
void Gfx_DeleteIb(GfxResourceID* ib) { }
|
|
||||||
|
|
||||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
|
||||||
if (!vb || *vb == GFX_NULL) return;
|
|
||||||
if (*vb != gl_DYNAMICLISTID) glDeleteLists(*vb, 1);
|
|
||||||
*vb = GFX_NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void GL_SetupVbPos3fCol4b(void) {
|
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)0);
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)12);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SetupVbPos3fTex2fCol4b(void) {
|
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)0);
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)12);
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)16);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SetupVbPos3fCol4b_Range(int startVertex) {
|
|
||||||
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fC4b);
|
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)(offset));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)(offset + 12));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GL_SetupVbPos3fTex2fCol4b_Range(int startVertex) {
|
|
||||||
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b);
|
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12));
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
|
||||||
if (fmt == gfx_batchFormat) return;
|
|
||||||
|
|
||||||
if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
}
|
|
||||||
gfx_batchFormat = fmt;
|
|
||||||
gfx_batchStride = gfx_strideSizes[fmt];
|
|
||||||
|
|
||||||
if (fmt == VERTEX_FORMAT_P3FT2FC4B) {
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
gl_setupVBFunc = GL_SetupVbPos3fTex2fCol4b;
|
|
||||||
gl_setupVBRangeFunc = GL_SetupVbPos3fTex2fCol4b_Range;
|
|
||||||
} else {
|
|
||||||
gl_setupVBFunc = GL_SetupVbPos3fCol4b;
|
|
||||||
gl_setupVBRangeFunc = GL_SetupVbPos3fCol4b_Range;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CC_BUILD_GL11
|
|
||||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||||
uint32_t size = vCount * gfx_batchStride;
|
uint32_t size = vCount * gfx_batchStride;
|
||||||
_glBindBuffer(GL_ARRAY_BUFFER, vb);
|
_glBindBuffer(GL_ARRAY_BUFFER, vb);
|
||||||
_glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
_glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_DrawVb_Lines(int verticesCount) {
|
|
||||||
gl_setupVBFunc();
|
|
||||||
glDrawArrays(GL_LINES, 0, verticesCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
|
|
||||||
gl_setupVBRangeFunc(startVertex);
|
|
||||||
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
|
||||||
gl_setupVBFunc();
|
|
||||||
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) {
|
|
||||||
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b);
|
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12));
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16));
|
|
||||||
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
|
||||||
gl_activeList = gl_DYNAMICLISTID;
|
|
||||||
gl_dynamicListData = vertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GL_V16(VertexP3fC4b v) {
|
|
||||||
glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A);
|
|
||||||
glVertex3f(v.X, v.Y, v.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GL_V24(VertexP3fT2fC4b v) {
|
|
||||||
glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A);
|
|
||||||
glTexCoord2f(v.U, v.V);
|
|
||||||
glVertex3f(v.X, v.Y, v.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GL_DrawDynamicTriangles(int verticesCount, int startVertex) {
|
|
||||||
int i;
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
|
|
||||||
if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
|
|
||||||
VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData;
|
|
||||||
for (i = startVertex; i < startVertex + verticesCount; i += 4) {
|
|
||||||
GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); GL_V24(ptr[i + 2]);
|
|
||||||
GL_V24(ptr[i + 2]); GL_V24(ptr[i + 3]); GL_V24(ptr[i + 0]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData;
|
|
||||||
for (i = startVertex; i < startVertex + verticesCount; i += 4) {
|
|
||||||
GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); GL_V16(ptr[i + 2]);
|
|
||||||
GL_V16(ptr[i + 2]); GL_V16(ptr[i + 3]); GL_V16(ptr[i + 0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_DrawVb_Lines(int verticesCount) {
|
|
||||||
int i;
|
|
||||||
glBegin(GL_LINES);
|
|
||||||
|
|
||||||
if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
|
|
||||||
VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData;
|
|
||||||
for (i = 0; i < verticesCount; i += 2) { GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); }
|
|
||||||
} else {
|
|
||||||
VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData;
|
|
||||||
for (i = 0; i < verticesCount; i += 2) { GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); }
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
|
|
||||||
if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); }
|
|
||||||
else { GL_DrawDynamicTriangles(verticesCount, startVertex); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
|
||||||
if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); }
|
|
||||||
else { GL_DrawDynamicTriangles(verticesCount, 0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
static GfxResourceID gl_lastPartialList;
|
|
||||||
void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) {
|
|
||||||
/* TODO: This renders the whole map, bad performance!! FIX FIX */
|
|
||||||
if (gl_activeList == gl_lastPartialList) return;
|
|
||||||
glCallList(gl_activeList);
|
|
||||||
gl_lastPartialList = gl_activeList;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
|
||||||
*---------------------------------------------------------Matrices--------------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
static GLenum matrix_modes[3] = { GL_PROJECTION, GL_MODELVIEW, GL_TEXTURE };
|
|
||||||
static int lastMatrix;
|
|
||||||
|
|
||||||
void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) {
|
|
||||||
if (type != lastMatrix) { lastMatrix = type; glMatrixMode(matrix_modes[type]); }
|
|
||||||
glLoadMatrixf((float*)matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_LoadIdentityMatrix(MatrixType type) {
|
|
||||||
if (type != lastMatrix) { lastMatrix = type; glMatrixMode(matrix_modes[type]); }
|
|
||||||
glLoadIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) {
|
|
||||||
Matrix_OrthographicOffCenter(matrix, 0.0f, width, height, 0.0f, -10000.0f, 10000.0f);
|
|
||||||
}
|
|
||||||
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) {
|
|
||||||
Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-----------------------------------------------------------Misc----------------------------------------------------------*
|
*-----------------------------------------------------------Misc----------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
@ -1554,13 +1297,419 @@ void Gfx_Clear(void) {
|
|||||||
|
|
||||||
void Gfx_EndFrame(void) {
|
void Gfx_EndFrame(void) {
|
||||||
GLContext_SwapBuffers();
|
GLContext_SwapBuffers();
|
||||||
#ifdef CC_BUILD_GL11
|
|
||||||
gl_activeList = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_OnWindowResize(void) {
|
void Gfx_OnWindowResize(void) {
|
||||||
glViewport(0, 0, Game.Width, Game.Height);
|
glViewport(0, 0, Game.Width, Game.Height);
|
||||||
GLContext_Update();
|
GLContext_Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*------------------------------------------------------OpenGL modern------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
#ifdef CC_BUILD_GLMODERN
|
||||||
|
static GLuint GL_CompileShader(GLenum type, const char* src) {
|
||||||
|
GLint temp;
|
||||||
|
GLuint shader = glCreateShader(type);
|
||||||
|
if (!shader) Logger_Abort("Failed to create shader");
|
||||||
|
|
||||||
|
glShaderSource(shader, 1, &src, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &temp);
|
||||||
|
|
||||||
|
if (temp) return shader;
|
||||||
|
temp = 0;
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &temp);
|
||||||
|
|
||||||
|
if (temp > 1) {
|
||||||
|
char logInfo[2048];
|
||||||
|
glGetShaderInfoLog(shader, 2047, NULL, logInfo);
|
||||||
|
|
||||||
|
logInfo[2047] = '\0';
|
||||||
|
Platform_LogConst(logInfo);
|
||||||
|
}
|
||||||
|
Logger_Abort("Failed to compile shader");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint GL_CompileProgram(const char* vShaderSrc, const char* fShaderSrc) {
|
||||||
|
GLuint vertex, fragment, program;
|
||||||
|
GLint temp;
|
||||||
|
|
||||||
|
vertex = GL_CompileShader(GL_VERTEX_SHADER, vShaderSrc);
|
||||||
|
fragment = GL_CompileShader(GL_FRAGMENT_SHADER, fShaderSrc);
|
||||||
|
program = glCreateProgram();
|
||||||
|
if (!program) Logger_Abort("Failed to create program");
|
||||||
|
|
||||||
|
glAttachShader(program, vertex);
|
||||||
|
glAttachShader(program, fragment);
|
||||||
|
glLinkProgram(program);
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &temp);
|
||||||
|
|
||||||
|
if (temp) {
|
||||||
|
glDetachShader(program, vertex);
|
||||||
|
glDetachShader(program, fragment);
|
||||||
|
|
||||||
|
glDeleteShader(vertex);
|
||||||
|
glDeleteShader(fragment);
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
temp = 0;
|
||||||
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &temp);
|
||||||
|
|
||||||
|
if (temp > 1) {
|
||||||
|
char logInfo[2048];
|
||||||
|
glGetProgramInfoLog(program, 2047, NULL, logInfo);
|
||||||
|
|
||||||
|
logInfo[2047] = '\0';
|
||||||
|
Platform_LogConst(logInfo);
|
||||||
|
}
|
||||||
|
Logger_Abort("Failed to compile program");
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetFog(bool enabled) { }
|
||||||
|
void Gfx_SetFogCol(PackedCol col) { }
|
||||||
|
void Gfx_SetFogDensity(float value) { }
|
||||||
|
void Gfx_SetFogEnd(float value) { }
|
||||||
|
void Gfx_SetFogMode(FogFunc func) { }
|
||||||
|
|
||||||
|
void Gfx_SetTexturing(bool enabled) { }
|
||||||
|
void Gfx_SetAlphaTest(bool enabled) { }
|
||||||
|
void Gfx_SetAlphaTestFunc(CompareFunc func, float refValue) { }
|
||||||
|
|
||||||
|
static struct Matrix view, proj;
|
||||||
|
void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) {
|
||||||
|
if (type == MATRIX_VIEW) view = *matrix;
|
||||||
|
if (type == MATRIX_PROJECTION) proj = *matrix;
|
||||||
|
|
||||||
|
struct Matrix mvp;
|
||||||
|
Matrix_Mul(&mvp, &view, &proj);
|
||||||
|
glUniformMatrix4fv(0, 1, false, &mvp);
|
||||||
|
}
|
||||||
|
void Gfx_LoadIdentityMatrix(MatrixType type) {
|
||||||
|
Gfx_LoadMatrix(type, &Matrix_Identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_CheckSupport(void) { }
|
||||||
|
static void GL_InitState(void) {
|
||||||
|
GLuint prog = GL_CompileProgram(
|
||||||
|
"attribute vec3 in_pos;\n"\
|
||||||
|
"attribute vec4 in_col;\n"\
|
||||||
|
"attribute vec2 in_uv;\n"\
|
||||||
|
"varying vec4 out_col;\n"\
|
||||||
|
"varying vec2 out_uv;\n"\
|
||||||
|
"uniform mat4 mvp;\n"\
|
||||||
|
"void main() {\n"\
|
||||||
|
" gl_Position = mvp * vec4(in_pos, 1.0);\n"\
|
||||||
|
" out_col = in_col;\n"\
|
||||||
|
" out_uv = in_uv;\n"\
|
||||||
|
"}",
|
||||||
|
|
||||||
|
"precision highp float;\n"\
|
||||||
|
"varying vec4 out_col;\n"\
|
||||||
|
"varying vec2 out_uv;\n"\
|
||||||
|
"uniform sampler2D texImage;\n"\
|
||||||
|
"void main() {\n"\
|
||||||
|
" gl_FragColor = texture2D(texImage, out_uv) * out_col;\n"\
|
||||||
|
"}");
|
||||||
|
glUseProgram(prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetVertexFormat(VertexFormat fmt) { }
|
||||||
|
void Gfx_DrawVb_Lines(int verticesCount) { }
|
||||||
|
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { }
|
||||||
|
void Gfx_DrawVb_IndexedTris(int verticesCount) { }
|
||||||
|
|
||||||
|
void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) {
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b);
|
||||||
|
//GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(VertexP3fT2fC4b), (void*)(offset));
|
||||||
|
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(VertexP3fT2fC4b), (void*)(offset + 12));
|
||||||
|
glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(VertexP3fT2fC4b), (void*)(offset + 16));
|
||||||
|
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*------------------------------------------------------OpenGL legacy------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
#ifndef CC_BUILD_GLMODERN
|
||||||
|
static PackedCol gl_lastFogCol;
|
||||||
|
static float gl_lastFogEnd = -1, gl_lastFogDensity = -1;
|
||||||
|
static int gl_lastFogMode = -1;
|
||||||
|
|
||||||
|
void Gfx_SetFog(bool enabled) {
|
||||||
|
gfx_fogEnabled = enabled;
|
||||||
|
gl_Toggle(GL_FOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetFogCol(PackedCol col) {
|
||||||
|
float rgba[4];
|
||||||
|
if (PackedCol_Equals(col, gl_lastFogCol)) return;
|
||||||
|
|
||||||
|
rgba[0] = col.R / 255.0f; rgba[1] = col.G / 255.0f;
|
||||||
|
rgba[2] = col.B / 255.0f; rgba[3] = col.A / 255.0f;
|
||||||
|
|
||||||
|
glFogfv(GL_FOG_COLOR, rgba);
|
||||||
|
gl_lastFogCol = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetFogDensity(float value) {
|
||||||
|
if (value == gl_lastFogDensity) return;
|
||||||
|
glFogf(GL_FOG_DENSITY, value);
|
||||||
|
gl_lastFogDensity = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetFogEnd(float value) {
|
||||||
|
if (value == gl_lastFogEnd) return;
|
||||||
|
glFogf(GL_FOG_END, value);
|
||||||
|
gl_lastFogEnd = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetFogMode(FogFunc func) {
|
||||||
|
static GLint modes[3] = { GL_LINEAR, GL_EXP, GL_EXP2 };
|
||||||
|
if (func == gl_lastFogMode) return;
|
||||||
|
|
||||||
|
glFogi(GL_FOG_MODE, modes[func]);
|
||||||
|
gl_lastFogMode = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetTexturing(bool enabled) { gl_Toggle(GL_TEXTURE_2D); }
|
||||||
|
void Gfx_SetAlphaTest(bool enabled) { gl_Toggle(GL_ALPHA_TEST); }
|
||||||
|
void Gfx_SetAlphaTestFunc(CompareFunc func, float value) {
|
||||||
|
glAlphaFunc(gl_compare[func], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLenum matrix_modes[3] = { GL_PROJECTION, GL_MODELVIEW, GL_TEXTURE };
|
||||||
|
static int lastMatrix;
|
||||||
|
|
||||||
|
void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) {
|
||||||
|
if (type != lastMatrix) { lastMatrix = type; glMatrixMode(matrix_modes[type]); }
|
||||||
|
glLoadMatrixf((float*)matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_LoadIdentityMatrix(MatrixType type) {
|
||||||
|
if (type != lastMatrix) { lastMatrix = type; glMatrixMode(matrix_modes[type]); }
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_InitState(void) {
|
||||||
|
glHint(GL_FOG_HINT, GL_NICEST);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*----------------------------------------------------------Drawing--------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
static void GL_SetupVbPos3fCol4b(void) {
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)0);
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)12);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_SetupVbPos3fTex2fCol4b(void) {
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)0);
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)12);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_SetupVbPos3fCol4b_Range(int startVertex) {
|
||||||
|
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fC4b);
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fC4b), (void*)(offset));
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fC4b), (void*)(offset + 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_SetupVbPos3fTex2fCol4b_Range(int startVertex) {
|
||||||
|
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b);
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset));
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12));
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||||
|
if (fmt == gfx_batchFormat) return;
|
||||||
|
|
||||||
|
if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
gfx_batchFormat = fmt;
|
||||||
|
gfx_batchStride = gfx_strideSizes[fmt];
|
||||||
|
|
||||||
|
if (fmt == VERTEX_FORMAT_P3FT2FC4B) {
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
gl_setupVBFunc = GL_SetupVbPos3fTex2fCol4b;
|
||||||
|
gl_setupVBRangeFunc = GL_SetupVbPos3fTex2fCol4b_Range;
|
||||||
|
} else {
|
||||||
|
gl_setupVBFunc = GL_SetupVbPos3fCol4b;
|
||||||
|
gl_setupVBRangeFunc = GL_SetupVbPos3fCol4b_Range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CC_BUILD_GL11
|
||||||
|
void Gfx_DrawVb_Lines(int verticesCount) {
|
||||||
|
gl_setupVBFunc();
|
||||||
|
glDrawArrays(GL_LINES, 0, verticesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
|
||||||
|
gl_setupVBRangeFunc(startVertex);
|
||||||
|
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
||||||
|
gl_setupVBFunc();
|
||||||
|
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) {
|
||||||
|
uint32_t offset = startVertex * (uint32_t)sizeof(VertexP3fT2fC4b);
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset));
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexP3fT2fC4b), (void*)(offset + 12));
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexP3fT2fC4b), (void*)(offset + 16));
|
||||||
|
glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_CheckSupport(void) {
|
||||||
|
const static String vboExt = String_FromConst("GL_ARB_vertex_buffer_object");
|
||||||
|
String extensions = String_FromReadonly(glGetString(GL_EXTENSIONS));
|
||||||
|
String version = String_FromReadonly(glGetString(GL_VERSION));
|
||||||
|
|
||||||
|
int major = (int)(version.buffer[0] - '0'); /* x.y. (and so forth) */
|
||||||
|
int minor = (int)(version.buffer[2] - '0');
|
||||||
|
|
||||||
|
/* Supported in core since 1.5 */
|
||||||
|
if (major > 1 || (major == 1 && minor >= 5)) {
|
||||||
|
_glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBuffer");
|
||||||
|
_glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffers");
|
||||||
|
_glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffers");
|
||||||
|
_glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferData");
|
||||||
|
_glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubData");
|
||||||
|
} else if (String_CaselessContains(&extensions, &vboExt)) {
|
||||||
|
_glBindBuffer = (FUNC_GLBINDBUFFER)GLContext_GetAddress("glBindBufferARB");
|
||||||
|
_glDeleteBuffers = (FUNC_GLDELETEBUFFERS)GLContext_GetAddress("glDeleteBuffersARB");
|
||||||
|
_glGenBuffers = (FUNC_GLGENBUFFERS)GLContext_GetAddress("glGenBuffersARB");
|
||||||
|
_glBufferData = (FUNC_GLBUFFERDATA)GLContext_GetAddress("glBufferDataARB");
|
||||||
|
_glBufferSubData = (FUNC_GLBUFFERSUBDATA)GLContext_GetAddress("glBufferSubDataARB");
|
||||||
|
} else {
|
||||||
|
Logger_Abort("Only OpenGL 1.1 supported.\n\n" \
|
||||||
|
"Compile the game with CC_BUILD_GL11, or ask on the classicube forums for it");
|
||||||
|
}
|
||||||
|
Gfx.CustomMipmapsLevels = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { return gl_DYNAMICLISTID; }
|
||||||
|
GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat fmt, int count) {
|
||||||
|
/* We need to setup client state properly when building the list */
|
||||||
|
int curFormat = gfx_batchFormat, stride;
|
||||||
|
Gfx_SetVertexFormat(fmt);
|
||||||
|
|
||||||
|
GLuint list = glGenLists(1);
|
||||||
|
glNewList(list, GL_COMPILE);
|
||||||
|
count &= ~0x01; /* Need to get rid of the 1 extra element, see comment in chunk mesh builder for why */
|
||||||
|
|
||||||
|
uint16_t indices[GFX_MAX_INDICES];
|
||||||
|
Gfx_MakeIndices(indices, ICOUNT(count));
|
||||||
|
stride = gfx_strideSizes[fmt];
|
||||||
|
|
||||||
|
glVertexPointer(3, GL_FLOAT, stride, vertices);
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)((uint8_t*)vertices + 12));
|
||||||
|
if (fmt == VERTEX_FORMAT_P3FT2FC4B) {
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, stride, (void*)((uint8_t*)vertices + 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, ICOUNT(count), GL_UNSIGNED_SHORT, indices);
|
||||||
|
glEndList();
|
||||||
|
Gfx_SetVertexFormat(curFormat);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { return GFX_NULL; }
|
||||||
|
void Gfx_BindVb(GfxResourceID vb) { gl_activeList = vb; }
|
||||||
|
void Gfx_BindIb(GfxResourceID ib) { }
|
||||||
|
void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||||
|
|
||||||
|
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||||
|
if (!vb || *vb == GFX_NULL) return;
|
||||||
|
if (*vb != gl_DYNAMICLISTID) glDeleteLists(*vb, 1);
|
||||||
|
*vb = GFX_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||||
|
gl_activeList = gl_DYNAMICLISTID;
|
||||||
|
gl_dynamicListData = vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_V16(VertexP3fC4b v) {
|
||||||
|
glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A);
|
||||||
|
glVertex3f(v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_V24(VertexP3fT2fC4b v) {
|
||||||
|
glColor4ub(v.Col.R, v.Col.G, v.Col.B, v.Col.A);
|
||||||
|
glTexCoord2f(v.U, v.V);
|
||||||
|
glVertex3f(v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_DrawDynamicTriangles(int verticesCount, int startVertex) {
|
||||||
|
int i;
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
|
if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
|
||||||
|
VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData;
|
||||||
|
for (i = startVertex; i < startVertex + verticesCount; i += 4) {
|
||||||
|
GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); GL_V24(ptr[i + 2]);
|
||||||
|
GL_V24(ptr[i + 2]); GL_V24(ptr[i + 3]); GL_V24(ptr[i + 0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData;
|
||||||
|
for (i = startVertex; i < startVertex + verticesCount; i += 4) {
|
||||||
|
GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); GL_V16(ptr[i + 2]);
|
||||||
|
GL_V16(ptr[i + 2]); GL_V16(ptr[i + 3]); GL_V16(ptr[i + 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_DrawVb_Lines(int verticesCount) {
|
||||||
|
int i;
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
|
||||||
|
if (gfx_batchFormat == VERTEX_FORMAT_P3FT2FC4B) {
|
||||||
|
VertexP3fT2fC4b* ptr = (VertexP3fT2fC4b*)gl_dynamicListData;
|
||||||
|
for (i = 0; i < verticesCount; i += 2) { GL_V24(ptr[i + 0]); GL_V24(ptr[i + 1]); }
|
||||||
|
} else {
|
||||||
|
VertexP3fC4b* ptr = (VertexP3fC4b*)gl_dynamicListData;
|
||||||
|
for (i = 0; i < verticesCount; i += 2) { GL_V16(ptr[i + 0]); GL_V16(ptr[i + 1]); }
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
|
||||||
|
if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); }
|
||||||
|
else { GL_DrawDynamicTriangles(verticesCount, startVertex); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
||||||
|
if (gl_activeList != gl_DYNAMICLISTID) { glCallList(gl_activeList); }
|
||||||
|
else { GL_DrawDynamicTriangles(verticesCount, 0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static GfxResourceID gl_lastPartialList;
|
||||||
|
void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) {
|
||||||
|
/* TODO: This renders the whole map, bad performance!! FIX FIX */
|
||||||
|
if (gl_activeList == gl_lastPartialList) return;
|
||||||
|
glCallList(gl_activeList);
|
||||||
|
gl_lastPartialList = gl_activeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL_CheckSupport(void) { }
|
||||||
|
#endif /* CC_BUILD_GL11 */
|
||||||
|
#endif /* !CC_BUILD_GLMODERN */
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user