Paletteshader #67

Merged
Indev450 merged 32 commits from paletteshader into Saturn-Next 2023-09-14 20:55:25 +02:00
14 changed files with 490 additions and 49 deletions

No files matched your search

+2
View File
@@ -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,
+6
View File
@@ -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;
+74 -18
View File
@@ -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
+3
View File
@@ -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;
+361 -20
View File
@@ -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, &ltcachetail->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, &ltcachehead->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(&currentSurfaceInfo, &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
+4
View File
@@ -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
+2 -2
View File
@@ -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
+11 -5
View File
@@ -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 <malloc.h> // 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;
}
-2
View File
@@ -104,6 +104,4 @@ UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
extern INT32 numtextures;
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
#endif
+6
View File
@@ -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;
//
+1
View File
@@ -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
+3
View File
@@ -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))
+3
View File
@@ -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;
+14 -2
View File
@@ -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