Skip to content

Commit

Permalink
Lit water support (issue #10)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-drexler committed Jan 5, 2022
1 parent e96a839 commit 3217fad
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 22 deletions.
9 changes: 8 additions & 1 deletion Quake/gl_model.c
Expand Up @@ -1225,7 +1225,14 @@ void Mod_LoadFaces (lump_t *l, qboolean bsp2)
}
else if (TEXTYPE_ISLIQUID (texture->type))
{
out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
out->flags |= SURF_DRAWTURB;
if (out->texinfo->flags & TEX_SPECIAL)
out->flags |= SURF_DRAWTILED;
else if (out->samples && !loadmodel->haslitwater)
{
Con_DPrintf ("Map has lit water\n");
loadmodel->haslitwater = true;
}

if (texture->type == TEXTYPE_LAVA)
out->flags |= SURF_DRAWLAVA;
Expand Down
1 change: 1 addition & 0 deletions Quake/gl_model.h
Expand Up @@ -508,6 +508,7 @@ typedef struct qmodel_s

int bspversion;
int contentstransparent; //spike -- added this so we can disable glitchy wateralpha where its not supported.
qboolean haslitwater;

//
// alias model
Expand Down
1 change: 1 addition & 0 deletions Quake/gl_rmain.c
Expand Up @@ -70,6 +70,7 @@ cvar_t r_fullbright = {"r_fullbright","0",CVAR_NONE};
cvar_t r_lightmap = {"r_lightmap","0",CVAR_NONE};
cvar_t r_shadows = {"r_shadows","0",CVAR_ARCHIVE};
cvar_t r_wateralpha = {"r_wateralpha","1",CVAR_ARCHIVE};
cvar_t r_litwater = {"r_litwater","1",CVAR_NONE};
cvar_t r_dynamic = {"r_dynamic","1",CVAR_ARCHIVE};
cvar_t r_novis = {"r_novis","0",CVAR_ARCHIVE};
#if defined(USE_SIMD)
Expand Down
1 change: 1 addition & 0 deletions Quake/gl_rmisc.c
Expand Up @@ -201,6 +201,7 @@ void R_Init (void)
Cvar_RegisterVariable (&r_shadows);
Cvar_RegisterVariable (&r_wateralpha);
Cvar_SetCallback (&r_wateralpha, R_SetWateralpha_f);
Cvar_RegisterVariable (&r_litwater);
Cvar_RegisterVariable (&r_dynamic);
Cvar_RegisterVariable (&r_novis);
#if defined(USE_SIMD)
Expand Down
10 changes: 5 additions & 5 deletions Quake/gl_shaders.c
Expand Up @@ -252,7 +252,7 @@ GL_CreateShaders
*/
void GL_CreateShaders (void)
{
int palettize, dither, alphatest, warp;
int palettize, dither, mode, warp;

glprogs.gui = GL_CreateProgram (gui_vertex_shader, gui_fragment_shader, "gui");
glprogs.viewblend = GL_CreateProgram (viewblend_vertex_shader, viewblend_fragment_shader, "viewblend");
Expand All @@ -262,13 +262,13 @@ void GL_CreateShaders (void)
glprogs.postprocess[palettize] = GL_CreateProgram (postprocess_vertex_shader, postprocess_fragment_shader, "postprocess|PALETTIZE %d", palettize);

for (dither = 0; dither < 3; dither++)
for (alphatest = 0; alphatest < 2; alphatest++)
glprogs.world[dither][alphatest] = GL_CreateProgram (world_vertex_shader, world_fragment_shader, "world|DITHER %d; ALPHATEST %d", dither, alphatest);
for (mode = 0; mode < 3; mode++)
glprogs.world[dither][mode] = GL_CreateProgram (world_vertex_shader, world_fragment_shader, "world|DITHER %d; MODE %d", dither, mode);

for (dither = 0; dither < 2; dither++)
{
for (alphatest = 0; alphatest < 2; alphatest++)
glprogs.alias[dither][alphatest] = GL_CreateProgram (alias_vertex_shader, alias_fragment_shader, "alias|DITHER %d; ALPHATEST %d", dither, alphatest);
for (mode = 0; mode < 2; mode++)
glprogs.alias[dither][mode] = GL_CreateProgram (alias_vertex_shader, alias_fragment_shader, "alias|DITHER %d; ALPHATEST %d", dither, mode);
glprogs.water[dither] = GL_CreateProgram (water_vertex_shader, water_fragment_shader, "water|DITHER %d", dither);
glprogs.skylayers[dither] = GL_CreateProgram (sky_layers_vertex_shader, sky_layers_fragment_shader, "sky layers|DITHER %d", dither);
glprogs.skycubemap[dither] = GL_CreateProgram (sky_cubemap_vertex_shader, sky_cubemap_fragment_shader, "sky cubemap|DITHER %d", dither);
Expand Down
22 changes: 15 additions & 7 deletions Quake/gl_shaders.h
Expand Up @@ -468,7 +468,11 @@ BINDLESS_VERTEX_HEADER
" out_depth = gl_Position.w;\n"
" out_coord = (gl_Position.xy / gl_Position.w * 0.5 + 0.5) * vec2(LIGHT_TILES_X, LIGHT_TILES_Y);\n"
" out_flags = call.flags;\n"
"#if MODE == " QS_STRINGIFY (WORLDSHADER_WATER) "\n"
" out_alpha = instance.alpha < 0.0 ? call.wateralpha : instance.alpha;\n"
"#else\n"
" out_alpha = instance.alpha < 0.0 ? 1.0 : instance.alpha;\n"
"#endif\n"
" vec4 styles = textureLod(LightmapStyles, in_uv.zw, 0.);\n"
" out_styles.x = GetLightStyle(int(styles.x * 255. + .5));\n"
" if (styles.y > 0.5)\n"
Expand Down Expand Up @@ -510,7 +514,7 @@ NOISE_FUNCTIONS
"layout(location=0) flat in uint in_flags;\n"
"layout(location=1) flat in float in_alpha;\n"
"layout(location=2) in vec3 in_pos;\n"
"#if ALPHATEST\n"
"#if MODE == " QS_STRINGIFY (WORLDSHADER_ALPHATEST) "\n"
" layout(location=3) centroid in vec2 in_uv;\n"
"#else\n"
" layout(location=3) in vec2 in_uv;\n"
Expand All @@ -528,26 +532,30 @@ NOISE_FUNCTIONS
"void main()\n"
"{\n"
" vec3 fullbright = vec3(0.);\n"
" vec2 uv = in_uv;\n"
"#if MODE == " QS_STRINGIFY (WORLDSHADER_WATER) "\n"
" uv = uv * 2.0 + 0.125 * sin(in_uv.yx * (3.14159265 * 2.0) + Time);\n"
"#endif\n"
"#if BINDLESS\n"
" sampler2D Tex = sampler2D(in_samplers.xy);\n"
" sampler2D FullbrightTex;\n"
" if ((in_flags & CF_USE_FULLBRIGHT) != 0u)\n"
" {\n"
" FullbrightTex = sampler2D(in_samplers.zw);\n"
" fullbright = texture(FullbrightTex, in_uv).rgb;\n"
" fullbright = texture(FullbrightTex, uv).rgb;\n"
" }\n"
"#else\n"
" if ((in_flags & CF_USE_FULLBRIGHT) != 0u)\n"
" fullbright = texture(FullbrightTex, in_uv).rgb;\n"
" fullbright = texture(FullbrightTex, uv).rgb;\n"
"#endif\n"
"#if DITHER >= 2\n"
" vec4 result = texture(Tex, in_uv, -1.0);\n"
" vec4 result = texture(Tex, uv, -1.0);\n"
"#elif DITHER\n"
" vec4 result = texture(Tex, in_uv, -0.5);\n"
" vec4 result = texture(Tex, uv, -0.5);\n"
"#else\n"
" vec4 result = texture(Tex, in_uv);\n"
" vec4 result = texture(Tex, uv);\n"
"#endif\n"
"#if ALPHATEST\n"
"#if MODE == " QS_STRINGIFY (WORLDSHADER_ALPHATEST) "\n"
" if (result.a < 0.666)\n"
" discard;\n"
"#endif\n"
Expand Down
6 changes: 5 additions & 1 deletion Quake/glquake.h
Expand Up @@ -102,6 +102,7 @@ extern cvar_t r_wateralpha;
extern cvar_t r_lavaalpha;
extern cvar_t r_telealpha;
extern cvar_t r_slimealpha;
extern cvar_t r_litwater;
extern cvar_t r_dynamic;
extern cvar_t r_novis;
extern cvar_t r_scale;
Expand Down Expand Up @@ -459,6 +460,9 @@ void GLMesh_DeleteVertexBuffers (void);

int R_LightPoint (vec3_t p, lightcache_t *cache);

#define WORLDSHADER_SOLID 0
#define WORLDSHADER_ALPHATEST 1
#define WORLDSHADER_WATER 2

typedef struct glprogs_s {
/* 2d */
Expand All @@ -468,7 +472,7 @@ typedef struct glprogs_s {
GLuint postprocess[3]; // [palettize:off/dithered/direct]

/* 3d */
GLuint world[3][2]; // [dither][alpha test]
GLuint world[3][3]; // [dither][mode:solid/alpha test/water]
GLuint water[2]; // [dither]
GLuint skystencil;
GLuint skylayers[2]; // [dither]
Expand Down
31 changes: 27 additions & 4 deletions Quake/r_brush.c
Expand Up @@ -188,8 +188,14 @@ static int AllocBlock (int w, int h, int *x, int *y)
lightmap_count++;
lightmaps = (lightmap_t *) realloc(lightmaps, sizeof(*lightmaps)*lightmap_count);
memset(&lightmaps[texnum], 0, sizeof(lightmaps[texnum]));
//as we're only tracking one texture, we don't need multiple copies any more.
// as we're only tracking one texture, we don't need multiple copies any more.
Chart_Init (&lightmap_chart, LMBLOCK_WIDTH, LMBLOCK_HEIGHT);
// reserve 1 texel for unlit water surfaces in maps with lit water
if (lightmap_count == 1)
{
lightmap_chart.x = 1;
lightmap_chart.allocated[0] = 1;
}
}

if (!Chart_Add (&lightmap_chart, w, h, x, y))
Expand Down Expand Up @@ -463,6 +469,9 @@ void GL_BuildLightmaps (void)
lm->yofs = (i / xblocks) * LMBLOCK_HEIGHT;
}

// fill reserved texel
lightmap_layers[0][0] = 0xff808080u;

// fill lightmap samples
for (i = 0, j = VEC_SIZE (lit_surfs); i < j; i++)
GL_FillSurfaceLightmap (lit_surfs[i]);
Expand Down Expand Up @@ -599,9 +608,17 @@ void GL_BuildBModelVertexBuffer (void)
}
else
{
texscalex = 1.f / texture->width;
texscaley = 1.f / texture->height;
useofs = 1.f;
if (fa->flags & SURF_DRAWTURB)
{
texscaley = texscalex = 1.f / 128.f; //warp animation repeats every 128
useofs = 0.f;
}
else
{
texscalex = 1.f / texture->width;
texscaley = 1.f / texture->height;
useofs = 1.f;
}
lm = &lightmaps[fa->lightmaptexturenum];
}

Expand Down Expand Up @@ -665,6 +682,12 @@ void GL_BuildBModelVertexBuffer (void)
verts[5] = s;
verts[6] = t;
}
else
{
// first lightmap texel is fullbright
verts[5] = 0.5f / lightmap_width;
verts[6] = 0.5f / lightmap_height;
}
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions Quake/r_world.c
Expand Up @@ -539,12 +539,12 @@ static void R_DrawBrushModels_Real (entity_t **ents, int count, brushpass_t pass
case BP_SOLID:
texbegin = 0;
texend = TEXTYPE_CUTOUT;
program = glprogs.world[q_max(0, (int)softemu - 1)][0];
program = glprogs.world[q_max(0, (int)softemu - 1)][WORLDSHADER_SOLID];
break;
case BP_ALPHATEST:
texbegin = TEXTYPE_CUTOUT;
texend = TEXTYPE_CUTOUT + 1;
program = glprogs.world[q_max(0, (int)softemu - 1)][1];
program = glprogs.world[q_max(0, (int)softemu - 1)][WORLDSHADER_ALPHATEST];
break;
case BP_SKYLAYERS:
texbegin = TEXTYPE_SKY;
Expand Down Expand Up @@ -653,7 +653,7 @@ void R_DrawBrushModels_Water (entity_t **ents, int count, qboolean translucent)
int i, j;
int totalinst, baseinst;
unsigned state;
GLuint buf;
GLuint buf, program;
GLbyte *ofs;

if (count > countof(bmodel_instances))
Expand All @@ -679,7 +679,12 @@ void R_DrawBrushModels_Water (entity_t **ents, int count, qboolean translucent)
else
state |= GLS_BLEND_OPAQUE;

R_ResetBModelCalls (glprogs.water[softemu == SOFTEMU_COARSE]);
if (cl.worldmodel->haslitwater && r_litwater.value)
program = glprogs.world[q_max(0, (int)softemu - 1)][WORLDSHADER_WATER];
else
program = glprogs.water[softemu == SOFTEMU_COARSE];

R_ResetBModelCalls (program);
GL_SetState (state);
GL_Bind (GL_TEXTURE2, r_fullbright_cheatsafe ? greytexture : lightmap_texture);

Expand Down

0 comments on commit 3217fad

Please sign in to comment.