mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-28 23:21:58 +00:00
OpenGL shader code rearrangement and shader pre-preprocessor
This commit is contained in:
parent
8b021ec16b
commit
de37df1be0
17 changed files with 980 additions and 633 deletions
|
@ -508,6 +508,7 @@ if(${SRB2_CONFIG_HWRENDER})
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_shaders.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c
|
||||
)
|
||||
|
||||
|
|
|
@ -288,7 +288,8 @@ else
|
|||
OPTS+=-DHWRENDER
|
||||
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
|
||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o \
|
||||
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
|
||||
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o \
|
||||
$(OBJDIR)/hw_shaders.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
|
||||
endif
|
||||
|
||||
OPTS += -DCOMPVERSION
|
||||
|
|
|
@ -76,7 +76,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
|
|||
// If batching is enabled, this function collects the polygon data and the chosen texture
|
||||
// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to
|
||||
// render the polygon immediately.
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial)
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial)
|
||||
{
|
||||
if (currently_batching)
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
|||
polygonArray[polygonArraySize].numVerts = iNumPts;
|
||||
polygonArray[polygonArraySize].polyFlags = PolyFlags;
|
||||
polygonArray[polygonArraySize].texture = current_texture;
|
||||
polygonArray[polygonArraySize].shader = shader;
|
||||
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||
polygonArraySize++;
|
||||
|
||||
|
@ -123,8 +123,8 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
|||
}
|
||||
else
|
||||
{
|
||||
if (shader)
|
||||
HWD.pfnSetShader(shader);
|
||||
if (shader_target != -1)
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(shader_target));
|
||||
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,32 +133,26 @@ typedef struct
|
|||
} FOutVector;
|
||||
|
||||
#ifdef GL_SHADERS
|
||||
// Predefined shader types
|
||||
|
||||
// Shader targets used to render specific types of geometry.
|
||||
// A shader target is resolved to an actual shader with HWR_GetShaderFromTarget.
|
||||
// The shader returned may be a base shader or a custom shader.
|
||||
enum
|
||||
{
|
||||
SHADER_DEFAULT = 0,
|
||||
|
||||
SHADER_FLOOR,
|
||||
SHADER_WALL,
|
||||
SHADER_SPRITE,
|
||||
SHADER_MODEL, SHADER_MODEL_LIGHTING,
|
||||
SHADER_MODEL,
|
||||
SHADER_WATER,
|
||||
SHADER_FOG,
|
||||
SHADER_SKY,
|
||||
|
||||
NUMBASESHADERS,
|
||||
NUMSHADERTARGETS,
|
||||
};
|
||||
|
||||
// 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;
|
||||
// Must be at least NUMSHADERTARGETS*2 to fit base and custom shaders for each shader target.
|
||||
#define HWR_MAXSHADERS NUMSHADERTARGETS*2
|
||||
|
||||
// Custom shader reference table
|
||||
typedef struct
|
||||
|
@ -300,6 +294,14 @@ enum hwdsetspecialstate
|
|||
|
||||
typedef enum hwdsetspecialstate hwdspecialstate_t;
|
||||
|
||||
enum hwdshaderstage
|
||||
{
|
||||
HWD_SHADERSTAGE_VERTEX,
|
||||
HWD_SHADERSTAGE_FRAGMENT,
|
||||
};
|
||||
|
||||
typedef enum hwdshaderstage hwdshaderstage_t;
|
||||
|
||||
// Lactozilla: Shader options
|
||||
enum hwdshaderoption
|
||||
{
|
||||
|
|
|
@ -68,13 +68,13 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
|
|||
#define SCREENVERTS 10
|
||||
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
|
||||
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void);
|
||||
EXPORT void HWRAPI(CleanShaders) (void);
|
||||
EXPORT void HWRAPI(SetShader) (int type);
|
||||
EXPORT boolean HWRAPI(InitShaders) (void);
|
||||
EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage);
|
||||
EXPORT boolean HWRAPI(CompileShader) (int slot);
|
||||
EXPORT void HWRAPI(SetShader) (int slot);
|
||||
EXPORT void HWRAPI(UnSetShader) (void);
|
||||
|
||||
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment);
|
||||
|
||||
// ==========================================================================
|
||||
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
|
||||
|
@ -120,13 +120,13 @@ struct hwdriver_s
|
|||
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
|
||||
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
|
||||
|
||||
CompileShaders pfnCompileShaders;
|
||||
CleanShaders pfnCleanShaders;
|
||||
InitShaders pfnInitShaders;
|
||||
LoadShader pfnLoadShader;
|
||||
CompileShader pfnCompileShader;
|
||||
SetShader pfnSetShader;
|
||||
UnSetShader pfnUnSetShader;
|
||||
|
||||
SetShaderInfo pfnSetShaderInfo;
|
||||
LoadCustomShader pfnLoadCustomShader;
|
||||
};
|
||||
|
||||
extern struct hwdriver_s hwdriver;
|
||||
|
|
|
@ -136,4 +136,18 @@ void HWR_SetPalette(RGBA_t *palette);
|
|||
extern INT32 patchformat;
|
||||
extern INT32 textureformat;
|
||||
|
||||
// --------
|
||||
// hw_shaders.c
|
||||
// --------
|
||||
boolean HWR_InitShaders(void);
|
||||
void HWR_CompileShaders(void);
|
||||
|
||||
int HWR_GetShaderFromTarget(int shader_target);
|
||||
|
||||
void HWR_LoadAllCustomShaders(void);
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
|
||||
const char *HWR_GetShaderName(INT32 shader);
|
||||
|
||||
extern customshaderxlat_t shaderxlat[];
|
||||
|
||||
#endif //_HW_GLOB_
|
||||
|
|
|
@ -167,13 +167,15 @@ precise_t ps_hw_batchdrawtime = 0;
|
|||
boolean gl_init = false;
|
||||
boolean gl_maploaded = false;
|
||||
boolean gl_sessioncommandsadded = false;
|
||||
boolean gl_shadersavailable = true;
|
||||
// false if shaders have not been initialized yet, or if shaders are not available
|
||||
boolean gl_shadersavailable = false;
|
||||
|
||||
// ==========================================================================
|
||||
// Lighting
|
||||
// ==========================================================================
|
||||
|
||||
static boolean HWR_UseShader(void)
|
||||
// Returns true if shaders can be used.
|
||||
boolean HWR_UseShader(void)
|
||||
{
|
||||
return (cv_glshaders.value && gl_shadersavailable);
|
||||
}
|
||||
|
@ -376,7 +378,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
|||
static FOutVector *planeVerts = NULL;
|
||||
static UINT16 numAllocedPlaneVerts = 0;
|
||||
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
|
||||
// no convex poly were generated for this subsector
|
||||
if (!xsub->planepoly)
|
||||
|
@ -798,7 +800,7 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I
|
|||
//
|
||||
static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
|
||||
{
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
||||
|
@ -2687,7 +2689,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
|
|||
{
|
||||
FSurfaceInfo Surf;
|
||||
FOutVector *v3d;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
|
||||
size_t nrPlaneVerts = polysector->numVertices;
|
||||
INT32 i;
|
||||
|
@ -3598,7 +3600,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
float fscale; float fx; float fy; float offset;
|
||||
extracolormap_t *colormap = NULL;
|
||||
FBITFIELD blendmode = PF_Translucent|PF_Modulated;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
UINT8 i;
|
||||
SINT8 flip = P_MobjFlip(thing);
|
||||
|
||||
|
@ -3745,7 +3747,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
boolean lightset = true;
|
||||
FBITFIELD blend = 0;
|
||||
FBITFIELD occlusion;
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
boolean use_linkdraw_hack = false;
|
||||
UINT8 alpha;
|
||||
|
||||
|
@ -4259,7 +4261,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
}
|
||||
|
||||
{
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
FBITFIELD blend = 0;
|
||||
FBITFIELD occlusion;
|
||||
boolean use_linkdraw_hack = false;
|
||||
|
@ -4327,7 +4329,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
// Sprite drawer for precipitation
|
||||
static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
|
||||
{
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
FBITFIELD blend = 0;
|
||||
FOutVector wallVerts[4];
|
||||
patch_t *gpatch;
|
||||
|
@ -4765,7 +4767,6 @@ static void HWR_CreateDrawNodes(void)
|
|||
|
||||
// Okay! Let's draw it all! Woo!
|
||||
HWD.pfnSetTransform(&atransform);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
|
||||
for (i = 0; i < p; i++)
|
||||
{
|
||||
|
@ -5674,7 +5675,8 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWR_BuildSkyDome();
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(SHADER_SKY); // sky shader
|
||||
if (HWR_UseShader())
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_SKY));
|
||||
HWD.pfnSetTransform(&dometransform);
|
||||
HWD.pfnRenderSkyDome(&gl_sky);
|
||||
}
|
||||
|
@ -5760,8 +5762,6 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWD.pfnUnSetShader();
|
||||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5851,13 +5851,7 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean
|
|||
//
|
||||
static void HWR_SetShaderState(void)
|
||||
{
|
||||
hwdshaderoption_t state = cv_glshaders.value;
|
||||
|
||||
if (!cv_glallowshaders.value)
|
||||
state = (cv_glshaders.value == HWD_SHADEROPTION_ON ? HWD_SHADEROPTION_NOCUSTOM : cv_glshaders.value);
|
||||
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader());
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
@ -6303,13 +6297,14 @@ void HWR_LoadLevel(void)
|
|||
// 3D ENGINE COMMANDS
|
||||
// ==========================================================================
|
||||
|
||||
static CV_PossibleValue_t glshaders_cons_t[] = {{HWD_SHADEROPTION_OFF, "Off"}, {HWD_SHADEROPTION_ON, "On"}, {HWD_SHADEROPTION_NOCUSTOM, "Ignore custom shaders"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
|
||||
|
||||
static void CV_glfiltermode_OnChange(void);
|
||||
static void CV_glanisotropic_OnChange(void);
|
||||
static void CV_glmodellighting_OnChange(void);
|
||||
|
||||
static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
|
||||
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
|
||||
|
@ -6332,7 +6327,7 @@ consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0
|
|||
|
||||
consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL);
|
||||
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glmodellighting_OnChange);
|
||||
|
||||
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL);
|
||||
consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
@ -6359,6 +6354,13 @@ static void CV_glanisotropic_OnChange(void)
|
|||
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value);
|
||||
}
|
||||
|
||||
static void CV_glmodellighting_OnChange(void)
|
||||
{
|
||||
// if shaders have been compiled, then they now need to be recompiled.
|
||||
if (gl_shadersavailable)
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
|
||||
//added by Hurdler: console varibale that are saved
|
||||
void HWR_AddCommands(void)
|
||||
{
|
||||
|
@ -6417,9 +6419,8 @@ void HWR_Startup(void)
|
|||
HWR_InitLight();
|
||||
#endif
|
||||
|
||||
gl_shadersavailable = HWR_InitShaders();
|
||||
HWR_LoadAllCustomShaders();
|
||||
if (!HWR_CompileShaders())
|
||||
gl_shadersavailable = false;
|
||||
}
|
||||
|
||||
if (rendermode == render_opengl)
|
||||
|
@ -6518,7 +6519,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
|
|||
FBITFIELD blendmode = blend;
|
||||
UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha
|
||||
|
||||
INT32 shader = SHADER_DEFAULT;
|
||||
INT32 shader = -1;
|
||||
|
||||
// Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting
|
||||
HWR_Lighting(pSurf, lightlevel, wallcolormap);
|
||||
|
@ -6716,182 +6717,4 @@ void HWR_DrawScreenFinalTexture(int width, int height)
|
|||
HWD.pfnDrawScreenFinalTexture(width, height);
|
||||
}
|
||||
|
||||
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
|
||||
{
|
||||
UINT16 i;
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
lump_p = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++)
|
||||
if (memcmp(lump_p->name, "SHADERS", 7) == 0)
|
||||
return i;
|
||||
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
boolean HWR_CompileShaders(void)
|
||||
{
|
||||
return HWD.pfnCompileShaders();
|
||||
}
|
||||
|
||||
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;
|
||||
char *stoken;
|
||||
char *value;
|
||||
size_t size;
|
||||
int linenum = 1;
|
||||
int shadertype = 0;
|
||||
int i;
|
||||
|
||||
lump = HWR_FindShaderDefs(wadnum);
|
||||
if (lump == INT16_MAX)
|
||||
return;
|
||||
|
||||
shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
||||
size = W_LumpLengthPwad(wadnum, lump);
|
||||
|
||||
line = Z_Malloc(size+1, PU_STATIC, NULL);
|
||||
M_Memcpy(line, shaderdef, size);
|
||||
line[size] = '\0';
|
||||
|
||||
stoken = strtok(line, "\r\n ");
|
||||
while (stoken)
|
||||
{
|
||||
if ((stoken[0] == '/' && stoken[1] == '/')
|
||||
|| (stoken[0] == '#'))// skip comments
|
||||
{
|
||||
stoken = strtok(NULL, "\r\n");
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!stricmp(stoken, "GLSL"))
|
||||
{
|
||||
value = strtok(NULL, "\r\n ");
|
||||
if (!value)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (!stricmp(value, "VERTEX"))
|
||||
shadertype = 1;
|
||||
else if (!stricmp(value, "FRAGMENT"))
|
||||
shadertype = 2;
|
||||
|
||||
skip_lump:
|
||||
stoken = strtok(NULL, "\r\n ");
|
||||
linenum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = strtok(NULL, "\r\n= ");
|
||||
if (!value)
|
||||
{
|
||||
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_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (!stricmp(shaderxlat[i].type, stoken))
|
||||
{
|
||||
size_t shader_size;
|
||||
char *shader_source;
|
||||
char *shader_lumpname;
|
||||
UINT16 shader_lumpnum;
|
||||
|
||||
if (PK3)
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "Shaders/sh_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "SH_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
|
||||
if (shader_lumpnum == INT16_MAX)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum);
|
||||
shader_source = Z_Malloc(shader_size, PU_STATIC, NULL);
|
||||
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
|
||||
|
||||
HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2));
|
||||
|
||||
Z_Free(shader_source);
|
||||
Z_Free(shader_lumpname);
|
||||
}
|
||||
}
|
||||
|
||||
skip_field:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
linenum++;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(line);
|
||||
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
|
||||
|
|
|
@ -65,6 +65,7 @@ void HWR_MakeScreenFinalTexture(void);
|
|||
void HWR_DrawScreenFinalTexture(int width, int height);
|
||||
|
||||
// This stuff is put here so models can use them
|
||||
boolean HWR_UseShader(void);
|
||||
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
|
||||
|
||||
|
@ -73,14 +74,6 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
|
|||
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
|
||||
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 glanisotropicmode_cons_t[];
|
||||
|
||||
#ifdef ALAM_LIGHTING
|
||||
|
|
|
@ -1644,7 +1644,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.mirror = atransform.mirror; // from Kart
|
||||
#endif
|
||||
|
||||
HWD.pfnSetShader(SHADER_MODEL); // model shader
|
||||
if (HWR_UseShader())
|
||||
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_MODEL));
|
||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
|
||||
}
|
||||
|
||||
|
|
756
src/hardware/hw_shaders.c
Normal file
756
src/hardware/hw_shaders.c
Normal file
|
@ -0,0 +1,756 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hw_shaders.h
|
||||
/// \brief Handles the shaders used by the game.
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "hw_drv.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// 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_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"#ifdef MODEL_LIGHTING\n" \
|
||||
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
|
||||
"float light = 0.75 + max(nDotVP, 0.0);\n" \
|
||||
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
|
||||
"#else\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// ==================
|
||||
// Fragment shaders
|
||||
// ==================
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_DOOM_COLORMAP \
|
||||
"float R_DoomColormap(float light, float z)\n" \
|
||||
"{\n" \
|
||||
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
|
||||
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
|
||||
"float startmap = (15.0 - lightnum) * 4.0;\n" \
|
||||
"float scale = 160.0 / (lightz + 1.0);\n" \
|
||||
"return startmap - scale * 0.5;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_DOOM_LIGHT_EQUATION \
|
||||
"float R_DoomLightingEquation(float light)\n" \
|
||||
"{\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
|
||||
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_TINT_EQUATION \
|
||||
"if (tint_color.a > 0.0) {\n" \
|
||||
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
|
||||
"float strength = sqrt(9.0 * tint_color.a);\n" \
|
||||
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color)
|
||||
#define GLSL_SOFTWARE_MODEL_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"#ifdef MODEL_LIGHTING\n" \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Water surface shader
|
||||
//
|
||||
// Mostly guesstimated, rather than the rest being built off Software science.
|
||||
// Still needs to distort things underneath/around the water...
|
||||
//
|
||||
|
||||
#define GLSL_WATER_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
"const float freq = 0.025;\n" \
|
||||
"const float amp = 0.025;\n" \
|
||||
"const float speed = 2.0;\n" \
|
||||
"const float pi = 3.14159;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
|
||||
"float a = -pi * (z * freq) + (leveltime * speed);\n" \
|
||||
"float sdistort = sin(a) * amp;\n" \
|
||||
"float cdistort = cos(a) * amp;\n" \
|
||||
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Fog block shader
|
||||
//
|
||||
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
|
||||
//
|
||||
|
||||
#define GLSL_FOG_FRAGMENT_SHADER \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 base_color = gl_Color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// ================
|
||||
// Shader sources
|
||||
// ================
|
||||
|
||||
static struct {
|
||||
const char *vertex;
|
||||
const char *fragment;
|
||||
} const gl_shadersources[] = {
|
||||
// Floor shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Wall shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Sprite shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Model shader
|
||||
{GLSL_MODEL_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_FRAGMENT_SHADER},
|
||||
|
||||
// Water shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
|
||||
|
||||
// Fog shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
|
||||
|
||||
// Sky shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int base_shader; // index of base shader_t
|
||||
int custom_shader; // index of custom shader_t
|
||||
} shadertarget_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *vertex;
|
||||
char *fragment;
|
||||
boolean compiled;
|
||||
} shader_t; // these are in an array and accessed by indices
|
||||
|
||||
// the array has NUMSHADERTARGETS entries for base shaders and for custom shaders
|
||||
// the array could be expanded in the future to fit "dynamic" custom shaders that
|
||||
// aren't fixed to shader targets
|
||||
static shader_t gl_shaders[NUMSHADERTARGETS*2];
|
||||
|
||||
static shadertarget_t gl_shadertargets[NUMSHADERTARGETS];
|
||||
|
||||
#define MODEL_LIGHTING_DEFINE "#define MODEL_LIGHTING"
|
||||
|
||||
// Initialize shader variables and the backend's shader system. Load the base shaders.
|
||||
// Returns false if shaders cannot be used.
|
||||
boolean HWR_InitShaders(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!HWD.pfnInitShaders())
|
||||
return false;
|
||||
|
||||
for (i = 0; i < NUMSHADERTARGETS; i++)
|
||||
{
|
||||
// set up string pointers for base shaders
|
||||
gl_shaders[i].vertex = Z_StrDup(gl_shadersources[i].vertex);
|
||||
gl_shaders[i].fragment = Z_StrDup(gl_shadersources[i].fragment);
|
||||
// set shader target indices to correct values
|
||||
gl_shadertargets[i].base_shader = i;
|
||||
gl_shadertargets[i].custom_shader = -1;
|
||||
}
|
||||
|
||||
HWR_CompileShaders();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// helper function: strstr but returns an int with the substring position
|
||||
// returns INT32_MAX if not found
|
||||
static INT32 strstr_int(const char *str1, const char *str2)
|
||||
{
|
||||
char *location = strstr(str1, str2);
|
||||
if (location)
|
||||
return location - str1;
|
||||
else
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
// Creates a preprocessed copy of the shader according to the current graphics settings
|
||||
// Returns a pointer to the results on success and NULL on failure.
|
||||
// Remember memory management of the returned string.
|
||||
static char *HWR_PreprocessShader(char *original)
|
||||
{
|
||||
const char *line_ending = "\n";
|
||||
int line_ending_len;
|
||||
char *read_pos = original;
|
||||
int insertion_pos = 0;
|
||||
int original_len = strlen(original);
|
||||
int distance_to_end = original_len;
|
||||
int new_len;
|
||||
char *new_shader;
|
||||
char *write_pos;
|
||||
|
||||
if (strstr(original, "\r\n"))
|
||||
{
|
||||
line_ending = "\r\n";
|
||||
// check that all line endings are same,
|
||||
// otherwise the parsing code won't function correctly
|
||||
while ((read_pos = strchr(read_pos, '\n')))
|
||||
{
|
||||
read_pos--;
|
||||
if (*read_pos != '\r')
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Shader contains mixed line ending types. Please use either only LF (Unix) or only CRLF (Windows) line endings.\n");
|
||||
return NULL;
|
||||
}
|
||||
read_pos += 2;
|
||||
}
|
||||
read_pos = original;
|
||||
}
|
||||
|
||||
line_ending_len = strlen(line_ending);
|
||||
|
||||
// We need to find a place to put the #define commands.
|
||||
// To stay within GLSL specs, they must be *after* the #version define,
|
||||
// if there is any. So we need to look for that. And also let's not
|
||||
// get fooled if there is a #version inside a comment!
|
||||
// Time for some string parsing :D
|
||||
|
||||
#define STARTSWITH(str, with_what) !strncmp(str, with_what, sizeof(with_what)-1)
|
||||
#define ADVANCE(amount) read_pos += amount; distance_to_end -= amount;
|
||||
while (true)
|
||||
{
|
||||
// we're at the start of a line or at the end of a block comment.
|
||||
// first get any possible whitespace out of the way
|
||||
int whitespace_len = strspn(read_pos, " \t");
|
||||
if (whitespace_len == distance_to_end)
|
||||
break; // we got to the end
|
||||
ADVANCE(whitespace_len)
|
||||
|
||||
if (STARTSWITH(read_pos, "#version"))
|
||||
{
|
||||
// getting closer
|
||||
INT32 newline_pos = strstr_int(read_pos, line_ending);
|
||||
INT32 line_comment_pos = strstr_int(read_pos, "//");
|
||||
INT32 block_comment_pos = strstr_int(read_pos, "/*");
|
||||
if (newline_pos == INT32_MAX && line_comment_pos == INT32_MAX &&
|
||||
block_comment_pos == INT32_MAX)
|
||||
{
|
||||
// #version is at the end of the file. Probably not a valid shader.
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Shader unexpectedly ends after #version.\n");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// insert at the earliest occurence of newline or comment after #version
|
||||
insertion_pos = min(line_comment_pos, block_comment_pos);
|
||||
insertion_pos = min(newline_pos, insertion_pos);
|
||||
insertion_pos += read_pos - original;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// go to next newline or end of next block comment if it starts before the newline
|
||||
// and is not inside a line comment
|
||||
INT32 newline_pos = strstr_int(read_pos, line_ending);
|
||||
INT32 line_comment_pos;
|
||||
INT32 block_comment_pos;
|
||||
// optimization: temporarily put a null at the line ending, so strstr does not needlessly
|
||||
// look past it since we're only interested in the current line
|
||||
if (newline_pos != INT32_MAX)
|
||||
read_pos[newline_pos] = '\0';
|
||||
line_comment_pos = strstr_int(read_pos, "//");
|
||||
block_comment_pos = strstr_int(read_pos, "/*");
|
||||
// restore the line ending, remove the null we just put there
|
||||
if (newline_pos != INT32_MAX)
|
||||
read_pos[newline_pos] = line_ending[0];
|
||||
if (line_comment_pos < block_comment_pos)
|
||||
{
|
||||
// line comment found, skip rest of the line
|
||||
if (newline_pos != INT32_MAX)
|
||||
{
|
||||
ADVANCE(newline_pos + line_ending_len)
|
||||
}
|
||||
else
|
||||
{
|
||||
// we got to the end
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (block_comment_pos < line_comment_pos)
|
||||
{
|
||||
// block comment found, skip past it
|
||||
INT32 block_comment_end;
|
||||
ADVANCE(block_comment_pos + 2)
|
||||
block_comment_end = strstr_int(read_pos, "*/");
|
||||
if (block_comment_end == INT32_MAX)
|
||||
{
|
||||
// could also leave insertion_pos at 0 and let the GLSL compiler
|
||||
// output an error message for this broken comment
|
||||
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Encountered unclosed block comment in shader.\n");
|
||||
return NULL;
|
||||
}
|
||||
ADVANCE(block_comment_end + 2)
|
||||
}
|
||||
else if (newline_pos == INT32_MAX)
|
||||
{
|
||||
// we got to the end
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nothing special on this line, move to the next one
|
||||
ADVANCE(newline_pos + line_ending_len)
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef STARTSWITH
|
||||
#undef ADVANCE
|
||||
|
||||
// Calculate length of modified shader.
|
||||
new_len = original_len;
|
||||
if (cv_glmodellighting.value)
|
||||
new_len += sizeof(MODEL_LIGHTING_DEFINE) - 1 + 2 * line_ending_len;
|
||||
|
||||
// Allocate memory for modified shader.
|
||||
new_shader = Z_Malloc(new_len + 1, PU_STATIC, NULL);
|
||||
|
||||
read_pos = original;
|
||||
write_pos = new_shader;
|
||||
|
||||
// Copy the part before our additions.
|
||||
M_Memcpy(write_pos, original, insertion_pos);
|
||||
read_pos += insertion_pos;
|
||||
write_pos += insertion_pos;
|
||||
|
||||
// Write the additions.
|
||||
if (cv_glmodellighting.value)
|
||||
{
|
||||
strcpy(write_pos, line_ending);
|
||||
write_pos += line_ending_len;
|
||||
strcpy(write_pos, MODEL_LIGHTING_DEFINE);
|
||||
write_pos += sizeof(MODEL_LIGHTING_DEFINE) - 1;
|
||||
strcpy(write_pos, line_ending);
|
||||
write_pos += line_ending_len;
|
||||
}
|
||||
|
||||
// Copy the part after our additions.
|
||||
M_Memcpy(write_pos, read_pos, original_len - insertion_pos);
|
||||
|
||||
// Terminate the new string.
|
||||
new_shader[new_len] = '\0';
|
||||
|
||||
return new_shader;
|
||||
}
|
||||
|
||||
// preprocess and compile shader at gl_shaders[index]
|
||||
static void HWR_CompileShader(int index)
|
||||
{
|
||||
char *vertex_source = gl_shaders[index].vertex;
|
||||
char *fragment_source = gl_shaders[index].fragment;
|
||||
|
||||
if (vertex_source)
|
||||
{
|
||||
char *preprocessed = HWR_PreprocessShader(vertex_source);
|
||||
if (!preprocessed) return;
|
||||
HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_VERTEX);
|
||||
}
|
||||
if (fragment_source)
|
||||
{
|
||||
char *preprocessed = HWR_PreprocessShader(fragment_source);
|
||||
if (!preprocessed) return;
|
||||
HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_FRAGMENT);
|
||||
}
|
||||
|
||||
gl_shaders[index].compiled = HWD.pfnCompileShader(index);
|
||||
}
|
||||
|
||||
// compile or recompile shaders
|
||||
void HWR_CompileShaders(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUMSHADERTARGETS; i++)
|
||||
{
|
||||
int custom_index = gl_shadertargets[i].custom_shader;
|
||||
HWR_CompileShader(i);
|
||||
if (!gl_shaders[i].compiled)
|
||||
CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Compilation failed for base %s shader!\n", shaderxlat[i].type);
|
||||
if (custom_index != -1)
|
||||
{
|
||||
HWR_CompileShader(custom_index);
|
||||
if (!gl_shaders[custom_index].compiled)
|
||||
CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Recompilation failed for the custom %s shader! See the console messages above for more information.\n", shaderxlat[i].type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HWR_GetShaderFromTarget(int shader_target)
|
||||
{
|
||||
int custom_shader = gl_shadertargets[shader_target].custom_shader;
|
||||
// use custom shader if following are true
|
||||
// - custom shader exists
|
||||
// - custom shader has been compiled successfully
|
||||
// - custom shaders are enabled
|
||||
// - custom shaders are allowed by the server
|
||||
if (custom_shader != -1 && gl_shaders[custom_shader].compiled &&
|
||||
cv_glshaders.value == 1 && cv_glallowshaders.value)
|
||||
return custom_shader;
|
||||
else
|
||||
return gl_shadertargets[shader_target].base_shader;
|
||||
}
|
||||
|
||||
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
|
||||
{
|
||||
UINT16 i;
|
||||
lumpinfo_t *lump_p;
|
||||
|
||||
lump_p = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++)
|
||||
if (memcmp(lump_p->name, "SHADERS", 7) == 0)
|
||||
return i;
|
||||
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
customshaderxlat_t shaderxlat[] =
|
||||
{
|
||||
{"Flat", SHADER_FLOOR},
|
||||
{"WallTexture", SHADER_WALL},
|
||||
{"Sprite", SHADER_SPRITE},
|
||||
{"Model", SHADER_MODEL},
|
||||
{"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;
|
||||
char *stoken;
|
||||
char *value;
|
||||
size_t size;
|
||||
int linenum = 1;
|
||||
int shadertype = 0;
|
||||
int i;
|
||||
boolean modified_shaders[NUMSHADERTARGETS] = {0};
|
||||
|
||||
if (!gl_shadersavailable)
|
||||
return;
|
||||
|
||||
lump = HWR_FindShaderDefs(wadnum);
|
||||
if (lump == INT16_MAX)
|
||||
return;
|
||||
|
||||
shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
||||
size = W_LumpLengthPwad(wadnum, lump);
|
||||
|
||||
line = Z_Malloc(size+1, PU_STATIC, NULL);
|
||||
M_Memcpy(line, shaderdef, size);
|
||||
line[size] = '\0';
|
||||
|
||||
stoken = strtok(line, "\r\n ");
|
||||
while (stoken)
|
||||
{
|
||||
if ((stoken[0] == '/' && stoken[1] == '/')
|
||||
|| (stoken[0] == '#'))// skip comments
|
||||
{
|
||||
stoken = strtok(NULL, "\r\n");
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
if (!stricmp(stoken, "GLSL"))
|
||||
{
|
||||
value = strtok(NULL, "\r\n ");
|
||||
if (!value)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (!stricmp(value, "VERTEX"))
|
||||
shadertype = 1;
|
||||
else if (!stricmp(value, "FRAGMENT"))
|
||||
shadertype = 2;
|
||||
|
||||
skip_lump:
|
||||
stoken = strtok(NULL, "\r\n ");
|
||||
linenum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = strtok(NULL, "\r\n= ");
|
||||
if (!value)
|
||||
{
|
||||
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_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; shaderxlat[i].type; i++)
|
||||
{
|
||||
if (!stricmp(shaderxlat[i].type, stoken))
|
||||
{
|
||||
size_t shader_string_length;
|
||||
char *shader_source;
|
||||
char *shader_lumpname;
|
||||
UINT16 shader_lumpnum;
|
||||
int shader_index; // index in gl_shaders
|
||||
|
||||
if (PK3)
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "Shaders/sh_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL);
|
||||
strcpy(shader_lumpname, "SH_");
|
||||
strcat(shader_lumpname, value);
|
||||
shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0);
|
||||
}
|
||||
|
||||
if (shader_lumpnum == INT16_MAX)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
shader_string_length = W_LumpLengthPwad(wadnum, shader_lumpnum) + 1;
|
||||
shader_source = Z_Malloc(shader_string_length, PU_STATIC, NULL);
|
||||
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
|
||||
shader_source[shader_string_length-1] = '\0';
|
||||
|
||||
shader_index = shaderxlat[i].id + NUMSHADERTARGETS;
|
||||
if (!modified_shaders[shaderxlat[i].id])
|
||||
{
|
||||
// this will clear any old custom shaders from previously loaded files
|
||||
// Z_Free checks if the pointer is NULL!
|
||||
Z_Free(gl_shaders[shader_index].vertex);
|
||||
gl_shaders[shader_index].vertex = NULL;
|
||||
Z_Free(gl_shaders[shader_index].fragment);
|
||||
gl_shaders[shader_index].fragment = NULL;
|
||||
}
|
||||
modified_shaders[shaderxlat[i].id] = true;
|
||||
|
||||
if (shadertype == 1)
|
||||
{
|
||||
if (gl_shaders[shader_index].vertex)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(gl_shaders[shader_index].vertex);
|
||||
}
|
||||
gl_shaders[shader_index].vertex = shader_source;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gl_shaders[shader_index].fragment)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
|
||||
Z_Free(gl_shaders[shader_index].fragment);
|
||||
}
|
||||
gl_shaders[shader_index].fragment = shader_source;
|
||||
}
|
||||
|
||||
Z_Free(shader_lumpname);
|
||||
}
|
||||
}
|
||||
|
||||
skip_field:
|
||||
stoken = strtok(NULL, "\r\n= ");
|
||||
linenum++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMSHADERTARGETS; i++)
|
||||
{
|
||||
if (modified_shaders[i])
|
||||
{
|
||||
int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders
|
||||
gl_shadertargets[i].custom_shader = shader_index;
|
||||
HWR_CompileShader(shader_index);
|
||||
if (!gl_shaders[shader_index].compiled)
|
||||
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(line);
|
||||
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
|
|
@ -598,14 +598,15 @@ typedef enum
|
|||
|
||||
typedef struct gl_shader_s
|
||||
{
|
||||
char *vertex_shader;
|
||||
char *fragment_shader;
|
||||
GLuint program;
|
||||
GLint uniforms[gluniform_max+1];
|
||||
boolean custom;
|
||||
} gl_shader_t;
|
||||
|
||||
static gl_shader_t gl_shaders[HWR_MAXSHADERS];
|
||||
static gl_shader_t gl_usershaders[HWR_MAXSHADERS];
|
||||
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
|
||||
|
||||
static gl_shader_t gl_fallback_shader;
|
||||
|
||||
// 09102020
|
||||
typedef struct gl_shaderstate_s
|
||||
|
@ -621,21 +622,17 @@ static gl_shaderstate_t gl_shaderstate;
|
|||
static INT32 shader_leveltime = 0;
|
||||
|
||||
// Lactozilla: Shader functions
|
||||
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader);
|
||||
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i);
|
||||
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
|
||||
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
|
||||
|
||||
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_VERTEX_SHADER \
|
||||
#define GLSL_FALLBACK_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
|
@ -644,226 +641,17 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
|||
"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 \
|
||||
#define GLSL_FALLBACK_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_DOOM_COLORMAP \
|
||||
"float R_DoomColormap(float light, float z)\n" \
|
||||
"{\n" \
|
||||
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
|
||||
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
|
||||
"float startmap = (15.0 - lightnum) * 4.0;\n" \
|
||||
"float scale = 160.0 / (lightz + 1.0);\n" \
|
||||
"return startmap - scale * 0.5;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_DOOM_LIGHT_EQUATION \
|
||||
"float R_DoomLightingEquation(float light)\n" \
|
||||
"{\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
|
||||
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_TINT_EQUATION \
|
||||
"if (tint_color.a > 0.0) {\n" \
|
||||
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
|
||||
"float strength = sqrt(9.0 * tint_color.a);\n" \
|
||||
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color)
|
||||
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Water surface shader
|
||||
//
|
||||
// Mostly guesstimated, rather than the rest being built off Software science.
|
||||
// Still needs to distort things underneath/around the water...
|
||||
//
|
||||
|
||||
#define GLSL_WATER_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
"const float freq = 0.025;\n" \
|
||||
"const float amp = 0.025;\n" \
|
||||
"const float speed = 2.0;\n" \
|
||||
"const float pi = 3.14159;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
|
||||
"float a = -pi * (z * freq) + (leveltime * speed);\n" \
|
||||
"float sdistort = sin(a) * amp;\n" \
|
||||
"float cdistort = cos(a) * amp;\n" \
|
||||
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Fog block shader
|
||||
//
|
||||
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
|
||||
//
|
||||
|
||||
#define GLSL_FOG_FRAGMENT_SHADER \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 base_color = gl_Color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// ================
|
||||
// Shader sources
|
||||
// ================
|
||||
|
||||
static struct {
|
||||
const char *vertex;
|
||||
const char *fragment;
|
||||
} const gl_shadersources[] = {
|
||||
// Default shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER},
|
||||
|
||||
// Floor shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Wall shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Sprite shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Model shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
|
||||
|
||||
// Model shader + diffuse lighting from above
|
||||
{GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER},
|
||||
|
||||
// Water shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
|
||||
|
||||
// Fog shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
|
||||
|
||||
// Sky shader
|
||||
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
#endif // GL_SHADERS
|
||||
|
||||
void SetupGLFunc4(void)
|
||||
|
@ -910,55 +698,19 @@ void SetupGLFunc4(void)
|
|||
pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps");
|
||||
}
|
||||
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void)
|
||||
EXPORT boolean HWRAPI(InitShaders) (void)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
GLint i;
|
||||
|
||||
if (!pglUseProgram)
|
||||
return false;
|
||||
|
||||
gl_customshaders[SHADER_DEFAULT].vertex = NULL;
|
||||
gl_customshaders[SHADER_DEFAULT].fragment = NULL;
|
||||
gl_fallback_shader.vertex_shader = Z_StrDup(GLSL_FALLBACK_VERTEX_SHADER);
|
||||
gl_fallback_shader.fragment_shader = Z_StrDup(GLSL_FALLBACK_FRAGMENT_SHADER);
|
||||
|
||||
for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++)
|
||||
if (!Shader_CompileProgram(&gl_fallback_shader, -1))
|
||||
{
|
||||
gl_shader_t *shader, *usershader;
|
||||
const GLchar *vert_shader = gl_shadersources[i].vertex;
|
||||
const GLchar *frag_shader = gl_shadersources[i].fragment;
|
||||
|
||||
if (i >= HWR_MAXSHADERS)
|
||||
break;
|
||||
|
||||
shader = &gl_shaders[i];
|
||||
usershader = &gl_usershaders[i];
|
||||
|
||||
if (shader->program)
|
||||
pglDeleteProgram(shader->program);
|
||||
if (usershader->program)
|
||||
pglDeleteProgram(usershader->program);
|
||||
|
||||
shader->program = 0;
|
||||
usershader->program = 0;
|
||||
|
||||
if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader))
|
||||
shader->program = 0;
|
||||
|
||||
// Compile custom shader
|
||||
if ((i == SHADER_DEFAULT) || !(gl_customshaders[i].vertex || gl_customshaders[i].fragment))
|
||||
continue;
|
||||
|
||||
// 18032019
|
||||
if (gl_customshaders[i].vertex)
|
||||
vert_shader = gl_customshaders[i].vertex;
|
||||
if (gl_customshaders[i].fragment)
|
||||
frag_shader = gl_customshaders[i].fragment;
|
||||
|
||||
if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader))
|
||||
{
|
||||
GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i));
|
||||
usershader->program = 0;
|
||||
}
|
||||
GL_MSG_Error("Failed to compile the fallback shader program!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -967,6 +719,58 @@ EXPORT boolean HWRAPI(CompileShaders) (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
gl_shader_t *shader;
|
||||
|
||||
if (slot < 0 || slot >= HWR_MAXSHADERS)
|
||||
I_Error("LoadShader: Invalid slot %d", slot);
|
||||
|
||||
shader = &gl_shaders[slot];
|
||||
|
||||
#define LOADSHADER(source) { \
|
||||
if (shader->source) \
|
||||
Z_Free(shader->source); \
|
||||
shader->source = code; \
|
||||
}
|
||||
|
||||
if (stage == HWD_SHADERSTAGE_VERTEX)
|
||||
LOADSHADER(vertex_shader)
|
||||
else if (stage == HWD_SHADERSTAGE_FRAGMENT)
|
||||
LOADSHADER(fragment_shader)
|
||||
else
|
||||
I_Error("LoadShader: invalid shader stage");
|
||||
|
||||
#undef LOADSHADER
|
||||
#else
|
||||
(void)slot;
|
||||
(void)code;
|
||||
(void)stage;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT boolean HWRAPI(CompileShader) (int slot)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (slot < 0 || slot >= HWR_MAXSHADERS)
|
||||
I_Error("CompileShader: Invalid slot %d", slot);
|
||||
|
||||
if (Shader_CompileProgram(&gl_shaders[slot], slot))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_shaders[slot].program = 0;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
(void)slot;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Shader info
|
||||
// Those are given to the uniforms.
|
||||
|
@ -989,84 +793,31 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value)
|
|||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Custom shader loading
|
||||
//
|
||||
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
shadersource_t *shader;
|
||||
|
||||
if (!pglUseProgram)
|
||||
return;
|
||||
|
||||
if (number < 1 || number > HWR_MAXSHADERS)
|
||||
I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS);
|
||||
else if (code == NULL)
|
||||
I_Error("LoadCustomShader: empty shader");
|
||||
|
||||
shader = &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
|
||||
COPYSHADER(vertex)
|
||||
|
||||
#else
|
||||
(void)number;
|
||||
(void)shader;
|
||||
(void)size;
|
||||
(void)fragment;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(SetShader) (int type)
|
||||
EXPORT void HWRAPI(SetShader) (int slot)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (gl_allowshaders != HWD_SHADEROPTION_OFF)
|
||||
{
|
||||
gl_shader_t *shader = gl_shaderstate.current;
|
||||
gl_shader_t *next_shader = &gl_shaders[slot]; // the gl_shader_t we are going to switch to
|
||||
|
||||
// If using model lighting, set the appropriate shader.
|
||||
// However don't override a custom shader.
|
||||
if (type == SHADER_MODEL && model_lighting
|
||||
&& !(gl_shaders[SHADER_MODEL].custom && !gl_shaders[SHADER_MODEL_LIGHTING].custom))
|
||||
type = SHADER_MODEL_LIGHTING;
|
||||
if (!next_shader->program)
|
||||
next_shader = &gl_fallback_shader; // unusable shader, use fallback instead
|
||||
|
||||
if ((shader == NULL) || (GLuint)type != gl_shaderstate.type)
|
||||
// update gl_shaderstate if an actual shader switch is needed
|
||||
if (gl_shaderstate.current != next_shader)
|
||||
{
|
||||
gl_shader_t *baseshader = &gl_shaders[type];
|
||||
gl_shader_t *usershader = &gl_usershaders[type];
|
||||
|
||||
if (usershader->program)
|
||||
shader = (gl_allowshaders == HWD_SHADEROPTION_NOCUSTOM) ? baseshader : usershader;
|
||||
else
|
||||
shader = baseshader;
|
||||
|
||||
gl_shaderstate.current = shader;
|
||||
gl_shaderstate.type = type;
|
||||
gl_shaderstate.current = next_shader;
|
||||
gl_shaderstate.program = next_shader->program;
|
||||
gl_shaderstate.type = slot;
|
||||
gl_shaderstate.changed = true;
|
||||
}
|
||||
|
||||
if (gl_shaderstate.program != shader->program)
|
||||
{
|
||||
gl_shaderstate.program = shader->program;
|
||||
gl_shaderstate.changed = true;
|
||||
}
|
||||
gl_shadersenabled = true;
|
||||
|
||||
gl_shadersenabled = (shader->program != 0);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void)type;
|
||||
(void)slot;
|
||||
#endif
|
||||
gl_shadersenabled = false;
|
||||
}
|
||||
|
@ -1085,25 +836,6 @@ EXPORT void HWRAPI(UnSetShader) (void)
|
|||
gl_shadersenabled = false;
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(CleanShaders) (void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// SetNoTexture : Disable texture
|
||||
// -----------------+
|
||||
|
@ -2052,69 +1784,91 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
|
|||
#endif
|
||||
}
|
||||
|
||||
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader)
|
||||
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
|
||||
{
|
||||
GLuint gl_vertShader, gl_fragShader;
|
||||
GLuint gl_vertShader = 0;
|
||||
GLuint gl_fragShader = 0;
|
||||
GLint result;
|
||||
const GLchar *vert_shader = shader->vertex_shader;
|
||||
const GLchar *frag_shader = shader->fragment_shader;
|
||||
|
||||
//
|
||||
// Load and compile vertex shader
|
||||
//
|
||||
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
|
||||
if (!gl_vertShader)
|
||||
if (shader->program)
|
||||
pglDeleteProgram(shader->program);
|
||||
|
||||
if (!vert_shader && !frag_shader)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i));
|
||||
GL_MSG_Error("Shader_CompileProgram: Missing shaders for shader program %s\n", HWR_GetShaderName(i));
|
||||
return false;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
|
||||
pglCompileShader(gl_vertShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
if (vert_shader)
|
||||
{
|
||||
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
return false;
|
||||
//
|
||||
// Load and compile vertex shader
|
||||
//
|
||||
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
|
||||
if (!gl_vertShader)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i));
|
||||
return false;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
|
||||
pglCompileShader(gl_vertShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Load and compile fragment shader
|
||||
//
|
||||
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!gl_fragShader)
|
||||
if (frag_shader)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i));
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Load and compile fragment shader
|
||||
//
|
||||
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!gl_fragShader)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i));
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
|
||||
pglCompileShader(gl_fragShader);
|
||||
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
|
||||
pglCompileShader(gl_fragShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
return false;
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
shader->program = pglCreateProgram();
|
||||
pglAttachShader(shader->program, gl_vertShader);
|
||||
pglAttachShader(shader->program, gl_fragShader);
|
||||
if (vert_shader)
|
||||
pglAttachShader(shader->program, gl_vertShader);
|
||||
if (frag_shader)
|
||||
pglAttachShader(shader->program, gl_fragShader);
|
||||
pglLinkProgram(shader->program);
|
||||
|
||||
// check link status
|
||||
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
|
||||
|
||||
// delete the shader objects
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
if (vert_shader)
|
||||
pglDeleteShader(gl_vertShader);
|
||||
if (frag_shader)
|
||||
pglDeleteShader(gl_fragShader);
|
||||
|
||||
// couldn't link?
|
||||
if (result != GL_TRUE)
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#define _CREATE_DLL_ // necessary for Unix AND Windows
|
||||
#include "../../doomdef.h"
|
||||
#include "../hw_drv.h"
|
||||
#include "../../z_zone.h"
|
||||
|
||||
// ==========================================================================
|
||||
// DEFINITIONS
|
||||
|
|
|
@ -392,6 +392,7 @@
|
|||
<ClCompile Include="..\hardware\hw_md2load.c" />
|
||||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.c" />
|
||||
<ClCompile Include="..\hardware\hw_shaders.c" />
|
||||
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
|
||||
<ClCompile Include="..\hardware\u_list.c" />
|
||||
<ClCompile Include="..\hu_stuff.c" />
|
||||
|
|
|
@ -684,6 +684,9 @@
|
|||
<ClCompile Include="..\hardware\hw_model.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_shaders.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\u_list.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -105,13 +105,13 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(MakeScreenFinalTexture);
|
||||
GETFUNC(DrawScreenFinalTexture);
|
||||
|
||||
GETFUNC(CompileShaders);
|
||||
GETFUNC(CleanShaders);
|
||||
GETFUNC(InitShaders);
|
||||
GETFUNC(LoadShader);
|
||||
GETFUNC(CompileShader);
|
||||
GETFUNC(SetShader);
|
||||
GETFUNC(UnSetShader);
|
||||
|
||||
GETFUNC(SetShaderInfo);
|
||||
GETFUNC(LoadCustomShader);
|
||||
|
||||
#else //HWRENDER
|
||||
if (0 == strcmp("FinishUpdate", funcName))
|
||||
|
|
|
@ -1878,13 +1878,13 @@ void VID_StartupOpenGL(void)
|
|||
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
|
||||
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
|
||||
|
||||
HWD.pfnCompileShaders = hwSym("CompileShaders",NULL);
|
||||
HWD.pfnCleanShaders = hwSym("CleanShaders",NULL);
|
||||
HWD.pfnInitShaders = hwSym("InitShaders",NULL);
|
||||
HWD.pfnLoadShader = hwSym("LoadShader",NULL);
|
||||
HWD.pfnCompileShader = hwSym("CompileShader",NULL);
|
||||
HWD.pfnSetShader = hwSym("SetShader",NULL);
|
||||
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
|
||||
|
||||
HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
|
||||
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
|
||||
|
||||
vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library
|
||||
|
||||
|
|
|
@ -859,10 +859,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
#ifdef HWRENDER
|
||||
// Read shaders from file
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#endif // HWRENDER
|
||||
|
||||
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
|
||||
|
|
Loading…
Reference in a new issue