diff --git a/src/client/refresh/gl3/gl3_light.c b/src/client/refresh/gl3/gl3_light.c index 2b1bc116..9be7e862 100644 --- a/src/client/refresh/gl3/gl3_light.c +++ b/src/client/refresh/gl3/gl3_light.c @@ -110,10 +110,26 @@ GL3_PushDlights(void) l = gl3_newrefdef.dlights; + gl3state.uniLightsData.numDynLights = gl3_newrefdef.num_dlights; + for (i = 0; i < gl3_newrefdef.num_dlights; i++, l++) { + gl3UniDynLight* udl = &gl3state.uniLightsData.dynLights[i]; GL3_MarkLights(l, 1 << i, gl3_worldmodel->nodes); + + VectorCopy(l->origin, udl->origin); + VectorCopy(l->color, udl->color); + udl->intensity = l->intensity; } + + assert(MAX_DLIGHTS == 32 && "If MAX_DLIGHTS changes, remember to adjust the uniform buffer definition in the shader!"); + + if(i < MAX_DLIGHTS) + { + memset(&gl3state.uniLightsData.dynLights[i], 0, (MAX_DLIGHTS-i)*sizeof(gl3state.uniLightsData.dynLights[0])); + } + + GL3_UpdateUBOLights(); } static int diff --git a/src/client/refresh/gl3/gl3_lightmap.c b/src/client/refresh/gl3/gl3_lightmap.c index ff29fc80..aa438b3e 100644 --- a/src/client/refresh/gl3/gl3_lightmap.c +++ b/src/client/refresh/gl3/gl3_lightmap.c @@ -126,6 +126,7 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa) float s, t; glpoly_t *poly; vec3_t total; + vec3_t normal; /* reconstruct the polygon */ pedges = currentmodel->edges; @@ -135,14 +136,25 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa) /* draw texture */ poly = Hunk_Alloc(sizeof(glpoly_t) + - (lnumverts - 4) * VERTEXSIZE * sizeof(float)); + (lnumverts - 4) * sizeof(gl3_3D_vtx_t)); poly->next = fa->polys; poly->flags = fa->flags; fa->polys = poly; poly->numverts = lnumverts; + VectorCopy(fa->plane->normal, normal); + + if(fa->flags & SURF_PLANEBACK) + { + // if for some reason the normal sticks to the back of the plane, invert it + // so it's usable for the shader + for (i=0; i<3; ++i) normal[i] = -normal[i]; + } + for (i = 0; i < lnumverts; i++) { + gl3_3D_vtx_t* vert = &poly->vertices[i]; + lindex = currentmodel->surfedges[fa->firstedge + i]; if (lindex > 0) @@ -163,9 +175,9 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa) t /= fa->texinfo->image->height; VectorAdd(total, vec, total); - VectorCopy(vec, poly->verts[i]); - poly->verts[i][3] = s; - poly->verts[i][4] = t; + VectorCopy(vec, vert->pos); + vert->texCoord[0] = s; + vert->texCoord[1] = t; /* lightmap texture coordinates */ s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; @@ -180,8 +192,10 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa) t += 8; t /= BLOCK_HEIGHT * 16; /* fa->texinfo->texture->height; */ - poly->verts[i][5] = s; - poly->verts[i][6] = t; + vert->lmTexCoord[0] = s; + vert->lmTexCoord[1] = t; + + VectorCopy(normal, vert->normal); } poly->numverts = lnumverts; diff --git a/src/client/refresh/gl3/gl3_shaders.c b/src/client/refresh/gl3/gl3_shaders.c index b461e343..6ec5c9bc 100644 --- a/src/client/refresh/gl3/gl3_shaders.c +++ b/src/client/refresh/gl3/gl3_shaders.c @@ -109,6 +109,7 @@ CreateShaderProgram(int numShaders, const GLuint* shaders) glBindAttribLocation(shaderProgram, GL3_ATTRIB_TEXCOORD, "texCoord"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_LMTEXCOORD, "lmTexCoord"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_COLOR, "vertColor"); + glBindAttribLocation(shaderProgram, GL3_ATTRIB_NORMAL, "normal"); // the following line is not necessary/implicit (as there's only one output) // glBindFragDataLocation(shaderProgram, 0, "outColor"); XXX would this even be here? @@ -260,9 +261,9 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n in vec2 texCoord; // GL3_ATTRIB_TEXCOORD in vec2 lmTexCoord; // GL3_ATTRIB_LMTEXCOORD in vec4 vertColor; // GL3_ATTRIB_COLOR + in vec3 normal; // GL3_ATTRIB_NORMAL out vec2 passTexCoord; - out vec2 passLMcoord; // for UBO shared between all 3D shaders layout (std140) uniform uni3D @@ -314,19 +315,55 @@ static const char* vertexSrc3D = MULTILINE_STRING( void main() { passTexCoord = texCoord; - passLMcoord = lmTexCoord; gl_Position = transProj * transModelView * vec4(position, 1.0); } ); -static const char* vertexSrc3DlmOnly = MULTILINE_STRING( +static const char* vertexSrc3Dflow = MULTILINE_STRING( // it gets attributes and uniforms from vertexCommon3D void main() { - //passTexCoord = texCoord; - passTexCoord = lmTexCoord-lmOffset; + passTexCoord = texCoord + vec2(0, scroll); + gl_Position = transProj * transModelView * vec4(position, 1.0); + } +); + +static const char* vertexSrc3Dlm = MULTILINE_STRING( + + // it gets attributes and uniforms from vertexCommon3D + + out vec2 passLMcoord; + out vec3 passWorldCoord; + out vec3 passNormal; + + void main() + { + passTexCoord = texCoord; + passLMcoord = lmTexCoord; + passWorldCoord = position; // TODO: multiply with model matrix for brush-based entities + passNormal = normalize(normal); // TODO: multiply with model matrix and normalize + + gl_Position = transProj * transModelView * vec4(position, 1.0); + } +); + +static const char* vertexSrc3DlmFlow = MULTILINE_STRING( + + // it gets attributes and uniforms from vertexCommon3D + + out vec2 passLMcoord; + out vec3 passWorldCoord; + out vec3 passNormal; + + void main() + { + passTexCoord = texCoord + vec2(0, scroll); + passLMcoord = lmTexCoord; + passWorldCoord = position; // TODO: multiply with model matrix for brush-based entities + passNormal = normalize(normal); // TODO: multiply with model matrix and normalize + gl_Position = transProj * transModelView * vec4(position, 1.0); } ); @@ -352,6 +389,19 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING( // it gets attributes and uniforms from fragmentCommon3D + struct DynLight { // gl3UniDynLight in C + vec3 lightOrigin; + float _pad; + vec3 lightColor; + float lightIntensity; + }; + + layout (std140) uniform uniLights + { + DynLight dynLights[32]; + uint numDynLights; + }; + uniform sampler2D tex; uniform sampler2D lightmap0; @@ -362,6 +412,8 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING( uniform vec4 lmScales[4]; in vec2 passLMcoord; + in vec3 passWorldCoord; + in vec3 passNormal; void main() { @@ -376,6 +428,39 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING( lmTex += texture(lightmap2, passLMcoord) * lmScales[2]; lmTex += texture(lightmap3, passLMcoord) * lmScales[3]; + float planeDist = -dot(passNormal, passWorldCoord); // signed dist to origin, hopefully like msurface_t->plane->dist + + // TODO: or is hardcoding 32 better? + for(uint i=uint(0); iverts[0]; - GL3_BindVAO(gl3state.vao3D); GL3_BindVBO(gl3state.vbo3D); - glBufferData(GL_ARRAY_BUFFER, VERTEXSIZE*sizeof(GLfloat)*p->numverts, v, GL_STREAM_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(gl3_3D_vtx_t)*p->numverts, p->vertices, GL_STREAM_DRAW); glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts); } @@ -201,7 +203,7 @@ GL3_DrawGLFlowingPoly(msurface_t *fa) GL3_BindVAO(gl3state.vao3D); GL3_BindVBO(gl3state.vbo3D); - glBufferData(GL_ARRAY_BUFFER, VERTEXSIZE*sizeof(GLfloat)*p->numverts, p->verts[0], GL_STREAM_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(gl3_3D_vtx_t)*p->numverts, p->vertices, GL_STREAM_DRAW); glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts); } @@ -241,10 +243,10 @@ DrawTriangleOutlines(void) for (k=0; k<3; k++) { - vtx[0+k] = p->verts [ 0 ][ k ]; - vtx[3+k] = p->verts [ j - 1 ][ k ]; - vtx[6+k] = p->verts [ j ][ k ]; - vtx[9+k] = p->verts [ 0 ][ k ]; + vtx[0+k] = p->vertices [ 0 ][ k ]; + vtx[3+k] = p->vertices [ j - 1 ][ k ]; + vtx[6+k] = p->vertices [ j ][ k ]; + vtx[9+k] = p->vertices [ 0 ][ k ]; } glEnableClientState( GL_VERTEX_ARRAY ); diff --git a/src/client/refresh/gl3/gl3_warp.c b/src/client/refresh/gl3/gl3_warp.c index 6e6d7f3d..18d0f97c 100644 --- a/src/client/refresh/gl3/gl3_warp.c +++ b/src/client/refresh/gl3/gl3_warp.c @@ -71,6 +71,9 @@ R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface) float s, t; vec3_t total; float total_s, total_t; + vec3_t normal; + + VectorCopy(warpface->plane->normal, normal); if (numverts > 60) { @@ -150,7 +153,7 @@ R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface) } /* add a point in the center to help keep warp valid */ - poly = Hunk_Alloc(sizeof(glpoly_t) + ((numverts - 4) + 2) * VERTEXSIZE * sizeof(float)); + poly = Hunk_Alloc(sizeof(glpoly_t) + ((numverts - 4) + 2) * sizeof(gl3_3D_vtx_t)); poly->next = warpface->polys; warpface->polys = poly; poly->numverts = numverts + 2; @@ -160,7 +163,7 @@ R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface) for (i = 0; i < numverts; i++, verts += 3) { - VectorCopy(verts, poly->verts[i + 1]); + VectorCopy(verts, poly->vertices[i + 1].pos); s = DotProduct(verts, warpface->texinfo->vecs[0]); t = DotProduct(verts, warpface->texinfo->vecs[1]); @@ -168,16 +171,19 @@ R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface) total_t += t; VectorAdd(total, verts, total); - poly->verts[i + 1][3] = s; - poly->verts[i + 1][4] = t; + poly->vertices[i + 1].texCoord[0] = s; + poly->vertices[i + 1].texCoord[1] = t; + VectorCopy(normal, poly->vertices[i + 1].normal); } - VectorScale(total, (1.0 / numverts), poly->verts[0]); - poly->verts[0][3] = total_s / numverts; - poly->verts[0][4] = total_t / numverts; + VectorScale(total, (1.0 / numverts), poly->vertices[0].pos); + poly->vertices[0].texCoord[0] = total_s / numverts; + poly->vertices[0].texCoord[1] = total_t / numverts; + VectorCopy(normal, poly->vertices[0].normal); /* copy first vertex to last */ - memcpy(poly->verts[i + 1], poly->verts[1], sizeof(poly->verts[0])); + //memcpy(poly->vertices[i + 1], poly->vertices[1], sizeof(poly->vertices[0])); + poly->vertices[i + 1] = poly->vertices[1]; } /* @@ -249,7 +255,7 @@ GL3_EmitWaterPolys(msurface_t *fa) for (bp = fa->polys; bp != NULL; bp = bp->next) { int numverts = bp->numverts; - glBufferData(GL_ARRAY_BUFFER, VERTEXSIZE*sizeof(GLfloat)*numverts, bp->verts[0], GL_STREAM_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(gl3_3D_vtx_t)*numverts, bp->vertices, GL_STREAM_DRAW); glDrawArrays(GL_TRIANGLE_FAN, 0, numverts); } } @@ -574,7 +580,7 @@ GL3_AddSkySurface(msurface_t *fa) { for (i = 0; i < p->numverts; i++) { - VectorSubtract(p->verts[i], gl3_origin, verts[i]); + VectorSubtract(p->vertices[i].pos, gl3_origin, verts[i]); } ClipSkyPolygon(p->numverts, verts[0], 0); diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 6de40c05..f0b367d3 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -70,7 +70,7 @@ enum { GL3_ATTRIB_TEXCOORD = 1, // for normal texture GL3_ATTRIB_LMTEXCOORD = 2, // for lightmap GL3_ATTRIB_COLOR = 3, // per-vertex color - // TODO: more? maybe normal + GL3_ATTRIB_NORMAL = 4, // vertex normal }; // TODO: do we need the following configurable? @@ -142,6 +142,21 @@ typedef struct GLfloat _padding[2]; // again, some padding to ensure this has right size } gl3Uni3D_t; +typedef struct +{ + vec3_t origin; + GLfloat _padding; + vec3_t color; + GLfloat intensity; +} gl3UniDynLight; + +typedef struct +{ + gl3UniDynLight dynLights[MAX_DLIGHTS]; + GLuint numDynLights; + GLfloat _padding[3]; +} gl3UniLights_t; + enum { // width and height used to be 128, so now we should be able to get the same lightmap data // that used 32 lightmaps before into one, so 4 lightmaps should be enough @@ -171,14 +186,10 @@ typedef struct 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; //enum stereo_modes stereo_mode; - //qboolean hwgamma; - GLuint currentVAO; GLuint currentVBO; GLuint currentEBO; @@ -205,7 +216,7 @@ typedef struct // NOTE: make sure siParticle is always the last shaderInfo (or adapt GL3_ShutdownShaders()) gl3ShaderInfo_t siParticle; // for particles. surprising, right? - GLuint vao3D, vbo3D; // for brushes etc, using 7 floats as vertex input (x,y,z, s,t, lms,lmt) + GLuint vao3D, vbo3D; // for brushes etc, using 1 floats as vertex input (x,y,z, s,t, lms,lmt, normX,normY,normZ) GLuint vaoAlias, vboAlias, eboAlias; // for models, using 9 floats as (x,y,z, s,t, r,g,b,a) GLuint vaoParticle, vboParticle; // for particles, using 9 floats (x,y,z, size,distance, r,g,b,a) @@ -213,9 +224,11 @@ typedef struct gl3UniCommon_t uniCommonData; gl3Uni2D_t uni2DData; gl3Uni3D_t uni3DData; + gl3UniLights_t uniLightsData; GLuint uniCommonUBO; GLuint uni2DUBO; GLuint uni3DUBO; + GLuint uniLightsUBO; } gl3state_t; @@ -274,22 +287,6 @@ typedef struct byte lightmap_buffers[MAX_LIGHTMAPS_PER_SURFACE][4 * BLOCK_WIDTH * BLOCK_HEIGHT]; } gl3lightmapstate_t; -// used for vertex array elements when drawing brushes, sprites, sky and more -// (ok, it has the layout used for rendering brushes, but is not used there) -typedef struct gl3_3D_vtx_s { - vec3_t pos; - float texCoord[2]; - float lmTexCoord[2]; // lightmap texture coordinate (sometimes unused) -} gl3_3D_vtx_t; - -// used for vertex array elements when drawing models -typedef struct gl3_alias_vtx_s { - GLfloat pos[3]; - GLfloat texCoord[2]; - GLfloat color[4]; -} gl3_alias_vtx_t; - - extern gl3model_t *gl3_worldmodel; extern gl3model_t *currentmodel; extern entity_t *currententity; @@ -466,6 +463,7 @@ extern void GL3_ShutdownShaders(void); extern void GL3_UpdateUBOCommon(void); extern void GL3_UpdateUBO2D(void); extern void GL3_UpdateUBO3D(void); +extern void GL3_UpdateUBOLights(void); // ############ Cvars ########### diff --git a/src/client/refresh/gl3/header/model.h b/src/client/refresh/gl3/header/model.h index 9c18a789..b9512084 100644 --- a/src/client/refresh/gl3/header/model.h +++ b/src/client/refresh/gl3/header/model.h @@ -43,9 +43,25 @@ enum { SURF_DRAWBACKGROUND = 0x40, SURF_UNDERWATER = 0x80, - VERTEXSIZE = 7 + //VERTEXSIZE = 7 - is 10 now, and I use a struct - TODO: REMOVE! }; +// used for vertex array elements when drawing brushes, sprites, sky and more +// (ok, it has the layout used for rendering brushes, but is not used there) +typedef struct gl3_3D_vtx_s { + vec3_t pos; + float texCoord[2]; + float lmTexCoord[2]; // lightmap texture coordinate (sometimes unused) + vec3_t normal; +} gl3_3D_vtx_t; + +// used for vertex array elements when drawing models +typedef struct gl3_alias_vtx_s { + GLfloat pos[3]; + GLfloat texCoord[2]; + GLfloat color[4]; +} gl3_alias_vtx_t; + /* in memory representation */ typedef struct { @@ -83,7 +99,7 @@ typedef struct glpoly_s struct glpoly_s *chain; int numverts; int flags; /* for SURF_UNDERWATER (not needed anymore?) */ - float verts[4][VERTEXSIZE]; /* variable sized (xyz s1t1 s2t2) */ + gl3_3D_vtx_t vertices[4]; /* variable sized */ } glpoly_t; typedef struct msurface_s