mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-17 23:21:22 +00:00
Merge branch 'slight-shader-cleanup' into 'next'
Shader code cleanup See merge request STJr/SRB2!1103
This commit is contained in:
commit
d73fbd8616
9 changed files with 286 additions and 238 deletions
|
@ -132,6 +132,43 @@ typedef struct
|
|||
FLOAT t; // t texture ordinate (t over w)
|
||||
} FOutVector;
|
||||
|
||||
#ifdef GL_SHADERS
|
||||
// Predefined shader types
|
||||
enum
|
||||
{
|
||||
SHADER_DEFAULT = 0,
|
||||
|
||||
SHADER_FLOOR,
|
||||
SHADER_WALL,
|
||||
SHADER_SPRITE,
|
||||
SHADER_MODEL, SHADER_MODEL_LIGHTING,
|
||||
SHADER_WATER,
|
||||
SHADER_FOG,
|
||||
SHADER_SKY,
|
||||
|
||||
NUMBASESHADERS,
|
||||
};
|
||||
|
||||
// Maximum amount of shader programs
|
||||
// Must be higher than NUMBASESHADERS
|
||||
#define HWR_MAXSHADERS 16
|
||||
|
||||
// Shader sources (vertex and fragment)
|
||||
typedef struct
|
||||
{
|
||||
char *vertex;
|
||||
char *fragment;
|
||||
} shadersource_t;
|
||||
|
||||
// Custom shader reference table
|
||||
typedef struct
|
||||
{
|
||||
const char *type;
|
||||
INT32 id;
|
||||
} customshaderxlat_t;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct vbo_vertex_s
|
||||
{
|
||||
float x, y, z;
|
||||
|
|
|
@ -68,14 +68,13 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
|
|||
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
|
||||
|
||||
// jimita
|
||||
EXPORT boolean HWRAPI(LoadShaders) (void);
|
||||
EXPORT void HWRAPI(KillShaders) (void);
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void);
|
||||
EXPORT void HWRAPI(CleanShaders) (void);
|
||||
EXPORT void HWRAPI(SetShader) (int shader);
|
||||
EXPORT void HWRAPI(UnSetShader) (void);
|
||||
|
||||
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment);
|
||||
EXPORT boolean HWRAPI(InitCustomShaders) (void);
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment);
|
||||
|
||||
// ==========================================================================
|
||||
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
|
||||
|
@ -120,14 +119,13 @@ struct hwdriver_s
|
|||
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
|
||||
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
|
||||
|
||||
LoadShaders pfnLoadShaders;
|
||||
KillShaders pfnKillShaders;
|
||||
CompileShaders pfnCompileShaders;
|
||||
CleanShaders pfnCleanShaders;
|
||||
SetShader pfnSetShader;
|
||||
UnSetShader pfnUnSetShader;
|
||||
|
||||
SetShaderInfo pfnSetShaderInfo;
|
||||
LoadCustomShader pfnLoadCustomShader;
|
||||
InitCustomShaders pfnInitCustomShaders;
|
||||
};
|
||||
|
||||
extern struct hwdriver_s hwdriver;
|
||||
|
|
|
@ -565,11 +565,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
|||
PolyFlags |= PF_Masked|PF_Modulated;
|
||||
|
||||
if (PolyFlags & PF_Fog)
|
||||
shader = 6; // fog shader
|
||||
shader = SHADER_FOG; // fog shader
|
||||
else if (PolyFlags & PF_Ripple)
|
||||
shader = 5; // water shader
|
||||
shader = SHADER_WATER; // water shader
|
||||
else
|
||||
shader = 1; // floor shader
|
||||
shader = SHADER_FLOOR; // floor shader
|
||||
|
||||
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
|
||||
|
||||
|
@ -766,7 +766,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
|
|||
break;
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(2); // wall shader
|
||||
HWD.pfnSetShader(SHADER_WALL); // wall shader
|
||||
HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal);
|
||||
}
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL
|
|||
{
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
||||
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader
|
||||
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, SHADER_WALL, false); // wall shader
|
||||
|
||||
#ifdef WALLSPLATS
|
||||
if (gl_curline->linedef->splats && cv_splats.value)
|
||||
|
@ -2843,7 +2843,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
|
|||
else
|
||||
blendmode |= PF_Masked|PF_Modulated|PF_Clip;
|
||||
|
||||
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader
|
||||
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, SHADER_FLOOR, false); // floor shader
|
||||
}
|
||||
|
||||
static void HWR_AddPolyObjectPlanes(void)
|
||||
|
@ -3655,7 +3655,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
HWR_Lighting(&sSurf, 0, colormap);
|
||||
sSurf.PolyColor.s.alpha = alpha;
|
||||
|
||||
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
|
||||
}
|
||||
|
||||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||
|
@ -3929,7 +3929,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
|
||||
Surf.PolyColor.s.alpha = alpha;
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
|
||||
|
||||
if (use_linkdraw_hack)
|
||||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
|
@ -3958,7 +3958,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
|
||||
Surf.PolyColor.s.alpha = alpha;
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
|
||||
|
||||
if (use_linkdraw_hack)
|
||||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
|
@ -4118,7 +4118,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
if (!occlusion) use_linkdraw_hack = true;
|
||||
}
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
|
||||
|
||||
if (use_linkdraw_hack)
|
||||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
|
@ -4220,7 +4220,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
|
|||
blend = PF_Translucent|PF_Occlude;
|
||||
}
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4563,7 +4563,7 @@ static void HWR_CreateDrawNodes(void)
|
|||
|
||||
// Okay! Let's draw it all! Woo!
|
||||
HWD.pfnSetTransform(&atransform);
|
||||
HWD.pfnSetShader(0);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
|
||||
for (i = 0; i < p; i++)
|
||||
{
|
||||
|
@ -5383,7 +5383,7 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWR_BuildSkyDome();
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(7); // sky shader
|
||||
HWD.pfnSetShader(SHADER_SKY); // sky shader
|
||||
HWD.pfnSetTransform(&dometransform);
|
||||
HWD.pfnRenderSkyDome(&gl_sky);
|
||||
}
|
||||
|
@ -5470,7 +5470,7 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(0);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5674,7 +5674,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
|
|||
|
||||
// Reset the shader state.
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value);
|
||||
HWD.pfnSetShader(0);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
|
||||
validcount++;
|
||||
|
||||
|
@ -5887,7 +5887,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
|
|||
|
||||
// Reset the shader state.
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value);
|
||||
HWD.pfnSetShader(0);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
|
||||
rs_numbspcalls = 0;
|
||||
rs_numpolyobjects = 0;
|
||||
|
@ -6090,7 +6090,6 @@ void HWR_Startup(void)
|
|||
// do this once
|
||||
if (!startupdone)
|
||||
{
|
||||
INT32 i;
|
||||
CONS_Printf("HWR_Startup()...\n");
|
||||
|
||||
HWR_InitPolyPool();
|
||||
|
@ -6101,10 +6100,8 @@ void HWR_Startup(void)
|
|||
HWR_InitLight();
|
||||
#endif
|
||||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_ReadShaders(i, (wadfiles[i]->type == RET_PK3));
|
||||
if (!HWR_LoadShaders())
|
||||
HWR_LoadAllCustomShaders();
|
||||
if (!HWR_CompileShaders())
|
||||
gl_shadersavailable = false;
|
||||
}
|
||||
|
||||
|
@ -6196,7 +6193,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
|||
|
||||
pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting
|
||||
|
||||
shader = 2; // wall shader
|
||||
shader = SHADER_WALL; // wall shader
|
||||
|
||||
if (blend & PF_Environment)
|
||||
blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects
|
||||
|
@ -6204,7 +6201,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
|||
if (fogwall)
|
||||
{
|
||||
blendmode |= PF_Fog;
|
||||
shader = 6; // fog shader
|
||||
shader = SHADER_FOG; // fog shader
|
||||
}
|
||||
|
||||
blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency
|
||||
|
@ -6389,13 +6386,7 @@ void HWR_DrawScreenFinalTexture(int width, int height)
|
|||
}
|
||||
|
||||
// jimita 18032019
|
||||
typedef struct
|
||||
{
|
||||
char type[16];
|
||||
INT32 id;
|
||||
} shaderxlat_t;
|
||||
|
||||
static inline UINT16 HWR_CheckShader(UINT16 wadnum)
|
||||
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
|
||||
{
|
||||
UINT16 i;
|
||||
lumpinfo_t *lump_p;
|
||||
|
@ -6408,12 +6399,34 @@ static inline UINT16 HWR_CheckShader(UINT16 wadnum)
|
|||
return INT16_MAX;
|
||||
}
|
||||
|
||||
boolean HWR_LoadShaders(void)
|
||||
boolean HWR_CompileShaders(void)
|
||||
{
|
||||
return HWD.pfnInitCustomShaders();
|
||||
return HWD.pfnCompileShaders();
|
||||
}
|
||||
|
||||
void HWR_ReadShaders(UINT16 wadnum, boolean PK3)
|
||||
customshaderxlat_t shaderxlat[] =
|
||||
{
|
||||
{"Flat", SHADER_FLOOR},
|
||||
{"WallTexture", SHADER_WALL},
|
||||
{"Sprite", SHADER_SPRITE},
|
||||
{"Model", SHADER_MODEL},
|
||||
{"ModelLighting", SHADER_MODEL_LIGHTING},
|
||||
{"WaterRipple", SHADER_WATER},
|
||||
{"Fog", SHADER_FOG},
|
||||
{"Sky", SHADER_SKY},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
void HWR_LoadAllCustomShaders(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3));
|
||||
}
|
||||
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
|
||||
{
|
||||
UINT16 lump;
|
||||
char *shaderdef, *line;
|
||||
|
@ -6424,19 +6437,7 @@ void HWR_ReadShaders(UINT16 wadnum, boolean PK3)
|
|||
int shadertype = 0;
|
||||
int i;
|
||||
|
||||
#define SHADER_TYPES 7
|
||||
shaderxlat_t shaderxlat[SHADER_TYPES] =
|
||||
{
|
||||
{"Flat", 1},
|
||||
{"WallTexture", 2},
|
||||
{"Sprite", 3},
|
||||
{"Model", 4},
|
||||
{"WaterRipple", 5},
|
||||
{"Fog", 6},
|
||||
{"Sky", 7},
|
||||
};
|
||||
|
||||
lump = HWR_CheckShader(wadnum);
|
||||
lump = HWR_FindShaderDefs(wadnum);
|
||||
if (lump == INT16_MAX)
|
||||
return;
|
||||
|
||||
|
@ -6462,7 +6463,7 @@ void HWR_ReadShaders(UINT16 wadnum, boolean PK3)
|
|||
value = strtok(NULL, "\r\n ");
|
||||
if (!value)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto skip_lump;
|
||||
}
|
||||
|
@ -6481,19 +6482,19 @@ skip_lump:
|
|||
value = strtok(NULL, "\r\n= ");
|
||||
if (!value)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!shadertype)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < SHADER_TYPES; i++)
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (!stricmp(shaderxlat[i].type, stoken))
|
||||
{
|
||||
|
@ -6519,7 +6520,7 @@ skip_lump:
|
|||
|
||||
if (shader_lumpnum == INT16_MAX)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(shader_lumpname);
|
||||
continue;
|
||||
}
|
||||
|
@ -6545,4 +6546,22 @@ skip_field:
|
|||
return;
|
||||
}
|
||||
|
||||
const char *HWR_GetShaderName(INT32 shader)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (shader)
|
||||
{
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (shaderxlat[i].id == shader)
|
||||
return shaderxlat[i].type;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
return "Default";
|
||||
}
|
||||
|
||||
#endif // HWRENDER
|
||||
|
|
|
@ -70,8 +70,13 @@ void HWR_DrawScreenFinalTexture(int width, int height);
|
|||
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
|
||||
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
|
||||
|
||||
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
|
||||
boolean HWR_LoadShaders(void);
|
||||
boolean HWR_CompileShaders(void);
|
||||
|
||||
void HWR_LoadAllCustomShaders(void);
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
|
||||
const char *HWR_GetShaderName(INT32 shader);
|
||||
|
||||
extern customshaderxlat_t shaderxlat[];
|
||||
|
||||
extern CV_PossibleValue_t granisotropicmode_cons_t[];
|
||||
|
||||
|
|
|
@ -1572,7 +1572,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.mirror = atransform.mirror; // from Kart
|
||||
#endif
|
||||
|
||||
HWD.pfnSetShader(4); // model shader
|
||||
HWD.pfnSetShader(SHADER_MODEL); // model shader
|
||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,9 +91,10 @@ static GLuint startScreenWipe = 0;
|
|||
static GLuint endScreenWipe = 0;
|
||||
static GLuint finalScreenTexture = 0;
|
||||
|
||||
// Lactozilla: Set shader programs and uniforms
|
||||
// Lactozilla: Shader functions
|
||||
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
|
||||
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
|
||||
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
|
||||
|
||||
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
|
@ -578,15 +579,12 @@ static PFNglUniform2fv pglUniform2fv;
|
|||
static PFNglUniform3fv pglUniform3fv;
|
||||
static PFNglGetUniformLocation pglGetUniformLocation;
|
||||
|
||||
#define MAXSHADERS 16
|
||||
#define MAXSHADERPROGRAMS 16
|
||||
|
||||
// 18032019
|
||||
static char *gl_customvertexshaders[MAXSHADERS];
|
||||
static char *gl_customfragmentshaders[MAXSHADERS];
|
||||
static GLuint gl_currentshaderprogram = 0;
|
||||
static boolean gl_shaderprogramchanged = true;
|
||||
|
||||
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
|
||||
|
||||
// 13062019
|
||||
typedef enum
|
||||
{
|
||||
|
@ -610,17 +608,59 @@ typedef struct gl_shaderprogram_s
|
|||
boolean custom;
|
||||
GLint uniforms[gluniform_max+1];
|
||||
} gl_shaderprogram_t;
|
||||
static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS];
|
||||
static gl_shaderprogram_t gl_shaderprograms[HWR_MAXSHADERS];
|
||||
|
||||
// Shader info
|
||||
static INT32 shader_leveltime = 0;
|
||||
|
||||
// ========================
|
||||
// Fragment shader macros
|
||||
// ========================
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// GLSL Software fragment shader
|
||||
// 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 \
|
||||
|
@ -761,22 +801,10 @@ static INT32 shader_leveltime = 0;
|
|||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// GLSL 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"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
|
@ -784,97 +812,42 @@ static INT32 shader_leveltime = 0;
|
|||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
static const char *fragment_shaders[] = {
|
||||
// Default fragment shader
|
||||
GLSL_DEFAULT_FRAGMENT_SHADER,
|
||||
// ================
|
||||
// Shader sources
|
||||
// ================
|
||||
|
||||
// Floor fragment shader
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER,
|
||||
static struct {
|
||||
const char *vertex;
|
||||
const char *fragment;
|
||||
} const gl_shadersources[] = {
|
||||
// Default shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER},
|
||||
|
||||
// Wall fragment shader
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER,
|
||||
// Floor shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Sprite fragment shader
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER,
|
||||
// Wall shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Model fragment shader
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER,
|
||||
// Sprite shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Water fragment shader
|
||||
GLSL_WATER_FRAGMENT_SHADER,
|
||||
// Model shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Fog fragment shader
|
||||
GLSL_FOG_FRAGMENT_SHADER,
|
||||
// Model shader + diffuse lighting from above
|
||||
{GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER},
|
||||
|
||||
// Sky fragment shader
|
||||
GLSL_SKY_FRAGMENT_SHADER,
|
||||
// Water shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
|
||||
|
||||
// Model fragment shader + diffuse lighting from above
|
||||
GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER,
|
||||
// Fog shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
|
||||
|
||||
NULL,
|
||||
};
|
||||
// Sky shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
|
||||
|
||||
// ======================
|
||||
// Vertex shader macros
|
||||
// ======================
|
||||
|
||||
//
|
||||
// GLSL 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"
|
||||
|
||||
static const char *vertex_shaders[] = {
|
||||
// Default vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Floor vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Wall vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Sprite vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Model vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Water vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Fog vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Sky vertex shader
|
||||
GLSL_DEFAULT_VERTEX_SHADER,
|
||||
|
||||
// Model vertex shader + diffuse lighting from above
|
||||
GLSL_MODEL_LIGHTING_VERTEX_SHADER,
|
||||
|
||||
NULL,
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
#endif // GL_SHADERS
|
||||
|
@ -920,7 +893,7 @@ void SetupGLFunc4(void)
|
|||
}
|
||||
|
||||
// jimita
|
||||
EXPORT boolean HWRAPI(LoadShaders) (void)
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
GLuint gl_vertShader, gl_fragShader;
|
||||
|
@ -928,25 +901,23 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
|
||||
if (!pglUseProgram) return false;
|
||||
|
||||
gl_customvertexshaders[0] = NULL;
|
||||
gl_customfragmentshaders[0] = NULL;
|
||||
gl_customshaders[0].vertex = NULL;
|
||||
gl_customshaders[0].fragment = NULL;
|
||||
|
||||
for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++)
|
||||
for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++)
|
||||
{
|
||||
gl_shaderprogram_t *shader;
|
||||
const GLchar* vert_shader = vertex_shaders[i];
|
||||
const GLchar* frag_shader = fragment_shaders[i];
|
||||
boolean custom = ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0));
|
||||
const GLchar *vert_shader = gl_shadersources[i].vertex;
|
||||
const GLchar *frag_shader = gl_shadersources[i].fragment;
|
||||
boolean custom = ((gl_customshaders[i].vertex || gl_customshaders[i].fragment) && (i > 0));
|
||||
|
||||
// 18032019
|
||||
if (gl_customvertexshaders[i])
|
||||
vert_shader = gl_customvertexshaders[i];
|
||||
if (gl_customfragmentshaders[i])
|
||||
frag_shader = gl_customfragmentshaders[i];
|
||||
if (gl_customshaders[i].vertex)
|
||||
vert_shader = gl_customshaders[i].vertex;
|
||||
if (gl_customshaders[i].fragment)
|
||||
frag_shader = gl_customshaders[i].fragment;
|
||||
|
||||
if (i >= MAXSHADERS)
|
||||
break;
|
||||
if (i >= MAXSHADERPROGRAMS)
|
||||
if (i >= HWR_MAXSHADERS)
|
||||
break;
|
||||
|
||||
shader = &gl_shaderprograms[i];
|
||||
|
@ -959,7 +930,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
|
||||
if (!gl_vertShader)
|
||||
{
|
||||
GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i);
|
||||
GL_MSG_Error("CompileShaders: Error creating vertex shader %s\n", HWR_GetShaderName(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -970,15 +941,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
GLchar* infoLog;
|
||||
GLint logLength;
|
||||
|
||||
pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
|
||||
infoLog = malloc(logLength);
|
||||
pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog);
|
||||
|
||||
GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog);
|
||||
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -988,7 +951,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!gl_fragShader)
|
||||
{
|
||||
GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i);
|
||||
GL_MSG_Error("CompileShaders: Error creating fragment shader %s\n", HWR_GetShaderName(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -999,15 +962,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
GLchar* infoLog;
|
||||
GLint logLength;
|
||||
|
||||
pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
|
||||
infoLog = malloc(logLength);
|
||||
pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog);
|
||||
|
||||
GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog);
|
||||
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1028,7 +983,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
{
|
||||
shader->program = 0;
|
||||
shader->custom = false;
|
||||
GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i);
|
||||
GL_MSG_Error("CompileShaders: Error linking shader program %s\n", HWR_GetShaderName(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1048,8 +1003,10 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
|
|||
|
||||
#undef GETUNI
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1077,25 +1034,34 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value)
|
|||
//
|
||||
// Custom shader loading
|
||||
//
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment)
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (!pglUseProgram) return;
|
||||
if (number < 1 || number > MAXSHADERS)
|
||||
I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS);
|
||||
shadersource_t *shader;
|
||||
|
||||
if (fragment)
|
||||
{
|
||||
gl_customfragmentshaders[number] = malloc(size+1);
|
||||
strncpy(gl_customfragmentshaders[number], shader, size);
|
||||
gl_customfragmentshaders[number][size] = 0;
|
||||
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 = &gl_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
|
||||
{
|
||||
gl_customvertexshaders[number] = malloc(size+1);
|
||||
strncpy(gl_customvertexshaders[number], shader, size);
|
||||
gl_customvertexshaders[number][size] = 0;
|
||||
}
|
||||
COPYSHADER(vertex)
|
||||
|
||||
#else
|
||||
(void)number;
|
||||
(void)shader;
|
||||
|
@ -1104,14 +1070,6 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boo
|
|||
#endif
|
||||
}
|
||||
|
||||
EXPORT boolean HWRAPI(InitCustomShaders) (void)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
KillShaders();
|
||||
return LoadShaders();
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(SetShader) (int shader)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
|
@ -1119,9 +1077,9 @@ EXPORT void HWRAPI(SetShader) (int shader)
|
|||
{
|
||||
// If using model lighting, set the appropriate shader.
|
||||
// However don't override a custom shader.
|
||||
// Should use an enum or something...
|
||||
if (shader == 4 && model_lighting && !gl_shaderprograms[4].custom)
|
||||
shader = 8;
|
||||
if (shader == SHADER_MODEL && model_lighting
|
||||
&& !(gl_shaderprograms[SHADER_MODEL].custom && !gl_shaderprograms[SHADER_MODEL_LIGHTING].custom))
|
||||
shader = SHADER_MODEL_LIGHTING;
|
||||
if ((GLuint)shader != gl_currentshaderprogram)
|
||||
{
|
||||
gl_currentshaderprogram = shader;
|
||||
|
@ -1146,9 +1104,23 @@ EXPORT void HWRAPI(UnSetShader) (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(KillShaders) (void)
|
||||
EXPORT void HWRAPI(CleanShaders) (void)
|
||||
{
|
||||
// unused.........................
|
||||
INT32 i;
|
||||
|
||||
for (i = 1; i < HWR_MAXSHADERS; i++)
|
||||
{
|
||||
shadersource_t *shader = &gl_customshaders[i];
|
||||
|
||||
if (shader->vertex)
|
||||
free(shader->vertex);
|
||||
|
||||
if (shader->fragment)
|
||||
free(shader->fragment);
|
||||
|
||||
shader->vertex = NULL;
|
||||
shader->fragment = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
|
@ -2017,6 +1989,25 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
|
|||
#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);
|
||||
}
|
||||
|
||||
GL_MSG_Error("CompileShaders: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : ""));
|
||||
|
||||
if (infoLog)
|
||||
free(infoLog);
|
||||
}
|
||||
|
||||
// code that is common between DrawPolygon and DrawIndexedTriangles
|
||||
// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching
|
||||
static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags)
|
||||
|
|
|
@ -104,14 +104,13 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(MakeScreenFinalTexture);
|
||||
GETFUNC(DrawScreenFinalTexture);
|
||||
|
||||
GETFUNC(LoadShaders);
|
||||
GETFUNC(KillShaders);
|
||||
GETFUNC(CompileShaders);
|
||||
GETFUNC(CleanShaders);
|
||||
GETFUNC(SetShader);
|
||||
GETFUNC(UnSetShader);
|
||||
|
||||
GETFUNC(SetShaderInfo);
|
||||
GETFUNC(LoadCustomShader);
|
||||
GETFUNC(InitCustomShaders);
|
||||
|
||||
#else //HWRENDER
|
||||
if (0 == strcmp("FinishUpdate", funcName))
|
||||
|
|
|
@ -1660,7 +1660,7 @@ static void Impl_SetWindowName(const char *title)
|
|||
static void Impl_SetWindowIcon(void)
|
||||
{
|
||||
if (window && icoSurface)
|
||||
SDL_SetWindowIcon(window, icoSurface);
|
||||
SDL_SetWindowIcon(window, icoSurface);
|
||||
}
|
||||
|
||||
static void Impl_VideoSetupSDLBuffer(void)
|
||||
|
@ -1770,7 +1770,7 @@ void I_StartupGraphics(void)
|
|||
// Window icon
|
||||
#ifdef HAVE_IMAGE
|
||||
icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Fury: we do window initialization after GL setup to allow
|
||||
// SDL_GL_LoadLibrary to work well on Windows
|
||||
|
@ -1855,14 +1855,13 @@ void VID_StartupOpenGL(void)
|
|||
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
|
||||
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
|
||||
|
||||
HWD.pfnLoadShaders = hwSym("LoadShaders",NULL);
|
||||
HWD.pfnKillShaders = hwSym("KillShaders",NULL);
|
||||
HWD.pfnCompileShaders = hwSym("CompileShaders",NULL);
|
||||
HWD.pfnCleanShaders = hwSym("CleanShaders",NULL);
|
||||
HWD.pfnSetShader = hwSym("SetShader",NULL);
|
||||
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
|
||||
|
||||
HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
|
||||
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
|
||||
HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL);
|
||||
|
||||
vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library
|
||||
|
||||
|
|
|
@ -849,8 +849,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
// Read shaders from file
|
||||
if (rendermode == render_opengl && (vid_opengl_state == 1))
|
||||
{
|
||||
HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_LoadShaders();
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#endif // HWRENDER
|
||||
|
||||
|
|
Loading…
Reference in a new issue