diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 89308f13fe525edeabd4cb24bfaeb7f8b84eb2a0..afbeaa1e7b1fc9b65d4a49c1348ff1ad139f31ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -530,10 +530,14 @@ if(${SRB2_CONFIG_HWRENDER}) set(SRB2_R_OPENGL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/shaders/gl_shaders.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_glcommon/r_glcommon.c ) set(SRB2_R_OPENGL_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/shaders/gl_shaders.h + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_glcommon/r_glcommon.h ) endif() diff --git a/src/Makefile b/src/Makefile index 09e37121258f5ff28dd9b6baebd2c41304870e25..58e7428faf80c4a004c30c42000da4a46e2270c3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -663,7 +663,7 @@ ifdef MINGW all_dll: opengl_dll ds3d_dll fmod_dll openal_dll opengl_dll: $(BIN)/r_opengl.dll -$(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o +$(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o $(OBJDIR)/r_glcommon.o $(OBJDIR)/gl_shaders.o -$(MKDIR) $(BIN) @echo Linking R_OpenGL.dll... $(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lgdi32 -static-libgcc @@ -706,7 +706,14 @@ endif else ifdef SDL ifdef MINGW +$(OBJDIR)/gl_shaders.o: hardware/shaders/gl_shaders.c hardware/shaders/gl_shaders.h \ + hardware/r_opengl/r_opengl.h doomdef.h doomtype.h doomdata.h hardware/hw_dll.h + $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ +$(OBJDIR)/r_glcommon.o: hardware/r_glcommon/r_glcommon.c hardware/r_glcommon/r_glcommon.h \ + doomdef.h doomtype.h doomdata.h hardware/hw_dll.h + $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ + hardware/r_glcommon/r_glcommon.h hardware/shaders/gl_shaders.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_gpu.h screen.h \ command.h hardware/hw_data.h hardware/hw_defs.h \ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ @@ -716,7 +723,14 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h $(echoName) $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ else +$(OBJDIR)/gl_shaders.o: hardware/shaders/gl_shaders.c hardware/shaders/gl_shaders.h \ + hardware/r_opengl/r_opengl.h doomdef.h doomtype.h doomdata.h hardware/hw_dll.h + $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ +$(OBJDIR)/r_glcommon.o: hardware/r_glcommon/r_glcommon.c hardware/r_glcommon/r_glcommon.h \ + doomdef.h doomtype.h doomdata.h hardware/hw_dll.h + $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ + hardware/r_glcommon/r_glcommon.h hardware/shaders/gl_shaders.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_gpu.h screen.h \ command.h hardware/hw_data.h hardware/hw_defs.h \ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ @@ -807,7 +821,14 @@ $(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h ifdef MINGW ifndef SDL ifndef NOHW +$(OBJDIR)/gl_shaders.o: hardware/shaders/gl_shaders.c hardware/shaders/gl_shaders.h \ + hardware/r_opengl/r_opengl.h doomdef.h doomtype.h doomdata.h hardware/hw_dll.h + $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ +$(OBJDIR)/r_glcommon.o: hardware/r_glcommon/r_glcommon.c hardware/r_glcommon/r_glcommon.h \ + doomdef.h doomtype.h doomdata.h hardware/hw_dll.h + $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ + hardware/r_glcommon/r_glcommon.h hardware/shaders/gl_shaders.h \ doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_gpu.h screen.h \ command.h hardware/hw_data.h hardware/hw_defs.h \ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 981d15d1532543c078d0c8b91d1b3c63eada6fb6..7aecad8e3e29a1baa458a63b0a244ea39c1ca3e7 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -31,8 +31,6 @@ #define GPU_DEFAULTMIX 0x00000000 #define GPU_DEFAULTFOG 0xFF000000 -#define SCREENVERTS 10 - // RGBA Color components with float type ranging [ 0 ... 1 ] struct FRGBAFloat { @@ -212,6 +210,9 @@ enum EFilterMode GPU_TEXFILTER_MIXED3, }; +// Vertex count for post processing effects +#define GPU_POSTIMGVERTS 10 + #ifdef GL_SHADERS // Predefined shader types enum @@ -226,6 +227,11 @@ enum SHADER_FOG, SHADER_SKY, +#ifdef HAVE_GLES2 + SHADER_FADEMASK, + SHADER_FADEMASK_ADDITIVEANDSUBTRACTIVE, +#endif + NUMBASESHADERS, }; diff --git a/src/hardware/hw_gpu.c b/src/hardware/hw_gpu.c new file mode 100644 index 0000000000000000000000000000000000000000..5052148931ac0c16450e3d82d73201093b6591fd --- /dev/null +++ b/src/hardware/hw_gpu.c @@ -0,0 +1,26 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_gpu.c +/// \brief GPU low-level interface API + +#ifdef HWRENDER + +#include "r_opengl/r_opengl.h" + +// ========================================================================== +// the hardware driver object +// ========================================================================== +struct GPURenderingAPI *GPU = NULL; + +void GPUInterface_Load(struct GPURenderingAPI **api) +{ + *api = &GLInterfaceAPI; +} + +#endif // HWRENDER diff --git a/src/hardware/hw_gpu.h b/src/hardware/hw_gpu.h new file mode 100644 index 0000000000000000000000000000000000000000..03f522cfe87c1aa169c601119da7174c355bfe1a --- /dev/null +++ b/src/hardware/hw_gpu.h @@ -0,0 +1,74 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_gpu.h +/// \brief GPU low-level interface API + +#ifndef __HWR_GPU_H__ +#define __HWR_GPU_H__ + +#include "../screen.h" +#include "hw_data.h" +#include "hw_defs.h" +#include "hw_md2.h" + +struct GPURenderingAPI +{ + boolean (*Init) (void); + void (*FinishUpdate) (INT32 waitvbl); + + void (*SetState) (INT32 State, INT32 Value); + void (*SetTransform) (FTransform *ptransform); + void (*SetBlend) (UINT32 PolyFlags); + void (*SetPalette) (RGBA_t *palette); + void (*ClearBuffer) (boolean ColorMask, boolean DepthMask, FRGBAFloat *ClearColor); + + void (*DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, UINT32 iNumPts, UINT32 PolyFlags); + void (*DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, UINT32 iNumPts, UINT32 PolyFlags, UINT32 *IndexArray); + void (*Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); + void (*DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); + void (*DrawSkyDome) (FSkyDome *sky); + + void (*SetTexture) (HWRTexture_t *TexInfo); + void (*UpdateTexture) (HWRTexture_t *TexInfo); + void (*DeleteTexture) (HWRTexture_t *TexInfo); + + void (*ClearTextureCache) (void); + INT32 (*GetTextureUsed) (void); + + void (*CreateModelVBOs) (model_t *model); + + void (*ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); + void (*GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); + + void (*MakeScreenTexture) (void); + void (*MakeScreenFinalTexture) (void); + void (*FlushScreenTextures) (void); + + void (*StartScreenWipe) (void); + void (*EndScreenWipe) (void); + void (*DoScreenWipe) (void); + void (*DrawIntermissionBG) (void); + void (*DrawScreenFinalTexture) (int width, int height); + + void (*PostImgRedraw) (float points[GPU_POSTIMGVERTS][GPU_POSTIMGVERTS][2]); + + boolean (*CompileShaders) (void); + void (*CleanShaders) (void); + void (*SetShader) (int type); + void (*UnSetShader) (void); + + void (*SetShaderInfo) (INT32 info, INT32 value); + void (*LoadCustomShader) (int number, char *code, size_t size, boolean isfragment); +}; + +extern struct GPURenderingAPI *GPU; + +void GPUInterface_Load(struct GPURenderingAPI **api); + +#endif // __HWR_GPU_H__ diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5395f918aad5f2120e93b846a9e488eabf9aaf40..b63d0df61a260772312f92b2d682500c4b7fe0dc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6518,7 +6518,7 @@ void HWR_DoPostProcessor(player_t *player) if (*type == postimg_water || *type == postimg_heat) { // 10 by 10 grid. 2 coordinates (xy) - float v[SCREENVERTS][SCREENVERTS][2]; + float v[GPU_POSTIMGVERTS][GPU_POSTIMGVERTS][2]; static double disStart = 0; UINT8 x, y; INT32 WAVELENGTH; @@ -6539,13 +6539,13 @@ void HWR_DoPostProcessor(player_t *player) FREQUENCY = 4; // Lower is faster } - for (x = 0; x < SCREENVERTS; x++) + for (x = 0; x < GPU_POSTIMGVERTS; x++) { - for (y = 0; y < SCREENVERTS; y++) + for (y = 0; y < GPU_POSTIMGVERTS; y++) { // Change X position based on its Y position. - v[x][y][0] = (x/((float)(SCREENVERTS-1.0f)/9.0f))-4.5f + (float)sin((disStart+(y*WAVELENGTH))/FREQUENCY)/AMPLITUDE; - v[x][y][1] = (y/((float)(SCREENVERTS-1.0f)/9.0f))-4.5f; + v[x][y][0] = (x/((float)(GPU_POSTIMGVERTS-1.0f)/9.0f))-4.5f + (float)sin((disStart+(y*WAVELENGTH))/FREQUENCY)/AMPLITUDE; + v[x][y][1] = (y/((float)(GPU_POSTIMGVERTS-1.0f)/9.0f))-4.5f; } } GPU->PostImgRedraw(v); diff --git a/src/hardware/r_glcommon/r_glcommon.c b/src/hardware/r_glcommon/r_glcommon.c new file mode 100644 index 0000000000000000000000000000000000000000..cf552d2fcf69cd5195273a56e6294a3422f2773d --- /dev/null +++ b/src/hardware/r_glcommon/r_glcommon.c @@ -0,0 +1,1041 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_glcommon.c +/// \brief Common OpenGL functions shared by OpenGL backends + +#include "r_glcommon.h" + +#include "../../doomdata.h" +#include "../../doomtype.h" +#include "../../doomdef.h" +#include "../../console.h" + +#ifdef GL_SHADERS +#include "../shaders/gl_shaders.h" +#endif + +#include <stdarg.h> + +const GLubyte *GLVersion = NULL; +const GLubyte *GLRenderer = NULL; +const GLubyte *GLExtensions = NULL; + +GLint GLMajorVersion = 0; +GLint GLMinorVersion = 0; + +// ========================================================================== +// GLOBALS +// ========================================================================== + +RGBA_t GPUTexturePalette[256]; +GLint GPUTextureFormat; +GLint GPUScreenWidth, GPUScreenHeight; +GLbyte GPUScreenDepth; +GLint GPUMaximumAnisotropy; + +FTextureInfo *TexCacheTail = NULL; +FTextureInfo *TexCacheHead = NULL; + +GLuint CurrentTexture = 0; +GLuint BlankTexture = 0; + +GLuint ScreenTexture = 0; +GLuint FinalScreenTexture = 0; +GLuint WipeStartTexture = 0; +GLuint WipeEndTexture = 0; + +UINT32 CurrentPolyFlags; + +GLboolean MipmappingEnabled = GL_FALSE; +GLboolean ModelLightingEnabled = GL_FALSE; + +GLint MipmapMinFilter = GL_LINEAR; +GLint MipmapMagFilter = GL_LINEAR; +GLint AnisotropicFilter = 0; + +float NearClippingPlane = NZCLIP_PLANE; + +// ========================================================================== +// EXTENSIONS +// ========================================================================== + +boolean GLExtension_multitexture; +boolean GLExtension_vertex_buffer_object; +boolean GLExtension_texture_filter_anisotropic; +boolean GLExtension_vertex_program; +boolean GLExtension_fragment_program; +boolean GLExtension_shaders; // Not an extension on its own, but it is set if multiple extensions are available. + +static FExtensionList const ExtensionList[] = { + {"GL_ARB_multitexture", &GLExtension_multitexture}, + {"GL_ARB_vertex_buffer_object", &GLExtension_vertex_buffer_object}, + {"GL_ARB_texture_filter_anisotropic", &GLExtension_texture_filter_anisotropic}, + {"GL_EXT_texture_filter_anisotropic", &GLExtension_texture_filter_anisotropic}, + {"GL_ARB_vertex_program", &GLExtension_vertex_program}, + {"GL_ARB_fragment_program", &GLExtension_fragment_program}, + {NULL, NULL} +}; + +static void PrintExtensions(const GLubyte *extensions); + +// ========================================================================== +// OPENGL FUNCTIONS +// ========================================================================== + +#ifndef STATIC_OPENGL +/* Miscellaneous */ +PFNglClear pglClear; +PFNglGetFloatv pglGetFloatv; +PFNglGetIntegerv pglGetIntegerv; +PFNglGetString pglGetString; +PFNglClearColor pglClearColor; +PFNglColorMask pglColorMask; +PFNglAlphaFunc pglAlphaFunc; +PFNglBlendFunc pglBlendFunc; +PFNglCullFace pglCullFace; +PFNglPolygonOffset pglPolygonOffset; +PFNglEnable pglEnable; +PFNglDisable pglDisable; + +/* Depth buffer */ +PFNglDepthFunc pglDepthFunc; +PFNglDepthMask pglDepthMask; + +/* Transformation */ +PFNglViewport pglViewport; + +/* Raster functions */ +PFNglPixelStorei pglPixelStorei; +PFNglReadPixels pglReadPixels; + +/* Texture mapping */ +PFNglTexParameteri pglTexParameteri; +PFNglTexImage2D pglTexImage2D; +PFNglTexSubImage2D pglTexSubImage2D; + +/* Drawing functions */ +PFNglDrawArrays pglDrawArrays; +PFNglDrawElements pglDrawElements; + +/* Texture objects */ +PFNglGenTextures pglGenTextures; +PFNglDeleteTextures pglDeleteTextures; +PFNglBindTexture pglBindTexture; + +/* Texture mapping */ +PFNglCopyTexImage2D pglCopyTexImage2D; +PFNglCopyTexSubImage2D pglCopyTexSubImage2D; + +/* 1.3 functions for multitexturing */ +PFNglActiveTexture pglActiveTexture; +#endif + +// +// Multi-texturing +// + +#ifndef HAVE_GLES2 +#ifndef STATIC_OPENGL +PFNglClientActiveTexture pglClientActiveTexture; +#endif +#endif + +// +// Mipmapping +// + +#ifdef HAVE_GLES +PFNglGenerateMipmap pglGenerateMipmap; +#endif + +// +// Depth functions +// +#ifndef HAVE_GLES + PFNglClearDepth pglClearDepth; + PFNglDepthRange pglDepthRange; +#else + PFNglClearDepthf pglClearDepthf; + PFNglDepthRangef pglDepthRangef; +#endif + +// +// Legacy functions +// + +#ifndef HAVE_GLES2 +#ifndef STATIC_OPENGL +/* Transformation */ +PFNglMatrixMode pglMatrixMode; +PFNglViewport pglViewport; +PFNglPushMatrix pglPushMatrix; +PFNglPopMatrix pglPopMatrix; +PFNglLoadIdentity pglLoadIdentity; +PFNglMultMatrixf pglMultMatrixf; +PFNglRotatef pglRotatef; +PFNglScalef pglScalef; +PFNglTranslatef pglTranslatef; + +/* Drawing functions */ +PFNglVertexPointer pglVertexPointer; +PFNglNormalPointer pglNormalPointer; +PFNglTexCoordPointer pglTexCoordPointer; +PFNglColorPointer pglColorPointer; +PFNglEnableClientState pglEnableClientState; +PFNglDisableClientState pglDisableClientState; + +/* Lighting */ +PFNglShadeModel pglShadeModel; +PFNglLightfv pglLightfv; +PFNglLightModelfv pglLightModelfv; +PFNglMaterialfv pglMaterialfv; + +/* Texture mapping */ +PFNglTexEnvi pglTexEnvi; +#endif +#endif // HAVE_GLES2 + +// Color +#ifdef HAVE_GLES +PFNglColor4f pglColor4f; +#else +PFNglColor4ubv pglColor4ubv; +#endif + +/* 1.5 functions for buffers */ +PFNglGenBuffers pglGenBuffers; +PFNglBindBuffer pglBindBuffer; +PFNglBufferData pglBufferData; +PFNglDeleteBuffers pglDeleteBuffers; + +/* 2.0 functions */ +PFNglBlendEquation pglBlendEquation; + +// ========================================================================== +// FUNCTIONS +// ========================================================================== + +boolean GLBackend_Init(void) +{ + return GLBackend_LoadFunctions(); +} + +boolean GLBackend_InitContext(void) +{ + if (GLVersion == NULL || GLRenderer == NULL) + { + GLVersion = pglGetString(GL_VERSION); + GLRenderer = pglGetString(GL_RENDERER); + + pglGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion); + pglGetIntegerv(GL_MINOR_VERSION, &GLMinorVersion); + + GL_DBG_Printf("OpenGL %s\n", GLVersion); + GL_DBG_Printf("Version: %d.%d\n", GLMajorVersion, GLMinorVersion); + GL_DBG_Printf("GPU: %s\n", GLRenderer); + +#if !defined(__ANDROID__) + if (strcmp((const char*)GLRenderer, "GDI Generic") == 0 && + strcmp((const char*)GLVersion, "1.1.0") == 0) + { + // Oh no... Windows gave us the GDI Generic rasterizer, so something is wrong... + // The game will crash later on when unsupported OpenGL commands are encountered. + // Instead of a nondescript crash, show a more informative error message. + // Also set the renderer variable back to software so the next launch won't + // repeat this error. + CV_StealthSet(&cv_renderer, "Software"); + I_Error("OpenGL Error: Failed to access the GPU. There may be an issue with your graphics drivers."); + } +#endif + } + + if (GLExtensions == NULL) + GLExtension_Init(); + + return true; +} + +boolean GLBackend_LoadCommonFunctions(void) +{ +#define GETOPENGLFUNC(func) \ + p ## gl ## func = GLBackend_GetFunction("gl" #func); \ + if (!(p ## gl ## func)) \ + { \ + GL_MSG_Error("failed to get OpenGL function: %s", #func); \ + return false; \ + } \ + + GETOPENGLFUNC(ClearColor) + + GETOPENGLFUNC(Clear) + GETOPENGLFUNC(ColorMask) + GETOPENGLFUNC(AlphaFunc) + GETOPENGLFUNC(BlendFunc) + GETOPENGLFUNC(CullFace) + GETOPENGLFUNC(PolygonOffset) + GETOPENGLFUNC(Enable) + GETOPENGLFUNC(Disable) + GETOPENGLFUNC(GetFloatv) + GETOPENGLFUNC(GetIntegerv) + GETOPENGLFUNC(GetString) + + GETOPENGLFUNC(DepthFunc) + GETOPENGLFUNC(DepthMask) + + GETOPENGLFUNC(Viewport) + + GETOPENGLFUNC(DrawArrays) + GETOPENGLFUNC(DrawElements) + + GETOPENGLFUNC(PixelStorei) + GETOPENGLFUNC(ReadPixels) + + GETOPENGLFUNC(TexParameteri) + GETOPENGLFUNC(TexImage2D) + GETOPENGLFUNC(TexSubImage2D) + + GETOPENGLFUNC(GenTextures) + GETOPENGLFUNC(DeleteTextures) + GETOPENGLFUNC(BindTexture) + + GETOPENGLFUNC(CopyTexImage2D) + GETOPENGLFUNC(CopyTexSubImage2D) + + return true; +} + +boolean GLBackend_LoadLegacyFunctions(void) +{ +#ifndef HAVE_GLES2 + GETOPENGLFUNC(MatrixMode) + GETOPENGLFUNC(Viewport) + GETOPENGLFUNC(PushMatrix) + GETOPENGLFUNC(PopMatrix) + GETOPENGLFUNC(LoadIdentity) + GETOPENGLFUNC(MultMatrixf) + GETOPENGLFUNC(Rotatef) + GETOPENGLFUNC(Scalef) + GETOPENGLFUNC(Translatef) + + GETOPENGLFUNC(ShadeModel) + GETOPENGLFUNC(Lightfv) + GETOPENGLFUNC(LightModelfv) + GETOPENGLFUNC(Materialfv) +#endif + + return true; +} + +#undef GETOPENGLFUNC + +INT32 GLBackend_GetShaderType(INT32 type) +{ +#ifdef GL_SHADERS + // If using model lighting, set the appropriate shader. + // However don't override a custom shader. + if (type == SHADER_MODEL && ModelLightingEnabled + && !(ShaderObjects[SHADER_MODEL].custom && !ShaderObjects[SHADER_MODEL_LIGHTING].custom)) + return SHADER_MODEL_LIGHTING; +#endif + + return type; +} + +static void SetBlendEquation(GLenum mode) +{ + if (pglBlendEquation) + pglBlendEquation(mode); +} + +static void SetBlendMode(UINT32 flags) +{ + // Set blending function + switch (flags) + { + case PF_Translucent & PF_Blending: + pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency + break; + case PF_Masked & PF_Blending: + // Hurdler: does that mean lighting is only made by alpha src? + // it sounds ok, but not for polygonsmooth + pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture + break; + case PF_Additive & PF_Blending: + case PF_Subtractive & PF_Blending: + case PF_ReverseSubtract & PF_Blending: + case PF_Environment & PF_Blending: + pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + break; + case PF_AdditiveSource & PF_Blending: + pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest + break; + case PF_Multiplicative & PF_Blending: + pglBlendFunc(GL_DST_COLOR, GL_ZERO); + break; + case PF_Fog & PF_Fog: + // Sryder: Fog + // multiplies input colour by input alpha, and destination colour by input colour, then adds them + pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); + break; + default: // must be 0, otherwise it's an error + // No blending + pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending + break; + } + + // Set blending equation + switch (flags) + { + case PF_Subtractive & PF_Blending: + SetBlendEquation(GL_FUNC_SUBTRACT); + break; + case PF_ReverseSubtract & PF_Blending: + // good for shadow + // not really but what else ? + SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + break; + default: + SetBlendEquation(GL_FUNC_ADD); + break; + } + + // Alpha test + switch (flags) + { + case PF_Masked & PF_Blending: + pglAlphaFunc(GL_GREATER, 0.5f); + break; + case PF_Translucent & PF_Blending: + case PF_Additive & PF_Blending: + case PF_AdditiveSource & PF_Blending: + case PF_Subtractive & PF_Blending: + case PF_ReverseSubtract & PF_Blending: + case PF_Environment & PF_Blending: + case PF_Multiplicative & PF_Blending: + pglAlphaFunc(GL_NOTEQUAL, 0.0f); + break; + case PF_Fog & PF_Fog: + pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments + break; + default: + pglAlphaFunc(GL_GREATER, 0.5f); + break; + } +} + +// PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0, +// is it faster when pixels are discarded ? + +void SetBlendingStates(UINT32 PolyFlags) +{ + UINT32 Xor = CurrentPolyFlags^PolyFlags; + + if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible)) + { + if (Xor & PF_Blending) // if blending mode must be changed + SetBlendMode(PolyFlags & PF_Blending); + +#ifndef HAVE_GLES2 + if (Xor & PF_NoAlphaTest) + { + if (PolyFlags & PF_NoAlphaTest) + pglDisable(GL_ALPHA_TEST); + else + pglEnable(GL_ALPHA_TEST); // discard 0 alpha pixels (holes in texture) + } +#endif + + if (Xor & PF_Decal) + { + if (PolyFlags & PF_Decal) + pglEnable(GL_POLYGON_OFFSET_FILL); + else + pglDisable(GL_POLYGON_OFFSET_FILL); + } + + if (Xor & PF_NoDepthTest) + { + if (PolyFlags & PF_NoDepthTest) + pglDepthFunc(GL_ALWAYS); + else + pglDepthFunc(GL_LEQUAL); + } + + if (Xor & PF_RemoveYWrap) + { + if (PolyFlags & PF_RemoveYWrap) + SetClamp(GL_TEXTURE_WRAP_T); + } + + if (Xor & PF_ForceWrapX) + { + if (PolyFlags & PF_ForceWrapX) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + } + + if (Xor & PF_ForceWrapY) + { + if (PolyFlags & PF_ForceWrapY) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + +#ifndef HAVE_GLES2 + if (Xor & PF_Modulated) + { + if (PolyFlags & PF_Modulated) + { // mix texture colour with Surface->PolyColor + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + else + { // colour from texture is unchanged before blending + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } + } +#endif + + if (Xor & PF_Occlude) // depth test but (no) depth write + { + if (PolyFlags&PF_Occlude) + { + pglDepthMask(1); + } + else + pglDepthMask(0); + } + ////Hurdler: not used if we don't define POLYSKY + if (Xor & PF_Invisible) + { + if (PolyFlags&PF_Invisible) + pglBlendFunc(GL_ZERO, GL_ONE); // transparent blending + else + { // big hack: (TODO: manage that better) + // we test only for PF_Masked because PF_Invisible is only used + // (for now) with it (yeah, that's crappy, sorry) + if ((PolyFlags&PF_Blending)==PF_Masked) + pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); + } + } + if (PolyFlags & PF_NoTexture) + { + SetNoTexture(); + } + } + + CurrentPolyFlags = PolyFlags; +} + +void SetSurface(INT32 w, INT32 h) +{ + SetModelView(w, h); + SetStates(); + pglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void GLExtension_Init(void) +{ + INT32 i = 0; + + GLExtensions = pglGetString(GL_EXTENSIONS); + + GL_DBG_Printf("Extensions: "); + PrintExtensions(GLExtensions); + + while (ExtensionList[i].name) + { + const FExtensionList *ext = &ExtensionList[i]; + + if (GLExtension_Available(ext->name)) + { + (*ext->extension) = true; + GL_DBG_Printf("Extension %s is supported\n", ext->name); + } + else + { + (*ext->extension) = false; + GL_DBG_Printf("Extension %s is unsupported\n", ext->name); + } + + i++; + } + +#ifdef GL_SHADERS + if (GLExtension_vertex_program && GLExtension_fragment_program && GLBackend_GetFunction("glUseProgram")) + GLExtension_shaders = true; +#endif + + if (GLExtension_texture_filter_anisotropic) + pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GPUMaximumAnisotropy); + else + GPUMaximumAnisotropy = 0; +} + +boolean GLExtension_Available(const char *extension) +{ +#if defined(HAVE_GLES) && defined(HAVE_SDL) + return (SDL_GL_ExtensionSupported(extension) == SDL_TRUE ? true : false); +#else + const GLubyte *start = GLExtensions; + GLubyte *where, *terminator; + + if (!extension || !start) + return false; + + where = (GLubyte *) strchr(extension, ' '); + if (where || *extension == '\0') + return false; + + for (;;) + { + where = (GLubyte *) strstr((const char *) start, extension); + if (!where) + break; + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') + return true; + start = terminator; + } + + return false; +#endif +} + +static void PrintExtensions(const GLubyte *extensions) +{ + size_t size = strlen((const char *)extensions) + 1; + char *tk, *ext = calloc(size, sizeof(char)); + + memcpy(ext, extensions, size); + tk = strtok(ext, " "); + + while (tk) + { + GL_DBG_Printf("%s", tk); + tk = strtok(NULL, " "); + if (tk) + GL_DBG_Printf(" ", tk); + } + + GL_DBG_Printf("\n"); + free(ext); +} + +static size_t lerpBufferSize = 0; +float *vertBuffer = NULL; +float *normBuffer = NULL; + +static size_t lerpTinyBufferSize = 0; +short *vertTinyBuffer = NULL; +char *normTinyBuffer = NULL; + +// Static temporary buffer for doing frame interpolation +// 'size' is the vertex size +void GLModel_AllocLerpBuffer(size_t size) +{ + if (lerpBufferSize >= size) + return; + + if (vertBuffer != NULL) + free(vertBuffer); + + if (normBuffer != NULL) + free(normBuffer); + + lerpBufferSize = size; + vertBuffer = malloc(lerpBufferSize); + normBuffer = malloc(lerpBufferSize); +} + +// Static temporary buffer for doing frame interpolation +// 'size' is the vertex size +void GLModel_AllocLerpTinyBuffer(size_t size) +{ + if (lerpTinyBufferSize >= size) + return; + + if (vertTinyBuffer != NULL) + free(vertTinyBuffer); + + if (normTinyBuffer != NULL) + free(normTinyBuffer); + + lerpTinyBufferSize = size; + vertTinyBuffer = malloc(lerpTinyBufferSize); + normTinyBuffer = malloc(lerpTinyBufferSize / 2); +} + +static void CreateModelVBO(mesh_t *mesh, mdlframe_t *frame) +{ + int bufferSize = sizeof(vbo64_t)*mesh->numTriangles * 3; + vbo64_t *buffer = (vbo64_t*)malloc(bufferSize); + vbo64_t *bufPtr = buffer; + + float *vertPtr = frame->vertices; + float *normPtr = frame->normals; + float *tanPtr = frame->tangents; + float *uvPtr = mesh->uvs; + float *lightPtr = mesh->lightuvs; + char *colorPtr = frame->colors; + + int i; + for (i = 0; i < mesh->numTriangles * 3; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr != NULL) + { + bufPtr->tan0 = *tanPtr++; + bufPtr->tan1 = *tanPtr++; + bufPtr->tan2 = *tanPtr++; + } + + if (lightPtr != NULL) + { + bufPtr->s1 = *lightPtr++; + bufPtr->t1 = *lightPtr++; + } + + if (colorPtr) + { + bufPtr->r = *colorPtr++; + bufPtr->g = *colorPtr++; + bufPtr->b = *colorPtr++; + bufPtr->a = *colorPtr++; + } + else + { + bufPtr->r = 255; + bufPtr->g = 255; + bufPtr->b = 255; + bufPtr->a = 255; + } + + bufPtr++; + } + + pglGenBuffers(1, &frame->vboID); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); + free(buffer); + + // Don't leave the array buffer bound to the model, + // since this is called mid-frame + pglBindBuffer(GL_ARRAY_BUFFER, 0); +} + +static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame) +{ + int bufferSize = sizeof(vbotiny_t)*mesh->numTriangles * 3; + vbotiny_t *buffer = (vbotiny_t*)malloc(bufferSize); + vbotiny_t *bufPtr = buffer; + + short *vertPtr = frame->vertices; + char *normPtr = frame->normals; + float *uvPtr = mesh->uvs; + char *tanPtr = frame->tangents; + + int i; + for (i = 0; i < mesh->numVertices; i++) + { + bufPtr->x = *vertPtr++; + bufPtr->y = *vertPtr++; + bufPtr->z = *vertPtr++; + + bufPtr->nx = *normPtr++; + bufPtr->ny = *normPtr++; + bufPtr->nz = *normPtr++; + + bufPtr->s0 = *uvPtr++; + bufPtr->t0 = *uvPtr++; + + if (tanPtr) + { + bufPtr->tanx = *tanPtr++; + bufPtr->tany = *tanPtr++; + bufPtr->tanz = *tanPtr++; + } + + bufPtr++; + } + + pglGenBuffers(1, &frame->vboID); + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); + free(buffer); + + // Don't leave the array buffer bound to the model, + // since this is called mid-frame + pglBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void GLModel_GenerateVBOs(model_t *model) +{ + int i; + + if (!GLExtension_vertex_buffer_object) + return; + + for (i = 0; i < model->numMeshes; i++) + { + mesh_t *mesh = &model->meshes[i]; + + if (mesh->frames) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + mdlframe_t *frame = &mesh->frames[j]; + if (frame->vboID) + pglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + CreateModelVBO(mesh, frame); + } + } + else if (mesh->tinyframes) + { + int j; + for (j = 0; j < model->meshes[i].numFrames; j++) + { + tinyframe_t *frame = &mesh->tinyframes[j]; + if (frame->vboID) + pglDeleteBuffers(1, &frame->vboID); + frame->vboID = 0; + CreateModelVBOTiny(mesh, frame); + } + } + } +} + +// Deletes all textures. +void GLTexture_Flush(void) +{ + while (TexCacheHead) + { + FTextureInfo *pTexInfo = TexCacheHead; + HWRTexture_t *texture = pTexInfo->texture; + + if (pTexInfo->name) + { + pglDeleteTextures(1, (GLuint *)&pTexInfo->name); + pTexInfo->name = 0; + } + + if (texture) + texture->downloaded = 0; + + TexCacheHead = pTexInfo->next; + free(pTexInfo); + } + + TexCacheTail = TexCacheHead = NULL; // Hurdler: well, TexCacheHead is already NULL + CurrentTexture = 0; +} + +// Sets texture filtering mode. +void GLTexture_SetFilterMode(INT32 mode) +{ + switch (mode) + { + case GPU_TEXFILTER_TRILINEAR: + MipmapMinFilter = GL_LINEAR_MIPMAP_LINEAR; + MipmapMagFilter = GL_LINEAR; + MipmappingEnabled = GL_TRUE; + break; + case GPU_TEXFILTER_BILINEAR: + MipmapMinFilter = MipmapMagFilter = GL_LINEAR; + MipmappingEnabled = GL_FALSE; + break; + case GPU_TEXFILTER_POINTSAMPLED: + MipmapMinFilter = MipmapMagFilter = GL_NEAREST; + MipmappingEnabled = GL_FALSE; + break; + case GPU_TEXFILTER_MIXED1: + MipmapMinFilter = GL_NEAREST; + MipmapMagFilter = GL_LINEAR; + MipmappingEnabled = GL_FALSE; + break; + case GPU_TEXFILTER_MIXED2: + MipmapMinFilter = GL_LINEAR; + MipmapMagFilter = GL_NEAREST; + MipmappingEnabled = GL_FALSE; + break; + case GPU_TEXFILTER_MIXED3: + MipmapMinFilter = GL_LINEAR_MIPMAP_LINEAR; + MipmapMagFilter = GL_NEAREST; + MipmappingEnabled = GL_TRUE; + break; + default: + MipmapMagFilter = GL_LINEAR; + MipmapMinFilter = GL_NEAREST; + } +} + +// Deletes a single texture. +void GLTexture_Delete(HWRTexture_t *pTexInfo) +{ + FTextureInfo *head = TexCacheHead; + + while (head) + { + if (head->name == pTexInfo->downloaded) + { + if (head->next) + head->next->prev = head->prev; + if (head->prev) + head->prev->next = head->next; + free(head); + break; + } + + head = head->next; + } +} + +// Calculates total memory usage by textures, excluding mipmaps. +INT32 GLTexture_GetMemoryUsage(FTextureInfo *head) +{ + INT32 res = 0; + + while (head) + { + // Figure out the correct bytes-per-pixel for this texture + // This follows format2bpp in hw_cache.c + INT32 bpp = 1; + UINT32 format = head->format; + if (format == GPU_TEXFMT_RGBA) + bpp = 4; + else if (format == GPU_TEXFMT_ALPHA_INTENSITY_88 || format == GPU_TEXFMT_AP_88) + bpp = 2; + + // Add it up! + res += head->height*head->width*bpp; + head = head->next; + } + + return res; +} + +// Generates a screen texture. +void GLTexture_GenerateScreenTexture(GLuint *name) +{ + INT32 texsize = 2048; + boolean firstTime = ((*name) == 0); + + // Use a power of two texture, dammit + if (GPUScreenWidth <= 512) + texsize = 512; + else if (GPUScreenWidth <= 1024) + texsize = 1024; + + // Create screen texture + if (firstTime) + pglGenTextures(1, name); + pglBindTexture(GL_TEXTURE_2D, *name); + + if (firstTime) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + SetClamp(GL_TEXTURE_WRAP_S); + SetClamp(GL_TEXTURE_WRAP_T); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + } + else + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); + + CurrentTexture = *name; +} + +// -----------------+ +// GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, +// : else do nothing +// Returns : +// -----------------+ + +#ifdef DEBUG_TO_FILE +FILE *gllogstream; +#endif + +#define VA_DBG_BUF_SIZE 8192 + +#define VA_DBG_PRINT \ + static char str[VA_DBG_BUF_SIZE] = ""; \ + va_list arglist; \ + va_start(arglist, format); \ + vsnprintf(str, VA_DBG_BUF_SIZE, format, arglist); \ + va_end(arglist); \ + +#define VA_DBG_LOGFILE \ + if (!gllogstream) \ + gllogstream = fopen("ogllog.txt", "w"); \ + fwrite(str, strlen(str), 1, gllogstream); + +void GL_DBG_Printf(const char *format, ...) +{ + VA_DBG_PRINT + +#ifdef HAVE_SDL + CONS_Debug(DBG_RENDER, "%s", str); +#endif + +#ifdef DEBUG_TO_FILE + VA_DBG_LOGFILE +#endif +} + +// -----------------+ +// GL_MSG_Warning : Raises a warning. +// : +// Returns : +// -----------------+ + +void GL_MSG_Warning(const char *format, ...) +{ + VA_DBG_PRINT + +#ifdef HAVE_SDL + CONS_Alert(CONS_WARNING, "%s", str); +#endif + +#ifdef DEBUG_TO_FILE + VA_DBG_LOGFILE +#endif +} + +// -----------------+ +// GL_MSG_Error : Raises an error. +// : +// Returns : +// -----------------+ + +void GL_MSG_Error(const char *format, ...) +{ + VA_DBG_PRINT + +#ifdef HAVE_SDL + CONS_Alert(CONS_ERROR, "%s", str); +#endif + +#ifdef DEBUG_TO_FILE + VA_DBG_LOGFILE +#endif +} + +#undef VA_DBG_PRINT +#undef VA_DBG_LOGFILE +#undef VA_DBG_BUF_SIZE diff --git a/src/hardware/r_glcommon/r_glcommon.h b/src/hardware/r_glcommon/r_glcommon.h new file mode 100644 index 0000000000000000000000000000000000000000..3900b79055ef188ecaa4ad58546a9aa35108371a --- /dev/null +++ b/src/hardware/r_glcommon/r_glcommon.h @@ -0,0 +1,561 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_glcommon.h +/// \brief Common OpenGL functions and structs shared by OpenGL backends + +#ifndef _R_GLCOMMON_H_ +#define _R_GLCOMMON_H_ + +#define GL_GLEXT_PROTOTYPES + +#if defined(HAVE_GLES2) + #include <GLES2/gl2.h> + #include <GLES2/gl2ext.h> +#elif defined(HAVE_GLES) + #include <GLES/gl.h> + #include <GLES/glext.h> +#else + #ifdef HAVE_SDL + #define _MATH_DEFINES_DEFINED + + #ifdef _MSC_VER + #pragma warning(disable : 4214 4244) + #endif + + #include "SDL_opengl.h" //Alam_GBC: Simple, yes? + + #ifdef _MSC_VER + #pragma warning(default : 4214 4244) + #endif + #else + #include <GL/gl.h> + #include <GL/glu.h> + #if defined(STATIC_OPENGL) + #include <GL/glext.h> + #endif + #endif +#endif + +// For GLExtension_Available +#ifdef HAVE_SDL +#define _MATH_DEFINES_DEFINED +#include "SDL.h" +#endif + +#include "../../doomdata.h" +#include "../../doomtype.h" +#include "../../doomdef.h" + +#include "../../hardware/hw_data.h" // HWRTexture_s +#include "../../hardware/hw_defs.h" // FTextureInfo +#include "../../hardware/hw_model.h" // model_t / mesh_t / mdlframe_t +#include "../r_opengl/r_vbo.h" + +void GL_DBG_Printf(const char *format, ...); +void GL_MSG_Warning(const char *format, ...); +void GL_MSG_Error(const char *format, ...); + +#ifdef DEBUG_TO_FILE +extern FILE *gllogstream; +#endif + +#ifndef R_GL_APIENTRY + #if defined(_WIN32) + #define R_GL_APIENTRY APIENTRY + #else + #define R_GL_APIENTRY + #endif +#endif + +// ========================================================================== +// PROTOS +// ========================================================================== + +#ifdef STATIC_OPENGL +/* Miscellaneous */ +#define pglClear glClear +#define pglGetFloatv glGetFloatv +#define pglGetIntegerv glGetIntegerv +#define pglGetString glGetString +#define pglClearColor glClearColor +#define pglColorMask glColorMask +#define pglAlphaFunc glAlphaFunc +#define pglBlendFunc glBlendFunc +#define pglCullFace glCullFace +#define pglPolygonOffset glPolygonOffset +#define pglEnable glEnable +#define pglDisable glDisable + +/* Depth buffer */ +#define pglDepthMask glDepthMask +#define pglDepthRange glDepthRange + +/* Transformation */ +#define pglViewport glViewport + +/* Raster functions */ +#define pglPixelStorei glPixelStorei +#define pglReadPixels glReadPixels + +/* Texture mapping */ +#define pglTexParameteri glTexParameteri +#define pglTexImage2D glTexImage2D +#define pglTexSubImage2D glTexSubImage2D + +/* Drawing functions */ +#define pglDrawArrays glDrawArrays +#define pglDrawElements glDrawElements + +/* Texture objects */ +#define pglGenTextures glGenTextures +#define pglDeleteTextures glDeleteTextures +#define pglBindTexture glBindTexture + +/* Texture mapping */ +#define pglCopyTexImage2D glCopyTexImage2D +#define pglCopyTexSubImage2D glCopyTexSubImage2D + +/* 1.3 functions for multitexturing */ +#define pglActiveTexture glActiveTexture +#else +/* Miscellaneous */ +typedef void (R_GL_APIENTRY * PFNglClear) (GLbitfield mask); +extern PFNglClear pglClear; +typedef void (R_GL_APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); +extern PFNglGetFloatv pglGetFloatv; +typedef void (R_GL_APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params); +extern PFNglGetIntegerv pglGetIntegerv; +typedef const GLubyte * (R_GL_APIENTRY * PFNglGetString) (GLenum name); +extern PFNglGetString pglGetString; +typedef void (R_GL_APIENTRY * PFNglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +extern PFNglClearColor pglClearColor; +typedef void (R_GL_APIENTRY * PFNglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +extern PFNglColorMask pglColorMask; +typedef void (R_GL_APIENTRY * PFNglAlphaFunc) (GLenum func, GLclampf ref); +extern PFNglAlphaFunc pglAlphaFunc; +typedef void (R_GL_APIENTRY * PFNglBlendFunc) (GLenum sfactor, GLenum dfactor); +extern PFNglBlendFunc pglBlendFunc; +typedef void (R_GL_APIENTRY * PFNglCullFace) (GLenum mode); +extern PFNglCullFace pglCullFace; +typedef void (R_GL_APIENTRY * PFNglPolygonOffset) (GLfloat factor, GLfloat units); +extern PFNglPolygonOffset pglPolygonOffset; +typedef void (R_GL_APIENTRY * PFNglEnable) (GLenum cap); +extern PFNglEnable pglEnable; +typedef void (R_GL_APIENTRY * PFNglDisable) (GLenum cap); +extern PFNglDisable pglDisable; + +/* Depth buffer */ +typedef void (R_GL_APIENTRY * PFNglDepthFunc) (GLenum func); +extern PFNglDepthFunc pglDepthFunc; +typedef void (R_GL_APIENTRY * PFNglDepthMask) (GLboolean flag); +extern PFNglDepthMask pglDepthMask; + +/* Transformation */ +typedef void (R_GL_APIENTRY * PFNglViewport) (GLint x, GLint y, GLsizei width, GLsizei height); +extern PFNglViewport pglViewport; + +/* Raster functions */ +typedef void (R_GL_APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param); +extern PFNglPixelStorei pglPixelStorei; +typedef void (R_GL_APIENTRY * PFNglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +extern PFNglReadPixels pglReadPixels; + +/* Texture mapping */ +typedef void (R_GL_APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint param); +extern PFNglTexParameteri pglTexParameteri; +typedef void (R_GL_APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +extern PFNglTexImage2D pglTexImage2D; +typedef void (R_GL_APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +extern PFNglTexSubImage2D pglTexSubImage2D; + +/* Drawing functions */ +typedef void (R_GL_APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count); +extern PFNglDrawArrays pglDrawArrays; +typedef void (R_GL_APIENTRY * PFNglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +extern PFNglDrawElements pglDrawElements; + +/* Texture objects */ +typedef void (R_GL_APIENTRY * PFNglGenTextures) (GLsizei n, const GLuint *textures); +extern PFNglGenTextures pglGenTextures; +typedef void (R_GL_APIENTRY * PFNglDeleteTextures) (GLsizei n, const GLuint *textures); +extern PFNglDeleteTextures pglDeleteTextures; +typedef void (R_GL_APIENTRY * PFNglBindTexture) (GLenum target, GLuint texture); +extern PFNglBindTexture pglBindTexture; + +/* Texture mapping */ +typedef void (R_GL_APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +extern PFNglCopyTexImage2D pglCopyTexImage2D; +typedef void (R_GL_APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +extern PFNglCopyTexSubImage2D pglCopyTexSubImage2D; + +/* 1.3 functions for multitexturing */ +typedef void (R_GL_APIENTRY * PFNglActiveTexture) (GLenum); +extern PFNglActiveTexture pglActiveTexture; +#endif + +// +// Multi-texturing +// + +#ifndef HAVE_GLES2 + #ifdef STATIC_OPENGL + #define pglClientActiveTexture glClientActiveTexture + #else + typedef void (R_GL_APIENTRY * PFNglClientActiveTexture) (GLenum); + extern PFNglClientActiveTexture pglClientActiveTexture; + #endif +#endif + +// +// Mipmapping +// + +#ifdef HAVE_GLES +/* Texture mapping */ +typedef void (R_GL_APIENTRY * PFNglGenerateMipmap) (GLenum target); +extern PFNglGenerateMipmap pglGenerateMipmap; +#endif + +// +// Depth functions +// +#ifndef HAVE_GLES + #ifdef STATIC_OPENGL + #define pglClearDepth glClearDepth + #define pglDepthFunc glDepthFunc + #else + typedef void (R_GL_APIENTRY * PFNglClearDepth) (GLclampd depth); + extern PFNglClearDepth pglClearDepth; + typedef void (R_GL_APIENTRY * PFNglDepthRange) (GLclampd near_val, GLclampd far_val); + extern PFNglDepthRange pglDepthRange; + #endif +#else + #ifdef STATIC_OPENGL + #define pglClearDepthf glClearDepthf + #define pglDepthFuncf glDepthFuncf + #else + typedef void (R_GL_APIENTRY * PFNglClearDepthf) (GLclampf depth); + extern PFNglClearDepthf pglClearDepthf; + typedef void (R_GL_APIENTRY * PFNglDepthRangef) (GLclampf near_val, GLclampf far_val); + extern PFNglDepthRangef pglDepthRangef; + #endif +#endif + +// +// Legacy functions +// + +#ifndef HAVE_GLES2 +#ifdef STATIC_OPENGL +/* Transformation */ +#define pglMatrixMode glMatrixMode +#define pglViewport glViewport +#define pglPushMatrix glPushMatrix +#define pglPopMatrix glPopMatrix +#define pglLoadIdentity glLoadIdentity +#define pglMultMatrixf glMultMatrixf +#define pglRotatef glRotatef +#define pglScalef glScalef +#define pglTranslatef glTranslatef + +/* Drawing functions */ +#define pglVertexPointer glVertexPointer +#define pglNormalPointer glNormalPointer +#define pglTexCoordPointer glTexCoordPointer +#define pglColorPointer glColorPointer +#define pglEnableClientState glEnableClientState +#define pglDisableClientState glDisableClientState + +/* Lighting */ +#define pglShadeModel glShadeModel +#define pglLightfv glLightfv +#define pglLightModelfv glLightModelfv +#define pglMaterialfv glMaterialfv + +/* Texture mapping */ +#define pglTexEnvi glTexEnvi + +#else // STATIC_OPENGL + +typedef void (R_GL_APIENTRY * PFNglMatrixMode) (GLenum mode); +extern PFNglMatrixMode pglMatrixMode; +typedef void (R_GL_APIENTRY * PFNglPushMatrix) (void); +extern PFNglPushMatrix pglPushMatrix; +typedef void (R_GL_APIENTRY * PFNglPopMatrix) (void); +extern PFNglPopMatrix pglPopMatrix; +typedef void (R_GL_APIENTRY * PFNglLoadIdentity) (void); +extern PFNglLoadIdentity pglLoadIdentity; +typedef void (R_GL_APIENTRY * PFNglMultMatrixf) (const GLfloat *m); +extern PFNglMultMatrixf pglMultMatrixf; +typedef void (R_GL_APIENTRY * PFNglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +extern PFNglRotatef pglRotatef; +typedef void (R_GL_APIENTRY * PFNglScalef) (GLfloat x, GLfloat y, GLfloat z); +extern PFNglScalef pglScalef; +typedef void (R_GL_APIENTRY * PFNglTranslatef) (GLfloat x, GLfloat y, GLfloat z); +extern PFNglTranslatef pglTranslatef; + +/* Drawing Functions */ +typedef void (R_GL_APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern PFNglVertexPointer pglVertexPointer; +typedef void (R_GL_APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); +extern PFNglNormalPointer pglNormalPointer; +typedef void (R_GL_APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern PFNglTexCoordPointer pglTexCoordPointer; +typedef void (R_GL_APIENTRY * PFNglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern PFNglColorPointer pglColorPointer; +typedef void (R_GL_APIENTRY * PFNglEnableClientState) (GLenum cap); +extern PFNglEnableClientState pglEnableClientState; +typedef void (R_GL_APIENTRY * PFNglDisableClientState) (GLenum cap); +extern PFNglDisableClientState pglDisableClientState; + +/* Lighting */ +typedef void (R_GL_APIENTRY * PFNglShadeModel) (GLenum mode); +extern PFNglShadeModel pglShadeModel; +typedef void (R_GL_APIENTRY * PFNglLightfv) (GLenum light, GLenum pname, GLfloat *params); +extern PFNglLightfv pglLightfv; +typedef void (R_GL_APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params); +extern PFNglLightModelfv pglLightModelfv; +typedef void (R_GL_APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params); +extern PFNglMaterialfv pglMaterialfv; + +/* Texture mapping */ +typedef void (R_GL_APIENTRY * PFNglTexEnvi) (GLenum target, GLenum pname, GLint param); +extern PFNglTexEnvi pglTexEnvi; +#endif +#endif // HAVE_GLES2 + +// Color +#ifdef HAVE_GLES + #ifdef STATIC_OPENGL + #define pglColor4f glColor4f + #else + typedef void (*PFNglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + extern PFNglColor4f pglColor4f; + #endif +#else + #ifdef STATIC_OPENGL + #define pglColor4ubv glColor4ubv + #else + typedef void (R_GL_APIENTRY * PFNglColor4ubv) (const GLubyte *v); + extern PFNglColor4ubv pglColor4ubv; + #endif +#endif + +/* 1.5 functions for buffers */ +typedef void (R_GL_APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers); +extern PFNglGenBuffers pglGenBuffers; +typedef void (R_GL_APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer); +extern PFNglBindBuffer pglBindBuffer; +typedef void (R_GL_APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage); +extern PFNglBufferData pglBufferData; +typedef void (R_GL_APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); +extern PFNglDeleteBuffers pglDeleteBuffers; + +/* 2.0 functions */ +typedef void (R_GL_APIENTRY * PFNglBlendEquation) (GLenum mode); +extern PFNglBlendEquation pglBlendEquation; + +// ========================================================================== +// FUNCTIONS +// ========================================================================== + +void GLModel_GenerateVBOs(model_t *model); +void GLModel_AllocLerpBuffer(size_t size); +void GLModel_AllocLerpTinyBuffer(size_t size); + +void GLTexture_Flush(void); +void GLTexture_SetFilterMode(INT32 mode); +void GLTexture_Delete(HWRTexture_t *pTexInfo); +INT32 GLTexture_GetMemoryUsage(FTextureInfo *head); +void GLTexture_GenerateScreenTexture(GLuint *name); + +boolean GLBackend_Init(void); +boolean GLBackend_InitContext(void); +boolean GLBackend_LoadLibrary(void); +boolean GLBackend_LoadFunctions(void); +boolean GLBackend_LoadContextFunctions(void); +boolean GLBackend_LoadCommonFunctions(void); +boolean GLBackend_LoadLegacyFunctions(void); +void *GLBackend_GetFunction(const char *proc); + +INT32 GLBackend_GetShaderType(INT32 type); + +void GLExtension_Init(void); +boolean GLExtension_Available(const char *extension); + +void SetSurface(INT32 w, INT32 h); +void SetModelView(GLint w, GLint h); +void SetStates(void); +void SetBlendingStates(UINT32 PolyFlags); +void SetNoTexture(void); +void SetClamp(GLenum pname); + +// ========================================================================== +// CONSTANTS +// ========================================================================== + +#define N_PI_DEMI (M_PIl/2.0f) +#define ASPECT_RATIO (1.0f) +#define FIELD_OF_VIEW 90.0f + +#define FAR_CLIPPING_PLANE 32768.0f // Draw further! Tails 01-21-2001 + +// shortcut for ((float)1/i) +#define byte2float(x) (x / 255.0f) + +#define NULL_VBO_VERTEX ((FSkyVertex*)NULL) +#define sky_vbo_x (GLExtension_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &sky->data[0].x) +#define sky_vbo_u (GLExtension_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &sky->data[0].u) +#define sky_vbo_r (GLExtension_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &sky->data[0].r) + +/* 1.2 Parms */ +/* GL_CLAMP_TO_EDGE_EXT */ +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif +#ifndef GL_TEXTURE_MIN_LOD +#define GL_TEXTURE_MIN_LOD 0x813A +#endif +#ifndef GL_TEXTURE_MAX_LOD +#define GL_TEXTURE_MAX_LOD 0x813B +#endif + +/* 1.3 GL_TEXTUREi */ +#ifndef GL_TEXTURE0 +#define GL_TEXTURE0 0x84C0 +#endif +#ifndef GL_TEXTURE1 +#define GL_TEXTURE1 0x84C1 +#endif + +/* 1.5 Parms */ +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif + +#ifndef GL_FUNC_ADD +#define GL_FUNC_ADD 0x8006 +#endif + +#ifndef GL_FUNC_SUBTRACT +#define GL_FUNC_SUBTRACT 0x800A +#endif + +#ifndef GL_FUNC_REVERSE_SUBTRACT +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#endif + +#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#endif + +#ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +// ========================================================================== +// STRUCTS +// ========================================================================== + +struct GLRGBAFloat +{ + GLfloat red; + GLfloat green; + GLfloat blue; + GLfloat alpha; +}; +typedef struct GLRGBAFloat GLRGBAFloat; + +struct FExtensionList +{ + const char *name; + boolean *extension; +}; +typedef struct FExtensionList FExtensionList; + +// ========================================================================== +// GLOBALS +// ========================================================================== + +extern const GLubyte *GLVersion; +extern const GLubyte *GLRenderer; +extern const GLubyte *GLExtensions; + +extern GLint GLMajorVersion; +extern GLint GLMinorVersion; + +extern struct GPURenderingAPI GLInterfaceAPI; + +extern RGBA_t GPUTexturePalette[256]; +extern GLint GPUTextureFormat; +extern GLint GPUScreenWidth, GPUScreenHeight; +extern GLbyte GPUScreenDepth; +extern GLint GPUMaximumAnisotropy; + +// Linked list of all textures. +extern FTextureInfo *TexCacheTail; +extern FTextureInfo *TexCacheHead; + +extern GLuint CurrentTexture; +extern GLuint BlankTexture; // With OpenGL 1.1+, the first texture should be 1 + +extern GLuint ScreenTexture; +extern GLuint FinalScreenTexture; +extern GLuint WipeStartTexture; +extern GLuint WipeEndTexture; + +extern UINT32 CurrentPolyFlags; + +extern GLboolean MipmappingEnabled; +extern GLboolean ModelLightingEnabled; + +extern GLint MipmapMinFilter; +extern GLint MipmapMagFilter; +extern GLint AnisotropicFilter; + +extern float NearClippingPlane; + +extern float *vertBuffer; +extern float *normBuffer; +extern short *vertTinyBuffer; +extern char *normTinyBuffer; + +#ifdef HAVE_GLES2 +typedef float fvector3_t[3]; +typedef float fvector4_t[4]; +typedef fvector4_t fmatrix4_t[4]; + +extern fmatrix4_t projMatrix; +extern fmatrix4_t viewMatrix; +extern fmatrix4_t modelMatrix; +#endif + +// ========================================================================== +// EXTENSIONS +// ========================================================================== + +extern boolean GLExtension_multitexture; +extern boolean GLExtension_vertex_buffer_object; +extern boolean GLExtension_texture_filter_anisotropic; +extern boolean GLExtension_vertex_program; +extern boolean GLExtension_fragment_program; +extern boolean GLExtension_shaders; + +#endif // _R_GLCOMMON_H_ diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 4275d7daee22ce7359a7724533464ee304a27429..99ffc64c5e414b38eacdb40709358b587776ae20 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -10,7 +10,6 @@ /// \brief OpenGL API for Sonic Robo Blast 2 #if defined (_WIN32) -//#define WIN32_LEAN_AND_MEAN #define RPC_NO_WINDOWS_H #include <windows.h> #endif @@ -24,1069 +23,91 @@ #include "r_opengl.h" #include "r_vbo.h" +#include "../shaders/gl_shaders.h" + #if defined (HWRENDER) && !defined (NOROPENGL) -struct GLRGBAFloat -{ - GLfloat red; - GLfloat green; - GLfloat blue; - GLfloat alpha; -}; -typedef struct GLRGBAFloat GLRGBAFloat; static const GLubyte white[4] = { 255, 255, 255, 255 }; // ========================================================================== -// CONSTANTS -// ========================================================================== - -#define ASPECT_RATIO (1.0f) //(320.0f/200.0f) -#define FIELD_OF_VIEW 90.0f - -#define FAR_CLIPPING_PLANE 32768.0f // Draw further! Tails 01-21-2001 -static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; - -#define N_PI_DEMI (M_PIl/2.0f) //(1.5707963268f) - -// ************************************************************************** // GLOBALS -// ************************************************************************** - -RGBA_t GPUTexturePalette[256]; -GLint GPUTextureFormat; -GLint GPUScreenWidth, GPUScreenHeight; -GLbyte GPUScreenDepth; -GLint GPUMaximumAnisotropy = 0; - -// Linked list of all textures. -static FTextureInfo *TexCacheTail = NULL; -static FTextureInfo *TexCacheHead = NULL; - -static GLuint CurrentTexture = 0; -static GLuint BlankTexture = 0; // With OpenGL 1.1+, the first texture should be 1 - -static GLuint ScreenTexture = 0; -static GLuint FinalScreenTexture = 0; -static GLuint WipeStartTexture = 0; -static GLuint WipeEndTexture = 0; - -static UINT32 CurrentPolyFlags; - -static GLboolean MipmappingEnabled = GL_FALSE; -static GLboolean ModelLightingEnabled = GL_FALSE; - -static GLint MipmapMinFilter = GL_LINEAR; -static GLint MipmapMagFilter = GL_LINEAR; -static GLint AnisotropicFilter = 0; - -const GLubyte *GLVersion = NULL; -const GLubyte *GLRenderer = NULL; -const GLubyte *GLExtensions = NULL; +// ========================================================================== // Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) static GLfloat ModelMatrix[16]; static GLfloat ProjectionMatrix[16]; static GLint SceneViewport[4]; -// shortcut for ((float)1/i) -#define byte2float(x) (x / 255.0f) - -// -----------------+ -// GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, -// : else do nothing -// Returns : -// -----------------+ - -#ifdef DEBUG_TO_FILE -FILE *gllogstream; -#endif - -FUNCPRINTF void GL_DBG_Printf(const char *format, ...) -{ -#ifdef DEBUG_TO_FILE - char str[4096] = ""; - va_list arglist; - - if (!gllogstream) - gllogstream = fopen("ogllog.txt", "w"); - - va_start(arglist, format); - vsnprintf(str, 4096, format, arglist); - va_end(arglist); - - fwrite(str, strlen(str), 1, gllogstream); -#else - (void)format; -#endif -} - -// -----------------+ -// GL_MSG_Warning : Raises a warning. -// : -// Returns : -// -----------------+ - -static void GL_MSG_Warning(const char *format, ...) -{ - char str[4096] = ""; - va_list arglist; - - va_start(arglist, format); - vsnprintf(str, 4096, format, arglist); - va_end(arglist); - -#ifdef HAVE_SDL - CONS_Alert(CONS_WARNING, "%s", str); -#endif -#ifdef DEBUG_TO_FILE - if (!gllogstream) - gllogstream = fopen("ogllog.txt", "w"); - fwrite(str, strlen(str), 1, gllogstream); -#endif -} - -// -----------------+ -// GL_MSG_Error : Raises an error. -// : -// Returns : -// -----------------+ - -static void GL_MSG_Error(const char *format, ...) -{ - char str[4096] = ""; - va_list arglist; - - va_start(arglist, format); - vsnprintf(str, 4096, format, arglist); - va_end(arglist); - -#ifdef HAVE_SDL - CONS_Alert(CONS_ERROR, "%s", str); -#endif -#ifdef DEBUG_TO_FILE - if (!gllogstream) - gllogstream = fopen("ogllog.txt", "w"); - fwrite(str, strlen(str), 1, gllogstream); -#endif -} - -#ifdef STATIC_OPENGL -/* 1.0 functions */ -/* Miscellaneous */ -#define pglClearColor glClearColor -//glClear -#define pglColorMask glColorMask -#define pglAlphaFunc glAlphaFunc -#define pglBlendFunc glBlendFunc -#define pglCullFace glCullFace -#define pglPolygonOffset glPolygonOffset -#define pglScissor glScissor -#define pglEnable glEnable -#define pglDisable glDisable -#define pglGetFloatv glGetFloatv -//glGetIntegerv -//glGetString -#define pglHint glHint - -/* Depth Buffer */ -#define pglClearDepth glClearDepth -#define pglDepthFunc glDepthFunc -#define pglDepthMask glDepthMask -#define pglDepthRange glDepthRange - -/* Transformation */ -#define pglMatrixMode glMatrixMode -#define pglViewport glViewport -#define pglPushMatrix glPushMatrix -#define pglPopMatrix glPopMatrix -#define pglLoadIdentity glLoadIdentity -#define pglMultMatrixf glMultMatrixf -#define pglRotatef glRotatef -#define pglScalef glScalef -#define pglTranslatef glTranslatef - -/* Drawing Functions */ -#define pglColor4ubv glColor4ubv -#define pglVertexPointer glVertexPointer -#define pglNormalPointer glNormalPointer -#define pglTexCoordPointer glTexCoordPointer -#define pglColorPointer glColorPointer -#define pglDrawArrays glDrawArrays -#define pglDrawElements glDrawElements -#define pglEnableClientState glEnableClientState -#define pglDisableClientState glDisableClientState - -/* Lighting */ -#define pglShadeModel glShadeModel -#define pglLightfv glLightfv -#define pglLightModelfv glLightModelfv -#define pglMaterialfv glMaterialfv -#define pglMateriali glMateriali - -/* Raster functions */ -#define pglPixelStorei glPixelStorei -#define pglReadPixels glReadPixels - -/* Texture mapping */ -#define pglTexEnvi glTexEnvi -#define pglTexParameteri glTexParameteri -#define pglTexImage2D glTexImage2D -#define pglTexSubImage2D glTexSubImage2D - -/* 1.1 functions */ -/* texture objects */ //GL_EXT_texture_object -#define pglGenTextures glGenTextures -#define pglDeleteTextures glDeleteTextures -#define pglBindTexture glBindTexture -/* texture mapping */ //GL_EXT_copy_texture -#define pglCopyTexImage2D glCopyTexImage2D -#define pglCopyTexSubImage2D glCopyTexSubImage2D - -#else //!STATIC_OPENGL - -/* 1.0 functions */ -/* Miscellaneous */ -typedef void (APIENTRY * PFNglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -static PFNglClearColor pglClearColor; -typedef void (APIENTRY * PFNglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -static PFNglColorMask pglColorMask; -typedef void (APIENTRY * PFNglAlphaFunc) (GLenum func, GLclampf ref); -static PFNglAlphaFunc pglAlphaFunc; -typedef void (APIENTRY * PFNglBlendFunc) (GLenum sfactor, GLenum dfactor); -static PFNglBlendFunc pglBlendFunc; -typedef void (APIENTRY * PFNglCullFace) (GLenum mode); -static PFNglCullFace pglCullFace; -typedef void (APIENTRY * PFNglPolygonOffset) (GLfloat factor, GLfloat units); -static PFNglPolygonOffset pglPolygonOffset; -typedef void (APIENTRY * PFNglScissor) (GLint x, GLint y, GLsizei width, GLsizei height); -static PFNglScissor pglScissor; -typedef void (APIENTRY * PFNglEnable) (GLenum cap); -static PFNglEnable pglEnable; -typedef void (APIENTRY * PFNglDisable) (GLenum cap); -static PFNglDisable pglDisable; -typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); -static PFNglGetFloatv pglGetFloatv; - -/* Depth Buffer */ -typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth); -static PFNglClearDepth pglClearDepth; -typedef void (APIENTRY * PFNglDepthFunc) (GLenum func); -static PFNglDepthFunc pglDepthFunc; -typedef void (APIENTRY * PFNglDepthMask) (GLboolean flag); -static PFNglDepthMask pglDepthMask; -typedef void (APIENTRY * PFNglDepthRange) (GLclampd near_val, GLclampd far_val); -static PFNglDepthRange pglDepthRange; - -/* Transformation */ -typedef void (APIENTRY * PFNglMatrixMode) (GLenum mode); -static PFNglMatrixMode pglMatrixMode; -typedef void (APIENTRY * PFNglViewport) (GLint x, GLint y, GLsizei width, GLsizei height); -static PFNglViewport pglViewport; -typedef void (APIENTRY * PFNglPushMatrix) (void); -static PFNglPushMatrix pglPushMatrix; -typedef void (APIENTRY * PFNglPopMatrix) (void); -static PFNglPopMatrix pglPopMatrix; -typedef void (APIENTRY * PFNglLoadIdentity) (void); -static PFNglLoadIdentity pglLoadIdentity; -typedef void (APIENTRY * PFNglMultMatrixf) (const GLfloat *m); -static PFNglMultMatrixf pglMultMatrixf; -typedef void (APIENTRY * PFNglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -static PFNglRotatef pglRotatef; -typedef void (APIENTRY * PFNglScalef) (GLfloat x, GLfloat y, GLfloat z); -static PFNglScalef pglScalef; -typedef void (APIENTRY * PFNglTranslatef) (GLfloat x, GLfloat y, GLfloat z); -static PFNglTranslatef pglTranslatef; - -/* Drawing Functions */ -typedef void (APIENTRY * PFNglColor4ubv) (const GLubyte *v); -static PFNglColor4ubv pglColor4ubv; -typedef void (APIENTRY * PFNglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -static PFNglVertexPointer pglVertexPointer; -typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); -static PFNglNormalPointer pglNormalPointer; -typedef void (APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -static PFNglTexCoordPointer pglTexCoordPointer; -typedef void (APIENTRY * PFNglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -static PFNglColorPointer pglColorPointer; -typedef void (APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count); -static PFNglDrawArrays pglDrawArrays; -typedef void (APIENTRY * PFNglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -static PFNglDrawElements pglDrawElements; -typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); -static PFNglEnableClientState pglEnableClientState; -typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap); -static PFNglDisableClientState pglDisableClientState; - -/* Lighting */ -typedef void (APIENTRY * PFNglShadeModel) (GLenum mode); -static PFNglShadeModel pglShadeModel; -typedef void (APIENTRY * PFNglLightfv) (GLenum light, GLenum pname, GLfloat *params); -static PFNglLightfv pglLightfv; -typedef void (APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params); -static PFNglLightModelfv pglLightModelfv; -typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params); -static PFNglMaterialfv pglMaterialfv; -typedef void (APIENTRY * PFNglMateriali) (GLint face, GLenum pname, GLint param); -static PFNglMateriali pglMateriali; - -/* Raster functions */ -typedef void (APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param); -static PFNglPixelStorei pglPixelStorei; -typedef void (APIENTRY * PFNglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -static PFNglReadPixels pglReadPixels; - -/* Texture mapping */ -typedef void (APIENTRY * PFNglTexEnvi) (GLenum target, GLenum pname, GLint param); -static PFNglTexEnvi pglTexEnvi; -typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint param); -static PFNglTexParameteri pglTexParameteri; -typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -static PFNglTexImage2D pglTexImage2D; -typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -static PFNglTexSubImage2D pglTexSubImage2D; - -/* 1.1 functions */ -/* texture objects */ //GL_EXT_texture_object -typedef void (APIENTRY * PFNglGenTextures) (GLsizei n, const GLuint *textures); -static PFNglGenTextures pglGenTextures; -typedef void (APIENTRY * PFNglDeleteTextures) (GLsizei n, const GLuint *textures); -static PFNglDeleteTextures pglDeleteTextures; -typedef void (APIENTRY * PFNglBindTexture) (GLenum target, GLuint texture); -static PFNglBindTexture pglBindTexture; -/* texture mapping */ //GL_EXT_copy_texture -typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -static PFNglCopyTexImage2D pglCopyTexImage2D; -typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; -#endif -/* GLU functions */ +//* GLU functions */ typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); static PFNgluBuild2DMipmaps pgluBuild2DMipmaps; -/* 1.3 functions for multitexturing */ -typedef void (APIENTRY *PFNglActiveTexture) (GLenum); -static PFNglActiveTexture pglActiveTexture; -typedef void (APIENTRY *PFNglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); -static PFNglMultiTexCoord2f pglMultiTexCoord2f; -typedef void (APIENTRY *PFNglMultiTexCoord2fv) (GLenum target, const GLfloat *v); -static PFNglMultiTexCoord2fv pglMultiTexCoord2fv; -typedef void (APIENTRY *PFNglClientActiveTexture) (GLenum); -static PFNglClientActiveTexture pglClientActiveTexture; - -/* 1.5 functions for buffers */ -typedef void (APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers); -static PFNglGenBuffers pglGenBuffers; -typedef void (APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer); -static PFNglBindBuffer pglBindBuffer; -typedef void (APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage); -static PFNglBufferData pglBufferData; -typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); -static PFNglDeleteBuffers pglDeleteBuffers; - -/* 2.0 functions */ -typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode); -static PFNglBlendEquation pglBlendEquation; - - -/* 1.2 Parms */ -/* GL_CLAMP_TO_EDGE_EXT */ -#ifndef GL_CLAMP_TO_EDGE -#define GL_CLAMP_TO_EDGE 0x812F -#endif -#ifndef GL_TEXTURE_MIN_LOD -#define GL_TEXTURE_MIN_LOD 0x813A -#endif -#ifndef GL_TEXTURE_MAX_LOD -#define GL_TEXTURE_MAX_LOD 0x813B -#endif - -/* 1.3 GL_TEXTUREi */ -#ifndef GL_TEXTURE0 -#define GL_TEXTURE0 0x84C0 -#endif -#ifndef GL_TEXTURE1 -#define GL_TEXTURE1 0x84C1 -#endif - -/* 1.5 Parms */ -#ifndef GL_ARRAY_BUFFER -#define GL_ARRAY_BUFFER 0x8892 -#endif -#ifndef GL_STATIC_DRAW -#define GL_STATIC_DRAW 0x88E4 -#endif - -boolean SetupGLfunc(void) +boolean GLBackend_LoadFunctions(void) { #ifndef STATIC_OPENGL -#define GETOPENGLFUNC(func, proc) \ - func = GetGLFunc(#proc); \ - if (!func) \ +#define GETOPENGLFUNC(func) \ + p ## gl ## func = GLBackend_GetFunction("gl" #func); \ + if (!(p ## gl ## func)) \ { \ - GL_MSG_Warning("failed to get OpenGL function: %s", #proc); \ + GL_MSG_Error("failed to get OpenGL function: %s", #func); \ + return false; \ } \ - GETOPENGLFUNC(pglClearColor, glClearColor) - - GETOPENGLFUNC(pglClear, glClear) - GETOPENGLFUNC(pglColorMask, glColorMask) - GETOPENGLFUNC(pglAlphaFunc, glAlphaFunc) - GETOPENGLFUNC(pglBlendFunc, glBlendFunc) - GETOPENGLFUNC(pglCullFace, glCullFace) - GETOPENGLFUNC(pglPolygonOffset, glPolygonOffset) - GETOPENGLFUNC(pglScissor, glScissor) - GETOPENGLFUNC(pglEnable, glEnable) - GETOPENGLFUNC(pglDisable, glDisable) - GETOPENGLFUNC(pglGetFloatv, glGetFloatv) - GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv) - GETOPENGLFUNC(pglGetString, glGetString) - - GETOPENGLFUNC(pglClearDepth, glClearDepth) - GETOPENGLFUNC(pglDepthFunc, glDepthFunc) - GETOPENGLFUNC(pglDepthMask, glDepthMask) - GETOPENGLFUNC(pglDepthRange, glDepthRange) - - GETOPENGLFUNC(pglMatrixMode, glMatrixMode) - GETOPENGLFUNC(pglViewport, glViewport) - GETOPENGLFUNC(pglPushMatrix, glPushMatrix) - GETOPENGLFUNC(pglPopMatrix, glPopMatrix) - GETOPENGLFUNC(pglLoadIdentity, glLoadIdentity) - GETOPENGLFUNC(pglMultMatrixf, glMultMatrixf) - GETOPENGLFUNC(pglRotatef, glRotatef) - GETOPENGLFUNC(pglScalef, glScalef) - GETOPENGLFUNC(pglTranslatef, glTranslatef) - - GETOPENGLFUNC(pglColor4ubv, glColor4ubv) - - GETOPENGLFUNC(pglVertexPointer, glVertexPointer) - GETOPENGLFUNC(pglNormalPointer, glNormalPointer) - GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) - GETOPENGLFUNC(pglColorPointer, glColorPointer) - GETOPENGLFUNC(pglDrawArrays, glDrawArrays) - GETOPENGLFUNC(pglDrawElements, glDrawElements) - GETOPENGLFUNC(pglEnableClientState, glEnableClientState) - GETOPENGLFUNC(pglDisableClientState, glDisableClientState) - - GETOPENGLFUNC(pglShadeModel, glShadeModel) - GETOPENGLFUNC(pglLightfv, glLightfv) - GETOPENGLFUNC(pglLightModelfv, glLightModelfv) - GETOPENGLFUNC(pglMaterialfv, glMaterialfv) - GETOPENGLFUNC(pglMateriali, glMateriali) - - GETOPENGLFUNC(pglPixelStorei, glPixelStorei) - GETOPENGLFUNC(pglReadPixels, glReadPixels) - - GETOPENGLFUNC(pglTexEnvi, glTexEnvi) - GETOPENGLFUNC(pglTexParameteri, glTexParameteri) - GETOPENGLFUNC(pglTexImage2D, glTexImage2D) - GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D) - - GETOPENGLFUNC(pglGenTextures, glGenTextures) - GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) - GETOPENGLFUNC(pglBindTexture, glBindTexture) - - GETOPENGLFUNC(pglCopyTexImage2D, glCopyTexImage2D) - GETOPENGLFUNC(pglCopyTexSubImage2D, glCopyTexSubImage2D) - -#undef GETOPENGLFUNC - -#endif - return true; -} - -static GLboolean ShadersEnabled = GL_FALSE; -static INT32 ShadersAllowed = GPU_SHADEROPTION_OFF; - -#ifdef GL_SHADERS -typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); -typedef void (APIENTRY *PFNglShaderSource) (GLuint, GLsizei, const GLchar**, GLint*); -typedef void (APIENTRY *PFNglCompileShader) (GLuint); -typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*); -typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); -typedef void (APIENTRY *PFNglDeleteShader) (GLuint); -typedef GLuint (APIENTRY *PFNglCreateProgram) (void); -typedef void (APIENTRY *PFNglDeleteProgram) (GLuint); -typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); -typedef void (APIENTRY *PFNglLinkProgram) (GLuint); -typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); -typedef void (APIENTRY *PFNglUseProgram) (GLuint); -typedef void (APIENTRY *PFNglUniform1i) (GLint, GLint); -typedef void (APIENTRY *PFNglUniform1f) (GLint, GLfloat); -typedef void (APIENTRY *PFNglUniform2f) (GLint, GLfloat, GLfloat); -typedef void (APIENTRY *PFNglUniform3f) (GLint, GLfloat, GLfloat, GLfloat); -typedef void (APIENTRY *PFNglUniform4f) (GLint, GLfloat, GLfloat, GLfloat, GLfloat); -typedef void (APIENTRY *PFNglUniform1fv) (GLint, GLsizei, const GLfloat*); -typedef void (APIENTRY *PFNglUniform2fv) (GLint, GLsizei, const GLfloat*); -typedef void (APIENTRY *PFNglUniform3fv) (GLint, GLsizei, const GLfloat*); -typedef GLint (APIENTRY *PFNglGetUniformLocation) (GLuint, const GLchar*); - -static PFNglCreateShader pglCreateShader; -static PFNglShaderSource pglShaderSource; -static PFNglCompileShader pglCompileShader; -static PFNglGetShaderiv pglGetShaderiv; -static PFNglGetShaderInfoLog pglGetShaderInfoLog; -static PFNglDeleteShader pglDeleteShader; -static PFNglCreateProgram pglCreateProgram; -static PFNglDeleteProgram pglDeleteProgram; -static PFNglAttachShader pglAttachShader; -static PFNglLinkProgram pglLinkProgram; -static PFNglGetProgramiv pglGetProgramiv; -static PFNglUseProgram pglUseProgram; -static PFNglUniform1i pglUniform1i; -static PFNglUniform1f pglUniform1f; -static PFNglUniform2f pglUniform2f; -static PFNglUniform3f pglUniform3f; -static PFNglUniform4f pglUniform4f; -static PFNglUniform1fv pglUniform1fv; -static PFNglUniform2fv pglUniform2fv; -static PFNglUniform3fv pglUniform3fv; -static PFNglGetUniformLocation pglGetUniformLocation; - -enum EShaderUniform -{ - // lighting - uniform_poly_color, - uniform_tint_color, - uniform_fade_color, - uniform_lighting, - uniform_fade_start, - uniform_fade_end, - - // misc. (custom shaders) - uniform_leveltime, - - uniform_max, -}; - -typedef struct FShaderObject -{ - GLuint program; - GLint uniforms[uniform_max+1]; - boolean custom; -} FShaderObject; - -static FShaderObject ShaderObjects[HWR_MAXSHADERS]; -static FShaderObject UserShaderObjects[HWR_MAXSHADERS]; -static FShaderSource CustomShaders[HWR_MAXSHADERS]; - -// 09102020 -typedef struct FShaderState -{ - FShaderObject *current; - GLuint type; - GLuint program; - boolean changed; -} FShaderState; -static FShaderState ShaderState; - -// Shader info -static INT32 ShaderLevelTime = 0; - -// Lactozilla: Shader functions -static boolean Shader_CompileProgram(FShaderObject *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader); -static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum); -static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); - -static GLRGBAFloat ShaderDefaultColor = {1.0f, 1.0f, 1.0f, 1.0f}; - -// ================ -// Vertex shaders -// ================ - -// -// Generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = gl_Color;\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// replicates the way fixed function lighting is used by the model lighting option, -// stores the lighting result to gl_Color -// (ambient lighting of 0.75 and diffuse lighting from above) -#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ - "float light = 0.75 + max(nDotVP, 0.0);\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// ================== -// Fragment shaders -// ================== - -// -// Generic fragment shader -// - -#define GLSL_DEFAULT_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ - "}\0" - -// -// Software fragment shader -// - -#define GLSL_DOOM_COLORMAP \ - "float R_DoomColormap(float light, float z)\n" \ - "{\n" \ - "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ - "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ - "float startmap = (15.0 - lightnum) * 4.0;\n" \ - "float scale = 160.0 / (lightz + 1.0);\n" \ - "return startmap - scale * 0.5;\n" \ - "}\n" - -#define GLSL_DOOM_LIGHT_EQUATION \ - "float R_DoomLightingEquation(float light)\n" \ - "{\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ - "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ - "}\n" - -#define GLSL_SOFTWARE_TINT_EQUATION \ - "if (tint_color.a > 0.0) {\n" \ - "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ - "float strength = sqrt(9.0 * tint_color.a);\n" \ - "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ - "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ - "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ - "}\n" - -#define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(lighting);\n" \ - "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ - "float fs = fade_start / 31.0;\n" \ - "float fe = fade_end / 31.0;\n" \ - "float fd = fe - fs;\n" \ - "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ - "}\n" \ - "final_color = mix(final_color, fade_color, darkness);\n" - -#define GLSL_SOFTWARE_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// same as above but multiplies results with the lighting value from the -// accompanying vertex shader (stored in gl_Color) -#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color *= gl_Color;\n" \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Water surface shader -// -// Mostly guesstimated, rather than the rest being built off Software science. -// Still needs to distort things underneath/around the water... -// - -#define GLSL_WATER_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - "uniform float leveltime;\n" \ - "const float freq = 0.025;\n" \ - "const float amp = 0.025;\n" \ - "const float speed = 2.0;\n" \ - "const float pi = 3.14159;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ - "float a = -pi * (z * freq) + (leveltime * speed);\n" \ - "float sdistort = sin(a) * amp;\n" \ - "float cdistort = cos(a) * amp;\n" \ - "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Fog block shader -// -// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha -// - -#define GLSL_FOG_FRAGMENT_SHADER \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 base_color = gl_Color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Sky fragment shader -// Modulates poly_color with gl_Color -// -#define GLSL_SKY_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ - "}\0" - -// ================ -// Shader sources -// ================ - -static struct { - const char *vertex; - const char *fragment; -} const gl_shadersources[] = { - // Default shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER}, - - // Floor shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Wall shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Sprite shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Model shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Model shader + diffuse lighting from above - {GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER}, - - // Water shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, - - // Fog shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, - - // Sky shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, - - {NULL, NULL}, -}; - -#endif // GL_SHADERS - -void SetupGLFunc4(void) -{ - pglActiveTexture = GetGLFunc("glActiveTexture"); - pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); - pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); - pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv"); - - /* 1.5 funcs */ - pglGenBuffers = GetGLFunc("glGenBuffers"); - pglBindBuffer = GetGLFunc("glBindBuffer"); - pglBufferData = GetGLFunc("glBufferData"); - pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); - - /* 2.0 funcs */ - pglBlendEquation = GetGLFunc("glBlendEquation"); - -#ifdef GL_SHADERS - pglCreateShader = GetGLFunc("glCreateShader"); - pglShaderSource = GetGLFunc("glShaderSource"); - pglCompileShader = GetGLFunc("glCompileShader"); - pglGetShaderiv = GetGLFunc("glGetShaderiv"); - pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); - pglDeleteShader = GetGLFunc("glDeleteShader"); - pglCreateProgram = GetGLFunc("glCreateProgram"); - pglDeleteProgram = GetGLFunc("glDeleteProgram"); - pglAttachShader = GetGLFunc("glAttachShader"); - pglLinkProgram = GetGLFunc("glLinkProgram"); - pglGetProgramiv = GetGLFunc("glGetProgramiv"); - pglUseProgram = GetGLFunc("glUseProgram"); - pglUniform1i = GetGLFunc("glUniform1i"); - pglUniform1f = GetGLFunc("glUniform1f"); - pglUniform2f = GetGLFunc("glUniform2f"); - pglUniform3f = GetGLFunc("glUniform3f"); - pglUniform4f = GetGLFunc("glUniform4f"); - pglUniform1fv = GetGLFunc("glUniform1fv"); - pglUniform2fv = GetGLFunc("glUniform2fv"); - pglUniform3fv = GetGLFunc("glUniform3fv"); - pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); -#endif - - // GLU - pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); -} - -// jimita -static boolean CompileShaders(void) -{ -#ifdef GL_SHADERS - GLint i; - - if (!pglUseProgram) + if (!GLBackend_LoadCommonFunctions()) return false; - CustomShaders[SHADER_DEFAULT].vertex = NULL; - CustomShaders[SHADER_DEFAULT].fragment = NULL; - - for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++) - { - FShaderObject *shader, *usershader; - const GLchar *vert_shader = gl_shadersources[i].vertex; - const GLchar *frag_shader = gl_shadersources[i].fragment; - - if (i >= HWR_MAXSHADERS) - break; - - shader = &ShaderObjects[i]; - usershader = &UserShaderObjects[i]; - - if (shader->program) - pglDeleteProgram(shader->program); - if (usershader->program) - pglDeleteProgram(usershader->program); - - shader->program = 0; - usershader->program = 0; + GETOPENGLFUNC(ClearDepth) + GETOPENGLFUNC(DepthRange) - if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader)) - shader->program = 0; + GETOPENGLFUNC(Color4ubv) - // Compile custom shader - if ((i == SHADER_DEFAULT) || !(CustomShaders[i].vertex || CustomShaders[i].fragment)) - continue; + GETOPENGLFUNC(VertexPointer) + GETOPENGLFUNC(NormalPointer) + GETOPENGLFUNC(TexCoordPointer) + GETOPENGLFUNC(ColorPointer) + GETOPENGLFUNC(EnableClientState) + GETOPENGLFUNC(DisableClientState) - // 18032019 - if (CustomShaders[i].vertex) - vert_shader = CustomShaders[i].vertex; - if (CustomShaders[i].fragment) - frag_shader = CustomShaders[i].fragment; + GETOPENGLFUNC(TexEnvi) - if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader)) - { - GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i)); - usershader->program = 0; - } - } - - SetShader(SHADER_DEFAULT); + if (!GLBackend_LoadLegacyFunctions()) + return false; - return true; -#else - return false; #endif + return true; } -// -// Shader info -// Those are given to the uniforms. -// - -static void SetShaderInfo(INT32 info, INT32 value) +boolean GLBackend_LoadContextFunctions(void) { -#ifdef GL_SHADERS - switch (info) + if (GLExtension_multitexture) { - case GPU_SHADERINFO_LEVELTIME: - ShaderLevelTime = value; - break; - default: - break; + GETOPENGLFUNC(ActiveTexture) + GETOPENGLFUNC(ClientActiveTexture) } -#else - (void)info; - (void)value; -#endif -} - -// -// Custom shader loading -// -static void LoadCustomShader(int number, char *code, size_t size, boolean isfragment) -{ -#ifdef GL_SHADERS - FShaderSource *shader; - - if (!pglUseProgram) - return; - - if (number < 1 || number > HWR_MAXSHADERS) - I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS); - else if (code == NULL) - I_Error("LoadCustomShader: empty shader"); - - shader = &CustomShaders[number]; -#define COPYSHADER(source) { \ - if (shader->source) \ - free(shader->source); \ - shader->source = malloc(size+1); \ - strncpy(shader->source, code, size); \ - shader->source[size] = 0; \ + if (GLExtension_vertex_buffer_object) + { + GETOPENGLFUNC(GenBuffers) + GETOPENGLFUNC(BindBuffer) + GETOPENGLFUNC(BufferData) + GETOPENGLFUNC(DeleteBuffers) } - if (isfragment) - COPYSHADER(fragment) - else - COPYSHADER(vertex) + if (GLMajorVersion >= 2) + GETOPENGLFUNC(BlendEquation) -#else - (void)number; - (void)shader; - (void)size; - (void)fragment; -#endif -} -static void SetShader(int type) -{ #ifdef GL_SHADERS - if (ShadersAllowed != GPU_SHADEROPTION_OFF) - { - FShaderObject *shader = ShaderState.current; - - // If using model lighting, set the appropriate shader. - // However don't override a custom shader. - if (type == SHADER_MODEL && ModelLightingEnabled - && !(ShaderObjects[SHADER_MODEL].custom && !ShaderObjects[SHADER_MODEL_LIGHTING].custom)) - type = SHADER_MODEL_LIGHTING; - - if ((shader == NULL) || (GLuint)type != ShaderState.type) - { - FShaderObject *baseshader = &ShaderObjects[type]; - FShaderObject *usershader = &UserShaderObjects[type]; - - if (usershader->program) - shader = (ShadersAllowed == GPU_SHADEROPTION_NOCUSTOM) ? baseshader : usershader; - else - shader = baseshader; - - ShaderState.current = shader; - ShaderState.type = type; - ShaderState.changed = true; - } - - if (ShaderState.program != shader->program) - { - ShaderState.program = shader->program; - ShaderState.changed = true; - } - - ShadersEnabled = (shader->program != 0) ? GL_TRUE : GL_FALSE; - return; - } -#else - (void)type; + if (GLExtension_shaders) + Shader_LoadFunctions(); #endif - ShadersEnabled = GL_FALSE; -} -static void UnSetShader(void) -{ -#ifdef GL_SHADERS - ShaderState.current = NULL; - ShaderState.type = 0; - ShaderState.program = 0; - - if (pglUseProgram) - pglUseProgram(0); -#endif - - ShadersEnabled = GL_FALSE; -} -static void CleanShaders(void) -{ - INT32 i; - - for (i = 1; i < HWR_MAXSHADERS; i++) - { - FShaderSource *shader = &CustomShaders[i]; - if (shader->vertex) - free(shader->vertex); - - if (shader->fragment) - free(shader->fragment); + // GLU + pgluBuild2DMipmaps = GLBackend_GetFunction("gluBuild2DMipmaps"); - shader->vertex = NULL; - shader->fragment = NULL; - } + return true; } -// -----------------+ -// SetNoTexture : Disable texture -// -----------------+ -static void SetNoTexture(void) -{ - // Disable texture. - if (CurrentTexture != BlankTexture) - { - if (BlankTexture == 0) - { - // Generate a 1x1 white pixel for the blank texture - pglGenTextures(1, &BlankTexture); - pglBindTexture(GL_TEXTURE_2D, BlankTexture); - pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, white); - } - else - pglBindTexture(GL_TEXTURE_2D, BlankTexture); - - CurrentTexture = BlankTexture; - } -} +#undef GETOPENGLFUNC static void GLPerspective(GLfloat fovy, GLfloat aspect) { @@ -1097,7 +118,7 @@ static void GLPerspective(GLfloat fovy, GLfloat aspect) { 0.0f, 0.0f, 1.0f,-1.0f}, { 0.0f, 0.0f, 0.0f, 0.0f}, }; - const GLfloat zNear = NEAR_CLIPPING_PLANE; + const GLfloat zNear = NearClippingPlane; const GLfloat zFar = FAR_CLIPPING_PLANE; const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); const GLfloat sine = sin(radians); @@ -1142,225 +163,78 @@ static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ, } if (fpclassify(in[3]) == FP_ZERO) return; in[0] /= in[3]; - in[1] /= in[3]; - in[2] /= in[3]; - /* Map x, y and z to range 0-1 */ - in[0] = in[0] * 0.5f + 0.5f; - in[1] = in[1] * 0.5f + 0.5f; - in[2] = in[2] * 0.5f + 0.5f; - - /* Map x,y to viewport */ - in[0] = in[0] * SceneViewport[2] + SceneViewport[0]; - in[1] = in[1] * SceneViewport[3] + SceneViewport[1]; - - *winX=in[0]; - *winY=in[1]; - *winZ=in[2]; -} - -// -----------------+ -// SetModelView : -// -----------------+ -void SetModelView(GLint w, GLint h) -{ -// GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); - - // The screen textures need to be flushed if the width or height change so that they be remade for the correct size - if (GPUScreenWidth != w || GPUScreenHeight != h) - FlushScreenTextures(); - - GPUScreenWidth = w; - GPUScreenHeight = h; - - pglViewport(0, 0, w, h); - - pglMatrixMode(GL_PROJECTION); - pglLoadIdentity(); - - pglMatrixMode(GL_MODELVIEW); - pglLoadIdentity(); - - GLPerspective(FIELD_OF_VIEW, ASPECT_RATIO); - //pglScalef(1.0f, 320.0f/200.0f, 1.0f); // gl_scalefrustum (ORIGINAL_ASPECT) - - // added for new coronas' code (without depth buffer) - pglGetIntegerv(GL_VIEWPORT, SceneViewport); - pglGetFloatv(GL_PROJECTION_MATRIX, ProjectionMatrix); -} - - -// -----------------+ -// SetStates : Set permanent states -// -----------------+ -void SetStates(void) -{ -#ifdef GL_LIGHT_MODEL_AMBIENT - GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; -#endif - -// GL_DBG_Printf("SetStates()\n"); - - // Hurdler: not necessary, is it? - pglShadeModel(GL_SMOOTH); // iterate vertice colors - //pglShadeModel(GL_FLAT); - - pglEnable(GL_TEXTURE_2D); // two-dimensional texturing - - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - pglEnable(GL_ALPHA_TEST); - pglAlphaFunc(GL_NOTEQUAL, 0.0f); - - //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) - pglEnable(GL_BLEND); // enable color blending - - pglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - //pglDisable(GL_DITHER); // faB: ??? (undocumented in OpenGL 1.1) - // Hurdler: yes, it is! - pglEnable(GL_DEPTH_TEST); // check the depth buffer - pglDepthMask(GL_TRUE); // enable writing to depth buffer - pglClearDepth(1.0f); - pglDepthRange(0.0f, 1.0f); - pglDepthFunc(GL_LEQUAL); - - // this set CurrentPolyFlags to the actual configuration - CurrentPolyFlags = 0xffffffff; - SetBlend(0); - - CurrentTexture = 0; - SetNoTexture(); - - pglPolygonOffset(-1.0f, -1.0f); - - //pglEnable(GL_CULL_FACE); - //pglCullFace(GL_FRONT); - - pglDisable(GL_FOG); + in[1] /= in[3]; + in[2] /= in[3]; + /* Map x, y and z to range 0-1 */ + in[0] = in[0] * 0.5f + 0.5f; + in[1] = in[1] * 0.5f + 0.5f; + in[2] = in[2] * 0.5f + 0.5f; - // Lighting for models -#ifdef GL_LIGHT_MODEL_AMBIENT - pglLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightDiffuse); - pglEnable(GL_LIGHT0); -#endif + /* Map x,y to viewport */ + in[0] = in[0] * SceneViewport[2] + SceneViewport[0]; + in[1] = in[1] * SceneViewport[3] + SceneViewport[1]; - // bp : when no t&l :) - pglLoadIdentity(); - pglScalef(1.0f, 1.0f, -1.0f); - pglGetFloatv(GL_MODELVIEW_MATRIX, ModelMatrix); // added for new coronas' code (without depth buffer) + *winX=in[0]; + *winY=in[1]; + *winZ=in[2]; } +// ========================================================================== +// API +// ========================================================================== // -----------------+ -// DeleteTexture : Deletes a texture from the GPU and frees its data +// Init : Initializes the OpenGL interface API // -----------------+ -static void DeleteTexture(HWRTexture_t *pTexInfo) +static boolean Init(void) { - FTextureInfo *head = TexCacheHead; - - if (!pTexInfo) - return; - else if (pTexInfo->downloaded) - pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded); - - while (head) - { - if (head->name == pTexInfo->downloaded) - { - if (head->next) - head->next->prev = head->prev; - if (head->prev) - head->prev->next = head->next; - free(head); - break; - } - - head = head->next; - } - - pTexInfo->downloaded = 0; + return GLBackend_Init(); } - // -----------------+ -// Flush : flush OpenGL textures -// : Clear list of downloaded mipmaps +// SetNoTexture : Disable texture // -----------------+ -void Flush(void) +void SetNoTexture(void) { - //GL_DBG_Printf ("HWR_Flush()\n"); - - while (TexCacheHead) + // Disable texture. + if (CurrentTexture != BlankTexture) { - FTextureInfo *pTexInfo = TexCacheHead; - HWRTexture_t *texture = pTexInfo->texture; - - if (pTexInfo->name) + if (BlankTexture == 0) { - pglDeleteTextures(1, (GLuint *)&pTexInfo->name); - pTexInfo->name = 0; + // Generate a 1x1 white pixel for the blank texture + pglGenTextures(1, &BlankTexture); + pglBindTexture(GL_TEXTURE_2D, BlankTexture); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, white); } + else + pglBindTexture(GL_TEXTURE_2D, BlankTexture); - if (texture) - texture->downloaded = 0; - - TexCacheHead = pTexInfo->next; - free(pTexInfo); + CurrentTexture = BlankTexture; } - - TexCacheTail = TexCacheHead = NULL; // Hurdler: well, TexCacheHead is already NULL - CurrentTexture = 0; } - // -----------------+ -// isExtAvailable : Look if an OpenGL extension is available -// Returns : true if extension available +// DeleteTexture : Deletes a texture from the GPU and frees its data // -----------------+ -INT32 isExtAvailable(const char *extension, const GLubyte *start) +static void DeleteTexture(HWRTexture_t *pTexInfo) { - GLubyte *where, *terminator; - - if (!extension || !start) return 0; - where = (GLubyte *) strchr(extension, ' '); - if (where || *extension == '\0') - return 0; - - for (;;) - { - where = (GLubyte *) strstr((const char *) start, extension); - if (!where) - break; - terminator = where + strlen(extension); - if (where == start || *(where - 1) == ' ') - if (*terminator == ' ' || *terminator == '\0') - return 1; - start = terminator; - } - return 0; -} - + if (!pTexInfo) + return; + else if (pTexInfo->downloaded) + pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded); -// -----------------+ -// Init : Initialise the OpenGL interface API -// Returns : -// -----------------+ -static boolean Init(void) -{ - return SetupGLfunc(); + GLTexture_Delete(pTexInfo); + pTexInfo->downloaded = 0; } - // -----------------+ // ClearTextureCache: Flush OpenGL textures from memory // -----------------+ static void ClearTextureCache(void) { - // GL_DBG_Printf ("HWR_Flush(exe)\n"); - Flush(); + GLTexture_Flush(); } - // -----------------+ // ReadRect : Read a rectangle region of the truecolor framebuffer // : store pixels as 16bit 565 RGB @@ -1412,7 +286,6 @@ static void ReadRect(INT32 x, INT32 y, INT32 width, INT32 height, } } - // -----------------+ // GClipRect : Defines the 2D hardware clipping window // -----------------+ @@ -1421,7 +294,7 @@ static void GClipRect(INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float near // GL_DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); pglViewport(minx, GPUScreenHeight-maxy, maxx-minx, maxy-miny); - NEAR_CLIPPING_PLANE = nearclip; + NearClippingPlane = nearclip; //pglScissor(minx, GPUScreenHeight-maxy, maxx-minx, maxy-miny); pglMatrixMode(GL_PROJECTION); @@ -1434,7 +307,6 @@ static void GClipRect(INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float near pglGetFloatv(GL_PROJECTION_MATRIX, ProjectionMatrix); } - // -----------------+ // SetPalette : Changes the current texture palette // -----------------+ @@ -1445,10 +317,23 @@ static void SetPalette(RGBA_t *palette) if (memcmp(&GPUTexturePalette, palette, palsize)) { memcpy(&GPUTexturePalette, palette, palsize); - Flush(); + GLTexture_Flush(); } } +void SetClamp(GLenum pname) +{ + pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp + pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE); +} + +// -----------------+ +// SetBlend : Set render mode +// -----------------+ +static void SetBlend(UINT32 PolyFlags) +{ + SetBlendingStates(PolyFlags); +} // -----------------+ // ClearBuffer : Clear the color/alpha/depth buffer(s) @@ -1479,9 +364,8 @@ static void ClearBuffer(boolean ColorMask, boolean DepthMask, FRGBAFloat *ClearC pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too } - // -----------------+ -// HWRAPI Draw2DLine: Render a 2D line +// Draw2DLine : Render a 2D line // -----------------+ static void Draw2DLine(F2DCoord * v1, F2DCoord * v2, @@ -1519,193 +403,9 @@ static void Draw2DLine(F2DCoord * v1, pglEnable(GL_TEXTURE_2D); } - // -----------------+ -// SetBlend : Set render mode +// UpdateTexture : Updates the texture data. // -----------------+ -// PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0, -// is it faster when pixels are discarded ? - -static void Clamp2D(GLenum pname) -{ - pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp - pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE); -} - -static void SetBlendEquation(GLenum mode) -{ - if (pglBlendEquation) - pglBlendEquation(mode); -} - -static void SetBlendMode(UINT32 flags) -{ - // Set blending function - switch (flags) - { - case PF_Translucent & PF_Blending: - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - break; - case PF_Masked & PF_Blending: - // Hurdler: does that mean lighting is only made by alpha src? - // it sounds ok, but not for polygonsmooth - pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture - break; - case PF_Additive & PF_Blending: - case PF_Subtractive & PF_Blending: - case PF_ReverseSubtract & PF_Blending: - case PF_Environment & PF_Blending: - pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - break; - case PF_AdditiveSource & PF_Blending: - pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest - break; - case PF_Multiplicative & PF_Blending: - pglBlendFunc(GL_DST_COLOR, GL_ZERO); - break; - case PF_Fog & PF_Fog: - // Sryder: Fog - // multiplies input colour by input alpha, and destination colour by input colour, then adds them - pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); - break; - default: // must be 0, otherwise it's an error - // No blending - pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending - break; - } - - // Set blending equation - switch (flags) - { - case PF_Subtractive & PF_Blending: - SetBlendEquation(GL_FUNC_SUBTRACT); - break; - case PF_ReverseSubtract & PF_Blending: - // good for shadow - // not really but what else ? - SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - break; - default: - SetBlendEquation(GL_FUNC_ADD); - break; - } - - // Alpha test - switch (flags) - { - case PF_Masked & PF_Blending: - pglAlphaFunc(GL_GREATER, 0.5f); - break; - case PF_Translucent & PF_Blending: - case PF_Additive & PF_Blending: - case PF_AdditiveSource & PF_Blending: - case PF_Subtractive & PF_Blending: - case PF_ReverseSubtract & PF_Blending: - case PF_Environment & PF_Blending: - case PF_Multiplicative & PF_Blending: - pglAlphaFunc(GL_NOTEQUAL, 0.0f); - break; - case PF_Fog & PF_Fog: - pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments - break; - default: - pglAlphaFunc(GL_GREATER, 0.5f); - break; - } -} -static void SetBlend(UINT32 PolyFlags) -{ - UINT32 Xor; - Xor = CurrentPolyFlags^PolyFlags; - if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible)) - { - if (Xor & PF_Blending) // if blending mode must be changed - SetBlendMode(PolyFlags & PF_Blending); - - if (Xor & PF_NoAlphaTest) - { - if (PolyFlags & PF_NoAlphaTest) - pglDisable(GL_ALPHA_TEST); - else - pglEnable(GL_ALPHA_TEST); // discard 0 alpha pixels (holes in texture) - } - - if (Xor & PF_Decal) - { - if (PolyFlags & PF_Decal) - pglEnable(GL_POLYGON_OFFSET_FILL); - else - pglDisable(GL_POLYGON_OFFSET_FILL); - } - - if (Xor & PF_NoDepthTest) - { - if (PolyFlags & PF_NoDepthTest) - pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST); - else - pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST); - } - - if (Xor & PF_RemoveYWrap) - { - if (PolyFlags & PF_RemoveYWrap) - Clamp2D(GL_TEXTURE_WRAP_T); - } - - if (Xor & PF_ForceWrapX) - { - if (PolyFlags & PF_ForceWrapX) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - } - - if (Xor & PF_ForceWrapY) - { - if (PolyFlags & PF_ForceWrapY) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - - if (Xor & PF_Modulated) - { - if (PolyFlags & PF_Modulated) - { // mix texture colour with Surface->PolyColor - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - else - { // colour from texture is unchanged before blending - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } - } - - if (Xor & PF_Occlude) // depth test but (no) depth write - { - if (PolyFlags&PF_Occlude) - { - pglDepthMask(1); - } - else - pglDepthMask(0); - } - ////Hurdler: not used if we don't define POLYSKY - if (Xor & PF_Invisible) - { - if (PolyFlags&PF_Invisible) - pglBlendFunc(GL_ZERO, GL_ONE); // transparent blending - else - { // big hack: (TODO: manage that better) - // we test only for PF_Masked because PF_Invisible is only used - // (for now) with it (yeah, that's crappy, sorry) - if ((PolyFlags&PF_Blending)==PF_Masked) - pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); - } - } - if (PolyFlags & PF_NoTexture) - { - SetNoTexture(); - } - } - CurrentPolyFlags = PolyFlags; -} - static void UploadTexture(HWRTexture_t *pTexInfo, const GLvoid *pTextureBuffer, GLenum format, boolean update) { INT32 w = pTexInfo->width; @@ -1736,9 +436,6 @@ static void UploadTexture(HWRTexture_t *pTexInfo, const GLvoid *pTextureBuffer, } } -// -----------------+ -// UpdateTexture : Updates the texture data. -// -----------------+ static void UpdateTexture(HWRTexture_t *pTexInfo) { boolean update = true; @@ -1867,14 +564,14 @@ static void UpdateTexture(HWRTexture_t *pTexInfo) if (pTexInfo->flags & TF_WRAPX) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); else - Clamp2D(GL_TEXTURE_WRAP_S); + SetClamp(GL_TEXTURE_WRAP_S); if (pTexInfo->flags & TF_WRAPY) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); else - Clamp2D(GL_TEXTURE_WRAP_T); + SetClamp(GL_TEXTURE_WRAP_T); - if (GPUMaximumAnisotropy) + if (GLExtension_texture_filter_anisotropic && GPUMaximumAnisotropy) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, AnisotropicFilter); } @@ -1902,202 +599,22 @@ static void SetTexture(HWRTexture_t *pTexInfo) UpdateTexture(pTexInfo); - newTex->texture = pTexInfo; - newTex->name = (UINT32)pTexInfo->downloaded; - newTex->width = (UINT32)pTexInfo->width; - newTex->height = (UINT32)pTexInfo->height; - newTex->format = (UINT32)pTexInfo->format; - - // insertion at the tail - if (TexCacheTail) - { - newTex->prev = TexCacheTail; - TexCacheTail->next = newTex; - TexCacheTail = newTex; - } - else // initialization of the linked list - TexCacheTail = TexCacheHead = newTex; - } -} - -static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) -{ -#ifdef GL_SHADERS - FShaderObject *shader = ShaderState.current; - - if (ShadersEnabled && (shader != NULL) && pglUseProgram) - { - if (!shader->program) - { - pglUseProgram(0); - return; - } - - if (ShaderState.changed) - { - pglUseProgram(shader->program); - ShaderState.changed = false; - } - - // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) - if (poly == NULL) - poly = &ShaderDefaultColor; - if (tint == NULL) - tint = &ShaderDefaultColor; - if (fade == NULL) - fade = &ShaderDefaultColor; - - #define UNIFORM_1(uniform, a, function) \ - if (uniform != -1) \ - function (uniform, a); - - #define UNIFORM_2(uniform, a, b, function) \ - if (uniform != -1) \ - function (uniform, a, b); - - #define UNIFORM_3(uniform, a, b, c, function) \ - if (uniform != -1) \ - function (uniform, a, b, c); - - #define UNIFORM_4(uniform, a, b, c, d, function) \ - if (uniform != -1) \ - function (uniform, a, b, c, d); - - // polygon - UNIFORM_4(shader->uniforms[uniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); - UNIFORM_4(shader->uniforms[uniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); - UNIFORM_4(shader->uniforms[uniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); - - if (Surface != NULL) - { - UNIFORM_1(shader->uniforms[uniform_lighting], Surface->LightInfo.LightLevel, pglUniform1f); - UNIFORM_1(shader->uniforms[uniform_fade_start], Surface->LightInfo.FadeStart, pglUniform1f); - UNIFORM_1(shader->uniforms[uniform_fade_end], Surface->LightInfo.FadeEnd, pglUniform1f); - } - - UNIFORM_1(shader->uniforms[uniform_leveltime], ((float)ShaderLevelTime) / TICRATE, pglUniform1f); - - #undef UNIFORM_1 - #undef UNIFORM_2 - #undef UNIFORM_3 - #undef UNIFORM_4 - } -#else - (void)Surface; - (void)poly; - (void)tint; - (void)fade; -#endif -} - -static boolean Shader_CompileProgram(FShaderObject *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader) -{ - GLuint gl_vertShader, gl_fragShader; - GLint result; - - // - // Load and compile vertex shader - // - gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); - if (!gl_vertShader) - { - GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i)); - return false; - } - - pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); - pglCompileShader(gl_vertShader); - - // check for compile errors - pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) - { - Shader_CompileError("Error compiling vertex shader", gl_vertShader, i); - pglDeleteShader(gl_vertShader); - return false; - } - - // - // Load and compile fragment shader - // - gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); - if (!gl_fragShader) - { - GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i)); - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); - return false; - } - - pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); - pglCompileShader(gl_fragShader); - - // check for compile errors - pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) - { - Shader_CompileError("Error compiling fragment shader", gl_fragShader, i); - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); - return false; - } - - shader->program = pglCreateProgram(); - pglAttachShader(shader->program, gl_vertShader); - pglAttachShader(shader->program, gl_fragShader); - pglLinkProgram(shader->program); - - // check link status - pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); - - // delete the shader objects - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); - - // couldn't link? - if (result != GL_TRUE) - { - GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i)); - pglDeleteProgram(shader->program); - return false; - } - - // 13062019 -#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); - - // lighting - shader->uniforms[uniform_poly_color] = GETUNI("poly_color"); - shader->uniforms[uniform_tint_color] = GETUNI("tint_color"); - shader->uniforms[uniform_fade_color] = GETUNI("fade_color"); - shader->uniforms[uniform_lighting] = GETUNI("lighting"); - shader->uniforms[uniform_fade_start] = GETUNI("fade_start"); - shader->uniforms[uniform_fade_end] = GETUNI("fade_end"); - - // misc. (custom shaders) - shader->uniforms[uniform_leveltime] = GETUNI("leveltime"); - -#undef GETUNI - - return true; -} - -static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum) -{ - GLchar *infoLog = NULL; - GLint logLength; - - pglGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength); + newTex->texture = pTexInfo; + newTex->name = (UINT32)pTexInfo->downloaded; + newTex->width = (UINT32)pTexInfo->width; + newTex->height = (UINT32)pTexInfo->height; + newTex->format = (UINT32)pTexInfo->format; - if (logLength) - { - infoLog = malloc(logLength); - pglGetShaderInfoLog(program, logLength, NULL, infoLog); + // insertion at the tail + if (TexCacheTail) + { + newTex->prev = TexCacheTail; + TexCacheTail->next = newTex; + TexCacheTail = newTex; + } + else // initialization of the linked list + TexCacheTail = TexCacheHead = newTex; } - - GL_MSG_Error("Shader_CompileProgram: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : "")); - - if (infoLog) - free(infoLog); } // code that is common between DrawPolygon and DrawIndexedTriangles @@ -2219,11 +736,12 @@ static void DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, UINT32 iNumP pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); if (PolyFlags & PF_ForceWrapX) - Clamp2D(GL_TEXTURE_WRAP_S); + SetClamp(GL_TEXTURE_WRAP_S); if (PolyFlags & PF_ForceWrapY) - Clamp2D(GL_TEXTURE_WRAP_T); + SetClamp(GL_TEXTURE_WRAP_T); } + static void DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, UINT32 iNumPts, UINT32 PolyFlags, UINT32 *IndexArray) { PreparePolygon(pSurf, pOutVerts, PolyFlags); @@ -2235,12 +753,6 @@ static void DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, UIN // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? } -static const boolean gl_ext_arb_vertex_buffer_object = true; - -#define NULL_VBO_VERTEX ((FSkyVertex*)NULL) -#define sky_vbo_x (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &sky->data[0].x) -#define sky_vbo_u (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &sky->data[0].u) -#define sky_vbo_r (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &sky->data[0].r) static void DrawSkyDome(FSkyDome *sky) { int i, j; @@ -2251,13 +763,13 @@ static void DrawSkyDome(FSkyDome *sky) if (sky->rebuild) { // delete VBO when already exists - if (gl_ext_arb_vertex_buffer_object) + if (GLExtension_vertex_buffer_object) { if (sky->vbo) pglDeleteBuffers(1, &sky->vbo); } - if (gl_ext_arb_vertex_buffer_object) + if (GLExtension_vertex_buffer_object) { // generate a new VBO and get the associated ID pglGenBuffers(1, &sky->vbo); @@ -2273,7 +785,7 @@ static void DrawSkyDome(FSkyDome *sky) } // bind VBO in order to use - if (gl_ext_arb_vertex_buffer_object) + if (GLExtension_vertex_buffer_object) pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); // activate and specify pointers to arrays @@ -2318,16 +830,13 @@ static void DrawSkyDome(FSkyDome *sky) pglColor4ubv(white); // bind with 0, so, switch back to normal pointer operation - if (gl_ext_arb_vertex_buffer_object) + if (GLExtension_vertex_buffer_object) pglBindBuffer(GL_ARRAY_BUFFER, 0); // deactivate color array pglDisableClientState(GL_COLOR_ARRAY); } -// ========================================================================== -// -// ========================================================================== static void SetState(INT32 State, INT32 Value) { switch (State) @@ -2341,54 +850,21 @@ static void SetState(INT32 State, INT32 Value) break; case GPU_STATE_TEXTUREFILTERMODE: - switch (Value) - { - case GPU_TEXFILTER_TRILINEAR: - MipmapMinFilter = GL_LINEAR_MIPMAP_LINEAR; - MipmapMagFilter = GL_LINEAR; - MipmappingEnabled = GL_TRUE; - break; - case GPU_TEXFILTER_BILINEAR: - MipmapMinFilter = MipmapMagFilter = GL_LINEAR; - MipmappingEnabled = GL_FALSE; - break; - case GPU_TEXFILTER_POINTSAMPLED: - MipmapMinFilter = MipmapMagFilter = GL_NEAREST; - MipmappingEnabled = GL_FALSE; - break; - case GPU_TEXFILTER_MIXED1: - MipmapMinFilter = GL_NEAREST; - MipmapMagFilter = GL_LINEAR; - MipmappingEnabled = GL_FALSE; - break; - case GPU_TEXFILTER_MIXED2: - MipmapMinFilter = GL_LINEAR; - MipmapMagFilter = GL_NEAREST; - MipmappingEnabled = GL_FALSE; - break; - case GPU_TEXFILTER_MIXED3: - MipmapMinFilter = GL_LINEAR_MIPMAP_LINEAR; - MipmapMagFilter = GL_NEAREST; - MipmappingEnabled = GL_TRUE; - break; - default: - MipmapMagFilter = GL_LINEAR; - MipmapMinFilter = GL_NEAREST; - } - + GLTexture_SetFilterMode(Value); if (!pgluBuild2DMipmaps) { MipmappingEnabled = GL_FALSE; MipmapMinFilter = GL_LINEAR; } - - Flush(); //??? if we want to change filter mode by texture, remove this + GLTexture_Flush(); //??? if we want to change filter mode by texture, remove this break; case GPU_STATE_TEXTUREANISOTROPICMODE: - AnisotropicFilter = min(Value, GPUMaximumAnisotropy); - if (GPUMaximumAnisotropy) - Flush(); //??? if we want to change filter mode by texture, remove this + if (GLExtension_texture_filter_anisotropic && GPUMaximumAnisotropy) + { + AnisotropicFilter = min(Value, GPUMaximumAnisotropy); + GLTexture_Flush(); //??? if we want to change filter mode by texture, remove this + } break; default: @@ -2396,201 +872,9 @@ static void SetState(INT32 State, INT32 Value) } } -static float *vertBuffer = NULL; -static float *normBuffer = NULL; -static size_t lerpBufferSize = 0; -static short *vertTinyBuffer = NULL; -static char *normTinyBuffer = NULL; -static size_t lerpTinyBufferSize = 0; - -// Static temporary buffer for doing frame interpolation -// 'size' is the vertex size -static void AllocLerpBuffer(size_t size) -{ - if (lerpBufferSize >= size) - return; - - if (vertBuffer != NULL) - free(vertBuffer); - - if (normBuffer != NULL) - free(normBuffer); - - lerpBufferSize = size; - vertBuffer = malloc(lerpBufferSize); - normBuffer = malloc(lerpBufferSize); -} - -// Static temporary buffer for doing frame interpolation -// 'size' is the vertex size -static void AllocLerpTinyBuffer(size_t size) -{ - if (lerpTinyBufferSize >= size) - return; - - if (vertTinyBuffer != NULL) - free(vertTinyBuffer); - - if (normTinyBuffer != NULL) - free(normTinyBuffer); - - lerpTinyBufferSize = size; - vertTinyBuffer = malloc(lerpTinyBufferSize); - normTinyBuffer = malloc(lerpTinyBufferSize / 2); -} - -#ifndef GL_STATIC_DRAW -#define GL_STATIC_DRAW 0x88E4 -#endif - -#ifndef GL_ARRAY_BUFFER -#define GL_ARRAY_BUFFER 0x8892 -#endif - -static void CreateModelVBO(mesh_t *mesh, mdlframe_t *frame) -{ - int bufferSize = sizeof(vbo64_t)*mesh->numTriangles * 3; - vbo64_t *buffer = (vbo64_t*)malloc(bufferSize); - vbo64_t *bufPtr = buffer; - - float *vertPtr = frame->vertices; - float *normPtr = frame->normals; - float *tanPtr = frame->tangents; - float *uvPtr = mesh->uvs; - float *lightPtr = mesh->lightuvs; - char *colorPtr = frame->colors; - - int i; - for (i = 0; i < mesh->numTriangles * 3; i++) - { - bufPtr->x = *vertPtr++; - bufPtr->y = *vertPtr++; - bufPtr->z = *vertPtr++; - - bufPtr->nx = *normPtr++; - bufPtr->ny = *normPtr++; - bufPtr->nz = *normPtr++; - - bufPtr->s0 = *uvPtr++; - bufPtr->t0 = *uvPtr++; - - if (tanPtr != NULL) - { - bufPtr->tan0 = *tanPtr++; - bufPtr->tan1 = *tanPtr++; - bufPtr->tan2 = *tanPtr++; - } - - if (lightPtr != NULL) - { - bufPtr->s1 = *lightPtr++; - bufPtr->t1 = *lightPtr++; - } - - if (colorPtr) - { - bufPtr->r = *colorPtr++; - bufPtr->g = *colorPtr++; - bufPtr->b = *colorPtr++; - bufPtr->a = *colorPtr++; - } - else - { - bufPtr->r = 255; - bufPtr->g = 255; - bufPtr->b = 255; - bufPtr->a = 255; - } - - bufPtr++; - } - - pglGenBuffers(1, &frame->vboID); - pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); - pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); - free(buffer); - - // Don't leave the array buffer bound to the model, - // since this is called mid-frame - pglBindBuffer(GL_ARRAY_BUFFER, 0); -} - -static void CreateModelVBOTiny(mesh_t *mesh, tinyframe_t *frame) -{ - int bufferSize = sizeof(vbotiny_t)*mesh->numTriangles * 3; - vbotiny_t *buffer = (vbotiny_t*)malloc(bufferSize); - vbotiny_t *bufPtr = buffer; - - short *vertPtr = frame->vertices; - char *normPtr = frame->normals; - float *uvPtr = mesh->uvs; - char *tanPtr = frame->tangents; - - int i; - for (i = 0; i < mesh->numVertices; i++) - { - bufPtr->x = *vertPtr++; - bufPtr->y = *vertPtr++; - bufPtr->z = *vertPtr++; - - bufPtr->nx = *normPtr++; - bufPtr->ny = *normPtr++; - bufPtr->nz = *normPtr++; - - bufPtr->s0 = *uvPtr++; - bufPtr->t0 = *uvPtr++; - - if (tanPtr) - { - bufPtr->tanx = *tanPtr++; - bufPtr->tany = *tanPtr++; - bufPtr->tanz = *tanPtr++; - } - - bufPtr++; - } - - pglGenBuffers(1, &frame->vboID); - pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); - pglBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW); - free(buffer); - - // Don't leave the array buffer bound to the model, - // since this is called mid-frame - pglBindBuffer(GL_ARRAY_BUFFER, 0); -} static void CreateModelVBOs(model_t *model) { - int i; - for (i = 0; i < model->numMeshes; i++) - { - mesh_t *mesh = &model->meshes[i]; - - if (mesh->frames) - { - int j; - for (j = 0; j < model->meshes[i].numFrames; j++) - { - mdlframe_t *frame = &mesh->frames[j]; - if (frame->vboID) - pglDeleteBuffers(1, &frame->vboID); - frame->vboID = 0; - CreateModelVBO(mesh, frame); - } - } - else if (mesh->tinyframes) - { - int j; - for (j = 0; j < model->meshes[i].numFrames; j++) - { - tinyframe_t *frame = &mesh->tinyframes[j]; - if (frame->vboID) - pglDeleteBuffers(1, &frame->vboID); - frame->vboID = 0; - CreateModelVBOTiny(mesh, frame); - } - } - } + GLModel_GenerateVBOs(model); } #define BUFFER_OFFSET(i) ((void*)(i)) @@ -2606,7 +890,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 boolean useTinyFrames; - boolean useVBO = true; + boolean useVBO = GLExtension_vertex_buffer_object; UINT32 flags; int i; @@ -2807,7 +1091,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 int j = 0; // Dangit, I soooo want to do this in a GLSL shader... - AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); + GLModel_AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); vertPtr = vertTinyBuffer; normPtr = normTinyBuffer; @@ -2861,7 +1145,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 int j = 0; // Dangit, I soooo want to do this in a GLSL shader... - AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); + GLModel_AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); vertPtr = vertBuffer; normPtr = normBuffer; //int j = 0; @@ -2898,7 +1182,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } // -----------------+ -// HWRAPI DrawModel : Draw a model +// DrawModel : Renders a model // -----------------+ static void DrawModel(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { @@ -2973,30 +1257,13 @@ static void SetTransform(FTransform *stransform) pglGetFloatv(GL_MODELVIEW_MATRIX, ModelMatrix); // added for new coronas' code (without depth buffer) } + static INT32 GetTextureUsed(void) { - FTextureInfo *tmp = TexCacheHead; - INT32 res = 0; - - while (tmp) - { - // Figure out the correct bytes-per-pixel for this texture - // This follows format2bpp in hw_cache.c - INT32 bpp = 1; - UINT32 format = tmp->format; - if (format == GPU_TEXFMT_RGBA) - bpp = 4; - else if (format == GPU_TEXFMT_ALPHA_INTENSITY_88 || format == GPU_TEXFMT_AP_88) - bpp = 2; - - // Add it up! - res += tmp->height*tmp->width*bpp; - tmp = tmp->next; - } - - return res; + return GLTexture_GetMemoryUsage(TexCacheHead); } -static void PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2]) + +static void PostImgRedraw(float points[GPU_POSTIMGVERTS][GPU_POSTIMGVERTS][2]) { INT32 x, y; float float_x, float_y, float_nextx, float_nexty; @@ -3012,14 +1279,14 @@ static void PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2]) }; // Use a power of two texture, dammit - if(GPUScreenWidth <= 1024) + if (GPUScreenWidth <= 1024) texsize = 1024; - if(GPUScreenWidth <= 512) + if (GPUScreenWidth <= 512) texsize = 512; // X/Y stretch fix for all resolutions(!) - xfix = (float)(texsize)/((float)((GPUScreenWidth)/(float)(SCREENVERTS-1))); - yfix = (float)(texsize)/((float)((GPUScreenHeight)/(float)(SCREENVERTS-1))); + xfix = (float)(texsize)/((float)((GPUScreenWidth)/(float)(GPU_POSTIMGVERTS-1))); + yfix = (float)(texsize)/((float)((GPUScreenHeight)/(float)(GPU_POSTIMGVERTS-1))); pglDisable(GL_DEPTH_TEST); pglDisable(GL_BLEND); @@ -3034,9 +1301,9 @@ static void PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2]) pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - for(x=0;x<SCREENVERTS-1;x++) + for(x=0;x<GPU_POSTIMGVERTS-1;x++) { - for(y=0;y<SCREENVERTS-1;y++) + for(y=0;y<GPU_POSTIMGVERTS-1;y++) { float stCoords[8]; float vertCoords[12]; @@ -3098,46 +1365,16 @@ static void FlushScreenTextures(void) WipeStartTexture = WipeEndTexture = 0; } -static void GenerateScreenTexture(GLuint *name) -{ - INT32 texsize = 2048; - boolean firstTime = ((*name) == 0); - - // Use a power of two texture, dammit - if(GPUScreenWidth <= 512) - texsize = 512; - else if (GPUScreenWidth <= 1024) - texsize = 1024; - - // Create screen texture - if (firstTime) - pglGenTextures(1, name); - pglBindTexture(GL_TEXTURE_2D, *name); - - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); - } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - CurrentTexture = *name; -} - // Create screen to fade from static void StartScreenWipe(void) { - GenerateScreenTexture(&WipeStartTexture); + GLTexture_GenerateScreenTexture(&WipeStartTexture); } // Create screen to fade to static void EndScreenWipe(void) { - GenerateScreenTexture(&WipeEndTexture); + GLTexture_GenerateScreenTexture(&WipeEndTexture); } // Draw the last scene under the intermission @@ -3146,7 +1383,7 @@ static void DrawIntermissionBG(void) float xfix, yfix; INT32 texsize = 2048; - const float screenVerts[12] = + const float GPU_POSTIMGVERTS[12] = { -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, @@ -3156,15 +1393,15 @@ static void DrawIntermissionBG(void) float fix[8]; - if(GPUScreenWidth <= 1024) + if (GPUScreenWidth <= 1024) texsize = 1024; - if(GPUScreenWidth <= 512) + if (GPUScreenWidth <= 512) texsize = 512; xfix = 1/((float)(texsize)/((float)((GPUScreenWidth)))); yfix = 1/((float)(texsize)/((float)((GPUScreenHeight)))); - // const float screenVerts[12] + // const float GPU_POSTIMGVERTS[12] // float fix[8]; fix[0] = 0.0f; @@ -3182,7 +1419,7 @@ static void DrawIntermissionBG(void) pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); - pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglVertexPointer(3, GL_FLOAT, 0, GPU_POSTIMGVERTS); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); CurrentTexture = ScreenTexture; @@ -3196,7 +1433,7 @@ static void DoScreenWipe(void) INT32 fademaskdownloaded = CurrentTexture; // the fade mask that has been set - const float screenVerts[12] = + const float GPU_POSTIMGVERTS[12] = { -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, @@ -3214,16 +1451,19 @@ static void DoScreenWipe(void) 1.0f, 1.0f }; + if (!GLExtension_multitexture) + return; + // Use a power of two texture, dammit - if(GPUScreenWidth <= 1024) + if (GPUScreenWidth <= 1024) texsize = 1024; - if(GPUScreenWidth <= 512) + if (GPUScreenWidth <= 512) texsize = 512; xfix = 1/((float)(texsize)/((float)((GPUScreenWidth)))); yfix = 1/((float)(texsize)/((float)((GPUScreenHeight)))); - // const float screenVerts[12] + // const float GPU_POSTIMGVERTS[12] // float fix[8]; fix[0] = 0.0f; @@ -3244,7 +1484,7 @@ static void DoScreenWipe(void) pglBindTexture(GL_TEXTURE_2D, WipeStartTexture); pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); - pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglVertexPointer(3, GL_FLOAT, 0, GPU_POSTIMGVERTS); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); @@ -3265,7 +1505,7 @@ static void DoScreenWipe(void) pglClientActiveTexture(GL_TEXTURE0); pglTexCoordPointer(2, GL_FLOAT, 0, fix); - pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglVertexPointer(3, GL_FLOAT, 0, GPU_POSTIMGVERTS); pglClientActiveTexture(GL_TEXTURE1); pglEnableClientState(GL_TEXTURE_COORD_ARRAY); pglTexCoordPointer(2, GL_FLOAT, 0, defaultST); @@ -3282,12 +1522,12 @@ static void DoScreenWipe(void) // Create a texture from the screen. static void MakeScreenTexture(void) { - GenerateScreenTexture(&ScreenTexture); + GLTexture_GenerateScreenTexture(&ScreenTexture); } static void MakeScreenFinalTexture(void) { - GenerateScreenTexture(&FinalScreenTexture); + GLTexture_GenerateScreenTexture(&FinalScreenTexture); } static void DrawScreenFinalTexture(int width, int height) @@ -3301,9 +1541,9 @@ static void DrawScreenFinalTexture(int width, int height) float off[12]; float fix[8]; - if(GPUScreenWidth <= 1024) + if (GPUScreenWidth <= 1024) texsize = 1024; - if(GPUScreenWidth <= 512) + if (GPUScreenWidth <= 512) texsize = 512; xfix = 1/((float)(texsize)/((float)((GPUScreenWidth)))); @@ -3362,6 +1602,60 @@ static void DrawScreenFinalTexture(int width, int height) CurrentTexture = FinalScreenTexture; } +static void SetShader(int type) +{ +#ifdef GL_SHADERS + Shader_Set(GLBackend_GetShaderType(type)); +#else + (void)type; +#endif +} + +static boolean CompileShaders(void) +{ +#ifdef GL_SHADERS + return Shader_Compile(); +#else + return false; +#endif +} + +static void SetShaderInfo(INT32 info, INT32 value) +{ +#ifdef GL_SHADERS + Shader_SetInfo(info, value); +#else + (void)info; + (void)value; +#endif +} + +static void LoadCustomShader(int number, char *shader, size_t size, boolean fragment) +{ +#ifdef GL_SHADERS + Shader_LoadCustom(number, shader, size, fragment); +#else + (void)number; + (void)shader; + (void)size; + (void)fragment; +#endif +} + +static void UnSetShader(void) +{ +#ifdef GL_SHADERS + Shader_UnSet(); +#endif +} + +static void CleanShaders(void) +{ +#ifdef GL_SHADERS + Shader_Clean(); +#endif +} + struct GPURenderingAPI GLInterfaceAPI = { Init, NULL, @@ -3411,4 +1705,82 @@ struct GPURenderingAPI GLInterfaceAPI = { LoadCustomShader, }; +// -----------------+ +// SetModelView : +// -----------------+ +void SetModelView(GLint w, GLint h) +{ +// GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); + + // The screen textures need to be flushed if the width or height change so that they be remade for the correct size + if (GPUScreenWidth != w || GPUScreenHeight != h) + FlushScreenTextures(); + + GPUScreenWidth = w; + GPUScreenHeight = h; + + pglViewport(0, 0, w, h); + + pglMatrixMode(GL_PROJECTION); + pglLoadIdentity(); + + pglMatrixMode(GL_MODELVIEW); + pglLoadIdentity(); + + GLPerspective(FIELD_OF_VIEW, ASPECT_RATIO); + + // added for new coronas' code (without depth buffer) + pglGetIntegerv(GL_VIEWPORT, SceneViewport); + pglGetFloatv(GL_PROJECTION_MATRIX, ProjectionMatrix); +} + + +// -----------------+ +// SetStates : Set permanent states +// -----------------+ +void SetStates(void) +{ +#ifdef GL_LIGHT_MODEL_AMBIENT + GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; +#endif + + pglEnable(GL_TEXTURE_2D); // two-dimensional texturing + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + pglEnable(GL_BLEND); // enable color blending + pglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + pglEnable(GL_ALPHA_TEST); + pglAlphaFunc(GL_NOTEQUAL, 0.0f); + + pglEnable(GL_DEPTH_TEST); // check the depth buffer + pglDepthMask(GL_TRUE); // enable writing to depth buffer + + pglClearDepth(1.0f); + pglDepthRange(0.0f, 1.0f); + pglDepthFunc(GL_LEQUAL); + + // Hurdler: not necessary, is it? + pglShadeModel(GL_SMOOTH); // iterate vertice colors + + // this set CurrentPolyFlags to the actual configuration + CurrentPolyFlags = 0xFFFFFFFF; + SetBlend(0); + + CurrentTexture = 0; + SetNoTexture(); + + pglPolygonOffset(-1.0f, -1.0f); + + pglLoadIdentity(); + pglScalef(1.0f, 1.0f, -1.0f); + pglGetFloatv(GL_MODELVIEW_MATRIX, ModelMatrix); // added for new coronas' code (without depth buffer) + + // Lighting for models +#ifdef GL_LIGHT_MODEL_AMBIENT + pglLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightDiffuse); + pglEnable(GL_LIGHT0); +#endif +} + #endif //HWRENDER diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 5ce8670afe58abe086b1f71ca28053ef9825e461..6c864373019dba29ab20e0bb29d04e2445edb0a8 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -1,21 +1,14 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1998-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief OpenGL API for Doom Legacy +/// \file r_opengl.h +/// \brief OpenGL API for Sonic Robo Blast 2 #ifndef _R_OPENGL_H_ #define _R_OPENGL_H_ @@ -27,7 +20,9 @@ #pragma warning(disable : 4214 4244) #endif +#ifndef HAVE_GLES2 #include "SDL_opengl.h" //Alam_GBC: Simple, yes? +#endif #ifdef _MSC_VER #pragma warning(default : 4214 4244) @@ -66,27 +61,12 @@ //#undef DEBUG_TO_FILE //#endif -#ifdef DEBUG_TO_FILE -extern FILE *gllogstream; -#endif +#include "../r_glcommon/r_glcommon.h" // ========================================================================== // PROTOS // ========================================================================== -void *GetGLFunc(const char *proc); -boolean SetupGLfunc(void); -void SetupGLFunc4(void); -void Flush(void); -INT32 isExtAvailable(const char *extension, const GLubyte *start); -void SetModelView(GLint w, GLint h); -void SetStates(void); - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -#endif - #ifdef USE_WGL_SWAP typedef BOOL (APIENTRY *PFNWGLEXTSWAPCONTROLPROC) (int); typedef int (APIENTRY *PFNWGLEXTGETSWAPINTERVALPROC) (void); @@ -94,39 +74,4 @@ extern PFNWGLEXTSWAPCONTROLPROC wglSwapIntervalEXT; extern PFNWGLEXTGETSWAPINTERVALPROC wglGetSwapIntervalEXT; #endif -#ifdef STATIC_OPENGL -#define pglClear glClear -#define pglGetIntegerv glGetIntegerv -#define pglGetString glGetString -#else -/* 1.0 Miscellaneous functions */ -typedef void (APIENTRY * PFNglClear) (GLbitfield mask); -extern PFNglClear pglClear; -typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params); -extern PFNglGetIntegerv pglGetIntegerv; -typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name); -extern PFNglGetString pglGetString; -#if 0 -typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c -static PFNglEnableClientState pglEnableClientState; -#endif -#endif - -// ========================================================================== -// GLOBAL -// ========================================================================== - -extern const GLubyte *GLVersion; -extern const GLubyte *GLRenderer; -extern const GLubyte *GLExtensions; - -extern GLint GPUTextureFormat; -extern RGBA_t GPUTexturePalette[256]; -extern GLint GPUScreenWidth; -extern GLint GPUScreenHeight; -extern GLbyte GPUScreenDepth; -extern GLint GPUMaximumAnisotropy; - -extern struct GPURenderingAPI GLInterfaceAPI; - #endif diff --git a/src/hardware/shaders/gl_shaders.c b/src/hardware/shaders/gl_shaders.c new file mode 100644 index 0000000000000000000000000000000000000000..756300cd7b41e3e7d66791720ec2fcb98a243c32 --- /dev/null +++ b/src/hardware/shaders/gl_shaders.c @@ -0,0 +1,613 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file gl_shaders.c +/// \brief OpenGL shaders + +#include "gl_shaders.h" +#include "../r_glcommon/r_glcommon.h" + +GLboolean ShadersEnabled = GL_FALSE; +INT32 ShadersAllowed = GPU_SHADEROPTION_OFF; + +typedef GLuint (R_GL_APIENTRY *PFNglCreateShader) (GLenum); +typedef void (R_GL_APIENTRY *PFNglShaderSource) (GLuint, GLsizei, const GLchar**, GLint*); +typedef void (R_GL_APIENTRY *PFNglCompileShader) (GLuint); +typedef void (R_GL_APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*); +typedef void (R_GL_APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); +typedef void (R_GL_APIENTRY *PFNglDeleteShader) (GLuint); +typedef GLuint (R_GL_APIENTRY *PFNglCreateProgram) (void); +typedef void (R_GL_APIENTRY *PFNglDeleteProgram) (GLuint); +typedef void (R_GL_APIENTRY *PFNglAttachShader) (GLuint, GLuint); +typedef void (R_GL_APIENTRY *PFNglLinkProgram) (GLuint); +typedef void (R_GL_APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); +typedef void (R_GL_APIENTRY *PFNglUseProgram) (GLuint); +typedef void (R_GL_APIENTRY *PFNglUniform1i) (GLint, GLint); +typedef void (R_GL_APIENTRY *PFNglUniform1f) (GLint, GLfloat); +typedef void (R_GL_APIENTRY *PFNglUniform2f) (GLint, GLfloat, GLfloat); +typedef void (R_GL_APIENTRY *PFNglUniform3f) (GLint, GLfloat, GLfloat, GLfloat); +typedef void (R_GL_APIENTRY *PFNglUniform4f) (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (R_GL_APIENTRY *PFNglUniform1fv) (GLint, GLsizei, const GLfloat*); +typedef void (R_GL_APIENTRY *PFNglUniform2fv) (GLint, GLsizei, const GLfloat*); +typedef void (R_GL_APIENTRY *PFNglUniform3fv) (GLint, GLsizei, const GLfloat*); +typedef void (R_GL_APIENTRY *PFNglUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *); +typedef GLint (R_GL_APIENTRY *PFNglGetUniformLocation) (GLuint, const GLchar*); +typedef GLint (R_GL_APIENTRY *PFNglGetAttribLocation) (GLuint, const GLchar*); + +static PFNglCreateShader pglCreateShader; +static PFNglShaderSource pglShaderSource; +static PFNglCompileShader pglCompileShader; +static PFNglGetShaderiv pglGetShaderiv; +static PFNglGetShaderInfoLog pglGetShaderInfoLog; +static PFNglDeleteShader pglDeleteShader; +static PFNglCreateProgram pglCreateProgram; +static PFNglDeleteProgram pglDeleteProgram; +static PFNglAttachShader pglAttachShader; +static PFNglLinkProgram pglLinkProgram; +static PFNglGetProgramiv pglGetProgramiv; +static PFNglUseProgram pglUseProgram; +static PFNglUniform1i pglUniform1i; +static PFNglUniform1f pglUniform1f; +static PFNglUniform2f pglUniform2f; +static PFNglUniform3f pglUniform3f; +static PFNglUniform4f pglUniform4f; +static PFNglUniform1fv pglUniform1fv; +static PFNglUniform2fv pglUniform2fv; +static PFNglUniform3fv pglUniform3fv; +static PFNglUniformMatrix4fv pglUniformMatrix4fv; +static PFNglGetUniformLocation pglGetUniformLocation; +static PFNglGetAttribLocation pglGetAttribLocation; + +FShaderObject ShaderObjects[HWR_MAXSHADERS]; +FShaderObject UserShaderObjects[HWR_MAXSHADERS]; +FShaderSource CustomShaders[HWR_MAXSHADERS]; + +FShaderState ShaderState; + +static GLRGBAFloat ShaderDefaultColor = {1.0f, 1.0f, 1.0f, 1.0f}; + +// Shader info +static INT32 ShaderLevelTime = 0; + +#ifdef HAVE_GLES2 +#include "shaders_gles2.h" +#else +#include "shaders_gl2.h" +#endif + +// ================ +// Shader sources +// ================ + +static struct { + const char *vertex; + const char *fragment; +} const ShaderSources[] = { + // Default shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER}, + + // Floor shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, + + // Wall shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, + + // Sprite shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, + + // Model shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, + + // Model shader + diffuse lighting from above + {GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER}, + + // Water shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, + + // Fog shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, + + // Sky shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, + + {NULL, NULL}, +}; + +void Shader_LoadFunctions(void) +{ + pglCreateShader = GLBackend_GetFunction("glCreateShader"); + pglShaderSource = GLBackend_GetFunction("glShaderSource"); + pglCompileShader = GLBackend_GetFunction("glCompileShader"); + pglGetShaderiv = GLBackend_GetFunction("glGetShaderiv"); + pglGetShaderInfoLog = GLBackend_GetFunction("glGetShaderInfoLog"); + pglDeleteShader = GLBackend_GetFunction("glDeleteShader"); + pglCreateProgram = GLBackend_GetFunction("glCreateProgram"); + pglDeleteProgram = GLBackend_GetFunction("glDeleteProgram"); + pglAttachShader = GLBackend_GetFunction("glAttachShader"); + pglLinkProgram = GLBackend_GetFunction("glLinkProgram"); + pglGetProgramiv = GLBackend_GetFunction("glGetProgramiv"); + pglUseProgram = GLBackend_GetFunction("glUseProgram"); + pglUniform1i = GLBackend_GetFunction("glUniform1i"); + pglUniform1f = GLBackend_GetFunction("glUniform1f"); + pglUniform2f = GLBackend_GetFunction("glUniform2f"); + pglUniform3f = GLBackend_GetFunction("glUniform3f"); + pglUniform4f = GLBackend_GetFunction("glUniform4f"); + pglUniform1fv = GLBackend_GetFunction("glUniform1fv"); + pglUniform2fv = GLBackend_GetFunction("glUniform2fv"); + pglUniform3fv = GLBackend_GetFunction("glUniform3fv"); + pglUniformMatrix4fv = GLBackend_GetFunction("glUniformMatrix4fv"); + pglGetUniformLocation = GLBackend_GetFunction("glGetUniformLocation"); + pglGetAttribLocation = GLBackend_GetFunction("glGetAttribLocation"); +} + +#ifdef HAVE_GLES2 +int Shader_AttribLoc(int loc) +{ + FShaderObject *shader = ShaderState.current; + int pos, attrib; + + EShaderAttribute LOC_TO_ATTRIB[attrib_max] = + { + attrib_position, // LOC_POSITION + attrib_texcoord, // LOC_TEXCOORD + LOC_TEXCOORD0 + attrib_normal, // LOC_NORMAL + attrib_colors, // LOC_COLORS + attrib_fadetexcoord, // LOC_TEXCOORD1 + }; + + if (shader == NULL) + I_Error("Shader_AttribLoc: shader not set"); + + attrib = LOC_TO_ATTRIB[loc]; + pos = shader->attributes[attrib]; + + if (pos == -1) + return 0; + + return pos; +} +#endif + +// +// Shader info +// Those are given to the uniforms. +// + +void Shader_SetInfo(INT32 info, INT32 value) +{ + switch (info) + { + case GPU_SHADERINFO_LEVELTIME: + ShaderLevelTime = value; + break; + default: + break; + } +} + +// +// Custom shader loading +// +void Shader_LoadCustom(int number, char *code, size_t size, boolean isfragment) +{ + FShaderSource *shader; + + if (!GLExtension_shaders) + return; + + if (number < 1 || number > HWR_MAXSHADERS) + I_Error("Shader_LoadCustom: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS); + else if (code == NULL) + I_Error("Shader_LoadCustom: empty shader"); + + shader = &CustomShaders[number]; + +#define COPYSHADER(source) { \ + if (shader->source) \ + free(shader->source); \ + shader->source = malloc(size+1); \ + strncpy(shader->source, code, size); \ + shader->source[size] = 0; \ + } + + if (isfragment) + COPYSHADER(fragment) + else + COPYSHADER(vertex) +} + +void Shader_Set(int type) +{ + FShaderObject *shader = ShaderState.current; + +#ifndef HAVE_GLES2 + if (ShadersAllowed == GPU_SHADEROPTION_OFF) + return; +#endif + + if ((shader == NULL) || (GLuint)type != ShaderState.type) + { + FShaderObject *baseshader = &ShaderObjects[type]; + FShaderObject *usershader = &UserShaderObjects[type]; + + if (usershader->program) + shader = (ShadersAllowed == GPU_SHADEROPTION_NOCUSTOM) ? baseshader : usershader; + else + shader = baseshader; + + ShaderState.current = shader; + ShaderState.type = type; + ShaderState.changed = true; + } + + if (ShaderState.program != shader->program) + { + ShaderState.program = shader->program; + ShaderState.changed = true; + } + +#ifdef HAVE_GLES2 + Shader_SetTransform(); + ShadersEnabled = true; +#else + ShadersEnabled = (shader->program != 0); +#endif +} + +void Shader_UnSet(void) +{ +#ifdef HAVE_GLES2 + Shader_Set(SHADER_DEFAULT); + Shader_SetUniforms(NULL, NULL, NULL, NULL); +#else + ShaderState.current = NULL; + ShaderState.type = 0; + ShaderState.program = 0; + + if (pglUseProgram) + pglUseProgram(0); + ShadersEnabled = false; +#endif +} + +void Shader_Clean(void) +{ + INT32 i; + + for (i = 1; i < HWR_MAXSHADERS; i++) + { + FShaderSource *shader = &CustomShaders[i]; + + if (shader->vertex) + free(shader->vertex); + + if (shader->fragment) + free(shader->fragment); + + shader->vertex = NULL; + shader->fragment = NULL; + } +} + +#ifdef HAVE_GLES2 +#define Shader_ErrorMessage I_Error +#else +#define Shader_ErrorMessage GL_MSG_Error +#endif + +static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum) +{ + GLchar *infoLog = NULL; + GLint logLength; + + pglGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength); + + if (logLength) + { + infoLog = malloc(logLength); + pglGetShaderInfoLog(program, logLength, NULL, infoLog); + } + + Shader_ErrorMessage("Shader_CompileProgram: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : "")); + + if (infoLog) + free(infoLog); +} + +static boolean Shader_CompileProgram(FShaderObject *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader) +{ + GLuint gl_vertShader, gl_fragShader; + GLint result; + + // + // Load and compile vertex shader + // + gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); + if (!gl_vertShader) + { + Shader_ErrorMessage("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i)); + return false; + } + + pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); + pglCompileShader(gl_vertShader); + + // check for compile errors + pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + Shader_CompileError("Error compiling vertex shader", gl_vertShader, i); + pglDeleteShader(gl_vertShader); + return false; + } + + // + // Load and compile fragment shader + // + gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); + if (!gl_fragShader) + { + Shader_ErrorMessage("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i)); + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + return false; + } + + pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); + pglCompileShader(gl_fragShader); + + // check for compile errors + pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + Shader_CompileError("Error compiling fragment shader", gl_fragShader, i); + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + return false; + } + + shader->program = pglCreateProgram(); + pglAttachShader(shader->program, gl_vertShader); + pglAttachShader(shader->program, gl_fragShader); + pglLinkProgram(shader->program); + + // check link status + pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); + + // delete the shader objects + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + + // couldn't link? + if (result != GL_TRUE) + { + Shader_ErrorMessage("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i)); + pglDeleteProgram(shader->program); + return false; + } + +#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform) + +#ifdef HAVE_GLES2 + memset(shader->projMatrix, 0x00, sizeof(fmatrix4_t)); + memset(shader->viewMatrix, 0x00, sizeof(fmatrix4_t)); + memset(shader->modelMatrix, 0x00, sizeof(fmatrix4_t)); + + // transform + shader->uniforms[uniform_model] = GETUNI("u_model"); + shader->uniforms[uniform_view] = GETUNI("u_view"); + shader->uniforms[uniform_projection] = GETUNI("u_projection"); + + // samplers + shader->uniforms[uniform_startscreen] = GETUNI("t_startscreen"); + shader->uniforms[uniform_endscreen] = GETUNI("t_endscreen"); + shader->uniforms[uniform_fademask] = GETUNI("t_fademask"); + + // misc. + shader->uniforms[uniform_isfadingin] = GETUNI("is_fading_in"); + shader->uniforms[uniform_istowhite] = GETUNI("is_to_white"); +#endif + + // lighting + shader->uniforms[uniform_poly_color] = GETUNI("poly_color"); + shader->uniforms[uniform_tint_color] = GETUNI("tint_color"); + shader->uniforms[uniform_fade_color] = GETUNI("fade_color"); + shader->uniforms[uniform_lighting] = GETUNI("lighting"); + shader->uniforms[uniform_fade_start] = GETUNI("fade_start"); + shader->uniforms[uniform_fade_end] = GETUNI("fade_end"); + + // misc. (custom shaders) + shader->uniforms[uniform_leveltime] = GETUNI("leveltime"); + +#undef GETUNI + +#ifdef HAVE_GLES2 + +#define GETATTRIB(attribute) pglGetAttribLocation(shader->program, attribute) + + shader->attributes[attrib_position] = GETATTRIB("a_position"); + shader->attributes[attrib_texcoord] = GETATTRIB("a_texcoord"); + shader->attributes[attrib_normal] = GETATTRIB("a_normal"); + shader->attributes[attrib_colors] = GETATTRIB("a_colors"); + shader->attributes[attrib_fadetexcoord] = GETATTRIB("a_fadetexcoord"); + +#undef GETATTRIB + +#endif + + return true; +} + +boolean Shader_Compile(void) +{ + GLint i; + + if (!GLExtension_shaders) + return false; + + CustomShaders[SHADER_DEFAULT].vertex = NULL; + CustomShaders[SHADER_DEFAULT].fragment = NULL; + + for (i = 0; ShaderSources[i].vertex && ShaderSources[i].fragment; i++) + { + FShaderObject *shader, *usershader; + const GLchar *vert_shader = ShaderSources[i].vertex; + const GLchar *frag_shader = ShaderSources[i].fragment; + + if (i >= HWR_MAXSHADERS) + break; + + shader = &ShaderObjects[i]; + usershader = &UserShaderObjects[i]; + + if (shader->program) + pglDeleteProgram(shader->program); + if (usershader->program) + pglDeleteProgram(usershader->program); + + shader->program = 0; + usershader->program = 0; + + if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader)) + shader->program = 0; + + // Compile custom shader + if ((i == SHADER_DEFAULT) || !(CustomShaders[i].vertex || CustomShaders[i].fragment)) + continue; + + // 18032019 + if (CustomShaders[i].vertex) + vert_shader = CustomShaders[i].vertex; + if (CustomShaders[i].fragment) + frag_shader = CustomShaders[i].fragment; + + if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader)) + { + GL_MSG_Warning("Shader_Compile: Could not compile custom shader program for %s\n", HWR_GetShaderName(i)); + usershader->program = 0; + } + } + + Shader_Set(SHADER_DEFAULT); + +#ifdef HAVE_GLES2 + pglUseProgram(ShaderState.program); + ShaderState.changed = false; +#endif + + return true; +} + +static void Shader_SetIfChanged(FShaderObject *shader) +{ + if (ShaderState.changed) + { + pglUseProgram(shader->program); + ShaderState.changed = false; + } +} + +#ifdef HAVE_GLES2 +void Shader_SetTransform(void) +{ + FShaderObject *shader = ShaderState.current; + if (!shader) + return; + + Shader_SetIfChanged(shader); + + if (memcmp(projMatrix, shader->projMatrix, sizeof(fmatrix4_t))) + { + memcpy(shader->projMatrix, projMatrix, sizeof(fmatrix4_t)); + pglUniformMatrix4fv(shader->uniforms[uniform_projection], 1, GL_FALSE, (float *)projMatrix); + } + + if (memcmp(viewMatrix, shader->viewMatrix, sizeof(fmatrix4_t))) + { + memcpy(shader->viewMatrix, viewMatrix, sizeof(fmatrix4_t)); + pglUniformMatrix4fv(shader->uniforms[uniform_view], 1, GL_FALSE, (float *)viewMatrix); + } + + if (memcmp(modelMatrix, shader->modelMatrix, sizeof(fmatrix4_t))) + { + memcpy(shader->modelMatrix, modelMatrix, sizeof(fmatrix4_t)); + pglUniformMatrix4fv(shader->uniforms[uniform_model], 1, GL_FALSE, (float *)modelMatrix); + } +} +#endif + +void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ + FShaderObject *shader = ShaderState.current; + + if (ShadersEnabled && (shader != NULL) && pglUseProgram) + { + if (!shader->program) + { + pglUseProgram(0); + return; + } + + Shader_SetIfChanged(shader); + + // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) + if (poly == NULL) + poly = &ShaderDefaultColor; + if (tint == NULL) + tint = &ShaderDefaultColor; + if (fade == NULL) + fade = &ShaderDefaultColor; + + #define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + #define UNIFORM_2(uniform, a, b, function) \ + if (uniform != -1) \ + function (uniform, a, b); + + #define UNIFORM_3(uniform, a, b, c, function) \ + if (uniform != -1) \ + function (uniform, a, b, c); + + #define UNIFORM_4(uniform, a, b, c, d, function) \ + if (uniform != -1) \ + function (uniform, a, b, c, d); + + // polygon + UNIFORM_4(shader->uniforms[uniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[uniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[uniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + + if (Surface != NULL) + { + UNIFORM_1(shader->uniforms[uniform_lighting], Surface->LightInfo.LightLevel, pglUniform1f); + UNIFORM_1(shader->uniforms[uniform_fade_start], Surface->LightInfo.FadeStart, pglUniform1f); + UNIFORM_1(shader->uniforms[uniform_fade_end], Surface->LightInfo.FadeEnd, pglUniform1f); + } + + UNIFORM_1(shader->uniforms[uniform_leveltime], ((float)ShaderLevelTime) / TICRATE, pglUniform1f); + + #undef UNIFORM_1 + #undef UNIFORM_2 + #undef UNIFORM_3 + #undef UNIFORM_4 + } +} + +void Shader_SetSampler(EShaderUniform uniform, GLint value) +{ + FShaderObject *shader = ShaderState.current; + if (!shader) + return; + + Shader_SetIfChanged(shader); + + if (shader->uniforms[uniform] != -1) + pglUniform1i(shader->uniforms[uniform], value); +} diff --git a/src/hardware/shaders/gl_shaders.h b/src/hardware/shaders/gl_shaders.h new file mode 100644 index 0000000000000000000000000000000000000000..f925c291fa52196c9ec9093f202967526a774217 --- /dev/null +++ b/src/hardware/shaders/gl_shaders.h @@ -0,0 +1,159 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 1998-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file gl_shaders.h +/// \brief OpenGL shaders + +#ifndef _GL_SHADERS_H_ +#define _GL_SHADERS_H_ + +#include "../../doomdef.h" +#include "../hw_gpu.h" + +#include "../r_glcommon/r_glcommon.h" + +extern GLboolean ShadersEnabled; +extern INT32 ShadersAllowed; + +#ifdef GL_SHADERS + +void Shader_LoadFunctions(void); + +enum +{ + LOC_POSITION = 0, + LOC_TEXCOORD = 1, + LOC_NORMAL = 2, + LOC_COLORS = 3, + + LOC_TEXCOORD0 = LOC_TEXCOORD, + LOC_TEXCOORD1 = 4 +}; + +#define MAXSHADERS 16 +#define MAXSHADERPROGRAMS 16 + +// 08072020 +typedef enum EShaderUniform +{ +#ifdef HAVE_GLES2 + // transform + uniform_model, + uniform_view, + uniform_projection, + + // samplers + uniform_startscreen, + uniform_endscreen, + uniform_fademask, +#endif + + // lighting + uniform_poly_color, + uniform_tint_color, + uniform_fade_color, + uniform_lighting, + uniform_fade_start, + uniform_fade_end, + + // misc. +#ifdef HAVE_GLES2 + uniform_isfadingin, + uniform_istowhite, +#endif + uniform_leveltime, + + uniform_max, +} EShaderUniform; + +// 27072020 +#ifdef HAVE_GLES2 +typedef enum EShaderAttribute +{ + attrib_position, // LOC_POSITION + attrib_texcoord, // LOC_TEXCOORD + LOC_TEXCOORD0 + attrib_normal, // LOC_NORMAL + attrib_colors, // LOC_COLORS + attrib_fadetexcoord, // LOC_TEXCOORD1 + + attrib_max, +} EShaderAttribute; +#endif + +typedef struct FShaderObject +{ + GLuint program; + boolean custom; + + GLint uniforms[uniform_max+1]; +#ifdef HAVE_GLES2 + GLint attributes[attribute_max+1]; +#endif + +#ifdef HAVE_GLES2 + fmatrix4_t projMatrix; + fmatrix4_t viewMatrix; + fmatrix4_t modelMatrix; +#endif +} FShaderObject; + +extern FShaderObject ShaderObjects[HWR_MAXSHADERS]; +extern FShaderObject UserShaderObjects[HWR_MAXSHADERS]; +extern FShaderSource CustomShaders[HWR_MAXSHADERS]; + +// 09102020 +typedef struct FShaderState +{ + FShaderObject *current; + GLuint type; + GLuint program; + boolean changed; +} FShaderState; +extern FShaderState ShaderState; + +void Shader_Set(int type); +void Shader_UnSet(void); + +#ifdef HAVE_GLES2 +void Shader_SetTransform(void); +#endif + +void Shader_LoadCustom(int number, char *code, size_t size, boolean isfragment); + +boolean Shader_Compile(void); +void Shader_Clean(void); + +void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +void Shader_SetSampler(EShaderUniform uniform, GLint value); +#define Shader_SetIntegerUniform Shader_SetSampler +void Shader_SetInfo(INT32 info, INT32 value); + +#ifdef HAVE_GLES2 +int Shader_AttribLoc(int loc); +#endif + +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif + +#endif // GL_SHADERS + +#endif // _GL_SHADERS_H_ diff --git a/src/hardware/shaders/shaders_gl2.h b/src/hardware/shaders/shaders_gl2.h new file mode 100644 index 0000000000000000000000000000000000000000..e7da80acd1c1a9ae466d3e73dabdfbd2f34ae42e --- /dev/null +++ b/src/hardware/shaders/shaders_gl2.h @@ -0,0 +1,149 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 1998-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file shaders_gl2.h +/// \brief OpenGL shader definitions + +#include "gl_shaders.h" + +// ================ +// Vertex shaders +// ================ + +// +// Generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +// +// Generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// replicates the way fixed function lighting is used by the model lighting option, +// stores the lighting result to gl_Color +// (ambient lighting of 0.75 and diffuse lighting from above) +#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ + "float light = 0.75 + max(nDotVP, 0.0);\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// +// Software fragment shader +// + +#include "shaders_software.h" + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + GLSL_DOOM_UNIFORMS \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 Texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 BaseColor = Texel * poly_color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "FinalColor.a = Texel.a * poly_color.a;\n" \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// same as above but multiplies results with the lighting value from the +// accompanying vertex shader (stored in gl_Color) +#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + GLSL_DOOM_UNIFORMS \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 Texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 BaseColor = Texel * poly_color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "FinalColor *= gl_Color;\n" \ + "FinalColor.a = Texel.a * poly_color.a;\n" \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// +// Water surface shader +// + +#define GLSL_WATER_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + GLSL_DOOM_UNIFORMS \ + GLSL_WATER_VARIABLES \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + GLSL_WATER_DISTORT \ + "vec4 WaterTexel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ + GLSL_WATER_MIX \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// +// Sky fragment shader +// Modulates poly_color with gl_Color +// + +#define GLSL_SKY_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ + "}\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +#define GLSL_FOG_FRAGMENT_SHADER \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 BaseColor = gl_Color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = FinalColor;\n" \ + "}\0" diff --git a/src/hardware/shaders/shaders_gles2.h b/src/hardware/shaders/shaders_gles2.h new file mode 100644 index 0000000000000000000000000000000000000000..3b2e99ff36fd19cae75979bd69f4e1ae7a29e4f0 --- /dev/null +++ b/src/hardware/shaders/shaders_gles2.h @@ -0,0 +1,241 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file shaders_gles2.h +/// \brief OpenGL ES shader definitions + +#include "gl_shaders.h" + +#define GLSL_BASE_VARYING \ + "varying vec2 v_texcoord;\n" \ + "varying vec3 v_normal;\n" \ + "varying vec4 v_colors;\n" + +// ================ +// Vertex shaders +// ================ + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "attribute vec3 a_position;\n" \ + "attribute vec2 a_texcoord;\n" \ + "attribute vec3 a_normal;\n" \ + "attribute vec4 a_colors;\n" \ + GLSL_BASE_VARYING \ + "uniform mat4 u_model;\n" \ + "uniform mat4 u_view;\n" \ + "uniform mat4 u_projection;\n" \ + "void main()\n" \ + "{\n" \ + "gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0f);\n" \ + "v_texcoord = vec2(a_texcoord.x, a_texcoord.y);\n" \ + "v_normal = a_normal;\n" \ + "v_colors = a_colors;\n" \ + "}\0" + +// +// Fade mask vertex shader +// + +#define GLSL_FADEMASK_VERTEX_SHADER \ + "attribute vec3 a_position;\n" \ + "attribute vec2 a_texcoord;\n" \ + "attribute vec2 a_fademasktexcoord;\n" \ + "varying vec2 v_texcoord;\n" \ + "varying vec3 v_fademasktexcoord;\n" \ + "uniform mat4 u_projection;\n" \ + "void main()\n" \ + "{\n" \ + "gl_Position = u_projection * vec4(a_position, 1.0f);\n" \ + "v_texcoord = vec2(a_texcoord.x, a_texcoord.y);\n" \ + "v_fademasktexcoord = vec2(a_fadetex.x, a_fadetex.y);\n" \ + "}\0" + +// replicates the way fixed function lighting is used by the model lighting option, +// stores the lighting result to gl_Color +// (ambient lighting of 0.75 and diffuse lighting from above) +#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ + "attribute vec3 a_position;\n" \ + "attribute vec2 a_texcoord;\n" \ + "attribute vec3 a_normal;\n" \ + "attribute vec4 a_colors;\n" \ + "varying vec2 v_texcoord;\n" \ + "varying vec3 v_normal;\n" \ + "varying vec4 v_colors;\n" \ + "uniform mat4 u_model;\n" \ + "uniform mat4 u_view;\n" \ + "uniform mat4 u_projection;\n" \ + "void main()\n" \ + "{\n" \ + "float nDotVP = dot(a_normal, vec3(0, 1, 0));\n" \ + "float light = 0.75 + max(nDotVP, 0.0);\n" \ + "gl_Position = u_projection * vec4(a_position, 1.0f);\n" \ + "v_texcoord = vec2(a_texcoord.x, a_texcoord.y);\n" \ + "v_normal = a_normal;\n" \ + "v_colors = vec4(light, light, light, 1.0) * a_colors;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +#define GLSL_BASE_SAMPLER "uniform sampler2D t_texsampler;\n" +#define GLSL_BASE_UNIFORMS \ + GLSL_BASE_SAMPLER \ + "uniform vec4 poly_color;\n" \ + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + GLSL_BASE_VARYING \ + GLSL_BASE_UNIFORMS \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(t_texsampler, v_texcoord) * poly_color;\n" \ + "}\0" + +// +// Sky fragment shader +// + +#define GLSL_SKY_FRAGMENT_SHADER \ + GLSL_BASE_VARYING \ + GLSL_BASE_UNIFORMS \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(t_texsampler, v_texcoord) * v_colors;\n" \ + "}\0" + +// +// Fade mask fragment shader +// + +#define GLSL_FADEMASK_BASE_IN \ + "varying vec2 v_texcoord;\n" \ + "varying vec3 v_fademasktexcoord;\n" \ + "uniform sampler2D t_startscreen;\n" \ + "uniform sampler2D t_endscreen;\n" \ + "uniform sampler2D t_fademask;\n" + +#define GLSL_FADEMASK_FRAGMENT_SHADER \ + GLSL_FADEMASK_BASE_IN \ + "void main(void) {\n" \ + "vec4 StartTexel = texture2D(t_startscreen, v_texcoord);\n" \ + "vec4 EndTexel = texture2D(t_endscreen, v_texcoord);\n" \ + "vec4 MaskTexel = texture2D(t_fademask, v_fademasktexcoord);\n" \ + "gl_FragColor = mix(StartTexel, EndTexel, MaskTexel.r);\n" \ + "}\0" + +// Lactozilla: Very simple shader that uses either additive +// or subtractive blending depending on the wipe style. +#define GLSL_FADEMASK_ADDITIVEANDSUBTRACTIVE_FRAGMENT_SHADER \ + GLSL_FADEMASK_BASE_IN \ + "uniform bool is_fading_in;\n" \ + "uniform bool is_to_white;\n" \ + "void main(void) {\n" \ + "vec4 MaskTexel = texture2D(t_fademask, v_fademasktexcoord);\n" \ + "vec4 MixTexel;\n" \ + "vec4 FinalColor;\n" \ + "float FadeAlpha = MaskTexel.r;\n" \ + "if (is_fading_in == true)\n" \ + "{\n" \ + "FadeAlpha = (1.0f - FadeAlpha);\n" \ + "MixTexel = texture2D(t_endscreen, v_texcoord);\n" \ + "}\n" \ + "else\n" \ + "MixTexel = texture2D(t_startscreen, v_texcoord);\n" \ + "float FadeRed = clamp((FadeAlpha * 3.0f), 0.0f, 1.0f);\n" \ + "float FadeGreen = clamp((FadeAlpha * 2.0f), 0.0f, 1.0f);\n" \ + "if (is_to_white == true)\n" \ + "{\n" \ + "FinalColor.r = MixTexel.r + FadeRed;\n" \ + "FinalColor.g = MixTexel.g + FadeGreen;\n" \ + "FinalColor.b = MixTexel.b + FadeAlpha;\n" \ + "}\n" \ + "else\n" \ + "{\n" \ + "FinalColor.r = MixTexel.r - FadeRed;\n" \ + "FinalColor.g = MixTexel.g - FadeGreen;\n" \ + "FinalColor.b = MixTexel.b - FadeAlpha;\n" \ + "}\n" \ + "FinalColor.a = 1.0f;\n" \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// +// Software fragment shader +// + +#include "shaders_software.h" + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + GLSL_BASE_VARYING \ + GLSL_BASE_SAMPLER \ + GLSL_DOOM_UNIFORMS \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 Texel = texture2D(t_texsampler, v_texcoord);\n" \ + "vec4 BaseColor = Texel * poly_color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "FinalColor.a = Texel.a * poly_color.a;\n" \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// same as above but multiplies results with the lighting value from the +// accompanying vertex shader (stored in gl_Color) +#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ + GLSL_BASE_VARYING \ + GLSL_BASE_SAMPLER \ + GLSL_DOOM_UNIFORMS \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 Texel = texture2D(t_texsampler, v_texcoord);\n" \ + "vec4 BaseColor = Texel * poly_color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "FinalColor *= v_colors;\n" \ + "FinalColor.a = Texel.a * poly_color.a;\n" \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// +// Water surface shader +// + +#define GLSL_WATER_FRAGMENT_SHADER \ + GLSL_BASE_VARYING \ + GLSL_BASE_SAMPLER \ + GLSL_DOOM_UNIFORMS \ + GLSL_WATER_VARIABLES \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + GLSL_WATER_DISTORT \ + "vec4 WaterTexel = texture2D(t_texsampler, vec2(v_texcoord.s - sdistort, v_texcoord.t - cdistort));\n" \ + GLSL_WATER_MIX \ + "gl_FragColor = FinalColor;\n" \ + "}\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +#define GLSL_FOG_FRAGMENT_SHADER \ + "varying vec2 v_texcoord;\n" \ + GLSL_DOOM_UNIFORMS \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 BaseColor = poly_color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = FinalColor;\n" \ + "}\0" diff --git a/src/hardware/shaders/shaders_software.h b/src/hardware/shaders/shaders_software.h new file mode 100644 index 0000000000000000000000000000000000000000..8cbfc2d4ca11430e55490385055a6ef33553d8a5 --- /dev/null +++ b/src/hardware/shaders/shaders_software.h @@ -0,0 +1,83 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 1998-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file shaders_software.h +/// \brief Software fragment shader + +#define GLSL_DOOM_UNIFORMS \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" + +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "return startmap - scale * 0.5;\n" \ + "}\n" + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 0.0) {\n" \ + "float bright = sqrt((BaseColor.r * BaseColor.r) + (BaseColor.g * BaseColor.g) + (BaseColor.b * BaseColor.b));\n" \ + "float strength = sqrt(9.0 * tint_color.a);\n" \ + "FinalColor.r = clamp((bright * (tint_color.r * strength)) + (BaseColor.r * (1.0 - strength)), 0.0, 1.0);\n" \ + "FinalColor.g = clamp((bright * (tint_color.g * strength)) + (BaseColor.g * (1.0 - strength)), 0.0, 1.0);\n" \ + "FinalColor.b = clamp((bright * (tint_color.b * strength)) + (BaseColor.b * (1.0 - strength)), 0.0, 1.0);\n" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(lighting);\n" \ + "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "float fs = fade_start / 31.0;\n" \ + "float fe = fade_end / 31.0;\n" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "FinalColor = mix(FinalColor, fade_color, darkness);\n" + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_VARIABLES \ + "uniform float leveltime;\n" \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" + +#define GLSL_WATER_DISTORT \ + "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" + +#define GLSL_WATER_MIX \ + "vec4 BaseColor = WaterTexel * poly_color;\n" \ + "vec4 FinalColor = BaseColor;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "FinalColor.a = WaterTexel.a * poly_color.a;\n" diff --git a/src/sdl/Makefile.cfg b/src/sdl/Makefile.cfg index 45d0d6ba75a666cba5e4e2c3a3f9704987705cb6..86957caaffc06e7acd16b8de8a12f57f80fe6b7d 100644 --- a/src/sdl/Makefile.cfg +++ b/src/sdl/Makefile.cfg @@ -50,7 +50,7 @@ endif OPTS+=-DDIRECTFULLSCREEN -DHAVE_SDL ifndef NOHW - OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o + OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/r_glcommon.o $(OBJDIR)/gl_shaders.o $(OBJDIR)/ogl_sdl.o endif ifdef NOMIXER diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 7dcf91823be97d3001030cb7abbc004fda7fcb90..f790d544b25162ddeb67eff8dee87c8be242d0e6 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -61,10 +61,11 @@ \return void */ -// + void *hwSym(const char *funcName,void *handle) { void *funcPointer = NULL; + if (0) ; #ifdef STATIC3DS GETFUNC(Startup); GETFUNC(AddSfx); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 2eb7c7496ab85491b42bfd4caa36c442e3f45bfa..03e460d0861bea66ddfe51ec5a00a0f08b22df34 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -75,9 +75,11 @@ #include "../r_main.h" #include "../lua_hook.h" #include "sdlmain.h" + #ifdef HWRENDER #include "../hardware/hw_main.h" #include "../hardware/hw_gpu.h" +#include "../hardware/r_glcommon/r_glcommon.h" // For dynamic referencing of HW rendering functions #include "hwsym_sdl.h" #include "ogl_sdl.h" @@ -1477,20 +1479,23 @@ static SDL_bool Impl_CreateContext(void) void VID_CheckGLLoaded(rendermode_t oldrender) { - (void)oldrender; #ifdef HWRENDER - if (vid.glstate == VID_GL_LIBRARY_ERROR) // Well, it didn't work the first time anyway. - { - CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); + if (vid.glstate != VID_GL_LIBRARY_ERROR) + return; + + // Well, it didn't work the first time anyway. + if (chosenrendermode == render_opengl) // fallback to software + rendermode = render_soft; + else rendermode = oldrender; - if (chosenrendermode == render_opengl) // fallback to software - rendermode = render_soft; - if (setrenderneeded) - { - CV_StealthSetValue(&cv_renderer, oldrender); - setrenderneeded = 0; - } + + if (setrenderneeded) + { + CV_StealthSetValue(&cv_renderer, oldrender); + setrenderneeded = 0; } +#else + (void)oldrender; #endif } @@ -1854,7 +1859,7 @@ void VID_StartupOpenGL(void) GPUInterface_Load(&GPU); - if (VID_LoadGPUAPI() && GPU->Init()) + if (GLBackend_LoadLibrary() && GPU->Init()) vid.glstate = VID_GL_LIBRARY_LOADED; else { diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 2c4ee341497019dee544b981e0b037b2527176e6..0df9fc051d603591839d852d0267c358381bf68b 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -72,7 +72,7 @@ PFNglGetString pglGetString; void *GLUhandle = NULL; SDL_GLContext sdlglcontext = 0; -void *GetGLFunc(const char *proc) +void *GLBackend_GetFunction(const char *proc) { if (strncmp(proc, "glu", 3) == 0) { @@ -84,7 +84,7 @@ void *GetGLFunc(const char *proc) return SDL_GL_GetProcAddress(proc); } -boolean VID_LoadGPUAPI(void) +boolean GLBackend_LoadLibrary(void) { #ifndef STATIC_OPENGL const char *OGLLibname = NULL; @@ -99,7 +99,7 @@ boolean VID_LoadGPUAPI(void) "Falling back to Software mode.\n", SDL_GetError()); if (!M_CheckParm("-OGLlib")) CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n"); - return 0; + return false; } #if 0 @@ -154,47 +154,16 @@ boolean VID_LoadGPUAPI(void) boolean OglSdlSurface(INT32 w, INT32 h) { INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; - static boolean first_init = false; - if (!first_init) - { - GLVersion = pglGetString(GL_VERSION); - GLRenderer = pglGetString(GL_RENDERER); - GLExtensions = pglGetString(GL_EXTENSIONS); - - GL_DBG_Printf("OpenGL %s\n", GLVersion); - GL_DBG_Printf("GPU: %s\n", GLRenderer); - GL_DBG_Printf("Extensions: %s\n", GLExtensions); + GLBackend_InitContext(); + GLBackend_LoadContextFunctions(); - if (strcmp((const char*)GLRenderer, "GDI Generic") == 0 && - strcmp((const char*)GLVersion, "1.1.0") == 0) - { - // Oh no... Windows gave us the GDI Generic rasterizer, so something is wrong... - // The game will crash later on when unsupported OpenGL commands are encountered. - // Instead of a nondescript crash, show a more informative error message. - // Also set the renderer variable back to software so the next launch won't - // repeat this error. - CV_StealthSet(&cv_renderer, "Software"); - I_Error("OpenGL Error: Failed to access the GPU. There may be an issue with your graphics drivers."); - } - } - first_init = true; - - if (isExtAvailable("GL_EXT_texture_filter_anisotropic", GLExtensions)) - pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GPUMaximumAnisotropy); - else - GPUMaximumAnisotropy = 1; - - SetupGLFunc4(); + SetSurface(w, h); glanisotropicmode_cons_t[1].value = GPUMaximumAnisotropy; SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0); - SetModelView(w, h); - SetStates(); - pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - HWR_Startup(); GPUTextureFormat = cbpp > 16 ? GL_RGBA : GL_RGB5_A1; @@ -224,7 +193,7 @@ void OglSdlFinishUpdate(boolean waitvbl) HWR_DrawScreenFinalTexture(sdlw, sdlh); SDL_GL_SwapWindow(window); - GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE); + GPU->GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE); // Sryder: We need to draw the final screen texture again into the other buffer in the original position so that // effects that want to take the old screen can do so after this