GL3: Support dynamic lights (mostly) + changes for that

Dynamic lights on normal world brushes work, on brush-based entities
probably not yet properly. For this I need the model matrix in the
shader to transform vertex positions and normals to worldspace
(they already are for world brushes, but not entities that might rotate
 and move etc).
Furthermore, while they dynamic lights look nice and smooth they might
need some fine tuning in the shader..

For this to work there are two bigger changes:
* the vertex data for brushes (gl3_3D_vtx_t) now also contains the
  vertex normal
  - glpoly_t contains array of gl3_3D_vtx_t instead of 7 floats
* 3D shaders now have in vec3 normal, bound to GL3_ATTRIB_NORMAL
* There's a new UBO for light data: uniLights, containing an array of
  up to 32 dynamic lights, with data copied from gl3_newrefdef.dlights
This commit is contained in:
Daniel Gibson 2017-03-27 01:02:54 +02:00
parent 6547e08c1a
commit d5cf8c2852
7 changed files with 235 additions and 75 deletions

View file

@ -110,10 +110,26 @@ GL3_PushDlights(void)
l = gl3_newrefdef.dlights; l = gl3_newrefdef.dlights;
gl3state.uniLightsData.numDynLights = gl3_newrefdef.num_dlights;
for (i = 0; i < gl3_newrefdef.num_dlights; i++, l++) for (i = 0; i < gl3_newrefdef.num_dlights; i++, l++)
{ {
gl3UniDynLight* udl = &gl3state.uniLightsData.dynLights[i];
GL3_MarkLights(l, 1 << i, gl3_worldmodel->nodes); 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 static int

View file

@ -126,6 +126,7 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa)
float s, t; float s, t;
glpoly_t *poly; glpoly_t *poly;
vec3_t total; vec3_t total;
vec3_t normal;
/* reconstruct the polygon */ /* reconstruct the polygon */
pedges = currentmodel->edges; pedges = currentmodel->edges;
@ -135,14 +136,25 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa)
/* draw texture */ /* draw texture */
poly = Hunk_Alloc(sizeof(glpoly_t) + poly = Hunk_Alloc(sizeof(glpoly_t) +
(lnumverts - 4) * VERTEXSIZE * sizeof(float)); (lnumverts - 4) * sizeof(gl3_3D_vtx_t));
poly->next = fa->polys; poly->next = fa->polys;
poly->flags = fa->flags; poly->flags = fa->flags;
fa->polys = poly; fa->polys = poly;
poly->numverts = lnumverts; 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++) for (i = 0; i < lnumverts; i++)
{ {
gl3_3D_vtx_t* vert = &poly->vertices[i];
lindex = currentmodel->surfedges[fa->firstedge + i]; lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0) if (lindex > 0)
@ -163,9 +175,9 @@ GL3_LM_BuildPolygonFromSurface(msurface_t *fa)
t /= fa->texinfo->image->height; t /= fa->texinfo->image->height;
VectorAdd(total, vec, total); VectorAdd(total, vec, total);
VectorCopy(vec, poly->verts[i]); VectorCopy(vec, vert->pos);
poly->verts[i][3] = s; vert->texCoord[0] = s;
poly->verts[i][4] = t; vert->texCoord[1] = t;
/* lightmap texture coordinates */ /* lightmap texture coordinates */
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; 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 += 8;
t /= BLOCK_HEIGHT * 16; /* fa->texinfo->texture->height; */ t /= BLOCK_HEIGHT * 16; /* fa->texinfo->texture->height; */
poly->verts[i][5] = s; vert->lmTexCoord[0] = s;
poly->verts[i][6] = t; vert->lmTexCoord[1] = t;
VectorCopy(normal, vert->normal);
} }
poly->numverts = lnumverts; poly->numverts = lnumverts;

View file

