Render lightmaps together with corresponding faces; gl_overbrightbits

pass both normal texture and lightmap to shader instead of rendering the
level geometry again with the lightmap and GL_BLEND.

This is not done, some translucent surfaces are buggy now and it's only
static lightmaps. For this to work properly I'll need to add some more
shaders with and without lightmaps and use them accordingly.
For example, translucent surfaces (SURF_TRANS33/66) never have
lightmaps, neither to pertubed ones (SURF_DRAWTURB) like water and lava,
but scrolling surfaces (SURF_FLOWING) like elevators do use lightmaps
(as long as they're not also transulcent or perturbed)...
This commit is contained in:
Daniel Gibson 2017-03-12 03:11:29 +01:00
parent 13789554ba
commit 516c417d91
10 changed files with 135 additions and 40 deletions

View file

@ -90,7 +90,7 @@ typedef struct {
typedef struct {
float rgb[3]; /* 0.0 - 2.0 */
float white; /* highest of rgb */
float white; /* r+g+b */
} lightstyle_t;
typedef struct {

View file

@ -442,7 +442,7 @@ R_RenderBrushPoly(msurface_t *fa)
R_Bind(image->texnum);
/* This is a hack ontop of a hack. Warping surfaces like those generated
by R_EmitWaterPolys() don't have a lightmap. Original Quake II therefor
by R_EmitWaterPolys() don't have a lightmap. Original Quake II therefore
negated the global intensity on those surfaces, because otherwise they
would show up much too bright. When we implemented overbright bits this
hack modified the global GL state in an incompatible way. So implement

View file

@ -365,6 +365,7 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
GLuint glTex;
glGenTextures(1, &glTex);
GL3_SelectTMU(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, glTex);
glTexImage2D(GL_TEXTURE_2D, 0, gl3_tex_solid_format,
@ -381,6 +382,7 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
drawTexturedRectangle(x, y, w, h, 0.0f, 0.0f, 1.0f, 1.0f);
glDeleteTextures(1, &glTex);
GL3_Bind(0);
}

View file

@ -95,6 +95,7 @@ GL3_TextureMode(char *string)
{
if ((glt->type != it_pic) && (glt->type != it_sky))
{
GL3_SelectTMU(GL_TEXTURE0);
GL3_Bind(glt->texnum);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
@ -109,7 +110,7 @@ GL3_TextureMode(char *string)
}
void
GL3_Bind(int texnum)
GL3_Bind(GLuint texnum)
{
extern gl3image_t *draw_chars;
@ -124,9 +125,29 @@ GL3_Bind(int texnum)
}
gl3state.currenttexture = texnum;
GL3_SelectTMU(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texnum);
}
void
GL3_BindLightmap(int lightmapnum)
{
if(lightmapnum < 0 || lightmapnum >= MAX_LIGHTMAPS)
{
R_Printf(PRINT_ALL, "WARNING: Invalid lightmapnum %i used!\n", lightmapnum);
return;
}
if (gl3state.currentlightmap == lightmapnum)
{
return;
}
gl3state.currentlightmap = lightmapnum;
GL3_SelectTMU(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gl3state.lightmap_textureIDs[lightmapnum]);
}
/*
* Returns has_alpha
*/
@ -301,7 +322,7 @@ GL3_LoadPic(char *name, byte *pic, int width, int realwidth,
image->texnum = texNum;
// glActiveTexture(GL_TEXTURE0); TODO: useful if we need >1 texture in the fragment shader
GL3_SelectTMU(GL_TEXTURE0);
GL3_Bind(texNum);
if (bits == 8)

View file

@ -53,7 +53,8 @@ GL3_LM_UploadBlock(qboolean dynamic)
texture = gl3_lms.current_lightmap_texture;
}
GL3_Bind(gl3state.lightmap_textureIDs[texture]);
GL3_SelectTMU(GL_TEXTURE1);
GL3_BindLightmap(texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -248,7 +249,7 @@ GL3_LM_BeginBuildingLightmaps(gl3model_t *m)
static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
int i;
unsigned dummy[128 * 128];
unsigned dummy[128 * 128] = {0};
memset(gl3_lms.allocated, 0, sizeof(gl3_lms.allocated));
@ -273,7 +274,8 @@ GL3_LM_BeginBuildingLightmaps(gl3model_t *m)
gl3_lms.internal_format = GL_LIGHTMAP_FORMAT;
/* initialize the dynamic lightmap texture */
GL3_Bind(gl3state.lightmap_textureIDs[0]);
GL3_SelectTMU(GL_TEXTURE1);
GL3_BindLightmap(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, gl3_lms.internal_format,

View file

@ -1553,9 +1553,6 @@ GL3_Clear(void)
glClearStencil(1);
glClear(GL_STENCIL_BUFFER_BIT);
}
glClear(GL_COLOR_BUFFER_BIT); // TODO: I added this and the next line - keep?
glClearColor(0.5, 0.5, 1, 0.5); // FIXME: this would prolly look better with black.
}
void
@ -1593,19 +1590,19 @@ GL3_BeginFrame(float camera_separation)
GL3_UpdateUBOCommon();
}
// Clamp overbrightbits
// in GL3, overbrightbits can have any positive value
// TODO: rename to gl3_overbrightbits?
if (gl_overbrightbits->modified)
{
if (gl_overbrightbits->value > 2 && gl_overbrightbits->value < 4)
gl_overbrightbits->modified = false;
if(gl_overbrightbits->value < 0.0f)
{
ri.Cvar_Set("gl_overbrightbits", "2");
}
else if (gl_overbrightbits->value > 4)
{
ri.Cvar_Set("gl_overbrightbits", "4");
ri.Cvar_Set("gl_overbrightbits", "0");
}
gl_overbrightbits->modified = false;
gl3state.uni3DData.overbrightbits = (gl_overbrightbits->value <= 0.0f) ? 1.0f : gl_overbrightbits->value;
GL3_UpdateUBO3D();
}
/* go into 2D mode */

View file

@ -220,6 +220,8 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
order += 3;
/* normals and vertexes come from the frame list */
// shadedots is set in GL3DrawAliasModel() according to rotation (around Z axis I think)
// to one of 16 (SHADEDOT_QUANT) presets in r_avertexnormal_dots
l = shadedots[verts[index_xyz].lightnormalindex];
for(j=0; j<3; ++j)
@ -621,15 +623,7 @@ GL3_DrawAliasModel(entity_t *e)
}
}
// Apply gl_overbrightbits to the mesh. If we don't do this they will appear slightly dimmer relative to walls.
if (gl_overbrightbits->value)
{
for (i = 0; i < 3; ++i)
{
shadelight[i] *= gl_overbrightbits->value;
}
}
// Note: gl_overbrightbits are now applied in shader.
/* ir goggles color override */
if ((gl3_newrefdef.rdflags & RDF_IRGOGGLES) && (currententity->flags & RF_IR_VISIBLE))

