GL3: Render models (weapons, items, monsters, projectiles etc)

introducing vertex color attributes GL3_ATTRIB_COLOR (it's used for
lighting models and to render models flat-colored, I think that's used
for quad damage effect and similar)
This commit is contained in:
Daniel Gibson 2017-02-20 02:03:31 +01:00
parent 098890805f
commit de0197a8c0
4 changed files with 169 additions and 77 deletions

View file

@ -87,7 +87,6 @@ LerpVerts(int nverts, dtrivertx_t *v, dtrivertx_t *ov,
static void static void
DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp) DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
{ {
unsigned short total;
GLenum type; GLenum type;
float l; float l;
daliasframe_t *frame, *oldframe; daliasframe_t *frame, *oldframe;
@ -101,6 +100,10 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
int i; int i;
int index_xyz; int index_xyz;
float *lerp; float *lerp;
// draw without texture? used for quad damage effect etc, I think
qboolean colorOnly = 0 != (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
RF_SHELL_HALF_DAM));
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->frame * paliashdr->framesize); + currententity->frame * paliashdr->framesize);
@ -121,12 +124,13 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
alpha = 1.0; alpha = 1.0;
} }
if (currententity->flags & if (colorOnly)
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
RF_SHELL_HALF_DAM))
{ {
//glDisable(GL_TEXTURE_2D); GL3_UseProgram(gl3state.si3DaliasColor.shaderProgram);
STUB_ONCE("TODO: OpenGL: use color-only shader!"); }
else
{
GL3_UseProgram(gl3state.si3Dalias.shaderProgram);
} }
frontlerp = 1.0 - backlerp; frontlerp = 1.0 - backlerp;
@ -156,6 +160,14 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
LerpVerts(paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv); LerpVerts(paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv);
typedef struct {
GLfloat pos[3];
GLfloat texCoord[2];
GLfloat color[4];
} gl3_alias_vtx;
assert(sizeof(gl3_alias_vtx) == 9*sizeof(GLfloat));
while (1) while (1)
{ {
/* get the vertex count and primitive type */ /* get the vertex count and primitive type */
@ -177,82 +189,58 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
type = GL_TRIANGLE_STRIP; type = GL_TRIANGLE_STRIP;
} }
total = count; gl3_alias_vtx buf[count];
GLfloat vtx[3*total];
GLfloat tex[2*total];
GLfloat clr[4 * total];
unsigned int index_vtx = 0;
unsigned int index_tex = 0;
unsigned int index_clr = 0;
if (currententity->flags & if (colorOnly)
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
{ {
do int i;
for(i=0; i<count; ++i)
{ {
int j=0;
gl3_alias_vtx* cur = &buf[i];
index_xyz = order[2]; index_xyz = order[2];
order += 3; order += 3;
clr[index_clr++] = shadelight[0]; for(j=0; j<3; ++j)
clr[index_clr++] = shadelight[1]; {
clr[index_clr++] = shadelight[2]; cur->pos[j] = s_lerped[index_xyz][j];
clr[index_clr++] = alpha; cur->color[j] = shadelight[j];
}
vtx[index_vtx++] = s_lerped[index_xyz][0]; cur->color[3] = alpha;
vtx[index_vtx++] = s_lerped[index_xyz][1];
vtx[index_vtx++] = s_lerped[index_xyz][2];
} }
while (--count);
} }
else else
{ {
do int i;
for(i=0; i<count; ++i)
{ {
int j=0;
gl3_alias_vtx* cur = &buf[i];
/* texture coordinates come from the draw list */ /* texture coordinates come from the draw list */
tex[index_tex++] = ((float *) order)[0]; cur->texCoord[0] = ((float *) order)[0];
tex[index_tex++] = ((float *) order)[1]; cur->texCoord[1] = ((float *) order)[1];
index_xyz = order[2]; index_xyz = order[2];
order += 3; order += 3;
/* normals and vertexes come from the frame list */ /* normals and vertexes come from the frame list */
l = shadedots[verts[index_xyz].lightnormalindex]; l = shadedots[verts[index_xyz].lightnormalindex];
clr[index_clr++] = l * shadelight[0]; for(j=0; j<3; ++j)
clr[index_clr++] = l * shadelight[1]; {
clr[index_clr++] = l * shadelight[2]; cur->pos[j] = s_lerped[index_xyz][j];
clr[index_clr++] = alpha; cur->color[j] = l * shadelight[j];
}
vtx[index_vtx++] = s_lerped[index_xyz][0]; cur->color[3] = alpha;
vtx[index_vtx++] = s_lerped[index_xyz][1];
vtx[index_vtx++] = s_lerped[index_xyz][2];
} }
while (--count);
} }
STUB_ONCE("TODO: OpenGL!"); GL3_BindVAO(gl3state.vaoAlias);
#if 0 GL3_BindVBO(gl3state.vboAlias);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vtx); glBufferData(GL_ARRAY_BUFFER, count*sizeof(gl3_alias_vtx), buf, GL_STREAM_DRAW);
glTexCoordPointer(2, GL_FLOAT, 0, tex); glDrawArrays(type, 0, count);
glColorPointer(4, GL_FLOAT, 0, clr);
glDrawArrays(type, 0, total);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
#endif // 0
}
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE |
RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
{
STUB_ONCE("TODO: OpenGL: use textured shader!");
//glEnable(GL_TEXTURE_2D);
} }
} }
@ -271,7 +259,7 @@ DrawAliasShadow(dmdl_t *paliashdr, int posenum)
height = -lheight + 0.1f; height = -lheight + 0.1f;
/* stencilbuffer shadows */ /* stencilbuffer shadows */
STUB_ONCE("TODO: OpenGL: stencil shadows!"); STUB_ONCE("TODO: OpenGL: *proper* stencil shadows!");
#if 0 #if 0
if (have_stencil && gl_stencilshadow->value) if (have_stencil && gl_stencilshadow->value)
{ {
@ -655,6 +643,7 @@ GL3_DrawAliasModel(entity_t *e)
shadelight[2] = 0.0; shadelight[2] = 0.0;
} }
// TODO: maybe we could somehow store the non-rotated normal and do the dot in shader?
shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] *
(SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
@ -667,8 +656,8 @@ GL3_DrawAliasModel(entity_t *e)
/* locate the proper data */ /* locate the proper data */
c_alias_polys += paliashdr->num_tris; c_alias_polys += paliashdr->num_tris;
STUB_ONCE("TODO: OpenGL3 stuff!");
#if 0
/* draw all the triangles */ /* draw all the triangles */
if (currententity->flags & RF_DEPTHHACK) if (currententity->flags & RF_DEPTHHACK)
{ {
@ -676,6 +665,8 @@ GL3_DrawAliasModel(entity_t *e)
glDepthRange(gl3depthmin, gl3depthmin + 0.3 * (gl3depthmax - gl3depthmin)); glDepthRange(gl3depthmin, gl3depthmin + 0.3 * (gl3depthmax - gl3depthmin));
} }
STUB_ONCE("TODO: Weapon model left hand (special case!)");
#if 0
if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F)) if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F))
{ {
extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect, extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect,
@ -692,12 +683,15 @@ GL3_DrawAliasModel(entity_t *e)
glCullFace(GL_BACK); glCullFace(GL_BACK);
} }
#endif // 0
//glPushMatrix();
hmm_mat4 origMVmat = gl3state.uni3DData.transModelViewMat4;
glPushMatrix();
e->angles[PITCH] = -e->angles[PITCH]; e->angles[PITCH] = -e->angles[PITCH];
GL3_RotateForEntity(e); GL3_RotateForEntity(e);
e->angles[PITCH] = -e->angles[PITCH]; e->angles[PITCH] = -e->angles[PITCH];
#endif // 0
/* select skin */ /* select skin */
if (currententity->skin) if (currententity->skin)
@ -728,18 +722,19 @@ GL3_DrawAliasModel(entity_t *e)
GL3_Bind(skin->texnum); GL3_Bind(skin->texnum);
STUB_ONCE("TODO: OpenGL3 stuff!"); STUB_ONCE("TODO: OpenGL3 stuff (shade model, texenv)!");
#if 0 #if 0
/* draw it */ /* draw it */
glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH);
R_TexEnv(GL_MODULATE); R_TexEnv(GL_MODULATE);
#endif // 0
if (currententity->flags & RF_TRANSLUCENT) if (currententity->flags & RF_TRANSLUCENT)
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
#endif // 0
if ((currententity->frame >= paliashdr->num_frames) || if ((currententity->frame >= paliashdr->num_frames) ||
(currententity->frame < 0)) (currententity->frame < 0))
@ -769,12 +764,16 @@ GL3_DrawAliasModel(entity_t *e)
DrawAliasFrameLerp(paliashdr, currententity->backlerp); DrawAliasFrameLerp(paliashdr, currententity->backlerp);
STUB_ONCE("TODO: even more OpenGL3 stuff!"); STUB_ONCE("TODO: even more OpenGL3 stuff!");
//R_TexEnv(GL_REPLACE);
//glShadeModel(GL_FLAT);
//glPopMatrix();
gl3state.uni3DData.transModelViewMat4 = origMVmat;
GL3_UpdateUBO3D();
#if 0 #if 0
R_TexEnv(GL_REPLACE);
glShadeModel(GL_FLAT);
glPopMatrix();
if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F)) if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F))
{ {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -782,6 +781,8 @@ GL3_DrawAliasModel(entity_t *e)
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glCullFace(GL_FRONT); glCullFace(GL_FRONT);
} }
#endif // 0
if (currententity->flags & RF_TRANSLUCENT) if (currententity->flags & RF_TRANSLUCENT)
{ {
@ -790,9 +791,10 @@ GL3_DrawAliasModel(entity_t *e)
if (currententity->flags & RF_DEPTHHACK) if (currententity->flags & RF_DEPTHHACK)
{ {
glDepthRange(gldepthmin, gldepthmax); glDepthRange(gl3depthmin, gl3depthmax);
} }
#if 0
if (gl_shadows->value && if (gl_shadows->value &&
!(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW))) !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW)))
{ {

View file

@ -108,6 +108,7 @@ CreateShaderProgram(int numShaders, const GLuint* shaders)
glBindAttribLocation(shaderProgram, GL3_ATTRIB_POSITION, "position"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_POSITION, "position");
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");
// 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?
@ -258,6 +259,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n
in vec3 position; // GL3_ATTRIB_POSITION in vec3 position; // GL3_ATTRIB_POSITION
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
out vec2 passTexCoord; out vec2 passTexCoord;
@ -354,6 +356,62 @@ static const char* vertexSrc3Dflow = MULTILINE_STRING(
} }
); );
static const char* vertexSrcAlias = MULTILINE_STRING(
// it gets attributes and uniforms from vertexCommon3D
out vec4 passColor;
void main()
{
passColor = vertColor;
passTexCoord = texCoord;
gl_Position = transProj * transModelView * vec4(position, 1.0);
}
);
static const char* fragmentSrcAlias = MULTILINE_STRING(
// it gets attributes and uniforms from fragmentCommon3D
uniform sampler2D tex;
in vec4 passColor;
void main()
{
vec4 texel = texture(tex, passTexCoord);
// apply gamma correction and intensity
texel.rgb *= intensity;
texel.a *= alpha; // is alpha even used here?
// TODO: is this really equivalent to GL_MODULATE's behavior of texture vs glColor()?
texel *= passColor;
outColor.rgb = pow(texel.rgb, vec3(gamma));
outColor.a = texel.a; // I think alpha shouldn't be modified by gamma and intensity
}
);
static const char* fragmentSrcAliasColor = MULTILINE_STRING(
// it gets attributes and uniforms from fragmentCommon3D
in vec4 passColor;
void main()
{
vec4 texel = passColor;
// apply gamma correction and intensity
texel.rgb *= intensity;
texel.a *= alpha; // is alpha even used here?
outColor.rgb = pow(texel.rgb, vec3(gamma));
outColor.a = texel.a; // I think alpha shouldn't be modified by gamma and intensity
}
);
#undef MULTILINE_STRING #undef MULTILINE_STRING
@ -608,6 +666,18 @@ qboolean GL3_InitShaders(void)
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textures 3D rendering!\n"); R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textures 3D rendering!\n");
return false; return false;
} }
if(!initShader3D(&gl3state.si3Dalias, vertexSrcAlias, fragmentSrcAlias))
{
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for rendering textured models!\n");
return false;
}
if(!initShader3D(&gl3state.si3DaliasColor, vertexSrcAlias, fragmentSrcAliasColor))
{
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for rendering flat-colored models!\n");
return false;
}
gl3state.currentShaderProgram = 0; gl3state.currentShaderProgram = 0;
return true; return true;