@ -109,6 +109,7 @@ CreateShaderProgram(int numShaders, const GLuint* shaders)
glBindAttribLocation(shaderProgram, GL3_ATTRIB_TEXCOORD, "texCoord"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_TEXCOORD, "texCoord");
glBindAttribLocation(shaderProgram, GL3_ATTRIB_LMTEXCOORD, "lmTexCoord"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_LMTEXCOORD, "lmTexCoord");
glBindAttribLocation(shaderProgram, GL3_ATTRIB_COLOR, "vertColor"); 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) // the following line is not necessary/implicit (as there's only one output)
// glBindFragDataLocation(shaderProgram, 0, "outColor"); XXX would this even be here? // 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 texCoord; // GL3_ATTRIB_TEXCOORD
in vec2 lmTexCoord; // GL3_ATTRIB_LMTEXCOORD in vec2 lmTexCoord; // GL3_ATTRIB_LMTEXCOORD
in vec4 vertColor; // GL3_ATTRIB_COLOR in vec4 vertColor; // GL3_ATTRIB_COLOR
in vec3 normal; // GL3_ATTRIB_NORMAL
out vec2 passTexCoord; out vec2 passTexCoord;
out vec2 passLMcoord;
// for UBO shared between all 3D shaders // for UBO shared between all 3D shaders
layout (std140) uniform uni3D layout (std140) uniform uni3D
@ -314,19 +315,55 @@ static const char* vertexSrc3D = MULTILINE_STRING(
void main() void main()
{ {
passTexCoord = texCoord; passTexCoord = texCoord;
passLMcoord = lmTexCoord;
gl_Position = transProj * transModelView * vec4(position, 1.0); 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 // it gets attributes and uniforms from vertexCommon3D
void main() void main()
{ {
//passTexCoord = texCoord; passTexCoord = texCoord + vec2(0, scroll);
passTexCoord = lmTexCoord-lmOffset; 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); 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 // 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 tex;
uniform sampler2D lightmap0; uniform sampler2D lightmap0;
@ -362,6 +412,8 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING(
uniform vec4 lmScales[4]; uniform vec4 lmScales[4];
in vec2 passLMcoord; in vec2 passLMcoord;
in vec3 passWorldCoord;
in vec3 passNormal;
void main() void main()
{ {
@ -376,6 +428,39 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING(
lmTex += texture(lightmap2, passLMcoord) * lmScales[2]; lmTex += texture(lightmap2, passLMcoord) * lmScales[2];
lmTex += texture(lightmap3, passLMcoord) * lmScales[3]; 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); i<numDynLights; ++i)
{
// I made the following up, it's probably not too cool..
// it basically checks if the light is on the right side of the surface
// and, if it is, sets intensity according to distance between light and pixel on surface
// signed distance between light and plane
float fdist = dot(passNormal, dynLights[i].lightOrigin) + planeDist;
if(fdist < 0) continue; // light is on wrong side of the plane
vec3 lightToPos = dynLights[i].lightOrigin - passWorldCoord;
float distLightToPos = length(lightToPos);
float fact = max(0, dynLights[i].lightIntensity - distLightToPos - 64); // FIXME: really - 64 for DLIGHT_CUTOFF?
lmTex.rgb += dynLights[i].lightColor * fact * (1.0/256.0);
/* // the following is kinda like phong and doesn't work yet
if(fdist < 0) continue; // light is on wrong side of the plane
float fact = dot(passNormal, normalize(dynLights[i].lightOrigin-passWorldCoord));
vec3 lightToPos = dynLights[i].lightOrigin - passWorldCoord;
float distLightToPos = length(lightToPos);
fact *= (dynLights[i].lightIntensity - distLightToPos);
//fact -= fdist;
fact = max(fact, 0);
lmTex.rgb += dynLights[i].lightColor * fact * (1.0/256.0);
*/
}
lmTex.rgb *= overbrightbits; lmTex.rgb *= overbrightbits;
outColor = lmTex*texel; outColor = lmTex*texel;
outColor.rgb = pow(outColor.rgb, vec3(gamma)); // apply gamma correction to result outColor.rgb = pow(outColor.rgb, vec3(gamma)); // apply gamma correction to result
@ -471,17 +556,6 @@ static const char* vertexSrc3Dwater = MULTILINE_STRING(
} }
); );
static const char* vertexSrc3Dflow = MULTILINE_STRING(
// it gets attributes and uniforms from vertexCommon3D
void main()
{
passTexCoord = texCoord + vec2(0, scroll);
passLMcoord = lmTexCoord;
gl_Position = transProj * transModelView * vec4(position, 1.0);
}
);
static const char* vertexSrcAlias = MULTILINE_STRING( static const char* vertexSrcAlias = MULTILINE_STRING(
// it gets attributes and uniforms from vertexCommon3D // it gets attributes and uniforms from vertexCommon3D
@ -589,7 +663,8 @@ static const char* fragmentSrcParticles = MULTILINE_STRING(
enum { enum {
GL3_BINDINGPOINT_UNICOMMON, GL3_BINDINGPOINT_UNICOMMON,
GL3_BINDINGPOINT_UNI2D, GL3_BINDINGPOINT_UNI2D,
GL3_BINDINGPOINT_UNI3D GL3_BINDINGPOINT_UNI3D,
GL3_BINDINGPOINT_UNILIGHTS
}; };
static qboolean static qboolean
@ -760,6 +835,28 @@ initShader3D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragS
goto err_cleanup; goto err_cleanup;
} }
blockIndex = glGetUniformBlockIndex(prog, "uniLights");
if(blockIndex != GL_INVALID_INDEX)
{
GLint blockSize;
glGetActiveUniformBlockiv(prog, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
if(blockSize != sizeof(gl3state.uniLightsData))
{
R_Printf(PRINT_ALL, "WARNING: OpenGL driver disagrees with us about UBO size of 'uniLights'\n");
R_Printf(PRINT_ALL, " OpenGL says %d, we say %d\n", blockSize, (int)sizeof(gl3state.uniLightsData));
goto err_cleanup;
}
glUniformBlockBinding(prog, blockIndex, GL3_BINDINGPOINT_UNILIGHTS);
}
else
{
// TODO: warn about this? only the lightmapped shaders have/need this..
R_Printf(PRINT_ALL, "WARNING: Couldn't find uniform block index 'uniLights'\n");
//goto err_cleanup;
}
// make sure texture is GL_TEXTURE0 // make sure texture is GL_TEXTURE0
GLint texLoc = glGetUniformLocation(prog, "tex"); GLint texLoc = glGetUniformLocation(prog, "tex");
@ -842,7 +939,13 @@ static void initUBOs(void)
glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uni3DUBO); glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uni3DUBO);
glBindBufferBase(GL_UNIFORM_BUFFER, GL3_BINDINGPOINT_UNI3D, gl3state.uni3DUBO); glBindBufferBase(GL_UNIFORM_BUFFER, GL3_BINDINGPOINT_UNI3D, gl3state.uni3DUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uni3DData), &gl3state.uni3DData, GL_DYNAMIC_DRAW); glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uni3DData), &gl3state.uni3DData, GL_DYNAMIC_DRAW);
gl3state.currentUBO = gl3state.uni3DUBO;
glGenBuffers(1, &gl3state.uniLightsUBO);
glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uniLightsUBO);
glBindBufferBase(GL_UNIFORM_BUFFER, GL3_BINDINGPOINT_UNILIGHTS, gl3state.uniLightsUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uniLightsData), &gl3state.uniLightsData, GL_DYNAMIC_DRAW);
gl3state.currentUBO = gl3state.uniLightsUBO;
} }
qboolean GL3_InitShaders(void) qboolean GL3_InitShaders(void)
@ -859,7 +962,7 @@ qboolean GL3_InitShaders(void)
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for color-only 2D rendering!\n"); R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for color-only 2D rendering!\n");
return false; return false;
} }
if(!initShader3D(&gl3state.si3Dlm, vertexSrc3D, fragmentSrc3Dlm)) if(!initShader3D(&gl3state.si3Dlm, vertexSrc3Dlm, fragmentSrc3Dlm))
{ {
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for textured 3D rendering with lightmap!\n"); R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for textured 3D rendering with lightmap!\n");
return false; return false;
@ -886,7 +989,7 @@ qboolean GL3_InitShaders(void)
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for water rendering!\n"); R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for water rendering!\n");
return false; return false;
} }
if(!initShader3D(&gl3state.si3DlmFlow, vertexSrc3Dflow, fragmentSrc3Dlm)) if(!initShader3D(&gl3state.si3DlmFlow, vertexSrc3DlmFlow, fragmentSrc3Dlm))
{ {
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textured 3D rendering with lightmap!\n"); R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textured 3D rendering with lightmap!\n");
return false; return false;
@ -941,10 +1044,10 @@ void GL3_ShutdownShaders(void)
*si = siZero; *si = siZero;
} }
// let's (ab)use the fact that all 3 UBO handles are consecutive fields // let's (ab)use the fact that all 4 UBO handles are consecutive fields
// of the gl3state struct // of the gl3state struct
glDeleteBuffers(3, &gl3state.uniCommonUBO); glDeleteBuffers(4, &gl3state.uniCommonUBO);
gl3state.uniCommonUBO = gl3state.uni2DUBO = gl3state.uni3DUBO = 0; gl3state.uniCommonUBO = gl3state.uni2DUBO = gl3state.uni3DUBO = gl3state.uniLightsUBO = 0;
} }
static inline void static inline void
@ -1008,3 +1111,8 @@ void GL3_UpdateUBO3D(void)
{ {
updateUBO(gl3state.uni3DUBO, sizeof(gl3state.uni3DData), &gl3state.uni3DData); updateUBO(gl3state.uni3DUBO, sizeof(gl3state.uni3DData), &gl3state.uni3DData);
} }
void GL3_UpdateUBOLights(void)
{
updateUBO(gl3state.uniLightsUBO, sizeof(gl3state.uniLightsData), &gl3state.uniLightsData);
}

