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
DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
{
unsigned short total;
GLenum type;
float l;
daliasframe_t *frame, *oldframe;
@ -101,6 +100,10 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
int i;
int index_xyz;
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
+ currententity->frame * paliashdr->framesize);
@ -121,12 +124,13 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
alpha = 1.0;
}
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
RF_SHELL_HALF_DAM))
if (colorOnly)
{
//glDisable(GL_TEXTURE_2D);
STUB_ONCE("TODO: OpenGL: use color-only shader!");
GL3_UseProgram(gl3state.si3DaliasColor.shaderProgram);
}
else
{
GL3_UseProgram(gl3state.si3Dalias.shaderProgram);
}
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);
typedef struct {
GLfloat pos[3];
GLfloat texCoord[2];
GLfloat color[4];
} gl3_alias_vtx;
assert(sizeof(gl3_alias_vtx) == 9*sizeof(GLfloat));
while (1)
{
/* get the vertex count and primitive type */
@ -177,82 +189,58 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
type = GL_TRIANGLE_STRIP;
}
total = 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;
gl3_alias_vtx buf[count];
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
if (colorOnly)
{
do
int i;
for(i=0; i<count; ++i)
{
int j=0;
gl3_alias_vtx* cur = &buf[i];
index_xyz = order[2];
order += 3;
clr[index_clr++] = shadelight[0];
clr[index_clr++] = shadelight[1];
clr[index_clr++] = shadelight[2];
clr[index_clr++] = alpha;
vtx[index_vtx++] = s_lerped[index_xyz][0];
vtx[index_vtx++] = s_lerped[index_xyz][1];
vtx[index_vtx++] = s_lerped[index_xyz][2];
for(j=0; j<3; ++j)
{
cur->pos[j] = s_lerped[index_xyz][j];
cur->color[j] = shadelight[j];
}
cur->color[3] = alpha;
}
while (--count);
}
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 */
tex[index_tex++] = ((float *) order)[0];
tex[index_tex++] = ((float *) order)[1];
cur->texCoord[0] = ((float *) order)[0];
cur->texCoord[1] = ((float *) order)[1];
index_xyz = order[2];
order += 3;
/* normals and vertexes come from the frame list */
l = shadedots[verts[index_xyz].lightnormalindex];
clr[index_clr++] = l * shadelight[0];
clr[index_clr++] = l * shadelight[1];
clr[index_clr++] = l * shadelight[2];
clr[index_clr++] = alpha;
vtx[index_vtx++] = s_lerped[index_xyz][0];
vtx[index_vtx++] = s_lerped[index_xyz][1];
vtx[index_vtx++] = s_lerped[index_xyz][2];
for(j=0; j<3; ++j)
{
cur->pos[j] = s_lerped[index_xyz][j];
cur->color[j] = l * shadelight[j];
}
cur->color[3] = alpha;
}
while (--count);
}
STUB_ONCE("TODO: OpenGL!");
#if 0
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
GL3_BindVAO(gl3state.vaoAlias);
GL3_BindVBO(gl3state.vboAlias);
glVertexPointer(3, GL_FLOAT, 0, vtx);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
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);
glBufferData(GL_ARRAY_BUFFER, count*sizeof(gl3_alias_vtx), buf, GL_STREAM_DRAW);
glDrawArrays(type, 0, count);
}
}
@ -271,7 +259,7 @@ DrawAliasShadow(dmdl_t *paliashdr, int posenum)
height = -lheight + 0.1f;
/* stencilbuffer shadows */
STUB_ONCE("TODO: OpenGL: stencil shadows!");
STUB_ONCE("TODO: OpenGL: *proper* stencil shadows!");
#if 0
if (have_stencil && gl_stencilshadow->value)
{
@ -655,6 +643,7 @@ GL3_DrawAliasModel(entity_t *e)
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] *
(SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
@ -667,8 +656,8 @@ GL3_DrawAliasModel(entity_t *e)
/* locate the proper data */
c_alias_polys += paliashdr->num_tris;
STUB_ONCE("TODO: OpenGL3 stuff!");
#if 0
/* draw all the triangles */
if (currententity->flags & RF_DEPTHHACK)
{
@ -676,6 +665,8 @@ GL3_DrawAliasModel(entity_t *e)
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))
{
extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect,
@ -692,12 +683,15 @@ GL3_DrawAliasModel(entity_t *e)
glCullFace(GL_BACK);
}
#endif // 0
//glPushMatrix();
hmm_mat4 origMVmat = gl3state.uni3DData.transModelViewMat4;
glPushMatrix();
e->angles[PITCH] = -e->angles[PITCH];
GL3_RotateForEntity(e);
e->angles[PITCH] = -e->angles[PITCH];
#endif // 0
/* select skin */
if (currententity->skin)
@ -728,18 +722,19 @@ GL3_DrawAliasModel(entity_t *e)
GL3_Bind(skin->texnum);
STUB_ONCE("TODO: OpenGL3 stuff!");
STUB_ONCE("TODO: OpenGL3 stuff (shade model, texenv)!");
#if 0
/* draw it */
glShadeModel(GL_SMOOTH);
R_TexEnv(GL_MODULATE);
#endif // 0
if (currententity->flags & RF_TRANSLUCENT)
{
glEnable(GL_BLEND);
}
#endif // 0
if ((currententity->frame >= paliashdr->num_frames) ||
(currententity->frame < 0))
@ -769,12 +764,16 @@ GL3_DrawAliasModel(entity_t *e)
DrawAliasFrameLerp(paliashdr, currententity->backlerp);
STUB_ONCE("TODO: even more OpenGL3 stuff!");
//R_TexEnv(GL_REPLACE);
//glShadeModel(GL_FLAT);
//glPopMatrix();
gl3state.uni3DData.transModelViewMat4 = origMVmat;
GL3_UpdateUBO3D();
#if 0
R_TexEnv(GL_REPLACE);
glShadeModel(GL_FLAT);
glPopMatrix();
if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F))
{
glMatrixMode(GL_PROJECTION);
@ -782,6 +781,8 @@ GL3_DrawAliasModel(entity_t *e)
glMatrixMode(GL_MODELVIEW);
glCullFace(GL_FRONT);
}
#endif // 0
if (currententity->flags & RF_TRANSLUCENT)
{
@ -790,9 +791,10 @@ GL3_DrawAliasModel(entity_t *e)
if (currententity->flags & RF_DEPTHHACK)
{
glDepthRange(gldepthmin, gldepthmax);
glDepthRange(gl3depthmin, gl3depthmax);
}
#if 0
if (gl_shadows->value &&
!(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_TEXCOORD, "texCoord");
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)
// 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 vec2 texCoord; // GL3_ATTRIB_TEXCOORD
in vec2 lmTexCoord; // GL3_ATTRIB_LMTEXCOORD
in vec4 vertColor; // GL3_ATTRIB_COLOR
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
@ -608,6 +666,18 @@ qboolean GL3_InitShaders(void)
R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textures 3D rendering!\n");
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;
return true;

View file

@ -59,6 +59,22 @@ void GL3_SurfInit(void)
glEnableVertexAttribArray(GL3_ATTRIB_LMTEXCOORD);
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)
@ -67,6 +83,11 @@ void GL3_SurfShutdown(void)
gl3state.vbo3D = 0;
glDeleteVertexArrays(1, &gl3state.vao3D);
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_TEXCOORD = 1, // for normal texture
GL3_ATTRIB_LMTEXCOORD = 2, // for lightmap
GL3_ATTRIB_COLOR = 3, // per-vertex color
// TODO: more? maybe normal and color?
};
@ -105,11 +106,6 @@ typedef struct
typedef struct
{
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;
typedef struct
@ -171,8 +167,11 @@ typedef struct
gl3ShaderInfo_t si3D;
gl3ShaderInfo_t si3Dturb; // for water etc
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 vaoAlias, vboAlias; // for models, using 9 floats as (x,y,z, s,t, r,g,b,a)
// UBOs and their data
gl3UniCommon_t uniCommonData;