diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 294e4e791..6002fcf18 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -224,6 +224,7 @@ struct FSurfaceInfo RGBA_t PolyColor; RGBA_t TintColor; RGBA_t FadeColor; + UINT32 LightTableId; FLightInfo LightInfo; // jimita 14032019 }; typedef struct FSurfaceInfo FSurfaceInfo; @@ -231,6 +232,7 @@ typedef struct FSurfaceInfo FSurfaceInfo; enum hwdsetspecialstate { HWD_SET_SHADERS, + HWD_SET_PALETTE_SHADER_ENABLED, HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREANISOTROPICMODE, diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 204c79dc1..d00055d59 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -80,6 +80,9 @@ EXPORT void HWRAPI(InitCustomShaders) (void); EXPORT void HWRAPI(StartBatching) (void); EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors); +EXPORT UINT32 HWRAPI(AddLightTable) (UINT8 *lighttable); +EXPORT void HWRAPI(ClearLightTableCache) (void); + // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM // ========================================================================== @@ -126,6 +129,9 @@ struct hwdriver_s StartBatching pfnStartBatching; RenderBatches pfnRenderBatches; + + AddLightTable pfnAddLightTable; + ClearLightTableCache pfnClearLightTableCache; }; extern struct hwdriver_s hwdriver; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 6a254a285..e534e4e09 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -30,6 +30,7 @@ #include "../r_fps.h" #include "../r_state.h" #include "../r_local.h" +#include "../r_data.h" #include "../r_patch.h" // a mystery as to what this is for #include "../r_bsp.h" // R_NoEncore #include "../r_main.h" // cv_fov @@ -60,10 +61,14 @@ struct hwdriver_s hwdriver; // Commands and console variables // ========================================================================== +// keep the state here instead of in the cv var, so it always matches the state in r_opengl.c +int gr_use_palette_shader = 0; + static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); static void CV_screentextures_ONChange(void); -static void CV_useCustomShaders_ONChange(void); +static void CV_useCustomShaders_ONChange(void); +static void CV_grpaletteshader_OnChange(void); static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, @@ -115,7 +120,9 @@ static INT32 current_bsp_culling_distance = 0; consvar_t cv_grscreentextures = {"gr_screentextures", "On", CV_CALL, CV_OnOff, CV_screentextures_ONChange, 0, NULL, NULL, 0, 0, NULL}; - consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE, CV_OnOff, CV_useCustomShaders_ONChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grusecustomshaders = {"gr_usecustomshaders", "Yes", CV_CALL|CV_SAVE, CV_OnOff, CV_useCustomShaders_ONChange, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_grpaletteshader = {"gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_grpaletteshader_OnChange, 0, NULL, NULL, 0, 0, NULL}; static void CV_filtermode_ONChange(void) { @@ -138,6 +145,17 @@ static void CV_useCustomShaders_ONChange(void) HWD.pfnInitCustomShaders(); } +static void CV_grpaletteshader_OnChange(void) +{ + if (rendermode == render_opengl) + { + HWD.pfnSetSpecialState(HWD_SET_PALETTE_SHADER_ENABLED, cv_grpaletteshader.value); + gr_use_palette_shader = cv_grpaletteshader.value; + //R_ClearColormaps(); + InitPalette(); + } +} + // ========================================================================== // Globals // ========================================================================== @@ -400,6 +418,7 @@ static size_t gr_numportalcullsectors = 0; void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) { RGBA_t poly_color, tint_color, fade_color; + boolean default_colormap = false; poly_color.rgba = 0xFFFFFFFF; tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : GL_DEFAULTMIX; @@ -451,6 +470,37 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col Surface->LightInfo.light_level = light_level; Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; + + if (gr_use_palette_shader) + { + if (!colormap) + { + colormap = &extra_colormaps[num_extra_colormaps]; + default_colormap = true; + } + if (!colormap->gl_lighttable_id) + { + UINT8 *colormap_pointer; + + if (default_colormap) + { + colormap_pointer = colormaps; + } + else + { + colormap_pointer = colormap->colormap; + } + colormap->gl_lighttable_id = HWD.pfnAddLightTable(colormap_pointer); + } + + Surface->LightTableId = colormap->gl_lighttable_id; + } +} + +void HWR_ClearLightTableCache() +{ + if (rendermode == render_opengl) + HWD.pfnClearLightTableCache(); } UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work @@ -723,7 +773,7 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei else if (PolyFlags & PF_Ripple) HWD.pfnSetShader(5); // water shader else - HWD.pfnSetShader(1); // floor shader + HWD.pfnSetShader(gr_use_palette_shader ? 9 : 1); // floor shader HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, false); @@ -861,7 +911,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) break; } - HWD.pfnSetShader(2); // wall shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 2); // wall shader HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, false); } } @@ -895,7 +945,7 @@ void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend { HWR_Lighting(pSurf, lightlevel, wallcolormap); - HWD.pfnSetShader(2); // wall shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 2); // wall shader // don't draw to color buffer when drawing to stencil if (gl_drawing_stencil) @@ -977,13 +1027,15 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa { if (pfloor && (pfloor->flags & FF_FOG)) { - lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y); colormap = pfloor->master->frontsector->extra_colormap; + lightnum = pfloor->master->frontsector->lightlevel; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } else { - lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y); colormap = list[i].extra_colormap; + lightnum = *list[i].lightlevel; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } } @@ -1383,8 +1435,9 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); } - lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = gr_frontsector->extra_colormap; + lightnum = gr_frontsector->lightlevel; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); if (gr_frontsector) Surf.PolyColor.s.alpha = 255; @@ -2205,8 +2258,10 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom blendmode = PF_Fog|PF_NoTexture; - lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; + lightnum = rover->master->frontsector->lightlevel; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); @@ -2328,8 +2383,9 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom blendmode = PF_Fog|PF_NoTexture; - lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; + lightnum = rover->master->frontsector->lightlevel; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); @@ -3036,7 +3092,7 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t else blendmode |= PF_Masked|PF_Modulated; - HWD.pfnSetShader(1); // floor shader + HWD.pfnSetShader(gr_use_palette_shader ? 9 : 1); // floor shader HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, false); } @@ -3835,7 +3891,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t if (sSurf.PolyColor.s.alpha > floorheight/4) { sSurf.PolyColor.s.alpha = (UINT8)(sSurf.PolyColor.s.alpha - floorheight/4); - HWD.pfnSetShader(1); // floor shader + HWD.pfnSetShader(gr_use_palette_shader ? 9 : 1); // floor shader HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, false); } } @@ -4202,7 +4258,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWD.pfnSetShader(3); // sprite shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 3); // sprite shader HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); top = bot; @@ -4242,7 +4298,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWD.pfnSetShader(3); // sprite shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 3); // sprite shader HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); } @@ -4395,7 +4451,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) blend = PF_Translucent|PF_Occlude; } - HWD.pfnSetShader(3); // sprite shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 3); // sprite shader HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); } } @@ -4489,7 +4545,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) blend = PF_Translucent|PF_Occlude; } - HWD.pfnSetShader(3); // sprite shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 3); // sprite shader HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); } @@ -6037,6 +6093,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_portalline); CV_RegisterVar(&cv_portalonly); CV_RegisterVar(&cv_secbright); + CV_RegisterVar(&cv_grpaletteshader); } // -------------------------------------------------------------------------- @@ -6078,7 +6135,6 @@ void HWR_Startup(void) } } - // -------------------------------------------------------------------------- // Free resources allocated by the hardware renderer // -------------------------------------------------------------------------- @@ -6100,7 +6156,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting - HWD.pfnSetShader(2); // wall shader + HWD.pfnSetShader(gr_use_palette_shader ? 10 : 2); // wall shader if (blend & PF_Environment) blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 51a362c9e..019b921c6 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -142,6 +142,8 @@ void HWR_AddLine(seg_t *line); boolean HWR_CheckBBox(fixed_t *bspcoord); void HWR_RenderDrawNodes(void); +void HWR_ClearLightTableCache(void); + // hw_main.c: Sprites void HWR_AddSprites(sector_t *sec); void HWR_ProjectSprite(mobj_t *thing); @@ -179,6 +181,7 @@ extern consvar_t cv_grfallbackplayermodel; extern consvar_t cv_grbatching; extern consvar_t cv_grrenderdistance; extern consvar_t cv_grusecustomshaders; +extern consvar_t cv_grpaletteshader; extern consvar_t cv_grportals; extern consvar_t cv_nostencil; extern consvar_t cv_secbright; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index b0c6ec8f6..49b9726dc 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -26,10 +26,15 @@ #include "r_opengl.h" #include "r_vbo.h" +#include "../../v_video.h" // pLocalPalette +#include "../../r_data.h" // NearestColor + #include "../../p_tick.h" // for leveltime (NOTE: THIS IS BAD, FIGURE OUT HOW TO PROPERLY IMPLEMENT gl_leveltime) #include "../../i_system.h" // for I_GetPreciseTime (batching time measurements) -// Eeeeh not sure is this right way, but it works +#include "../hw_main.h" + +// Eeeeh not sure is this right way, but it works < sry :c extern consvar_t cv_grusecustomshaders; extern fixed_t fovtan; // also extremely bad, I'm just too lazy!!! @@ -44,12 +49,15 @@ struct GLRGBAFloat GLfloat alpha; }; typedef struct GLRGBAFloat GLRGBAFloat; + static const GLubyte white[4] = { 255, 255, 255, 255 }; // ========================================================================== // CONSTANTS // ========================================================================== + + // With OpenGL 1.1+, the first texture should be 1 #define NOTEXTURE_NUM 0 @@ -70,8 +78,17 @@ static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; static FBITFIELD CurrentPolyFlags; -static FTextureInfo* gr_cachetail = NULL; -static FTextureInfo* gr_cachehead = NULL; +static FTextureInfo *gr_cachetail = NULL; +static FTextureInfo *gr_cachehead = NULL; + +typedef struct LightTableCacheEntry_s +{ + GLuint id; + struct LightTableCacheEntry_s *next; +} LightTableCacheEntry_t; + +LightTableCacheEntry_t *ltcachehead = NULL; +LightTableCacheEntry_t *ltcachetail = NULL; RGBA_t myPaletteData[256]; GLint screen_width = 0; // used by Draw2DLine() @@ -235,6 +252,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D +#define pglTexImage3D glTexImage3D /* Fog */ #define pglFogf glFogf @@ -355,6 +373,8 @@ typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint 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 * PFNglTexImage3D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexImage3D pglTexImage3D; /* Fog */ typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); @@ -511,6 +531,7 @@ 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 *PFNglUniform1iv) (GLint, GLsizei, const GLint*); typedef void (APIENTRY *PFNglUniform1f) (GLint, GLfloat); typedef void (APIENTRY *PFNglUniform2f) (GLint, GLfloat, GLfloat); typedef void (APIENTRY *PFNglUniform3f) (GLint, GLfloat, GLfloat, GLfloat); @@ -532,6 +553,7 @@ static PFNglLinkProgram pglLinkProgram; static PFNglGetProgramiv pglGetProgramiv; static PFNglUseProgram pglUseProgram; static PFNglUniform1i pglUniform1i; +static PFNglUniform1iv pglUniform1iv; static PFNglUniform1f pglUniform1f; static PFNglUniform2f pglUniform2f; static PFNglUniform3f pglUniform3f; @@ -555,6 +577,10 @@ static boolean gl_shaderprogramchanged = true; static boolean gl_batching = false;// are we currently collecting batches? +static GLint gl_palette[768]; +static INT32 gl_use_palette_shader = 0; +boolean gl_palette_initialized = false; + static INT32 gl_enable_screen_textures = 1; static GLint gl_portal_stencil_level = 0; @@ -571,10 +597,15 @@ typedef enum gluniform_lighting, gluniform_fade_start, gluniform_fade_end, - - // misc. (custom shaders) + + // palette rendering + gluniform_palette, + gluniform_color_lookup, + gluniform_lighttable_tex, + + // misc. gluniform_leveltime, - + gluniform_max, } gluniform_t; @@ -594,6 +625,18 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; // GLSL Software fragment shader // +#define GLSL_DOOM_COLORMAP_floors \ + "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 * 1.06 - scale * 0.5 * 1.15;\n" \ + "}\n" + +// 1.06 and 1.15 were chosen when trying to match software lighting in a test map + #define GLSL_DOOM_COLORMAP \ "float R_DoomColormap(float light, float z)\n" \ "{\n" \ @@ -604,6 +647,16 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; "return startmap - scale * 0.5;\n" \ "}\n" +#define GLSL_DOOM_COLORMAP_walls \ + "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 * 1.05 - scale * 1.0 * 1.1;\n" \ + "}\n" + #define GLSL_DOOM_LIGHT_EQUATION \ "float R_DoomLightingEquation(float light)\n" \ "{\n" \ @@ -631,16 +684,16 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; "}\n" \ "final_color = mix(final_color, fade_color, darkness);\n" -#define GLSL_SOFTWARE_FRAGMENT_SHADER \ +#define GLSL_SOFTWARE_UNIFORMS \ "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 \ + "uniform float fade_end;\n" + +#define GLSL_SOFTWARE_MAIN \ "void main(void) {\n" \ "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ "vec4 base_color = texel * poly_color;\n" \ @@ -649,7 +702,54 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; GLSL_SOFTWARE_FADE_EQUATION \ "final_color.a = texel.a * poly_color.a;\n" \ "gl_FragColor = final_color;\n" \ - "}\0" + "}\n" + +#define GLSL_SOFTWARE_FRAGMENT_SHADER_FLOORS \ + GLSL_SOFTWARE_UNIFORMS \ + GLSL_DOOM_COLORMAP_floors \ + GLSL_DOOM_LIGHT_EQUATION \ + GLSL_SOFTWARE_MAIN \ + "\0" + +#define GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS \ + GLSL_SOFTWARE_UNIFORMS \ + GLSL_DOOM_COLORMAP_walls \ + GLSL_DOOM_LIGHT_EQUATION \ + GLSL_SOFTWARE_MAIN \ + "\0" + +#define GLSL_SOFTWARE_PAL_UNIFORMS \ + "uniform sampler2D tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform sampler3D lookup_tex;\n" \ + "uniform int palette[768];\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + +#define GLSL_SOFTWARE_PAL_MAIN \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "int tex_pal_idx = int(texture3D(lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0);\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "int light_y = int(clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0));\n" \ + "vec2 lighttable_coord = vec2((float(tex_pal_idx) + 0.5) / 256.0, (float(light_y) + 0.5) / 32.0);\n" \ + "int final_idx = int(texture2D(lighttable_tex, lighttable_coord)[0] * 255.0);\n" \ + "vec4 final_color = vec4(float(palette[final_idx*3])/255.0, float(palette[final_idx*3+1])/255.0, float(palette[final_idx*3+2])/255.0, 1.0);\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" + +#define GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_FLOORS \ + GLSL_SOFTWARE_PAL_UNIFORMS \ + GLSL_DOOM_COLORMAP_floors \ + GLSL_SOFTWARE_PAL_MAIN \ + "\0" + +#define GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_WALLS \ + GLSL_SOFTWARE_PAL_UNIFORMS \ + GLSL_DOOM_COLORMAP_walls \ + GLSL_SOFTWARE_PAL_MAIN \ + "\0" // // Water surface shader @@ -708,6 +808,20 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; GLSL_SOFTWARE_FADE_EQUATION \ "gl_FragColor = final_color;\n" \ "}\0" + +// +// Palette color quantization shader +// + +#define GLSL_PALETTE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D lookup_tex;\n" \ + "uniform int palette[768];\n" \ + "void main(void) {\n" \ + "vec3 texel = vec3(texture2D(tex, gl_TexCoord[0].st));\n" \ + "int pal_idx = int(texture3D(lookup_tex, vec3((63.0/64.0) * texel + 1.0 / 128.0))[0] * 255.0);\n" \ + "gl_FragColor = vec4(float(palette[pal_idx*3])/255.0, float(palette[pal_idx*3+1])/255.0, float(palette[pal_idx*3+2])/255.0, 1.0);\n" \ + "}\0" // // GLSL generic fragment shader @@ -725,16 +839,16 @@ static const char *fragment_shaders[] = { GLSL_DEFAULT_FRAGMENT_SHADER, // Floor fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + GLSL_SOFTWARE_FRAGMENT_SHADER_FLOORS, // Wall fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS, // Sprite fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS, // Model fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + GLSL_SOFTWARE_FRAGMENT_SHADER_WALLS, // Water fragment shader GLSL_WATER_FRAGMENT_SHADER, @@ -747,6 +861,13 @@ static const char *fragment_shaders[] = { "void main(void) {\n" "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" "}\0", + + // Palette fragment shader + GLSL_PALETTE_FRAGMENT_SHADER, + + GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_FLOORS, + + GLSL_SOFTWARE_PAL_FRAGMENT_SHADER_WALLS, NULL, }; @@ -792,6 +913,13 @@ static const char *vertex_shaders[] = { // Sky vertex shader GLSL_DEFAULT_VERTEX_SHADER, + + // Palette vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + GLSL_DEFAULT_VERTEX_SHADER, + + GLSL_DEFAULT_VERTEX_SHADER, NULL, }; @@ -800,6 +928,7 @@ static const char *vertex_shaders[] = { void SetupGLFunc4(void) { + pglTexImage3D = GetGLFunc("glTexImage3D"); pglActiveTexture = GetGLFunc("glActiveTexture"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); @@ -826,6 +955,7 @@ void SetupGLFunc4(void) pglGetProgramiv = GetGLFunc("glGetProgramiv"); pglUseProgram = GetGLFunc("glUseProgram"); pglUniform1i = GetGLFunc("glUniform1i"); + pglUniform1iv = GetGLFunc("glUniform1iv"); pglUniform1f = GetGLFunc("glUniform1f"); pglUniform2f = GetGLFunc("glUniform2f"); pglUniform3f = GetGLFunc("glUniform3f"); @@ -858,12 +988,13 @@ EXPORT boolean HWRAPI(LoadShaders) (void) const GLchar* vert_shader = vertex_shaders[i]; const GLchar* frag_shader = fragment_shaders[i]; boolean custom = cv_grusecustomshaders.value && ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0)); - + // 18032019 if (cv_grusecustomshaders.value && gl_customvertexshaders[i]) vert_shader = gl_customvertexshaders[i]; if (cv_grusecustomshaders.value && gl_customfragmentshaders[i]) frag_shader = gl_customfragmentshaders[i]; + if (i >= MAXSHADERS) break; @@ -946,11 +1077,33 @@ EXPORT boolean HWRAPI(LoadShaders) (void) shader->uniforms[gluniform_lighting] = GETUNI("lighting"); shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); - + + // palette rendering + shader->uniforms[gluniform_palette] = GETUNI("palette"); + shader->uniforms[gluniform_color_lookup] = GETUNI("lookup_tex"); + shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex"); + // misc. (custom shaders) shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); - + #undef GETUNI + +// set permanent uniform values +#define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + pglUseProgram(shader->program); + + // texture unit numbers for the samplers used for palette rendering + UNIFORM_1(shader->uniforms[gluniform_palette], 2, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_color_lookup], 1, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_lighttable_tex], 2, pglUniform1i); + + pglUseProgram(0); + +#undef UNIFORM_1 + } #endif return true; @@ -962,7 +1115,9 @@ EXPORT boolean HWRAPI(LoadShaders) (void) EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) { #ifdef GL_SHADERS - if (!pglUseProgram) return; + if (!pglUseProgram) + return; + if (number < 1 || number > MAXSHADERS) I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); @@ -984,8 +1139,14 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boo EXPORT void HWRAPI(InitCustomShaders) (void) { #ifdef GL_SHADERS + KillShaders(); LoadShaders(); + +if (gl_use_palette_shader) + { + InitPalette(); + } #endif } @@ -1022,6 +1183,84 @@ EXPORT void HWRAPI(KillShaders) (void) // unused......................... } +GLuint palette_tex_num; +// length of one side of lookup texture +// smallest separation between all the colors in the srb2 palette is 6, so +// possibly a 64x64x64 lookup texture might be enough for 100% correct colors +// (min separation for 64^3 size is 4) +#define LUT_SIZE 64 +#define STEP_SIZE (256/LUT_SIZE) +// the +2 in the NearestColor call also needs to be adjusted if LUT_SIZE is changed! +// the hardcoded values in the shader also need to be adjusted if LUT_SIZE is changed! + +void InitPalette(void) +{ + int i, r, g, b; + // init the palette + for (i = 0; i < 256; i++) + { + // crush to 16-bit rgb565, like software currently does + float fred = (float)(pLocalPalette[i].s.red >> 3); + float fgreen = (float)(pLocalPalette[i].s.green >> 2); + float fblue = (float)(pLocalPalette[i].s.blue >> 3); + // restore to rgb888 + gl_palette[i*3] = (GLint)(fred / 31.0f * 255.0f); + gl_palette[i*3+1] = (GLint)(fgreen / 63.0f * 255.0f); + gl_palette[i*3+2] = (GLint)(fblue / 31.0f * 255.0f); + } + + // init the palette conversion lookup texture + GLubyte *pal_lookup_tex = malloc(LUT_SIZE*LUT_SIZE*LUT_SIZE*sizeof(GLubyte)); + + if (!pal_lookup_tex) + I_Error("Failed to allocate memory for generating palette lookup texture."); + + for (b = 0; b < LUT_SIZE; b++) + { + for (g = 0; g < LUT_SIZE; g++) + { + for (r = 0; r < LUT_SIZE; r++) + { + pal_lookup_tex[b*LUT_SIZE*LUT_SIZE+g*LUT_SIZE+r] = NearestColor(r*STEP_SIZE+0, g*STEP_SIZE+0, b*STEP_SIZE+0); + } + } + } +#undef STEP_SIZE + + + pglGenTextures(1, &palette_tex_num); + pglBindTexture(GL_TEXTURE_3D, palette_tex_num); + pglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (!pglTexImage3D) + I_Error("pglTexImage3D is NULL!"); + pglTexImage3D(GL_TEXTURE_3D, 0, GL_R8, LUT_SIZE, LUT_SIZE, LUT_SIZE, 0, GL_RED, GL_UNSIGNED_BYTE, pal_lookup_tex); + free(pal_lookup_tex); + pglUseProgram(gl_shaderprograms[8].program); + pglUniform1i(gl_shaderprograms[8].uniforms[gluniform_color_lookup], 1); // bind sampler to second texture unit + pglUniform1iv(gl_shaderprograms[8].uniforms[gluniform_palette], 768, gl_palette); + // bind the palette to the fancy shader here + pglUseProgram(gl_shaderprograms[9].program); + pglUniform1iv(gl_shaderprograms[9].uniforms[gluniform_palette], 768, gl_palette); + // bind tex unit 2 to lighttable tex + pglUniform1i(gl_shaderprograms[9].uniforms[gluniform_lighttable_tex], 2); + pglUniform1i(gl_shaderprograms[9].uniforms[gluniform_color_lookup], 1); + // bind the palette to the fancy shader here + pglUseProgram(gl_shaderprograms[10].program); + pglUniform1iv(gl_shaderprograms[10].uniforms[gluniform_palette], 768, gl_palette); + // bind tex unit 2 to lighttable tex + pglUniform1i(gl_shaderprograms[10].uniforms[gluniform_lighttable_tex], 2); + pglUniform1i(gl_shaderprograms[10].uniforms[gluniform_color_lookup], 1); + pglUseProgram(0); + pglBindTexture(GL_TEXTURE_3D, 0); + + // bind 3d lookup to unit 1, maybe it can stay there + pglActiveTexture(GL_TEXTURE1); + pglBindTexture(GL_TEXTURE_3D, palette_tex_num); + pglActiveTexture(GL_TEXTURE0); + gl_palette_initialized = true; +} + // -----------------+ // SetNoTexture : Disable texture // -----------------+ @@ -1201,6 +1440,46 @@ EXPORT void HWRAPI(ClearMipMapCache) (void) Flush(); } +EXPORT UINT32 HWRAPI(AddLightTable) (UINT8 *lighttable) +{ + LightTableCacheEntry_t *cache_entry = malloc(sizeof(LightTableCacheEntry_t)); + if (!ltcachetail) + { + ltcachehead = ltcachetail = cache_entry; + } + else + { + ltcachetail->next = cache_entry; + ltcachetail = cache_entry; + } + ltcachetail->next = NULL; + pglGenTextures(1, <cachetail->id); + if (!ltcachetail->id) + I_Error("hwr lighttable cache entry id is zero"); + pglBindTexture(GL_TEXTURE_2D, ltcachetail->id); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 256, 32, 0, GL_RED, GL_UNSIGNED_BYTE, lighttable); + + // restore previously bound texture + if (!gl_batching) + pglBindTexture(GL_TEXTURE_2D, tex_downloaded); + + return ltcachetail->id; +} + +// Delete light table textures, ids given before become invalid and must not be used. +EXPORT void HWRAPI(ClearLightTableCache) (void) +{ + while (ltcachehead) + { + pglDeleteTextures(1, <cachehead->id); + LightTableCacheEntry_t *next = ltcachehead->next; + free(ltcachehead); + ltcachehead = next; + } + ltcachetail = NULL; +} // -----------------+ // ReadRect : Read a rectangle region of the truecolor framebuffer @@ -1312,6 +1591,9 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, pglClear(ClearMask); pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too + + if (!gl_palette_initialized) + InitPalette(); // just gonna put this here for now } @@ -1886,6 +2168,12 @@ static int comparePolygons(const void *p1, const void *p2) diff = poly1->texNum - poly2->texNum; if (diff != 0) return diff; + + if (gl_use_palette_shader) + { + diff = poly1->surf.LightTableId - poly2->surf.LightTableId; + if (diff != 0) return diff; + } diff = poly1->polyFlags - poly2->polyFlags; if (diff != 0) return diff; @@ -2024,7 +2312,15 @@ EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, i firstFade.alpha = byte2float[currentSurfaceInfo.FadeColor.s.alpha]; if (gl_allowshaders) + { load_shaders(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade); + if (gl_use_palette_shader) + { + pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now + pglBindTexture(GL_TEXTURE_2D, currentSurfaceInfo.LightTableId); + pglActiveTexture(GL_TEXTURE0); + } + } if (currentPolyFlags & PF_NoTexture) currentTexture = 0; @@ -2135,7 +2431,21 @@ EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, i changeState = true; changePolyFlags = true; } - if (gl_allowshaders) + if ((gl_allowshaders) && (gl_use_palette_shader)) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || + currentSurfaceInfo.LightTableId != nextSurfaceInfo.LightTableId) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else if ((gl_allowshaders) && (!gl_use_palette_shader)) { if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || @@ -2265,7 +2575,15 @@ EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, i fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; load_shaders(&nextSurfaceInfo, &poly, &tint, &fade); + + if (gl_use_palette_shader) + { + pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now + pglBindTexture(GL_TEXTURE_2D, nextSurfaceInfo.LightTableId); + pglActiveTexture(GL_TEXTURE0); + } } + currentSurfaceInfo = nextSurfaceInfo; changeSurfaceInfo = false; @@ -2365,6 +2683,13 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI fade.green = byte2float[pSurf->FadeColor.s.green]; fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + + if (gl_use_palette_shader && gl_allowshaders) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); + pglActiveTexture(GL_TEXTURE0); + } } load_shaders(pSurf, &poly, &tint, &fade); @@ -2707,6 +3032,10 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) break; } break; + + case HWD_SET_PALETTE_SHADER_ENABLED: + gl_use_palette_shader = Value; + break; case HWD_SET_TEXTUREFILTERMODE: switch (Value) @@ -3775,6 +4104,12 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) clearColour.alpha = 1; ClearBuffer(true, false, false, &clearColour); pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + + if (gl_use_palette_shader && cv_grshaders.value) + { + pglUseProgram(gl_shaderprograms[8].program); // palette shader + pglActiveTexture(GL_TEXTURE1); + } pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); @@ -3783,6 +4118,12 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); tex_downloaded = finalScreenTexture; + + if (gl_use_palette_shader && cv_grshaders.value) + { + pglUseProgram(0); + pglActiveTexture(GL_TEXTURE0); + } } #endif //HWRENDER diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 6d11bf4e3..f4a3f3849 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -133,4 +133,8 @@ typedef enum GLF_NOTEXENV = 0x02, } oglflags_t; +// in order for custom playpals n shit to work properly +extern boolean gl_palette_initialized; +void InitPalette(void); + #endif diff --git a/src/m_menu.c b/src/m_menu.c index 980a4c694..acaf7cb99 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1347,7 +1347,8 @@ static menuitem_t OP_OpenGLOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "3D Models", &cv_grmdls, 5}, {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 15}, {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_grshaders, 25}, - {IT_STRING|IT_CVAR, NULL, "Use custom Shaders", &cv_grusecustomshaders, 35}, + //{IT_STRING|IT_CVAR, NULL, "Use custom Shaders", &cv_grusecustomshaders, 35}, + {IT_STRING|IT_CVAR, NULL, "Palette Rendering", &cv_grpaletteshader, 35}, {IT_STRING | IT_CVAR, NULL, "Min Shader Brightness", &cv_secbright, 45}, {IT_STRING|IT_CVAR, NULL, "Texture Quality", &cv_scr_depth, 65}, @@ -1407,7 +1408,6 @@ static menuitem_t OP_SoundOptionsMenu[] = {IT_STRING|IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 155} }; - static menuitem_t OP_SoundAdvancedMenu[] = { #ifdef HAVE_OPENMPT diff --git a/src/r_data.c b/src/r_data.c index f982b0366..40be149b1 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -26,6 +26,10 @@ #include "v_video.h" // pLocalPalette #include "dehacked.h" +#ifdef HWRENDER +#include "hardware/hw_main.h" +#endif + #if defined (_WIN32) || defined (_WIN32_WCE) #include // alloca(sizeof) #endif @@ -1137,6 +1141,10 @@ void R_ClearColormaps(void) foundcolormaps[i] = LUMPERROR; memset(extra_colormaps, 0, sizeof (extra_colormaps)); + +#ifdef HWRENDER + HWR_ClearLightTableCache(); +#endif } /*INT32 R_ColormapNumForName(char *name) @@ -1317,12 +1325,11 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) extra_colormaps[mapnum].fadeend = (UINT16)fadeend; extra_colormaps[mapnum].fog = fog; - if (rendermode == render_soft) - { + double r, g, b, cbrightness; int p; lighttable_t *colormap_p; - + // Initialise the map and delta arrays // map[i] stores an RGB color (as double) for index i, // which is then converted to SRB2's palette later @@ -1401,8 +1408,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) colormap_p2 += 256; } } - } - + return (INT32)mapnum; } diff --git a/src/r_data.h b/src/r_data.h index f371d40d7..6a8806988 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -104,6 +104,4 @@ UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); extern INT32 numtextures; -UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); - #endif diff --git a/src/r_defs.h b/src/r_defs.h index 559e3646b..7254a6289 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -62,6 +62,12 @@ typedef struct INT32 fadergba; // The colour the colourmaps fade to lighttable_t *colormap; + + +#ifdef HWRENDER + // The id of the hardware lighttable. Zero means it does not exist yet. + UINT32 gl_lighttable_id; +#endif } extracolormap_t; // diff --git a/src/r_main.c b/src/r_main.c index dc914e79a..512a2b65c 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1955,6 +1955,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_grshearing); CV_RegisterVar(&cv_grshaders); CV_RegisterVar(&cv_grusecustomshaders); + CV_RegisterVar(&cv_grpaletteshader); #endif #ifdef HWRENDER diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 2627c3fdb..dcaaa7f51 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -113,6 +113,9 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(StartBatching); GETFUNC(RenderBatches); + + GETFUNC(AddLightTable); + GETFUNC(ClearLightTableCache); #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index d08b267f0..16dfc716a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -2148,6 +2148,9 @@ void I_StartupGraphics(void) HWD.pfnStartBatching = hwSym("StartBatching",NULL); HWD.pfnRenderBatches = hwSym("RenderBatches",NULL); + + HWD.pfnAddLightTable = hwSym("AddLightTable",NULL); + HWD.pfnClearLightTableCache = hwSym("ClearLightTableCache",NULL); if (!HWD.pfnInit()) // load the OpenGL library rendermode = render_soft; diff --git a/src/v_video.c b/src/v_video.c index 602e89248..3be8fcf80 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -28,6 +28,7 @@ #ifdef HWRENDER #include "hardware/hw_main.h" +#include "hardware/r_opengl/r_opengl.h" #endif // Each screen is [vid.width*vid.height]; @@ -224,8 +225,14 @@ void V_SetPalette(INT32 palettenum) LoadMapPalette(); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft && rendermode != render_none) { + + if (cv_grpaletteshader.value == 1){ + // reset our palette lookups n shit + gl_palette_initialized = false; + InitPalette();} HWR_SetPalette(&pLocalPalette[palettenum*256]); + } #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else #endif @@ -238,8 +245,13 @@ void V_SetPaletteLump(const char *pal) { LoadPalette(pal); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft && rendermode != render_none) { + if (cv_grpaletteshader.value == 1){ + // reset our palette lookups n shit + gl_palette_initialized = false; + InitPalette();} HWR_SetPalette(pLocalPalette); + } #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else #endif