diff --git a/src/client/header/ref.h b/src/client/header/ref.h index 5dd8fe7a..5816e96e 100644 --- a/src/client/header/ref.h +++ b/src/client/header/ref.h @@ -109,7 +109,7 @@ typedef struct { int num_entities; entity_t *entities; - int num_dlights; + int num_dlights; // <= 32 (MAX_DLIGHTS) dlight_t *dlights; int num_particles; diff --git a/src/client/refresh/gl3/gl3_light.c b/src/client/refresh/gl3/gl3_light.c index 701aef68..fd5d5735 100644 --- a/src/client/refresh/gl3/gl3_light.c +++ b/src/client/refresh/gl3/gl3_light.c @@ -30,13 +30,12 @@ #define DLIGHT_CUTOFF 64 static int r_dlightframecount; -vec3_t pointcolor; -cplane_t *lightplane; /* used as shadow plane */ +static vec3_t pointcolor; +static cplane_t *lightplane; /* used as shadow plane */ vec3_t lightspot; static float s_blocklights[34 * 34 * 3]; - -void +void // bit: 1 << i for light number i, will be or'ed into msurface_t::dlightbits if surface is affected by this light GL3_MarkLights(dlight_t *light, int bit, mnode_t *node) { cplane_t *splitplane; @@ -258,6 +257,9 @@ GL3_LightPoint(vec3_t p, vec3_t color) end[1] = p[1]; end[2] = p[2] - 2048; + // TODO: don't just aggregate the color, but also save position of brightest+nearest light + // for shadow position and maybe lighting on model? + r = RecursiveLightPoint(gl3_worldmodel->nodes, p, end); if (r == -1) @@ -277,7 +279,7 @@ GL3_LightPoint(vec3_t p, vec3_t color) VectorSubtract(currententity->origin, dl->origin, dist); add = dl->intensity - VectorLength(dist); - add *= (1.0 / 256); + add *= (1.0f / 256.0f); if (add > 0) { @@ -410,7 +412,7 @@ GL3_BuildLightMap(msurface_t *surf, byte *dest, int stride) if (surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) { - ri.Sys_Error(ERR_DROP, "R_BuildLightMap called for non-lit surface"); + ri.Sys_Error(ERR_DROP, "GL3_BuildLightMap called for non-lit surface"); } smax = (surf->extents[0] >> 4) + 1; diff --git a/src/client/refresh/gl3/gl3_lightmap.c b/src/client/refresh/gl3/gl3_lightmap.c index d7bdd91e..06ca74e3 100644 --- a/src/client/refresh/gl3/gl3_lightmap.c +++ b/src/client/refresh/gl3/gl3_lightmap.c @@ -1,5 +1,6 @@ /* * Copyright (C) 1997-2001 Id Software, Inc. + * Copyright (C) 2016-2017 Daniel Gibson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,28 +41,28 @@ GL3_LM_InitBlock(void) void GL3_LM_UploadBlock(qboolean dynamic) { - STUB_ONCE("TODO: Implement!"); -#if 0 int texture; int height = 0; if (dynamic) { + STUB_ONCE("TODO: dynamic lightmap!"); texture = 0; + return; } else { texture = gl3_lms.current_lightmap_texture; } - GL3_Bind(gl3state.lightmap_textures + texture); + GL3_Bind(gl3state.lightmap_textureIDs[texture]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (dynamic) { int i; - + STUB_ONCE("TODO: dynamic lightmap!"); for (i = 0; i < BLOCK_WIDTH; i++) { if (gl3_lms.allocated[i] > height) @@ -87,7 +88,6 @@ GL3_LM_UploadBlock(qboolean dynamic) "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n"); } } -#endif // 0 } /* @@ -270,17 +270,12 @@ GL3_LM_BeginBuildingLightmaps(gl3model_t *m) gl3_newrefdef.lightstyles = lightstyles; STUB_ONCE("TODO: IMPLEMENT!"); -#if 0 - if (!gl_state.lightmap_textures) - { - gl3state.lightmap_textures = TEXNUM_LIGHTMAPS; - } gl3_lms.current_lightmap_texture = 1; gl3_lms.internal_format = GL_LIGHTMAP_FORMAT; - +#if 0 /* initialize the dynamic lightmap texture */ - GL3_Bind(gl_state.lightmap_textures + 0); + GL3_Bind(gl3state.lightmap_textureIDs[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, diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index 56920540..ce12a7aa 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -514,6 +514,8 @@ GL3_Init(void) R_Printf(PRINT_ALL, " - OpenGL Debug Output: Not Supported\n"); } + // generate texture handles for all possible lightmaps + glGenTextures(MAX_LIGHTMAPS, gl3state.lightmap_textureIDs); GL3_SetDefaultState(); diff --git a/src/client/refresh/gl3/gl3_shaders.c b/src/client/refresh/gl3/gl3_shaders.c index e27575de..3ad9332e 100644 --- a/src/client/refresh/gl3/gl3_shaders.c +++ b/src/client/refresh/gl3/gl3_shaders.c @@ -268,6 +268,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n { mat4 transProj; mat4 transModelView; // TODO: or maybe transViewProj and transModel ?? + vec2 lmOffset; float scroll; // for SURF_FLOWING float time; float alpha; @@ -294,6 +295,7 @@ static const char* fragmentCommon3D = MULTILINE_STRING(#version 150\n { mat4 transProj; mat4 transModelView; // TODO: or maybe transViewProj and transModel ?? + vec2 lmOffset; float scroll; // for SURF_FLOWING float time; float alpha; @@ -311,6 +313,18 @@ static const char* vertexSrc3D = MULTILINE_STRING( } ); +static const char* vertexSrc3Dlm = MULTILINE_STRING( + + // it gets attributes and uniforms from vertexCommon3D + + void main() + { + //passTexCoord = texCoord; + passTexCoord = lmTexCoord-lmOffset; + gl_Position = transProj * transModelView * vec4(position, 1.0); + } +); + static const char* fragmentSrc3D = MULTILINE_STRING( // it gets attributes and uniforms from fragmentCommon3D @@ -777,6 +791,11 @@ 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"); diff --git a/src/client/refresh/gl3/gl3_surf.c b/src/client/refresh/gl3/gl3_surf.c index 7f8f3b63..ea6c7c3f 100644 --- a/src/client/refresh/gl3/gl3_surf.c +++ b/src/client/refresh/gl3/gl3_surf.c @@ -271,64 +271,26 @@ static void DrawGLPolyChain(glpoly_t *p, float soffset, float toffset) { STUB_ONCE("TODO: Implement!"); -#if 0 - if ((soffset == 0) && (toffset == 0)) + + if(gl3state.uni3DData.lmOffset.X != soffset || gl3state.uni3DData.lmOffset.Y != toffset) { - for ( ; p != 0; p = p->chain) - { - float *v; - - v = p->verts[0]; - - if (v == NULL) - { - fprintf(stderr, "BUGFIX: R_DrawGLPolyChain: v==NULL\n"); - return; - } - - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v ); - glTexCoordPointer( 2, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v+5 ); - glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - } + gl3state.uni3DData.lmOffset = HMM_Vec2(soffset, toffset); + GL3_UpdateUBO3D(); } - else + + for ( ; p != NULL; p = p->chain) { - for ( ; p != 0; p = p->chain) + float* v = p->verts[0]; + + if (v == NULL) { - float *v; - int j; - - v = p->verts[0]; - - GLfloat tex[2*p->numverts]; - unsigned int index_tex = 0; - - for ( j = 0; j < p->numverts; j++, v += VERTEXSIZE ) - { - tex[index_tex++] = v [ 5 ] - soffset; - tex[index_tex++] = v [ 6 ] - toffset; - } - - v = p->verts [ 0 ]; - - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + fprintf(stderr, "BUGFIX: DrawGLPolyChain: v==NULL\n"); + return; } + + glBufferData(GL_ARRAY_BUFFER, VERTEXSIZE*sizeof(GLfloat)*p->numverts, v, GL_STREAM_DRAW); + glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts); } -#endif // 0 } /* @@ -353,16 +315,16 @@ BlendLightmaps(void) } STUB_ONCE("TODO: Implement!"); -#if 0 +#if 1 /* don't bother writing Z */ glDepthMask(0); /* set the appropriate blending mode unless we're only looking at the lightmaps. */ - if (!gl_lightmap->value) + if ( 1 ) // TODO !gl_lightmap->value) { glEnable(GL_BLEND); - +#if 0 if (gl_saturatelighting->value) { glBlendFunc(GL_ONE, GL_ONE); @@ -371,6 +333,10 @@ BlendLightmaps(void) { glBlendFunc(GL_ZERO, GL_SRC_COLOR); } +#endif // 0 + + glBlendFunc(GL_ZERO, GL_SRC_COLOR); + } if (currentmodel == gl3_worldmodel) @@ -378,6 +344,10 @@ BlendLightmaps(void) c_visible_lightmaps = 0; } + GL3_UseProgram(gl3state.si3Dlm.shaderProgram); + GL3_BindVAO(gl3state.vao3D); + GL3_BindVBO(gl3state.vbo3D); + /* render static lightmaps first */ for (i = 1; i < MAX_LIGHTMAPS; i++) { @@ -388,7 +358,7 @@ BlendLightmaps(void) c_visible_lightmaps++; } - GL3_Bind(gl_state.lightmap_textures + i); + GL3_Bind(gl3state.lightmap_textureIDs[i]); for (surf = gl3_lms.lightmap_surfaces[i]; surf != 0; @@ -397,11 +367,12 @@ BlendLightmaps(void) if (surf->polys) { // Apply overbright bits to the static lightmaps + /* if (gl_overbrightbits->value) { R_TexEnv(GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, gl_overbrightbits->value); - } + } */ DrawGLPolyChain(surf->polys, 0, 0); } @@ -409,6 +380,7 @@ BlendLightmaps(void) } } +#if 0 /* render dynamic lightmaps */ if (gl_dynamic->value) { @@ -439,7 +411,7 @@ BlendLightmaps(void) base += (surf->dlight_t * BLOCK_WIDTH + surf->dlight_s) * LIGHTMAP_BYTES; - R_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES); + GL3_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES); } else { @@ -485,7 +457,7 @@ BlendLightmaps(void) base += (surf->dlight_t * BLOCK_WIDTH + surf->dlight_s) * LIGHTMAP_BYTES; - R_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES); + GL3_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES); } } @@ -512,6 +484,7 @@ BlendLightmaps(void) } } } +#endif // 0 /* restore state */ glDisable(GL_BLEND); @@ -614,7 +587,7 @@ RenderBrushPoly(msurface_t *fa) } STUB_ONCE("TODO: lightmap support (=> esp. LM textures)") -#if 0 + // TODO: 2D texture array für lightmaps? if (is_dynamic) { @@ -622,12 +595,14 @@ RenderBrushPoly(msurface_t *fa) (fa->styles[maps] == 0)) && (fa->dlightframe != gl3_framecount)) { + // undo dynamic light changes, put into non-dynamic lightmap chain? + unsigned temp[34 * 34]; int smax, tmax; smax = (fa->extents[0] >> 4) + 1; tmax = (fa->extents[1] >> 4) + 1; - +#if 0 GL3_BuildLightMap(fa, (void *)temp, smax * 4); GL3_SetCacheState(fa); @@ -638,15 +613,16 @@ RenderBrushPoly(msurface_t *fa) fa->lightmapchain = gl3_lms.lightmap_surfaces[fa->lightmaptexturenum]; gl3_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; +#endif // 0 } else { + // dynamic lights: add to dynamic lightmap chain fa->lightmapchain = gl3_lms.lightmap_surfaces[0]; gl3_lms.lightmap_surfaces[0] = fa; } } - else -#endif // 0 + else // non-dynamic lightmap chain { fa->lightmapchain = gl3_lms.lightmap_surfaces[fa->lightmaptexturenum]; gl3_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 973b1cb3..57f5c197 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -130,13 +130,22 @@ typedef struct hmm_mat4 transProjMat4; hmm_mat4 transModelViewMat4; + hmm_vec2 lmOffset; + GLfloat scroll; // for SURF_FLOWING GLfloat time; // for warping surfaces like water & possibly other things GLfloat alpha; // for translucent surfaces (water, glass, ..) - GLfloat _padding; // again, some padding to ensure this has right size + GLfloat _padding[3]; // again, some padding to ensure this has right size } gl3Uni3D_t; +enum { + BLOCK_WIDTH = 128, + BLOCK_HEIGHT = 128, + LIGHTMAP_BYTES = 4, + MAX_LIGHTMAPS = 128 +}; + typedef struct { // TODO: what of this do we need? @@ -148,6 +157,7 @@ typedef struct unsigned char *d_16to8table; //int lightmap_textures; + GLuint lightmap_textureIDs[MAX_LIGHTMAPS]; // instead of lightmap_textures+i use lightmap_textureIDs[i] //int currenttextures[2]; GLuint currenttexture; @@ -173,6 +183,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 si3Dalias; // for models gl3ShaderInfo_t si3DaliasColor; // for models w/ flat colors @@ -235,17 +246,10 @@ enum {MAX_GL3TEXTURES = 1024}; // include this down here so it can use gl3image_t #include "model.h" -enum { - BLOCK_WIDTH = 128, - BLOCK_HEIGHT = 128, - LIGHTMAP_BYTES = 4, - MAX_LIGHTMAPS = 128 -}; - typedef struct { int internal_format; - int current_lightmap_texture; + int current_lightmap_texture; // index into gl3state.lightmap_textureIDs[] msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];