From 90fa50f4e170192cce8b5b3321fbf7c4d9be7a41 Mon Sep 17 00:00:00 2001 From: havoc Date: Sun, 25 Aug 2002 15:45:41 +0000 Subject: [PATCH] got rid of R_Mesh_Draw and R_Mesh_DrawPolygon, now all 3D geometry is drawn using R_Mesh_Draw_GetBuffer and R_Mesh_Render git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2285 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_backend.c | 247 +------------------------- gl_backend.h | 11 +- gl_models.c | 485 ++++++++++++++++++++++----------------------------- gl_rmain.c | 27 +++ gl_rsurf.c | 47 ++--- render.h | 4 + 6 files changed, 264 insertions(+), 557 deletions(-) diff --git a/gl_backend.c b/gl_backend.c index 1dff96e7..0c7c3150 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -70,8 +70,6 @@ void GL_PrintError(int errornumber, char *filename, int linenumber) float r_mesh_farclip; -int polyindexarray[768]; - static float viewdist; // sign bits (true if negative) for vpn[] entries, so quick integer compares can be used instead of float compares static int vpnbit0, vpnbit1, vpnbit2; @@ -293,8 +291,6 @@ static void gl_backend_newmap(void) void gl_backend_init(void) { - int i; - Cvar_RegisterVariable(&r_render); Cvar_RegisterVariable(&gl_dither); Cvar_RegisterVariable(&gl_lockarrays); @@ -308,12 +304,6 @@ void gl_backend_init(void) Cvar_RegisterVariable(&gl_mesh_drawmode); R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap); gl_backend_bufferchanges(true); - for (i = 0;i < 256;i++) - { - polyindexarray[i*3+0] = 0; - polyindexarray[i*3+1] = i + 1; - polyindexarray[i*3+2] = i + 2; - } } int arraylocked = false; @@ -1000,219 +990,6 @@ void R_Mesh_AddTransparent(void) currenttransvertex = 0; } -void R_Mesh_Draw(const rmeshinfo_t *m) -{ - // these are static because gcc runs out of virtual registers otherwise - static int i, j, overbright, *index; - static float *in, scaler; - static float cr, cg, cb, ca; - static buf_mesh_t *mesh; - static buf_vertex_t *vert; - static buf_fcolor_t *fcolor; - static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS]; - - if (!backendactive) - Sys_Error("R_Mesh_Draw: called when backend is not active\n"); - - if (m->index == NULL - || !m->numtriangles - || m->vertex == NULL - || !m->numverts) - Host_Error("R_Mesh_Draw: no triangles or verts\n"); - - // ignore meaningless alpha meshs - if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)) - { - if (m->color) - { - for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep) - if (*in >= 0.01f) - break; - if (i == m->numverts) - return; - } - else if (m->ca < 0.01f) - return; - } - - if (!backendactive) - Sys_Error("R_Mesh_Draw: called when backend is not active\n"); - -#ifdef DEBUGGL - for (i = 0;i < m->numtriangles * 3;i++) - if ((unsigned int) m->index[i] >= (unsigned int) m->numverts) - Host_Error("R_Mesh_Draw: invalid index (%i of %i verts)\n", m->index, m->numverts); -#endif - - // LordHavoc: removed this error condition because with floatcolors 0, - // the 3DFX driver works with very large meshs - // FIXME: we can work around this by falling back on non-array renderer if buffers are too big - //if (m->numtriangles > 1024 || m->numverts > 3072) - //{ - // Con_Printf("R_Mesh_Draw: mesh too big for 3DFX drivers, rejected\n"); - // return; - //} - - i = max(m->numtriangles * 3, m->numverts); - if (overflowedverts < i) - overflowedverts = i; - - if (m->numtriangles > max_meshs || m->numverts > max_verts) - { - Con_Printf("R_Mesh_Draw: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n"); - return; - } - - if (m->transparent) - { - overflowedtransverts += max(m->numtriangles * 3, m->numverts); - if (currenttransmesh >= max_transmeshs || (currenttranstriangle + m->numtriangles) > max_transmeshs || (currenttransvertex + m->numverts) > max_transverts) - { - if (!transranout) - { - Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n"); - transranout = true; - } - return; - } - - c_transmeshs++; - c_transtris += m->numtriangles; - vert = &buf_transvertex[currenttransvertex]; - fcolor = &buf_transfcolor[currenttransvertex]; - for (i = 0;i < backendunits;i++) - texcoord[i] = &buf_transtexcoord[i][currenttransvertex]; - - // transmesh is only for storage of transparent meshs until they - // are inserted into the main mesh array - mesh = &buf_transmesh[currenttransmesh++]; - mesh->firsttriangle = currenttranstriangle; - mesh->firstvert = currenttransvertex; - index = &buf_transtri[currenttranstriangle].index[0]; - - currenttranstriangle += m->numtriangles; - currenttransvertex += m->numverts; - } - else - { - if (currentmesh) - { - R_Mesh_Render(); - Con_Printf("mesh queue not empty, flushing.\n"); - } - - c_meshs++; - c_meshtris += m->numtriangles; - vert = &buf_vertex[currentvertex]; - fcolor = &buf_fcolor[currentvertex]; - for (i = 0;i < backendunits;i++) - texcoord[i] = &buf_texcoord[i][currentvertex]; - - // opaque meshs are rendered directly - mesh = &buf_mesh[currentmesh++]; - mesh->firsttriangle = currenttriangle; - mesh->firstvert = currentvertex; - index = &buf_tri[currenttriangle].index[0]; - - currenttriangle += m->numtriangles; - currentvertex += m->numverts; - } - - // code shared for transparent and opaque meshs - memcpy(index, m->index, sizeof(int[3]) * m->numtriangles); - mesh->blendfunc1 = m->blendfunc1; - mesh->blendfunc2 = m->blendfunc2; - mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite); - mesh->depthtest = !m->depthdisable; - mesh->triangles = m->numtriangles; - mesh->verts = m->numverts; - - overbright = false; - scaler = 1; - if (m->blendfunc1 == GL_DST_COLOR) - { - // check if it is a 2x modulate with framebuffer - if (m->blendfunc2 == GL_SRC_COLOR) - scaler *= 0.5f; - } - else if (m->blendfunc2 != GL_SRC_COLOR) - { - if (m->tex[0]) - { - overbright = gl_combine.integer; - if (overbright) - scaler *= 0.25f; - } - scaler *= overbrightscale; - } - - - j = -1; - for (i = 0;i < backendunits;i++) - { - if ((mesh->textures[i] = m->tex[i])) - j = i; - mesh->texturergbscale[i] = m->texrgbscale[i]; - if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4) - mesh->texturergbscale[i] = 1; - } - if (overbright && j >= 0) - mesh->texturergbscale[j] = 4; - - if (m->vertexstep != sizeof(buf_vertex_t)) - { - for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep) - { - vert[i].v[0] = in[0]; - vert[i].v[1] = in[1]; - vert[i].v[2] = in[2]; - } - } - else - memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t)); - - if (m->color) - { - for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep) - { - fcolor[i].c[0] = in[0] * scaler; - fcolor[i].c[1] = in[1] * scaler; - fcolor[i].c[2] = in[2] * scaler; - fcolor[i].c[3] = in[3]; - } - } - else - { - cr = m->cr * scaler; - cg = m->cg * scaler; - cb = m->cb * scaler; - ca = m->ca; - for (i = 0;i < m->numverts;i++) - { - fcolor[i].c[0] = cr; - fcolor[i].c[1] = cg; - fcolor[i].c[2] = cb; - fcolor[i].c[3] = ca; - } - } - - for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++) - { - if (j >= backendunits) - Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits); - if (m->texcoordstep[j] != sizeof(buf_texcoord_t)) - { - for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j]) - { - texcoord[j][i].t[0] = in[0]; - texcoord[j][i].t[1] = in[1]; - } - } - else - memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t)); - } -} - // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct // (this is used for very high speed rendering, no copying) int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright) @@ -1223,11 +1000,11 @@ int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright) buf_mesh_t *mesh; if (!backendactive) - Sys_Error("R_Mesh_Draw: called when backend is not active\n"); + Sys_Error("R_Mesh_Draw_GetBuffer: called when backend is not active\n"); if (!m->numtriangles || !m->numverts) - Host_Error("R_Mesh_Draw: no triangles or verts\n"); + Host_Error("R_Mesh_Draw_GetBuffer: no triangles or verts\n"); // LordHavoc: removed this error condition because with floatcolors 0, // the 3DFX driver works with very large meshs @@ -1255,7 +1032,7 @@ int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright) { if (!transranout) { - Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n"); + Con_Printf("R_Mesh_Draw_GetBuffer: ran out of room for transparent meshs\n"); transranout = true; } return false; @@ -1348,24 +1125,6 @@ int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright) return true; } -void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts) -{ - m->index = polyindexarray; - m->numverts = numverts; - m->numtriangles = numverts - 2; - if (m->numtriangles < 1) - { - Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n"); - return; - } - if (m->numtriangles >= 256) - { - Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n"); - return; - } - R_Mesh_Draw(m); -} - /* ============================================================================== diff --git a/gl_backend.h b/gl_backend.h index 01dc1060..2efbd9a0 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -68,20 +68,13 @@ void R_Mesh_ClearDepth(void); // (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_Render(void); -// queues a mesh to be rendered (invokes Render if queue is full) -// (only valid between R_Mesh_Start and R_Mesh_Finish) -void R_Mesh_Draw(const rmeshinfo_t *m); - // renders the queued transparent meshs // (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_AddTransparent(void); -// ease-of-use frontend to R_Mesh_Draw, set up meshinfo, except for index and numtriangles and numverts, then call this -// (only valid between R_Mesh_Start and R_Mesh_Finish) -void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts); - // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct -// (this is used for very high speed rendering, no copying) +// (it is up to the caller to fill in the geometry data) +// (make sure you scale your colors by the colorscale field) // (only valid between R_Mesh_Start and R_Mesh_Finish) int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright); diff --git a/gl_models.c b/gl_models.c index 47efa6d2..8b40edda 100644 --- a/gl_models.c +++ b/gl_models.c @@ -20,8 +20,6 @@ float *aliasvertnorm; int *aliasvertusage; zymbonematrix *zymbonepose; -rmeshinfo_t aliasmeshinfo; - mempool_t *gl_models_mempool; void gl_models_start(void) @@ -200,41 +198,6 @@ void R_AliasLerpVerts(int vertcount, } } -void R_DrawModelMesh(rtexture_t *skin, float *colors, float cred, float cgreen, float cblue) -{ - aliasmeshinfo.tex[0] = R_GetTexture(skin); - aliasmeshinfo.color = colors; - if (colors == NULL) - { - aliasmeshinfo.cr = cred; - aliasmeshinfo.cg = cgreen; - aliasmeshinfo.cb = cblue; - aliasmeshinfo.ca = currentrenderentity->alpha; - } - - c_alias_polys += aliasmeshinfo.numtriangles; - R_Mesh_Draw(&aliasmeshinfo); - R_Mesh_Render(); - - // leave it in a state for additional passes - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE; -} - -void R_TintModel(float *in, float *out, int verts, float r, float g, float b) -{ - int i; - for (i = 0;i < verts;i++) - { - out[0] = in[0] * r; - out[1] = in[1] * g; - out[2] = in[2] * b; - out[3] = in[3]; - in += 4; - out += 4; - } -} - skinframe_t *R_FetchSkinFrame(void) { model_t *model = currentrenderentity->model; @@ -272,231 +235,197 @@ void R_SetupMDLMD2Frames(float colorr, float colorg, float colorb) void R_DrawQ1Q2AliasModel (float fog) { + int c, pantsfullbright, shirtfullbright, colormapped; + float pantscolor[3], shirtcolor[3]; + qbyte *bcolor; + rmeshbufferinfo_t m; model_t *model; skinframe_t *skinframe; model = currentrenderentity->model; skinframe = R_FetchSkinFrame(); - if (fog && !(currentrenderentity->effects & EF_ADDITIVE)) - { - R_SetupMDLMD2Frames(1 - fog, 1 - fog, 1 - fog); - - memset(&aliasmeshinfo, 0, sizeof(aliasmeshinfo)); - - aliasmeshinfo.vertex = aliasvert; - aliasmeshinfo.vertexstep = sizeof(float[4]); - aliasmeshinfo.numverts = model->numverts; - aliasmeshinfo.numtriangles = model->numtris; - aliasmeshinfo.index = model->mdlmd2data_indices; - aliasmeshinfo.colorstep = sizeof(float[4]); - aliasmeshinfo.texcoords[0] = model->mdlmd2data_texcoords; - aliasmeshinfo.texcoordstep[0] = sizeof(float[2]); + colormapped = !skinframe->merged || (currentrenderentity->colormap >= 0 && skinframe->base && (skinframe->pants || skinframe->shirt)); + if (!colormapped && !fog && !skinframe->glow && !skinframe->fog) + { + // fastpath for the normal situation (one texture) + memset(&m, 0, sizeof(m)); if (currentrenderentity->effects & EF_ADDITIVE) { - aliasmeshinfo.transparent = true; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE; + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; } else if (currentrenderentity->alpha != 1.0 || skinframe->fog != NULL) { - aliasmeshinfo.transparent = true; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; } else { - aliasmeshinfo.transparent = false; - aliasmeshinfo.blendfunc1 = GL_ONE; - aliasmeshinfo.blendfunc2 = GL_ZERO; + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; } + m.numtriangles = model->numtris; + m.numverts = model->numverts; + m.tex[0] = R_GetTexture(skinframe->merged); - if (skinframe->base || skinframe->pants || skinframe->shirt || skinframe->glow || skinframe->merged) + c_alias_polys += m.numtriangles; + if (R_Mesh_Draw_GetBuffer(&m, true)) { - if (currentrenderentity->colormap >= 0 && (skinframe->base || skinframe->pants || skinframe->shirt)) - { - int c; - qbyte *color; - if (skinframe->base) - R_DrawModelMesh(skinframe->base, aliasvertcolor, 0, 0, 0); - if (skinframe->pants) - { - c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges - color = (qbyte *) (&d_8to24table[c]); - if (c >= 224) // fullbright ranges - R_DrawModelMesh(skinframe->pants, NULL, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - else - { - R_TintModel(aliasvertcolor, aliasvertcolor2, model->numverts, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - R_DrawModelMesh(skinframe->pants, aliasvertcolor2, 0, 0, 0); - } - } - if (skinframe->shirt) - { - c = currentrenderentity->colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges - color = (qbyte *) (&d_8to24table[c]); - if (c >= 224) // fullbright ranges - R_DrawModelMesh(skinframe->shirt, NULL, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - else - { - R_TintModel(aliasvertcolor, aliasvertcolor2, model->numverts, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - R_DrawModelMesh(skinframe->shirt, aliasvertcolor2, 0, 0, 0); - } - } - } - else - { - if (skinframe->merged) - R_DrawModelMesh(skinframe->merged, aliasvertcolor, 0, 0, 0); - else - { - if (skinframe->base) R_DrawModelMesh(skinframe->base, aliasvertcolor, 0, 0, 0); - if (skinframe->pants) R_DrawModelMesh(skinframe->pants, aliasvertcolor, 0, 0, 0); - if (skinframe->shirt) R_DrawModelMesh(skinframe->shirt, aliasvertcolor, 0, 0, 0); - } - } - if (skinframe->glow) R_DrawModelMesh(skinframe->glow, NULL, 1 - fog, 1 - fog, 1 - fog); - } - else - R_DrawModelMesh(0, NULL, 1 - fog, 1 - fog, 1 - fog); - - aliasmeshinfo.tex[0] = R_GetTexture(skinframe->fog); - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE; - aliasmeshinfo.color = NULL; + memcpy(m.index, model->mdlmd2data_indices, m.numtriangles * sizeof(int[3])); + memcpy(m.texcoords[0], model->mdlmd2data_texcoords, m.numverts * sizeof(float[2])); - aliasmeshinfo.cr = fogcolor[0]; - aliasmeshinfo.cg = fogcolor[1]; - aliasmeshinfo.cb = fogcolor[2]; - aliasmeshinfo.ca = currentrenderentity->alpha * fog; + aliasvert = m.vertex; + aliasvertcolor = m.color; + R_SetupMDLMD2Frames(m.colorscale * (1 - fog), m.colorscale * (1 - fog), m.colorscale * (1 - fog)); + aliasvert = aliasvertbuf; + aliasvertcolor = aliasvertcolorbuf; - c_alias_polys += aliasmeshinfo.numtriangles; - R_Mesh_Draw(&aliasmeshinfo); - R_Mesh_Render(); + R_Mesh_Render(); + } + return; } - else if (currentrenderentity->colormap >= 0 || !skinframe->merged || skinframe->glow || !r_quickmodels.integer) - { - R_SetupMDLMD2Frames(1 - fog, 1 - fog, 1 - fog); - memset(&aliasmeshinfo, 0, sizeof(aliasmeshinfo)); + R_SetupMDLMD2Frames(1 - fog, 1 - fog, 1 - fog); - aliasmeshinfo.vertex = aliasvert; - aliasmeshinfo.vertexstep = sizeof(float[4]); - aliasmeshinfo.numverts = model->numverts; - aliasmeshinfo.numtriangles = model->numtris; - aliasmeshinfo.index = model->mdlmd2data_indices; - aliasmeshinfo.colorstep = sizeof(float[4]); - aliasmeshinfo.texcoords[0] = model->mdlmd2data_texcoords; - aliasmeshinfo.texcoordstep[0] = sizeof(float[2]); + if (colormapped) + { + // 128-224 are backwards ranges + c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; + bcolor = (qbyte *) (&d_8to24table[c]); + pantsfullbright = c >= 224; + VectorScale(bcolor, (1.0f / 255.0f), pantscolor); + c = (currentrenderentity->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12; + bcolor = (qbyte *) (&d_8to24table[c]); + shirtfullbright = c >= 224; + VectorScale(bcolor, (1.0f / 255.0f), shirtcolor); + } + else + { + pantscolor[0] = pantscolor[1] = pantscolor[2] = shirtcolor[0] = shirtcolor[1] = shirtcolor[2] = 1; + pantsfullbright = shirtfullbright = false; + } - if (currentrenderentity->effects & EF_ADDITIVE) - { - aliasmeshinfo.transparent = true; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE; - } - else if (currentrenderentity->alpha != 1.0 || skinframe->fog != NULL) - { - aliasmeshinfo.transparent = true; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else - { - aliasmeshinfo.transparent = false; - aliasmeshinfo.blendfunc1 = GL_ONE; - aliasmeshinfo.blendfunc2 = GL_ZERO; - } + memset(&m, 0, sizeof(m)); + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (currentrenderentity->alpha != 1.0 || skinframe->fog != NULL) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } + m.numtriangles = model->numtris; + m.numverts = model->numverts; + m.tex[0] = colormapped ? R_GetTexture(skinframe->base) : R_GetTexture(skinframe->merged); + if (R_Mesh_Draw_GetBuffer(&m, true)) + { + c_alias_polys += m.numtriangles; + R_ModulateColors(aliasvertcolor, m.color, m.numverts, m.colorscale, m.colorscale, m.colorscale); + memcpy(m.index, model->mdlmd2data_indices, m.numtriangles * sizeof(int[3])); + memcpy(m.vertex, aliasvert, m.numverts * sizeof(float[4])); + memcpy(m.texcoords[0], model->mdlmd2data_texcoords, m.numverts * sizeof(float[2])); + R_Mesh_Render(); + } - if (skinframe->base || skinframe->pants || skinframe->shirt || skinframe->glow || skinframe->merged) + if (colormapped) + { + if (skinframe->pants) { - if (currentrenderentity->colormap >= 0 && (skinframe->base || skinframe->pants || skinframe->shirt)) + memset(&m, 0, sizeof(m)); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || currentrenderentity->alpha != 1.0 || skinframe->fog != NULL; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.numtriangles = model->numtris; + m.numverts = model->numverts; + m.tex[0] = R_GetTexture(skinframe->pants); + if (R_Mesh_Draw_GetBuffer(&m, true)) { - int c; - qbyte *color; - if (skinframe->base) - R_DrawModelMesh(skinframe->base, aliasvertcolor, 0, 0, 0); - if (skinframe->pants) - { - c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges - color = (qbyte *) (&d_8to24table[c]); - if (c >= 224) // fullbright ranges - R_DrawModelMesh(skinframe->pants, NULL, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - else - { - R_TintModel(aliasvertcolor, aliasvertcolor2, model->numverts, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - R_DrawModelMesh(skinframe->pants, aliasvertcolor2, 0, 0, 0); - } - } - if (skinframe->shirt) - { - c = currentrenderentity->colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges - color = (qbyte *) (&d_8to24table[c]); - if (c >= 224) // fullbright ranges - R_DrawModelMesh(skinframe->shirt, NULL, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - else - { - R_TintModel(aliasvertcolor, aliasvertcolor2, model->numverts, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f)); - R_DrawModelMesh(skinframe->shirt, aliasvertcolor2, 0, 0, 0); - } - } + c_alias_polys += m.numtriangles; + if (pantsfullbright) + R_FillColors(m.color, m.numverts, pantscolor[0] * m.colorscale, pantscolor[1] * m.colorscale, pantscolor[2] * m.colorscale, currentrenderentity->alpha); + else + R_ModulateColors(aliasvertcolor, m.color, m.numverts, pantscolor[0] * m.colorscale, pantscolor[1] * m.colorscale, pantscolor[2] * m.colorscale); + memcpy(m.index, model->mdlmd2data_indices, m.numtriangles * sizeof(int[3])); + memcpy(m.vertex, aliasvert, m.numverts * sizeof(float[4])); + memcpy(m.texcoords[0], model->mdlmd2data_texcoords, m.numverts * sizeof(float[2])); + R_Mesh_Render(); } - else + } + if (skinframe->shirt) + { + memset(&m, 0, sizeof(m)); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || currentrenderentity->alpha != 1.0 || skinframe->fog != NULL; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.numtriangles = model->numtris; + m.numverts = model->numverts; + m.tex[0] = R_GetTexture(skinframe->shirt); + if (R_Mesh_Draw_GetBuffer(&m, true)) { - if (skinframe->merged) - R_DrawModelMesh(skinframe->merged, aliasvertcolor, 0, 0, 0); + c_alias_polys += m.numtriangles; + if (shirtfullbright) + R_FillColors(m.color, m.numverts, shirtcolor[0] * m.colorscale, shirtcolor[1] * m.colorscale, shirtcolor[2] * m.colorscale, currentrenderentity->alpha); else - { - if (skinframe->base) R_DrawModelMesh(skinframe->base, aliasvertcolor, 0, 0, 0); - if (skinframe->pants) R_DrawModelMesh(skinframe->pants, aliasvertcolor, 0, 0, 0); - if (skinframe->shirt) R_DrawModelMesh(skinframe->shirt, aliasvertcolor, 0, 0, 0); - } + R_ModulateColors(aliasvertcolor, m.color, m.numverts, shirtcolor[0] * m.colorscale, shirtcolor[1] * m.colorscale, shirtcolor[2] * m.colorscale); + memcpy(m.index, model->mdlmd2data_indices, m.numtriangles * sizeof(int[3])); + memcpy(m.vertex, aliasvert, m.numverts * sizeof(float[4])); + memcpy(m.texcoords[0], model->mdlmd2data_texcoords, m.numverts * sizeof(float[2])); + R_Mesh_Render(); } - if (skinframe->glow) R_DrawModelMesh(skinframe->glow, NULL, 1 - fog, 1 - fog, 1 - fog); } - else - R_DrawModelMesh(0, NULL, 1 - fog, 1 - fog, 1 - fog); } - else + if (skinframe->glow) { - rmeshbufferinfo_t bufmesh; - memset(&bufmesh, 0, sizeof(bufmesh)); - if (currentrenderentity->effects & EF_ADDITIVE) - { - bufmesh.transparent = true; - bufmesh.blendfunc1 = GL_SRC_ALPHA; - bufmesh.blendfunc2 = GL_ONE; - } - else if (currentrenderentity->alpha != 1.0 || skinframe->fog != NULL) + memset(&m, 0, sizeof(m)); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || currentrenderentity->alpha != 1.0 || skinframe->fog != NULL; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.numtriangles = model->numtris; + m.numverts = model->numverts; + m.tex[0] = R_GetTexture(skinframe->glow); + if (R_Mesh_Draw_GetBuffer(&m, true)) { - bufmesh.transparent = true; - bufmesh.blendfunc1 = GL_SRC_ALPHA; - bufmesh.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + c_alias_polys += m.numtriangles; + R_FillColors(m.color, m.numverts, (1 - fog) * m.colorscale, (1 - fog) * m.colorscale, (1 - fog) * m.colorscale, currentrenderentity->alpha); + memcpy(m.index, model->mdlmd2data_indices, m.numtriangles * sizeof(int[3])); + memcpy(m.vertex, aliasvert, m.numverts * sizeof(float[4])); + memcpy(m.texcoords[0], model->mdlmd2data_texcoords, m.numverts * sizeof(float[2])); + R_Mesh_Render(); } - else + } + if (fog) + { + memset(&m, 0, sizeof(m)); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || currentrenderentity->alpha != 1.0 || skinframe->fog != NULL; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.numtriangles = model->numtris; + m.numverts = model->numverts; + m.tex[0] = R_GetTexture(skinframe->fog); + if (R_Mesh_Draw_GetBuffer(&m, false)) { - bufmesh.transparent = false; - bufmesh.blendfunc1 = GL_ONE; - bufmesh.blendfunc2 = GL_ZERO; + c_alias_polys += m.numtriangles; + R_FillColors(m.color, m.numverts, fog * m.colorscale, fog * m.colorscale, fog * m.colorscale, currentrenderentity->alpha); + memcpy(m.index, model->mdlmd2data_indices, m.numtriangles * sizeof(int[3])); + memcpy(m.vertex, aliasvert, m.numverts * sizeof(float[4])); + memcpy(m.texcoords[0], model->mdlmd2data_texcoords, m.numverts * sizeof(float[2])); + R_Mesh_Render(); } - bufmesh.numtriangles = model->numtris; - bufmesh.numverts = model->numverts; - bufmesh.tex[0] = R_GetTexture(skinframe->merged); - - R_Mesh_Draw_GetBuffer(&bufmesh, true); - - aliasvert = bufmesh.vertex; - aliasvertcolor = bufmesh.color; - memcpy(bufmesh.index, model->mdlmd2data_indices, bufmesh.numtriangles * sizeof(int[3])); - memcpy(bufmesh.texcoords[0], model->mdlmd2data_texcoords, bufmesh.numverts * sizeof(float[2])); - - fog = bufmesh.colorscale * (1 - fog); - R_SetupMDLMD2Frames(fog, fog, fog); - - aliasvert = aliasvertbuf; - aliasvertcolor = aliasvertcolorbuf; - R_Mesh_Render(); } } @@ -760,76 +689,76 @@ void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist) } } -void R_DrawZymoticModelMesh(zymtype1header_t *m) +void R_DrawZymoticModelMesh(zymtype1header_t *m, float fog) { + rmeshbufferinfo_t mbuf; int i, *renderlist; rtexture_t **texture; - // FIXME: do better fog - renderlist = (int *)(m->lump_render.start + (int) m); texture = (rtexture_t **)(m->lump_shaders.start + (int) m); - aliasmeshinfo.vertex = aliasvert; - aliasmeshinfo.vertexstep = sizeof(float[4]); - aliasmeshinfo.color = aliasvertcolor; - aliasmeshinfo.colorstep = sizeof(float[4]); - aliasmeshinfo.texcoords[0] = (float *)(m->lump_texcoords.start + (int) m); - aliasmeshinfo.texcoordstep[0] = sizeof(float[2]); - + renderlist = (int *)(m->lump_render.start + (int) m); for (i = 0;i < m->numshaders;i++) { - aliasmeshinfo.tex[0] = R_GetTexture(texture[i]); + memset(&mbuf, 0, sizeof(mbuf)); + mbuf.numverts = m->numverts; + mbuf.numtriangles = *renderlist++; if (currentrenderentity->effects & EF_ADDITIVE) { - aliasmeshinfo.transparent = true; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE; + mbuf.transparent = true; + mbuf.blendfunc1 = GL_SRC_ALPHA; + mbuf.blendfunc2 = GL_ONE; } else if (currentrenderentity->alpha != 1.0 || R_TextureHasAlpha(texture[i])) { - aliasmeshinfo.transparent = true; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + mbuf.transparent = true; + mbuf.blendfunc1 = GL_SRC_ALPHA; + mbuf.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; } else { - aliasmeshinfo.transparent = false; - aliasmeshinfo.blendfunc1 = GL_ONE; - aliasmeshinfo.blendfunc2 = GL_ZERO; + mbuf.transparent = false; + mbuf.blendfunc1 = GL_ONE; + mbuf.blendfunc2 = GL_ZERO; } - aliasmeshinfo.numtriangles = *renderlist++; - aliasmeshinfo.index = renderlist; - c_alias_polys += aliasmeshinfo.numtriangles; - R_Mesh_Draw(&aliasmeshinfo); - R_Mesh_Render(); - renderlist += aliasmeshinfo.numtriangles * 3; + mbuf.tex[0] = R_GetTexture(texture[i]); + if (R_Mesh_Draw_GetBuffer(&mbuf, true)) + { + c_alias_polys += mbuf.numtriangles; + memcpy(mbuf.index, renderlist, mbuf.numtriangles * sizeof(int[3])); + memcpy(mbuf.vertex, aliasvert, mbuf.numverts * sizeof(float[4])); + R_ModulateColors(aliasvertcolor, mbuf.color, mbuf.numverts, mbuf.colorscale, mbuf.colorscale, mbuf.colorscale); + //memcpy(mbuf.color, aliasvertcolor, mbuf.numverts * sizeof(float[4])); + memcpy(mbuf.texcoords[0], (float *)(m->lump_texcoords.start + (int) m), mbuf.numverts * sizeof(float[2])); + R_Mesh_Render(); + } + renderlist += mbuf.numtriangles * 3; } -} -void R_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m, float fog) -{ - int i, *renderlist; - - // FIXME: do better fog - renderlist = (int *)(m->lump_render.start + (int) m); - - aliasmeshinfo.tex[0] = 0; - aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; - aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - - aliasmeshinfo.cr = fogcolor[0]; - aliasmeshinfo.cg = fogcolor[1]; - aliasmeshinfo.cb = fogcolor[2]; - aliasmeshinfo.ca = currentrenderentity->alpha * fog; - - for (i = 0;i < m->numshaders;i++) + if (fog) { - aliasmeshinfo.numtriangles = *renderlist++; - aliasmeshinfo.index = renderlist; - c_alias_polys += aliasmeshinfo.numtriangles; - R_Mesh_Draw(&aliasmeshinfo); - R_Mesh_Render(); - renderlist += aliasmeshinfo.numtriangles * 3; + renderlist = (int *)(m->lump_render.start + (int) m); + for (i = 0;i < m->numshaders;i++) + { + memset(&mbuf, 0, sizeof(mbuf)); + mbuf.numverts = m->numverts; + mbuf.numtriangles = *renderlist++; + mbuf.transparent = currentrenderentity->effects & EF_ADDITIVE || currentrenderentity->alpha != 1.0 || R_TextureHasAlpha(texture[i]); + mbuf.blendfunc1 = GL_SRC_ALPHA; + mbuf.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + // FIXME: need alpha mask for fogging... + //mbuf.tex[0] = R_GetTexture(texture[i]); + if (R_Mesh_Draw_GetBuffer(&mbuf, false)) + { + c_alias_polys += mbuf.numtriangles; + memcpy(mbuf.index, renderlist, mbuf.numtriangles * sizeof(int[3])); + memcpy(mbuf.vertex, aliasvert, mbuf.numverts * sizeof(float[4])); + R_FillColors(mbuf.color, mbuf.numverts, fogcolor[0] * mbuf.colorscale, fogcolor[1] * mbuf.colorscale, fogcolor[2] * mbuf.colorscale, currentrenderentity->alpha * fog); + //memcpy(mbuf.texcoords[0], (float *)(m->lump_texcoords.start + (int) m), mbuf.numverts * sizeof(float[2])); + R_Mesh_Render(); + } + renderlist += mbuf.numtriangles * 3; + } } } @@ -845,13 +774,7 @@ void R_DrawZymoticModel (float fog) R_LightModel(m->numverts, 1 - fog, 1 - fog, 1 - fog, true); - memset(&aliasmeshinfo, 0, sizeof(aliasmeshinfo)); - aliasmeshinfo.numverts = m->numverts; - - R_DrawZymoticModelMesh(m); - - if (fog) - R_DrawZymoticModelMeshFog(currentrenderentity->origin, m, fog); + R_DrawZymoticModelMesh(m, fog); } void R_DrawAliasModel (void) diff --git a/gl_rmain.c b/gl_rmain.c index ad66314d..7640985b 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -69,6 +69,33 @@ cvar_t gl_fogend = {0, "gl_fogend","0"}; cvar_t r_textureunits = {0, "r_textureunits", "32"}; +void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b) +{ + int i; + for (i = 0;i < verts;i++) + { + out[0] = in[0] * r; + out[1] = in[1] * g; + out[2] = in[2] * b; + out[3] = in[3]; + in += 4; + out += 4; + } +} + +void R_FillColors(float *out, int verts, float r, float g, float b, float a) +{ + int i; + for (i = 0;i < verts;i++) + { + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = a; + out += 4; + } +} + /* ==================== R_TimeRefresh_f diff --git a/gl_rsurf.c b/gl_rsurf.c index dbe515c4..c9ce94ca 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1884,48 +1884,49 @@ void R_DrawSurfaces (int type) } } -static float portalpointbuffer[256][3]; - void R_DrawPortals(void) { int drawportals, i; + float *v; mportal_t *portal, *endportal; - mvertex_t *point; - rmeshinfo_t m; + rmeshbufferinfo_t m; drawportals = r_drawportals.integer; if (drawportals < 1) return; - memset(&m, 0, sizeof(m)); - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - m.vertex = &portalpointbuffer[0][0]; - m.vertexstep = sizeof(float[3]); - m.ca = 0.125; for (portal = cl.worldmodel->portals, endportal = portal + cl.worldmodel->numportals;portal < endportal;portal++) { if (portal->visframe == r_portalframecount) { - if (portal->numpoints <= 256) + memset(&m, 0, sizeof(m)); + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + m.numverts = portal->numpoints; + m.numtriangles = portal->numpoints - 2; + if (R_Mesh_Draw_GetBuffer(&m, false)) { + for (i = 0;i < m.numtriangles;i++) + { + m.index[i * 3 + 0] = 0; + m.index[i * 3 + 1] = i + 1; + m.index[i * 3 + 2] = i + 2; + } i = portal - cl.worldmodel->portals; - m.cr = ((i & 0x0007) >> 0) * (1.0f / 7.0f); - m.cg = ((i & 0x0038) >> 3) * (1.0f / 7.0f); - m.cb = ((i & 0x01C0) >> 6) * (1.0f / 7.0f); - point = portal->points; + R_FillColors(m.color, m.numverts, + ((i & 0x0007) >> 0) * (1.0f / 7.0f) * m.colorscale, + ((i & 0x0038) >> 3) * (1.0f / 7.0f) * m.colorscale, + ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * m.colorscale, + 0.125f); if (PlaneDiff(r_origin, (&portal->plane)) > 0) { - for (i = portal->numpoints - 1;i >= 0;i--) - VectorCopy(point[i].position, portalpointbuffer[i]); + for (i = portal->numpoints - 1, v = m.vertex;i >= 0;i--, v += 4) + VectorCopy(portal->points[i].position, v); } else - { - for (i = 0;i < portal->numpoints;i++) - VectorCopy(point[i].position, portalpointbuffer[i]); - } - R_Mesh_DrawPolygon(&m, portal->numpoints); + for (i = 0, v = m.vertex;i < portal->numpoints;i++, v += 4) + VectorCopy(portal->points[i].position, v); R_Mesh_Render(); } } diff --git a/render.h b/render.h index 16c158bc..394cc410 100644 --- a/render.h +++ b/render.h @@ -68,6 +68,10 @@ extern cvar_t r_novis; // detail texture stuff extern cvar_t r_detailtextures; +// useful functions for rendering +void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b); +void R_FillColors(float *out, int verts, float r, float g, float b, float a); + #define TOP_RANGE 16 // soldier uniform colors #define BOTTOM_RANGE 96 -- 2.39.2