View file

@ -44,7 +44,8 @@ extern int numgl3textures;
void GL3_SurfInit(void) void GL3_SurfInit(void)
{ {
// init the VAO and VBO for the standard vertexdata: 7 floats // init the VAO and VBO for the standard vertexdata: 7 floats
// (X, Y, Z), (S, T), (LMS, LMT) - last two for lightmap // (X, Y, Z), (S, T), (LMS, LMT), (normX, normY, normZ) - last two groups for lightmap/dynlights
// TODO: remove LMS, LMT? only used for lightmapped surfaces, but those need normal as well for dyn lights
glGenVertexArrays(1, &gl3state.vao3D); glGenVertexArrays(1, &gl3state.vao3D);
GL3_BindVAO(gl3state.vao3D); GL3_BindVAO(gl3state.vao3D);
@ -53,13 +54,16 @@ void GL3_SurfInit(void)
GL3_BindVBO(gl3state.vbo3D); GL3_BindVBO(gl3state.vbo3D);
glEnableVertexAttribArray(GL3_ATTRIB_POSITION); glEnableVertexAttribArray(GL3_ATTRIB_POSITION);
qglVertexAttribPointer(GL3_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 0); qglVertexAttribPointer(GL3_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(gl3_3D_vtx_t), 0);
glEnableVertexAttribArray(GL3_ATTRIB_TEXCOORD); glEnableVertexAttribArray(GL3_ATTRIB_TEXCOORD);
qglVertexAttribPointer(GL3_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 3*sizeof(GLfloat)); qglVertexAttribPointer(GL3_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(gl3_3D_vtx_t), offsetof(gl3_3D_vtx_t, texCoord));
glEnableVertexAttribArray(GL3_ATTRIB_LMTEXCOORD); glEnableVertexAttribArray(GL3_ATTRIB_LMTEXCOORD);
qglVertexAttribPointer(GL3_ATTRIB_LMTEXCOORD, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 5*sizeof(GLfloat)); qglVertexAttribPointer(GL3_ATTRIB_LMTEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(gl3_3D_vtx_t), offsetof(gl3_3D_vtx_t, lmTexCoord));
glEnableVertexAttribArray(GL3_ATTRIB_NORMAL);
qglVertexAttribPointer(GL3_ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(gl3_3D_vtx_t), offsetof(gl3_3D_vtx_t, normal));
// init VAO and VBO for model vertexdata: 9 floats // init VAO and VBO for model vertexdata: 9 floats
@ -168,11 +172,9 @@ TextureAnimation(mtexinfo_t *tex)
void void
GL3_DrawGLPoly(glpoly_t *p) GL3_DrawGLPoly(glpoly_t *p)
{ {
float* v = p->verts[0];
GL3_BindVAO(gl3state.vao3D); GL3_BindVAO(gl3state.vao3D);
GL3_BindVBO(gl3state.vbo3D); 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); glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
} }
@ -201,7 +203,7 @@ GL3_DrawGLFlowingPoly(msurface_t *fa)
GL3_BindVAO(gl3state.vao3D); GL3_BindVAO(gl3state.vao3D);
GL3_BindVBO(gl3state.vbo3D); 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); glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
} }
@ -241,10 +243,10 @@ DrawTriangleOutlines(void)
for (k=0; k<3; k++) for (k=0; k<3; k++)
{ {
vtx[0+k] = p->verts [ 0 ][ k ]; vtx[0+k] = p->vertices [ 0 ][ k ];
vtx[3+k] = p->verts [ j - 1 ][ k ]; vtx[3+k] = p->vertices [ j - 1 ][ k ];
vtx[6+k] = p->verts [ j ][ k ]; vtx[6+k] = p->vertices [ j ][ k ];
vtx[9+k] = p->verts [ 0 ][ k ]; vtx[9+k] = p->vertices [ 0 ][ k ];
} }
glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY );

