OpenGL shader code rearrangement and shader "pre-preprocessor"
The vanilla shader sources are moved out of r_opengl.c. All shaders are given to the backend instead by a new file, hw_shaders.c. As an exception, the backend will contain a fallback shader that is used when the backend user tries to use a broken shader. ("backend user" refers to the SRB2 code that uses the backend)
Handling of switching between custom and non-custom shaders is moved out of r_opengl.c. This may also help possible future efforts of making custom shaders more flexible. (like toggling each shader during runtime from Lua)
The functions of the new API for shader handling in the backend:
boolean InitShaders(void)
Prepares the shader system for use. Compiles the fallback shader. Returns false if shaders cannot be used. (either because of lack of support on the gpu or shader support being disabled during compiling SRB2)
void LoadShader(int slot, char *code, hwdshaderstage_t stage)
Loads shader source code from the null-terminated string code
into slot
. Valid slots are from 0 to HWR_MAXSHADERS
. stage
is either HWD_SHADERSTAGE_VERTEX
or HWD_SHADERSTAGE_FRAGMENT
. The memory in code
belongs to the backend now. Any previous shader code in slot
and stage
is freed from memory. (Perhaps in the far future the rest of the stages could be added)
boolean CompileShader(int slot)
Compiles the shader in slot
using the sources given with LoadShader
. Returns false on failure.
Functions that remain mostly the same: (SetShader
description and behaviour is slightly different)
void SetShader(int slot)
If shaders are enabled, the currently used shader is set to slot
. The shader must be loaded and compiled successfully to use it, otherwise the fallback shader is used.
void UnSetShader(void)
The fixed function pipeline is used for draw calls instead of shaders. (used for most/all non-3d stuff?)
void SetShaderInfo(hwdshaderinfo_t info, INT32 value)
Sets certain values that are given to shader uniform variables. (currently only level time)
hw_shaders.c
Each geometry type has a "shader target", which contains references to the vanilla and custom shaders used for that geometry. HWR_GetShaderFromTarget
is used to get the shader that should currently be used for that target.
enum
{
SHADER_FLOOR,
SHADER_WALL,
SHADER_SPRITE,
SHADER_MODEL,
SHADER_WATER,
SHADER_FOG,
SHADER_SKY,
NUMSHADERTARGETS,
};
Custom shader loading functions from hw_main.c
are adapted and moved to hw_shaders.c
.
The shader "pre-preprocessor"
All shaders (except for the fallback shader) will go through a new preprocessor before being handed over to the backend. This preprocessor serves the purpose of communicating relevant graphics settings to the shader by adding #define
lines to the source code of the shaders. (this new preprocessor is ran before the standard GLSL preprocessor, hence the "pre-preprocessor" name)
If a #version
line is present, the #define
lines are added after it. Otherwise they are added to the beginning of the shader.
The following definitions are added:
-
#define MODEL_LIGHTING
: Added if model lighting is enabled. -
#define PALETTE_RENDERING
: Planned definition that is to be used if palette rendering is enabled. -
Perhaps later some definitions about the current environment could be added, for example a definition for the OpenGL version.
When relevant graphics settings are changed, the shaders are reprocessed and recompiled.
This change merges the previously used "model" and "lit model" shaders together, eliminating the need for having separate shaders for every graphics setting combination.
This change will also make the implementation of palette shaders easier by providing a clear mechanism for switching them on or off. Custom shaders will also be able to support palette rendering.