View file

@ -262,6 +262,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n
in vec4 vertColor; // GL3_ATTRIB_COLOR
out vec2 passTexCoord;
out vec2 passLMcoord;
// for UBO shared between all 3D shaders
layout (std140) uniform uni3D
@ -272,6 +273,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n
float scroll; // for SURF_FLOWING
float time;
float alpha;
float overbrightbits;
};
);
@ -299,6 +301,7 @@ static const char* fragmentCommon3D = MULTILINE_STRING(#version 150\n
float scroll; // for SURF_FLOWING
float time;
float alpha;
float overbrightbits;
};
);
@ -309,6 +312,7 @@ static const char* vertexSrc3D = MULTILINE_STRING(
void main()
{
passTexCoord = texCoord;
passLMcoord = lmTexCoord;
gl_Position = transProj * transModelView * vec4(position, 1.0);
}
);
@ -328,6 +332,8 @@ static const char* vertexSrc3Dlm = MULTILINE_STRING(
static const char* fragmentSrc3D = MULTILINE_STRING(
// it gets attributes and uniforms from fragmentCommon3D
// TODO: will prolly need another version of this without lightmap,
// also shaders for that for flow (and more?) for translucent things that have no lightmap
uniform sampler2D tex;
@ -335,15 +341,42 @@ static const char* fragmentSrc3D = MULTILINE_STRING(
{
vec4 texel = texture(tex, passTexCoord);
// TODO: something about GL_BLEND vs GL_ALPHATEST etc
// apply gamma correction and intensity
// apply intensity and gamma
texel.rgb *= intensity;
outColor.rgb = pow(texel.rgb, vec3(gamma));
outColor.a = texel.a*alpha; // I think alpha shouldn't be modified by gamma and intensity
}
);
static const char* fragmentSrc3Dlm = MULTILINE_STRING(
// it gets attributes and uniforms from fragmentCommon3D
// TODO: will prolly need another version of this without lightmap,
// also shaders for that for flow (and more?) for translucent things that have no lightmap
uniform sampler2D tex;
uniform sampler2D lightmap;
in vec2 passLMcoord;
void main()
{
vec4 texel = texture(tex, passTexCoord);
// apply intensity
texel.rgb *= intensity;
// apply lightmap
vec4 lmTex = texture(lightmap, passLMcoord);
lmTex.rgb *= overbrightbits;
outColor = lmTex*texel;
outColor.rgb = pow(outColor.rgb, vec3(gamma)); // apply gamma correction to result
outColor.a = 1; // lightmaps aren't used with translucent surfaces
//texel.a*alpha; // I think alpha shouldn't be modified by gamma and intensity
}
);
static const char* fragmentSrc3Dcolor = MULTILINE_STRING(
// it gets attributes and uniforms from fragmentCommon3D
@ -437,6 +470,7 @@ static const char* vertexSrc3Dflow = MULTILINE_STRING(
void main()
{
passTexCoord = texCoord + vec2(0, scroll);
passLMcoord = lmTexCoord;
gl_Position = transProj * transModelView * vec4(position, 1.0);
}
);
@ -449,7 +483,7 @@ static const char* vertexSrcAlias = MULTILINE_STRING(
void main()
{
passColor = vertColor;
passColor = vertColor*overbrightbits;
passTexCoord = texCoord;
gl_Position = transProj * transModelView * vec4(position, 1.0);
}
@ -717,6 +751,18 @@ initShader3D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragS
goto err_cleanup;
}
// make sure texture is GL_TEXTURE0 and lightmap is GL_TEXTURE1
GLint texLoc = glGetUniformLocation(prog, "tex");
if(texLoc != -1)
{
glUniform1i(texLoc, 0);
}
GLint lmLoc = glGetUniformLocation(prog, "lightmap");
if(lmLoc != -1)
{
glUniform1i(lmLoc, 1);
}
shaderInfo->shaderProgram = prog;
// I think the shaders aren't needed anymore once they're linked into the program
@ -757,9 +803,12 @@ static void initUBOs(void)
// the matrices will be set to something more useful later, before being used
gl3state.uni3DData.transProjMat4 = HMM_Mat4();
gl3state.uni3DData.transModelViewMat4 = HMM_Mat4();
gl3state.uni3DData.lmOffset = HMM_Vec2(0.0f, 0.0f);
gl3state.uni3DData.scroll = 0.0f;
gl3state.uni3DData.time = 0.0f;
gl3state.uni3DData.alpha = 1.0f;
// gl_overbrightbits 0 means "no scaling" which is equivalent to multiplying with 1
gl3state.uni3DData.overbrightbits = (gl_overbrightbits->value <= 0.0f) ? 1.0f : gl_overbrightbits->value;
glGenBuffers(1, &gl3state.uni3DUBO);
glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uni3DUBO);
@ -781,7 +830,7 @@ qboolean GL3_InitShaders(void)
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for color-only 2D rendering!\n");
return false;
}
if(!initShader3D(&gl3state.si3D, vertexSrc3D, fragmentSrc3D))
if(!initShader3D(&gl3state.si3D, vertexSrc3D, fragmentSrc3Dlm))
{
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for textured 3D rendering!\n");
return false;
@ -791,17 +840,19 @@ qboolean GL3_InitShaders(void)
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for flat-colored 3D rendering!\n");
return false;
}
/*
if(!initShader3D(&gl3state.si3Dlm, vertexSrc3Dlm, fragmentSrc3D))
{
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for blending 3D lightmaps rendering!\n");
return false;
}
*/
if(!initShader3D(&gl3state.si3Dturb, vertexSrc3Dwater, fragmentSrc3D))
{
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for water rendering!\n");
return false;
}
if(!initShader3D(&gl3state.si3Dflow, vertexSrc3Dflow, fragmentSrc3D))
if(!initShader3D(&gl3state.si3Dflow, vertexSrc3Dflow, fragmentSrc3Dlm))
{
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textures 3D rendering!\n");
return false;

View file

@ -303,6 +303,8 @@ BlendLightmaps(void)
int i;
msurface_t *surf, *newdrawsurf = 0;
return; // XXX: remove the whole function
/* don't bother if we're set to fullbright */
if (gl_fullbright->value)
{
@ -342,7 +344,7 @@ BlendLightmaps(void)
c_visible_lightmaps = 0;
}
GL3_UseProgram(gl3state.si3Dlm.shaderProgram);
// GL3_UseProgram(gl3state.si3Dlm.shaderProgram); XXX!
GL3_BindVAO(gl3state.vao3D);
GL3_BindVBO(gl3state.vbo3D);
@ -547,6 +549,8 @@ RenderBrushPoly(msurface_t *fa)
// R_TexEnv(GL_REPLACE); TODO!
}
GL3_BindLightmap(fa->lightmaptexturenum);
if (fa->texinfo->flags & SURF_FLOWING)
{
GL3_DrawGLFlowingPoly(fa);
@ -556,6 +560,8 @@ RenderBrushPoly(msurface_t *fa)
GL3_DrawGLPoly(fa->polys);
}
STUB_ONCE("TODO: dynamic lightmap in shaders");
/* check for lightmap modification */
for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++)
{
@ -603,7 +609,8 @@ RenderBrushPoly(msurface_t *fa)
GL3_BuildLightMap(fa, (void *)temp, smax * 4);
GL3_SetCacheState(fa);
GL3_Bind(gl3state.lightmap_textureIDs[fa->lightmaptexturenum]);
GL3_SelectTMU(GL_TEXTURE1);
GL3_BindLightmap(fa->lightmaptexturenum);
glTexSubImage2D(GL_TEXTURE_2D, 0, fa->light_s, fa->light_t,
smax, tmax, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, temp);
@ -648,6 +655,8 @@ GL3_DrawAlphaSurfaces(void)
//intens = gl3state.inverse_intensity;
STUB_ONCE("Something about inverse intensity??");
STUB_ONCE("TODO: more shaders for rendering brushes (w/o lightmap for translucent etc)");
for (s = gl3_alpha_surfaces; s != NULL; s = s->texturechain)
{
GL3_Bind(s->texinfo->image->texnum);
@ -1016,6 +1025,8 @@ RecursiveWorldNode(mnode_t *node)
}
else
{
// TODO: RenderLightmappedPoly()
/* the polygon is visible, so add it to the texture sorted chain */
image = TextureAnimation(surf->texinfo);
surf->texturechain = image->texturechain;

View file

@ -135,8 +135,9 @@ typedef struct
GLfloat scroll; // for SURF_FLOWING
GLfloat time; // for warping surfaces like water & possibly other things
GLfloat alpha; // for translucent surfaces (water, glass, ..)
GLfloat overbrightbits; // gl_overbrightbits, applied to lightmaps (and elsewhere to models)
GLfloat _padding[3]; // again, some padding to ensure this has right size
GLfloat _padding[2]; // again, some padding to ensure this has right size
} gl3Uni3D_t;
enum {
@ -156,12 +157,16 @@ typedef struct
unsigned char *d_16to8table;
// "So color textures start at 0, the dynamic lightmap texture is always 1024 and the static lighmap are 1025 up to 1036."
// yes, dynamic lightmap is 1024, but I think there can be 127 dynamic lightmaps (MAX_LIGHTMAPS == 128)
//int lightmap_textures;
GLuint lightmap_textureIDs[MAX_LIGHTMAPS]; // instead of lightmap_textures+i use lightmap_textureIDs[i]
//int currenttextures[2];
GLuint currenttexture;
//int currenttmu;
GLuint currenttexture; // bound to GL_TEXTURE0
int currentlightmap; // lightmap_textureIDs[currentlightmap] bound to GL_TEXTURE1
GLuint currenttmu; // GL_TEXTURE0 or GL_TEXTURE1
//int currenttmu; // 0 for textures, 1 for lightmaps
//GLenum currenttarget;
//float camera_separation;
@ -183,7 +188,7 @@ typedef struct
gl3ShaderInfo_t si3Dsky;
gl3ShaderInfo_t si3Dsprite; // for sprites
gl3ShaderInfo_t si3DspriteAlpha; // for sprites with alpha-testing
gl3ShaderInfo_t si3Dlm; // for blended lightmaps TODO: prolly remove and use multitexturing
//gl3ShaderInfo_t si3Dlm; // for blended lightmaps TODO: prolly remove and use multitexturing
gl3ShaderInfo_t si3Dalias; // for models
gl3ShaderInfo_t si3DaliasColor; // for models w/ flat colors
@ -371,8 +376,20 @@ extern void GL3_Draw_Flash(const float color[4]);
extern void GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
// gl3_image.c
static inline void
GL3_SelectTMU(GLenum tmu)
{
if(gl3state.currenttmu != tmu)
{
glActiveTexture(tmu);
gl3state.currenttmu = tmu;
}
}
extern void GL3_TextureMode(char *string);
extern void GL3_Bind(int texnum);
extern void GL3_Bind(GLuint texnum);
extern void GL3_BindLightmap(int lightmapnum);
extern gl3image_t *GL3_LoadPic(char *name, byte *pic, int width, int realwidth,
int height, int realheight, imagetype_t type, int bits);
extern gl3image_t *GL3_FindImage(char *name, imagetype_t type);