View file

@ -71,6 +71,9 @@ R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface)
float s, t; float s, t;
vec3_t total; vec3_t total;
float total_s, total_t; float total_s, total_t;
vec3_t normal;
VectorCopy(warpface->plane->normal, normal);
if (numverts > 60) 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 */ /* 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; poly->next = warpface->polys;
warpface->polys = poly; warpface->polys = poly;
poly->numverts = numverts + 2; 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) 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]); s = DotProduct(verts, warpface->texinfo->vecs[0]);
t = DotProduct(verts, warpface->texinfo->vecs[1]); t = DotProduct(verts, warpface->texinfo->vecs[1]);
@ -168,16 +171,19 @@ R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface)
total_t += t; total_t += t;
VectorAdd(total, verts, total); VectorAdd(total, verts, total);
poly->verts[i + 1][3] = s; poly->vertices[i + 1].texCoord[0] = s;
poly->verts[i + 1][4] = t; poly->vertices[i + 1].texCoord[1] = t;
VectorCopy(normal, poly->vertices[i + 1].normal);
} }
VectorScale(total, (1.0 / numverts), poly->verts[0]); VectorScale(total, (1.0 / numverts), poly->vertices[0].pos);
poly->verts[0][3] = total_s / numverts; poly->vertices[0].texCoord[0] = total_s / numverts;
poly->verts[0][4] = total_t / numverts; poly->vertices[0].texCoord[1] = total_t / numverts;
VectorCopy(normal, poly->vertices[0].normal);
/* copy first vertex to last */ /* 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) for (bp = fa->polys; bp != NULL; bp = bp->next)
{ {
int numverts = bp->numverts; 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); glDrawArrays(GL_TRIANGLE_FAN, 0, numverts);
} }
} }
@ -574,7 +580,7 @@ GL3_AddSkySurface(msurface_t *fa)
{ {
for (i = 0; i < p->numverts; i++) 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); ClipSkyPolygon(p->numverts, verts[0], 0);

View file

@ -70,7 +70,7 @@ enum {
GL3_ATTRIB_TEXCOORD = 1, // for normal texture GL3_ATTRIB_TEXCOORD = 1, // for normal texture
GL3_ATTRIB_LMTEXCOORD = 2, // for lightmap GL3_ATTRIB_LMTEXCOORD = 2, // for lightmap
GL3_ATTRIB_COLOR = 3, // per-vertex color GL3_ATTRIB_COLOR = 3, // per-vertex color
// TODO: more? maybe normal GL3_ATTRIB_NORMAL = 4, // vertex normal
}; };
// TODO: do we need the following configurable? // 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 GLfloat _padding[2]; // again, some padding to ensure this has right size
} gl3Uni3D_t; } 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 { enum {
// width and height used to be 128, so now we should be able to get the same lightmap data // 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 // 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 GLuint currenttexture; // bound to GL_TEXTURE0
int currentlightmap; // lightmap_textureIDs[currentlightmap] bound to GL_TEXTURE1 int currentlightmap; // lightmap_textureIDs[currentlightmap] bound to GL_TEXTURE1
GLuint currenttmu; // GL_TEXTURE0 or GL_TEXTURE1 GLuint currenttmu; // GL_TEXTURE0 or GL_TEXTURE1
//int currenttmu; // 0 for textures, 1 for lightmaps
//GLenum currenttarget;
//float camera_separation; //float camera_separation;
//enum stereo_modes stereo_mode; //enum stereo_modes stereo_mode;
//qboolean hwgamma;
GLuint currentVAO; GLuint currentVAO;
GLuint currentVBO; GLuint currentVBO;
GLuint currentEBO; GLuint currentEBO;
@ -205,7 +216,7 @@ typedef struct
// NOTE: make sure siParticle is always the last shaderInfo (or adapt GL3_ShutdownShaders()) // NOTE: make sure siParticle is always the last shaderInfo (or adapt GL3_ShutdownShaders())
gl3ShaderInfo_t siParticle; // for particles. surprising, right? 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 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) 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; gl3UniCommon_t uniCommonData;
gl3Uni2D_t uni2DData; gl3Uni2D_t uni2DData;
gl3Uni3D_t uni3DData; gl3Uni3D_t uni3DData;
gl3UniLights_t uniLightsData;
GLuint uniCommonUBO; GLuint uniCommonUBO;
GLuint uni2DUBO; GLuint uni2DUBO;
GLuint uni3DUBO; GLuint uni3DUBO;
GLuint uniLightsUBO;
} gl3state_t; } gl3state_t;
@ -274,22 +287,6 @@ typedef struct
byte lightmap_buffers[MAX_LIGHTMAPS_PER_SURFACE][4 * BLOCK_WIDTH * BLOCK_HEIGHT]; byte lightmap_buffers[MAX_LIGHTMAPS_PER_SURFACE][4 * BLOCK_WIDTH * BLOCK_HEIGHT];
} gl3lightmapstate_t; } 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 *gl3_worldmodel;
extern gl3model_t *currentmodel; extern gl3model_t *currentmodel;
extern entity_t *currententity; extern entity_t *currententity;
@ -466,6 +463,7 @@ extern void GL3_ShutdownShaders(void);
extern void GL3_UpdateUBOCommon(void); extern void GL3_UpdateUBOCommon(void);
extern void GL3_UpdateUBO2D(void); extern void GL3_UpdateUBO2D(void);
extern void GL3_UpdateUBO3D(void); extern void GL3_UpdateUBO3D(void);
extern void GL3_UpdateUBOLights(void);
// ############ Cvars ########### // ############ Cvars ###########

View file

@ -43,9 +43,25 @@ enum {
SURF_DRAWBACKGROUND = 0x40, SURF_DRAWBACKGROUND = 0x40,
SURF_UNDERWATER = 0x80, 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 */ /* in memory representation */
typedef struct typedef struct
{ {
@ -83,7 +99,7 @@ typedef struct glpoly_s
struct glpoly_s *chain; struct glpoly_s *chain;
int numverts; int numverts;
int flags; /* for SURF_UNDERWATER (not needed anymore?) */ 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; } glpoly_t;
typedef struct msurface_s typedef struct msurface_s