View file

@ -59,6 +59,22 @@ void GL3_SurfInit(void)
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, VERTEXSIZE*sizeof(GLfloat), 5*sizeof(GLfloat));
glGenVertexArrays(1, &gl3state.vaoAlias);
GL3_BindVAO(gl3state.vaoAlias);
glGenBuffers(1, &gl3state.vboAlias);
GL3_BindVBO(gl3state.vboAlias);
glEnableVertexAttribArray(GL3_ATTRIB_POSITION);
qglVertexAttribPointer(GL3_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), 0);
glEnableVertexAttribArray(GL3_ATTRIB_TEXCOORD);
qglVertexAttribPointer(GL3_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), 3*sizeof(GLfloat));
glEnableVertexAttribArray(GL3_ATTRIB_COLOR);
qglVertexAttribPointer(GL3_ATTRIB_COLOR, 2, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), 5*sizeof(GLfloat));
} }
void GL3_SurfShutdown(void) void GL3_SurfShutdown(void)
@ -67,6 +83,11 @@ void GL3_SurfShutdown(void)
gl3state.vbo3D = 0; gl3state.vbo3D = 0;
glDeleteVertexArrays(1, &gl3state.vao3D); glDeleteVertexArrays(1, &gl3state.vao3D);
gl3state.vao3D = 0; gl3state.vao3D = 0;
glDeleteBuffers(1, &gl3state.vboAlias);
gl3state.vboAlias = 0;
glDeleteVertexArrays(1, &gl3state.vaoAlias);
gl3state.vaoAlias = 0;
} }
/* /*

View file

@ -69,6 +69,7 @@ enum {
GL3_ATTRIB_POSITION = 0, GL3_ATTRIB_POSITION = 0,
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
// TODO: more? maybe normal and color? // TODO: more? maybe normal and color?
}; };
@ -105,11 +106,6 @@ typedef struct
typedef struct typedef struct
{ {
GLuint shaderProgram; GLuint shaderProgram;
//GLint uniColor;
//GLint uniProjMatrix; // for 2D shaders this is the only one used
//GLint uniModelViewMatrix; // TODO: or even pass as 2 matrices?
} gl3ShaderInfo_t; } gl3ShaderInfo_t;
typedef struct typedef struct
@ -171,8 +167,11 @@ typedef struct
gl3ShaderInfo_t si3D; gl3ShaderInfo_t si3D;
gl3ShaderInfo_t si3Dturb; // for water etc gl3ShaderInfo_t si3Dturb; // for water etc
gl3ShaderInfo_t si3Dflow; // for flowing/scrolling things (conveyor, ..?) gl3ShaderInfo_t si3Dflow; // for flowing/scrolling things (conveyor, ..?)
gl3ShaderInfo_t si3Dalias; // for models
gl3ShaderInfo_t si3DaliasColor; // for models w/ flat colors
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 7 floats as vertex input (x,y,z, s,t, lms,lmt)
GLuint vaoAlias, vboAlias; // for models, using 9 floats as (x,y,z, s,t, r,g,b,a)
// UBOs and their data // UBOs and their data
gl3UniCommon_t uniCommonData; gl3UniCommon_t uniCommonData;