From 4a43205a0993d496822f3460158a41fd4f96c800 Mon Sep 17 00:00:00 2001 From: havoc Date: Fri, 13 Apr 2018 02:23:34 +0000 Subject: [PATCH] CSQC polygonbegin functionality now uses the CL_MeshEntities system, this finally makes it possible to use shaders on those polygons. UI elements (DrawQ_ system) now use the CL_MeshEntities system, but still renders the mesh the old way, shader support is planned. DrawQ_Line no longer uses GL_LINES, it now produces a polygon in the CL_MeshEntities system, so shownetgraph and r_speeds_graph features now work on D3D9/DPSOFTRAST/GLES2 render paths. Added MATERIALFLAG_VERTEXCOLOR as a special case for rgbgen vertex shaders that are being used by CL_MeshEntities meshes, currently this is an unlit type of material but lighting support for it is planned. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12388 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 2 +- cl_screen.c | 74 ++----- clvm_cmds.c | 280 ++++-------------------- csprogs.h | 2 - draw.h | 11 +- gl_draw.c | 564 +++++++++++-------------------------------------- gl_rmain.c | 35 ++- model_alias.c | 8 +- model_brush.c | 6 +- model_brush.h | 2 + model_shared.c | 21 +- model_shared.h | 2 +- mvm_cmds.c | 4 +- progsvm.h | 44 +--- r_lightning.c | 6 +- render.h | 37 ++-- 16 files changed, 263 insertions(+), 835 deletions(-) diff --git a/cl_main.c b/cl_main.c index 8753a5eb..f70aeb8a 100644 --- a/cl_main.c +++ b/cl_main.c @@ -2406,7 +2406,7 @@ void CL_MeshEntities_Init(void) ent->state_current.active = true; ent->render.model = cl_meshentitymodels + i; ent->render.alpha = 1; - ent->render.flags = RENDER_SHADOW | RENDER_LIGHT | RENDER_CUSTOMIZEDMODELLIGHT; + ent->render.flags = RENDER_SHADOW | RENDER_LIGHT; ent->render.framegroupblend[0].lerp = 1; ent->render.frameblend[0].lerp = 1; VectorSet(ent->render.colormod, 1, 1, 1); diff --git a/cl_screen.c b/cl_screen.c index b62fa45e..733aca06 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -252,14 +252,12 @@ static void SCR_CheckDrawCenterString (void) static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, int graphheight, float graphscale, int graphlimit, const char *label, float textsize, int packetcounter, netgraphitem_t *netgraph) { netgraphitem_t *graph; - int j, x, y, numlines; + int j, x, y; int totalbytes = 0; char bytesstring[128]; float g[NETGRAPH_PACKETS][7]; float *a; float *b; - r_vertexgeneric_t vertex[(NETGRAPH_PACKETS+2)*6*2]; - r_vertexgeneric_t *v; DrawQ_Fill(graphx, graphy, graphwidth, graphheight + textsize * 2, 0, 0, 0, 0.5, 0); // draw the bar graph itself memset(g, 0, sizeof(g)); @@ -299,38 +297,18 @@ static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, g[j][6] = bound(0.0f, g[j][6], 1.0f); } // render the lines for the graph - numlines = 0; - v = vertex; for (j = 0;j < NETGRAPH_PACKETS;j++) { a = g[j]; b = g[(j+1)%NETGRAPH_PACKETS]; if (a[0] < 0.0f || b[0] > 1.0f || b[0] < a[0]) continue; - VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[2], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[2], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - - VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[1], 0.0f);Vector4Set(v->color4f, 1.0f, 0.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[1], 0.0f);Vector4Set(v->color4f, 1.0f, 0.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - - VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[5], 0.0f);Vector4Set(v->color4f, 0.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[5], 0.0f);Vector4Set(v->color4f, 0.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - - VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[4], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[4], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - - VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[3], 0.0f);Vector4Set(v->color4f, 1.0f, 0.5f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[3], 0.0f);Vector4Set(v->color4f, 1.0f, 0.5f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - - VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[6], 0.0f);Vector4Set(v->color4f, 0.0f, 0.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[6], 0.0f);Vector4Set(v->color4f, 0.0f, 0.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++; - - numlines += 6; - } - if (numlines > 0) - { - R_Mesh_PrepareVertices_Generic(numlines*2, vertex, NULL, 0); - DrawQ_Lines(0.0f, numlines, 0, false); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[2], graphx + graphwidth * b[0], graphy + graphheight * b[2], 1.0f, 1.0f, 1.0f, 1.0f, 0); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[1], graphx + graphwidth * b[0], graphy + graphheight * b[1], 1.0f, 0.0f, 0.0f, 1.0f, 0); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[5], graphx + graphwidth * b[0], graphy + graphheight * b[5], 0.0f, 1.0f, 0.0f, 1.0f, 0); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[4], graphx + graphwidth * b[0], graphy + graphheight * b[4], 1.0f, 1.0f, 1.0f, 1.0f, 0); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[3], graphx + graphwidth * b[0], graphy + graphheight * b[3], 1.0f, 0.5f, 0.0f, 1.0f, 0); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[6], graphx + graphwidth * b[0], graphy + graphheight * b[6], 0.0f, 0.0f, 1.0f, 1.0f, 0); } x = graphx; y = graphy + graphheight; @@ -1134,8 +1112,7 @@ static void R_TimeReport_EndFrame(void) if (cls.r_speeds_graph_length) { char legend[128]; - r_vertexgeneric_t *v; - int i, numlines; + int i; const int *data; float x, y, width, height, scalex, scaley; int range_default = max(r_speeds_graph_maxdefault.integer, 1); @@ -1215,9 +1192,6 @@ static void R_TimeReport_EndFrame(void) // legend text is drawn after the graphs // render the graph lines, we'll go back and render the legend text later scalex = (float)width / (1000000.0 * r_speeds_graph_seconds.value); - // get space in a vertex buffer to draw this - numlines = stats * (graph_length - 1); - v = R_Mesh_PrepareVertices_Generic_Lock(numlines * 2); stats = 0; for (color = 0;color < R_SPEEDS_GRAPH_COLORS;color++) { @@ -1240,39 +1214,19 @@ static void R_TimeReport_EndFrame(void) sum = 0; for (i = 0;i < graph_length - 1;) { - v->vertex3f[0] = x + width - sum * scalex; - if (v->vertex3f[0] < x) - v->vertex3f[0] = x; - v->vertex3f[1] = y + height - (data[index] - range_min) * scaley; - v->vertex3f[2] = 0; - v->color4f[0] = r_speeds_graph_colors[color][0]; - v->color4f[1] = r_speeds_graph_colors[color][1]; - v->color4f[2] = r_speeds_graph_colors[color][2]; - v->color4f[3] = r_speeds_graph_colors[color][3]; - v->texcoord2f[0] = 0; - v->texcoord2f[1] = 0; - v++; + float x1, y1, x2, y2; + x1 = max(x, x + width - sum * scalex); + y1 = y + height - (data[index] - range_min) * scaley; sum += graph_data[r_stat_timedelta * graph_length + index]; index--; if (index < 0) index = graph_length - 1; i++; - v->vertex3f[0] = x + width - sum * scalex; - if (v->vertex3f[0] < x) - v->vertex3f[0] = x; - v->vertex3f[1] = y + height - (data[index] - range_min) * scaley; - v->vertex3f[2] = 0; - v->color4f[0] = r_speeds_graph_colors[color][0]; - v->color4f[1] = r_speeds_graph_colors[color][1]; - v->color4f[2] = r_speeds_graph_colors[color][2]; - v->color4f[3] = r_speeds_graph_colors[color][3]; - v->texcoord2f[0] = 0; - v->texcoord2f[1] = 0; - v++; + x2 = max(x, x + width - sum * scalex); + y2 = y + height - (data[index] - range_min) * scaley; + DrawQ_Line(1, x1, y1, x2, y2, r_speeds_graph_colors[color][0], r_speeds_graph_colors[color][1], r_speeds_graph_colors[color][2], r_speeds_graph_colors[color][3], 0); } } - R_Mesh_PrepareVertices_Generic_Unlock(); - DrawQ_Lines(0.0f, numlines, 0, false); } // return to not drawing anything if r_render is 0 diff --git a/clvm_cmds.c b/clvm_cmds.c index 27d247f7..02f16078 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -3252,7 +3252,6 @@ static void VM_CL_GetEntity (prvm_prog_t *prog) static void VM_CL_R_RenderScene (prvm_prog_t *prog) { double t = Sys_DirtyTime(); - vmpolygons_t *polys = &prog->vmpolygons; VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene); // update the views @@ -3269,275 +3268,88 @@ static void VM_CL_R_RenderScene (prvm_prog_t *prog) // we need to update any RENDER_VIEWMODEL entities at this point because // csqc supplies its own view matrix CL_UpdateViewEntities(); + CL_MeshEntities_AddToScene(); CL_UpdateEntityShading(); // now draw stuff! R_RenderView(); - polys->num_vertices = polys->num_triangles = 0; + Mod_Mesh_Reset(CL_Mesh_CSQC()); // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0; prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t; } -static void VM_ResizePolygons(vmpolygons_t *polys) -{ - float *oldvertex3f = polys->data_vertex3f; - float *oldcolor4f = polys->data_color4f; - float *oldtexcoord2f = polys->data_texcoord2f; - vmpolygons_triangle_t *oldtriangles = polys->data_triangles; - unsigned short *oldsortedelement3s = polys->data_sortedelement3s; - polys->max_vertices = min(polys->max_triangles*3, 65536); - polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3])); - polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4])); - polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2])); - polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t)); - polys->data_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[3])); - if (polys->num_vertices) - { - memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3])); - memcpy(polys->data_color4f, oldcolor4f, polys->num_vertices*sizeof(float[4])); - memcpy(polys->data_texcoord2f, oldtexcoord2f, polys->num_vertices*sizeof(float[2])); - } - if (polys->num_triangles) - { - memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t)); - memcpy(polys->data_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3])); - } - if (oldvertex3f) - Mem_Free(oldvertex3f); - if (oldcolor4f) - Mem_Free(oldcolor4f); - if (oldtexcoord2f) - Mem_Free(oldtexcoord2f); - if (oldtriangles) - Mem_Free(oldtriangles); - if (oldsortedelement3s) - Mem_Free(oldsortedelement3s); -} - -static void VM_InitPolygons (vmpolygons_t* polys) -{ - memset(polys, 0, sizeof(*polys)); - polys->pool = Mem_AllocPool("VMPOLY", 0, NULL); - polys->max_triangles = 1024; - VM_ResizePolygons(polys); - polys->initialized = true; -} - -static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) -{ - int surfacelistindex; - vmpolygons_t *polys = (vmpolygons_t *)ent; -// R_Mesh_ResetTextureState(); - R_EntityMatrix(&identitymatrix); - GL_CullFace(GL_NONE); - GL_DepthTest(true); // polys in 3D space shall always have depth test - GL_DepthRange(0, 1); - R_Mesh_PrepareVertices_Generic_Arrays(polys->num_vertices, polys->data_vertex3f, polys->data_color4f, polys->data_texcoord2f); - - for (surfacelistindex = 0;surfacelistindex < numsurfaces;) - { - int numtriangles = 0; - rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture; - int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag; - DrawQ_ProcessDrawFlag(drawflag, polys->data_triangles[surfacelist[surfacelistindex]].hasalpha); - R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1, false, false, false); - numtriangles = 0; - for (;surfacelistindex < numsurfaces;surfacelistindex++) - { - if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag) - break; - VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles); - numtriangles++; - } - R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, NULL, 0, polys->data_sortedelement3s, NULL, 0); - } -} - -static void VMPolygons_Store(vmpolygons_t *polys) -{ - qboolean hasalpha; - int i; - - // detect if we have alpha - hasalpha = polys->begin_texture_hasalpha; - for(i = 0; !hasalpha && (i < polys->begin_vertices); ++i) - if(polys->begin_color[i][3] < 1) - hasalpha = true; - - if (polys->begin_draw2d) - { - // draw the polygon as 2D immediately - drawqueuemesh_t mesh; - mesh.texture = polys->begin_texture; - mesh.num_vertices = polys->begin_vertices; - mesh.num_triangles = polys->begin_vertices-2; - mesh.data_element3i = polygonelement3i; - mesh.data_element3s = polygonelement3s; - mesh.data_vertex3f = polys->begin_vertex[0]; - mesh.data_color4f = polys->begin_color[0]; - mesh.data_texcoord2f = polys->begin_texcoord[0]; - DrawQ_Mesh(&mesh, polys->begin_drawflag, hasalpha); - } - else - { - // queue the polygon as 3D for sorted transparent rendering later - if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2) - { - while (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2) - polys->max_triangles *= 2; - VM_ResizePolygons(polys); - } - if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices) - { - // needle in a haystack! - // polys->num_vertices was used for copying where we actually want to copy begin_vertices - // that also caused it to not render the first polygon that is added - // --blub - memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3])); - memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4])); - memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_vertices * sizeof(float[2])); - for (i = 0;i < polys->begin_vertices-2;i++) - { - polys->data_triangles[polys->num_triangles].texture = polys->begin_texture; - polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag; - polys->data_triangles[polys->num_triangles].elements[0] = polys->num_vertices; - polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1; - polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2; - polys->data_triangles[polys->num_triangles].hasalpha = hasalpha; - polys->num_triangles++; - } - polys->num_vertices += polys->begin_vertices; - } - } - polys->begin_active = false; -} - -// TODO: move this into the client code and clean-up everything else, too! [1/6/2008 Black] -// LordHavoc: agreed, this is a mess -void VM_CL_AddPolygonsToMeshQueue (prvm_prog_t *prog) -{ - int i; - vmpolygons_t *polys = &prog->vmpolygons; - vec3_t center; - - // only add polygons of the currently active prog to the queue - if there is none, we're done - if( !prog ) - return; - - if (!polys->num_triangles) - return; - - for (i = 0;i < polys->num_triangles;i++) - { - VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center); - R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL); - } - - /*polys->num_triangles = 0; // now done after rendering the scene, - polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */ -} - //void(string texturename, float flag[, float is2d]) R_BeginPolygon static void VM_CL_R_PolygonBegin (prvm_prog_t *prog) { - const char *picname; - skinframe_t *sf; - vmpolygons_t *polys = &prog->vmpolygons; - int tf; - - // TODO instead of using skinframes here (which provides the benefit of - // better management of flags, and is more suited for 3D rendering), what - // about supporting Q3 shaders? + const char *texname; + int drawflags; + qboolean draw2d; + dp_model_t *mod; VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_PolygonBegin); - if (!polys->initialized) - VM_InitPolygons(polys); - if (polys->begin_active) - { - VM_Warning(prog, "VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n"); - return; - } - picname = PRVM_G_STRING(OFS_PARM0); - - sf = NULL; - if(*picname) - { - tf = TEXF_ALPHA; - if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP) - tf |= TEXF_MIPMAP; + texname = PRVM_G_STRING(OFS_PARM0); + drawflags = (int)PRVM_G_FLOAT(OFS_PARM1); + // weird hacky way to figure out if this is a 2D HUD polygon or a scene polygon + draw2d = (prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : r_refdef.draw2dstage); - do - { - sf = R_SkinFrame_FindNextByName(sf, picname); - } - while(sf && sf->textureflags != tf); - - if(!sf || !sf->base) - sf = R_SkinFrame_LoadExternal(picname, tf, true, true); - - if(sf) - R_SkinFrame_MarkUsed(sf); - } - - polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white; - polys->begin_texture_hasalpha = (sf && sf->base) ? sf->hasalpha : false; - polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK; - polys->begin_vertices = 0; - polys->begin_active = true; - polys->begin_draw2d = (prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : r_refdef.draw2dstage); + // we need to remember whether this is a 2D or 3D mesh we're adding to + mod = draw2d ? CL_Mesh_UI() : CL_Mesh_CSQC(); + prog->polygonbegin_model = mod; + Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, texname, drawflags, TEXF_ALPHA, MATERIALFLAG_VERTEXCOLOR), draw2d); } //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex static void VM_CL_R_PolygonVertex (prvm_prog_t *prog) { - vmpolygons_t *polys = &prog->vmpolygons; + const prvm_vec_t *v = PRVM_G_VECTOR(OFS_PARM0); + const prvm_vec_t *tc = PRVM_G_VECTOR(OFS_PARM1); + const prvm_vec_t *c = PRVM_G_VECTOR(OFS_PARM2); + const prvm_vec_t a = PRVM_G_FLOAT(OFS_PARM3); + dp_model_t *mod = prog->polygonbegin_model; + int e0, e1, e2; + msurface_t *surf; VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex); - if (!polys->begin_active) + if (!mod || mod->num_surfaces == 0) { VM_Warning(prog, "VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n"); return; } - if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS) + surf = &mod->data_surfaces[mod->num_surfaces - 1]; + e2 = Mod_Mesh_IndexForVertex(mod, surf, v[0], v[1], v[2], 0, 0, 0, tc[0], tc[1], 0, 0, c[0], c[1], c[2], a); + if (surf->num_vertices >= 3) { - VM_Warning(prog, "VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS); - return; + // the first element is the start of the triangle fan + e0 = surf->num_firstvertex; + // the second element is the previous vertex + e1 = e0 + 1; + if (surf->num_triangles > 0) + e1 = mod->surfmesh.data_element3i[(surf->num_firsttriangle + surf->num_triangles) * 3 - 1]; + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); } - - polys->begin_vertex[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM0)[0]; - polys->begin_vertex[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM0)[1]; - polys->begin_vertex[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM0)[2]; - polys->begin_texcoord[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM1)[0]; - polys->begin_texcoord[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM1)[1]; - polys->begin_color[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM2)[0]; - polys->begin_color[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM2)[1]; - polys->begin_color[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM2)[2]; - polys->begin_color[polys->begin_vertices][3] = PRVM_G_FLOAT(OFS_PARM3); - polys->begin_vertices++; } //void() R_EndPolygon static void VM_CL_R_PolygonEnd (prvm_prog_t *prog) { - vmpolygons_t *polys = &prog->vmpolygons; + dp_model_t *mod = prog->polygonbegin_model; + msurface_t *surf; VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd); - if (!polys->begin_active) + if (!mod || mod->num_surfaces == 0) { VM_Warning(prog, "VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n"); return; } - polys->begin_active = false; - if (polys->begin_vertices >= 3) - VMPolygons_Store(polys); - else - VM_Warning(prog, "VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices); + surf = &mod->data_surfaces[mod->num_surfaces - 1]; + Mod_BuildNormals(surf->num_firstvertex, surf->num_vertices, surf->num_triangles, mod->surfmesh.data_vertex3f, mod->surfmesh.data_element3i + 3 * surf->num_firsttriangle, mod->surfmesh.data_normal3f, true); + prog->polygonbegin_model = NULL; } /* @@ -4934,27 +4746,15 @@ NULL const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t); -void VM_Polygons_Reset(prvm_prog_t *prog) -{ - vmpolygons_t *polys = &prog->vmpolygons; - - // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system - if(polys->initialized) - { - Mem_FreePool(&polys->pool); - polys->initialized = false; - } -} - void CLVM_init_cmd(prvm_prog_t *prog) { VM_Cmd_Init(prog); - VM_Polygons_Reset(prog); + prog->polygonbegin_model = NULL; } void CLVM_reset_cmd(prvm_prog_t *prog) { World_End(&cl.world); VM_Cmd_Reset(prog); - VM_Polygons_Reset(prog); + prog->polygonbegin_model = NULL; } diff --git a/csprogs.h b/csprogs.h index 226cf96c..bb05e380 100644 --- a/csprogs.h +++ b/csprogs.h @@ -100,8 +100,6 @@ void CL_VM_Parse_CenterPrint(const char *msg); int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent); int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *shadingorigin); void CL_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix); -/* VMs exposing the polygon calls must call this on Init/Reset */ -void VM_Polygons_Reset(prvm_prog_t *prog); void QW_CL_StartUpload(unsigned char *data, int size); void CSQC_UpdateNetworkTimes(double newtime, double oldtime); diff --git a/draw.h b/draw.h index 59470b6e..bbd964ed 100644 --- a/draw.h +++ b/draw.h @@ -157,23 +157,18 @@ float DrawQ_TextWidth_UntilWidth_TrackColors(const char *text, size_t *maxlen, f float DrawQ_TextWidth_UntilWidth_TrackColors_Scale(const char *text, size_t *maxlen, float w, float h, float sw, float sh, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt, float maxwidth); // draw a very fancy pic (per corner texcoord/color control), the order is tl, tr, bl, br void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags); -// draw a triangle mesh -void DrawQ_Mesh(drawqueuemesh_t *mesh, int flags, qboolean hasalpha); // set the clipping area void DrawQ_SetClipArea(float x, float y, float width, float height); // reset the clipping area void DrawQ_ResetClipArea(void); // draw a line void DrawQ_Line(float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags); -// draw a lot of lines (call R_Mesh_PrepareVertices_Generic first) -void DrawQ_Lines(float width, int numlines, int flags, qboolean hasalpha); -// draw a line loop -void DrawQ_LineLoop(drawqueuemesh_t *mesh, int flags); // resets r_refdef.draw2dstage void DrawQ_Finish(void); -void DrawQ_ProcessDrawFlag(int flags, qboolean alpha); // sets GL_DepthMask and GL_BlendFunc void DrawQ_RecalcView(void); // use this when changing r_refdef.view.* from e.g. csqc - +// batch draw the pending geometry in the CL_Mesh_UI() model and reset the model, +// to be called by things like DrawQ_SetClipArea which make disruptive state changes. +void DrawQ_FlushUI(void); const char *Draw_GetPicName(cachepic_t *pic); int Draw_GetPicWidth(cachepic_t *pic); diff --git a/gl_draw.c b/gl_draw.c index 4e0bfd6f..5f8a358d 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -748,188 +748,64 @@ static void _DrawQ_Setup(void) // see R_ResetViewRendering2D { if (r_refdef.draw2dstage == 1) return; + DrawQ_FlushUI(); r_refdef.draw2dstage = 1; - R_ResetViewRendering2D_Common(0, NULL, NULL, vid_conwidth.integer, vid_conheight.integer); } qboolean r_draw2d_force = false; -static void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alpha) -{ - _DrawQ_Setup(); - if(!r_draw2d.integer && !r_draw2d_force) - return; - DrawQ_ProcessDrawFlag(flags, (alpha < 1) || (pic && pic->skinframe && pic->skinframe->hasalpha)); -} -void DrawQ_ProcessDrawFlag(int flags, qboolean alpha) -{ - if(flags == DRAWFLAG_ADDITIVE) - { - GL_DepthMask(false); - GL_BlendFunc(alpha ? GL_SRC_ALPHA : GL_ONE, GL_ONE); - } - else if(flags == DRAWFLAG_MODULATE) - { - GL_DepthMask(false); - GL_BlendFunc(GL_DST_COLOR, GL_ZERO); - } - else if(flags == DRAWFLAG_2XMODULATE) - { - GL_DepthMask(false); - GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); - } - else if(flags == DRAWFLAG_SCREEN) - { - GL_DepthMask(false); - GL_BlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE); - } - else if(alpha) - { - GL_DepthMask(false); - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - { - GL_DepthMask(true); - GL_BlendFunc(GL_ONE, GL_ZERO); - } -} void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags) { - float floats[36]; - - _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha); - if(!r_draw2d.integer && !r_draw2d_force) - return; - -// R_Mesh_ResetTextureState(); - floats[12] = 0.0f;floats[13] = 0.0f; - floats[14] = 1.0f;floats[15] = 0.0f; - floats[16] = 1.0f;floats[17] = 1.0f; - floats[18] = 0.0f;floats[19] = 1.0f; - floats[20] = floats[24] = floats[28] = floats[32] = red; - floats[21] = floats[25] = floats[29] = floats[33] = green; - floats[22] = floats[26] = floats[30] = floats[34] = blue; - floats[23] = floats[27] = floats[31] = floats[35] = alpha; - if (pic) - { - if (width == 0) - width = pic->width; - if (height == 0) - height = pic->height; - R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false); - -#if 0 - // AK07: lets be texel correct on the corners - { - float horz_offset = 0.5f / pic->width; - float vert_offset = 0.5f / pic->height; - - floats[12] = 0.0f + horz_offset;floats[13] = 0.0f + vert_offset; - floats[14] = 1.0f - horz_offset;floats[15] = 0.0f + vert_offset; - floats[16] = 1.0f - horz_offset;floats[17] = 1.0f - vert_offset; - floats[18] = 0.0f + horz_offset;floats[19] = 1.0f - vert_offset; - } -#endif - } - else - R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true); - - floats[2] = floats[5] = floats[8] = floats[11] = 0; - floats[0] = floats[9] = x; - floats[1] = floats[4] = y; - floats[3] = floats[6] = x + width; - floats[7] = floats[10] = y + height; - - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + dp_model_t *mod = CL_Mesh_UI(); + msurface_t *surf; + int e0, e1, e2, e3; + _DrawQ_Setup(); + if (!pic) + pic = Draw_CachePic("white"); + if (width == 0) + width = pic->width; + if (height == 0) + height = pic->height; + surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_VERTEXCOLOR), true); + e0 = Mod_Mesh_IndexForVertex(mod, surf, x , y , 0, 0, 0, -1, 0, 0, 0, 0, red, green, blue, alpha); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y , 0, 0, 0, -1, 1, 0, 0, 0, red, green, blue, alpha); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y + height, 0, 0, 0, -1, 1, 1, 0, 0, red, green, blue, alpha); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x , y + height, 0, 0, 0, -1, 0, 1, 0, 0, red, green, blue, alpha); + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); } void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, float org_x, float org_y, float angle, float red, float green, float blue, float alpha, int flags) { - float floats[36]; float af = DEG2RAD(-angle); // forward float ar = DEG2RAD(-angle + 90); // right float sinaf = sin(af); float cosaf = cos(af); float sinar = sin(ar); float cosar = cos(ar); - - _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha); - if(!r_draw2d.integer && !r_draw2d_force) - return; - -// R_Mesh_ResetTextureState(); - if (pic) - { - if (width == 0) - width = pic->width; - if (height == 0) - height = pic->height; - R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false); - } - else - R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true); - - floats[2] = floats[5] = floats[8] = floats[11] = 0; - -// top left - floats[0] = x - cosaf*org_x - cosar*org_y; - floats[1] = y - sinaf*org_x - sinar*org_y; - -// top right - floats[3] = x + cosaf*(width-org_x) - cosar*org_y; - floats[4] = y + sinaf*(width-org_x) - sinar*org_y; - -// bottom right - floats[6] = x + cosaf*(width-org_x) + cosar*(height-org_y); - floats[7] = y + sinaf*(width-org_x) + sinar*(height-org_y); - -// bottom left - floats[9] = x - cosaf*org_x + cosar*(height-org_y); - floats[10] = y - sinaf*org_x + sinar*(height-org_y); - - floats[12] = 0.0f;floats[13] = 0.0f; - floats[14] = 1.0f;floats[15] = 0.0f; - floats[16] = 1.0f;floats[17] = 1.0f; - floats[18] = 0.0f;floats[19] = 1.0f; - floats[20] = floats[24] = floats[28] = floats[32] = red; - floats[21] = floats[25] = floats[29] = floats[33] = green; - floats[22] = floats[26] = floats[30] = floats[34] = blue; - floats[23] = floats[27] = floats[31] = floats[35] = alpha; - - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + dp_model_t *mod = CL_Mesh_UI(); + msurface_t *surf; + int e0, e1, e2, e3; + _DrawQ_Setup(); + if (!pic) + pic = Draw_CachePic("white"); + if (width == 0) + width = pic->width; + if (height == 0) + height = pic->height; + surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_VERTEXCOLOR), true); + e0 = Mod_Mesh_IndexForVertex(mod, surf, x - cosaf * org_x - cosar * org_y, y - sinaf * org_x - sinar * org_y, 0, 0, 0, -1, 0, 0, 0, 0, red, green, blue, alpha); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x + cosaf * (width - org_x) - cosar * org_y, y + sinaf * (width - org_x) - sinar * org_y, 0, 0, 0, -1, 1, 0, 0, 0, red, green, blue, alpha); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x + cosaf * (width - org_x) + cosar * (height - org_y), sinaf*(width - org_x) + sinar * (height - org_y), 0, 0, 0, -1, 1, 1, 0, 0, red, green, blue, alpha); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x - cosaf * org_x + cosar * (height - org_y), y - sinaf * org_x + sinar * (height - org_y), 0, 0, 0, -1, 0, 1, 0, 0, red, green, blue, alpha); + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); } void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags) { - float floats[36]; - - _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha); - if(!r_draw2d.integer && !r_draw2d_force) - return; - -// R_Mesh_ResetTextureState(); - R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true); - - floats[2] = floats[5] = floats[8] = floats[11] = 0; - floats[0] = floats[9] = x; - floats[1] = floats[4] = y; - floats[3] = floats[6] = x + width; - floats[7] = floats[10] = y + height; - floats[12] = 0.0f;floats[13] = 0.0f; - floats[14] = 1.0f;floats[15] = 0.0f; - floats[16] = 1.0f;floats[17] = 1.0f; - floats[18] = 0.0f;floats[19] = 1.0f; - floats[20] = floats[24] = floats[28] = floats[32] = red; - floats[21] = floats[25] = floats[29] = floats[33] = green; - floats[22] = floats[26] = floats[30] = floats[34] = blue; - floats[23] = floats[27] = floats[31] = floats[35] = alpha; - - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); + DrawQ_Pic(x, y, Draw_CachePic("white"), width, height, red, green, blue, alpha, flags); } /// color tag printing @@ -1178,11 +1054,6 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma int shadow, colorindex = STRING_COLOR_DEFAULT; size_t i; float x = startx, y, s, t, u, v, thisw; - float *av, *at, *ac; - int batchcount; - static float vertex3f[QUADELEMENTS_MAXQUADS*4*3]; - static float texcoord2f[QUADELEMENTS_MAXQUADS*4*2]; - static float color4f[QUADELEMENTS_MAXQUADS*4*4]; Uchar ch, mapch, nextch; Uchar prevch = 0; // used for kerning int tempcolorindex; @@ -1199,11 +1070,15 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma size_t bytes_left; float dw, dh; const float *width_of; - + dp_model_t *mod = CL_Mesh_UI(); + msurface_t *surf = NULL; + int e0, e1, e2, e3; int tw, th; tw = Draw_GetPicWidth(fnt->pic); th = Draw_GetPicHeight(fnt->pic); + _DrawQ_Setup(); + if (!h) h = w; if (!h) { h = w = 1; @@ -1233,20 +1108,9 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma if (maxlen < 1) maxlen = 1<<30; - _DrawQ_SetupAndProcessDrawFlag(flags, NULL, 0); if(!r_draw2d.integer && !r_draw2d_force) return startx + DrawQ_TextWidth_UntilWidth_TrackColors_Scale(text, &maxlen, w, h, sw, sh, NULL, ignorecolorcodes, fnt, 1000000000); -// R_Mesh_ResetTextureState(); - if (!fontmap) - R_Mesh_TexBind(0, Draw_GetPicTexture(fnt->pic)); - R_SetupShader_Generic(Draw_GetPicTexture(fnt->pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false); - - ac = color4f; - at = texcoord2f; - av = vertex3f; - batchcount = 0; - //ftbase_x = snap_to_pixel_x(ftbase_x); if(snap) { @@ -1363,23 +1227,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma if (ch > 0xFF) goto out; if (fontmap) - { - if (map != ft2_oldstyle_map) - { - if (batchcount) - { - // switching from freetype to non-freetype rendering - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); - batchcount = 0; - ac = color4f; - at = texcoord2f; - av = vertex3f; - } - R_SetupShader_Generic(Draw_GetPicTexture(fnt->pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false); - map = ft2_oldstyle_map; - } - } + map = ft2_oldstyle_map; prevch = 0; //num = (unsigned char) text[i]; //thisw = fnt->width_of[num]; @@ -1399,46 +1247,17 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma u = 0.0625f * thisw - (1.0f / tw); v = 0.0625f - (1.0f / th); } - ac[ 0] = DrawQ_Color[0];ac[ 1] = DrawQ_Color[1];ac[ 2] = DrawQ_Color[2];ac[ 3] = DrawQ_Color[3]; - ac[ 4] = DrawQ_Color[0];ac[ 5] = DrawQ_Color[1];ac[ 6] = DrawQ_Color[2];ac[ 7] = DrawQ_Color[3]; - ac[ 8] = DrawQ_Color[0];ac[ 9] = DrawQ_Color[1];ac[10] = DrawQ_Color[2];ac[11] = DrawQ_Color[3]; - ac[12] = DrawQ_Color[0];ac[13] = DrawQ_Color[1];ac[14] = DrawQ_Color[2];ac[15] = DrawQ_Color[3]; - at[ 0] = s ; at[ 1] = t ; - at[ 2] = s+u ; at[ 3] = t ; - at[ 4] = s+u ; at[ 5] = t+v ; - at[ 6] = s ; at[ 7] = t+v ; - av[ 0] = x ; av[ 1] = y ; av[ 2] = 10; - av[ 3] = x+dw*thisw ; av[ 4] = y ; av[ 5] = 10; - av[ 6] = x+dw*thisw ; av[ 7] = y+dh ; av[ 8] = 10; - av[ 9] = x ; av[10] = y+dh ; av[11] = 10; - ac += 16; - at += 8; - av += 12; - batchcount++; - if (batchcount >= QUADELEMENTS_MAXQUADS) - { - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); - batchcount = 0; - ac = color4f; - at = texcoord2f; - av = vertex3f; - } + surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, fnt->pic->name, flags, TEXF_ALPHA | TEXF_CLAMP, MATERIALFLAG_VERTEXCOLOR), true); + e0 = Mod_Mesh_IndexForVertex(mod, surf, x , y , 10, 0, 0, -1, s , t , 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x+dw*thisw, y , 10, 0, 0, -1, s+u, t , 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x+dw*thisw, y+dh, 10, 0, 0, -1, s+u, t+v, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x , y+dh, 10, 0, 0, -1, s , t+v, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); x += width_of[ch] * dw; } else { if (!map || map == ft2_oldstyle_map || ch < map->start || ch >= map->start + FONT_CHARS_PER_MAP) { - // new charmap - need to render - if (batchcount) - { - // we need a different character map, render what we currently have: - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); - batchcount = 0; - ac = color4f; - at = texcoord2f; - av = vertex3f; - } // find the new map map = FontMap_FindForChar(fontmap, ch); if (!map) @@ -1455,7 +1274,6 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma break; } } - R_SetupShader_Generic(Draw_GetPicTexture(map->pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false); } mapch = ch - map->start; @@ -1470,35 +1288,17 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma } else kx = ky = 0; - ac[ 0] = DrawQ_Color[0]; ac[ 1] = DrawQ_Color[1]; ac[ 2] = DrawQ_Color[2]; ac[ 3] = DrawQ_Color[3]; - ac[ 4] = DrawQ_Color[0]; ac[ 5] = DrawQ_Color[1]; ac[ 6] = DrawQ_Color[2]; ac[ 7] = DrawQ_Color[3]; - ac[ 8] = DrawQ_Color[0]; ac[ 9] = DrawQ_Color[1]; ac[10] = DrawQ_Color[2]; ac[11] = DrawQ_Color[3]; - ac[12] = DrawQ_Color[0]; ac[13] = DrawQ_Color[1]; ac[14] = DrawQ_Color[2]; ac[15] = DrawQ_Color[3]; - at[0] = map->glyphs[mapch].txmin; at[1] = map->glyphs[mapch].tymin; - at[2] = map->glyphs[mapch].txmax; at[3] = map->glyphs[mapch].tymin; - at[4] = map->glyphs[mapch].txmax; at[5] = map->glyphs[mapch].tymax; - at[6] = map->glyphs[mapch].txmin; at[7] = map->glyphs[mapch].tymax; - av[ 0] = x + dw * map->glyphs[mapch].vxmin; av[ 1] = y + dh * map->glyphs[mapch].vymin; av[ 2] = 10; - av[ 3] = x + dw * map->glyphs[mapch].vxmax; av[ 4] = y + dh * map->glyphs[mapch].vymin; av[ 5] = 10; - av[ 6] = x + dw * map->glyphs[mapch].vxmax; av[ 7] = y + dh * map->glyphs[mapch].vymax; av[ 8] = 10; - av[ 9] = x + dw * map->glyphs[mapch].vxmin; av[10] = y + dh * map->glyphs[mapch].vymax; av[11] = 10; + surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, map->pic->name, flags, TEXF_ALPHA | TEXF_CLAMP, MATERIALFLAG_VERTEXCOLOR), true); + e0 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmin, y + dh * map->glyphs[mapch].vymin, 10, 0, 0, -1, map->glyphs[mapch].txmin, map->glyphs[mapch].tymin, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmax, y + dh * map->glyphs[mapch].vymin, 10, 0, 0, -1, map->glyphs[mapch].txmax, map->glyphs[mapch].tymin, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmax, y + dh * map->glyphs[mapch].vymax, 10, 0, 0, -1, map->glyphs[mapch].txmax, map->glyphs[mapch].tymax, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmin, y + dh * map->glyphs[mapch].vymax, 10, 0, 0, -1, map->glyphs[mapch].txmin, map->glyphs[mapch].tymax, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]); + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); //x -= ftbase_x; y -= ftbase_y; x += thisw * dw; - ac += 16; - at += 8; - av += 12; - batchcount++; - if (batchcount >= QUADELEMENTS_MAXQUADS) - { - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); - batchcount = 0; - ac = color4f; - at = texcoord2f; - av = vertex3f; - } //prevmap = map; prevch = ch; @@ -1511,11 +1311,6 @@ out: } } } - if (batchcount > 0) - { - R_Mesh_PrepareVertices_Generic_Arrays(batchcount * 4, vertex3f, color4f, texcoord2f); - R_Mesh_Draw(0, batchcount * 4, 0, batchcount * 2, quadelement3i, NULL, 0, quadelement3s, NULL, 0); - } if (outcolor) *outcolor = colorindex; @@ -1586,195 +1381,57 @@ static int DrawQ_BuildColoredText(char *output2c, size_t maxoutchars, const char void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags) { - float floats[36]; - - _DrawQ_SetupAndProcessDrawFlag(flags, pic, a1*a2*a3*a4); - if(!r_draw2d.integer && !r_draw2d_force) - return; - -// R_Mesh_ResetTextureState(); - if (pic) - { - if (width == 0) - width = pic->width; - if (height == 0) - height = pic->height; - R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & (DRAWFLAGS_BLEND | DRAWFLAG_NOGAMMA)) ? false : true, true, false); - } - else - R_SetupShader_Generic_NoTexture((flags & (DRAWFLAGS_BLEND | DRAWFLAG_NOGAMMA)) ? false : true, true); - - floats[2] = floats[5] = floats[8] = floats[11] = 0; - floats[0] = floats[9] = x; - floats[1] = floats[4] = y; - floats[3] = floats[6] = x + width; - floats[7] = floats[10] = y + height; - floats[12] = s1;floats[13] = t1; - floats[14] = s2;floats[15] = t2; - floats[16] = s4;floats[17] = t4; - floats[18] = s3;floats[19] = t3; - floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1; - floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2; - floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4; - floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3; - - R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); -} - -void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha) -{ + dp_model_t *mod = CL_Mesh_UI(); + msurface_t *surf; + int e0, e1, e2, e3; _DrawQ_Setup(); - if(!r_draw2d.integer && !r_draw2d_force) - return; - DrawQ_ProcessDrawFlag(flags, hasalpha); - -// R_Mesh_ResetTextureState(); - R_SetupShader_Generic(mesh->texture, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false); - - R_Mesh_PrepareVertices_Generic_Arrays(mesh->num_vertices, mesh->data_vertex3f, mesh->data_color4f, mesh->data_texcoord2f); - R_Mesh_Draw(0, mesh->num_vertices, 0, mesh->num_triangles, mesh->data_element3i, NULL, 0, mesh->data_element3s, NULL, 0); -} - -void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags) -{ - _DrawQ_SetupAndProcessDrawFlag(flags, NULL, 1); - if(!r_draw2d.integer && !r_draw2d_force) - return; - - GL_Color(1,1,1,1); - switch(vid.renderpath) - { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: -#ifndef USE_GLES2 - { - int num; - CHECKGLERROR - qglBegin(GL_LINE_LOOP); - for (num = 0;num < mesh->num_vertices;num++) - { - if (mesh->data_color4f) - GL_Color(mesh->data_color4f[num*4+0], mesh->data_color4f[num*4+1], mesh->data_color4f[num*4+2], mesh->data_color4f[num*4+3]); - qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]); - } - qglEnd(); - CHECKGLERROR - } -#endif - break; - case RENDERPATH_D3D9: - //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_SOFT: - //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_GLES1: - case RENDERPATH_GLES2: - //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; - } + if (!pic) + pic = Draw_CachePic("white"); + if (width == 0) + width = pic->width; + if (height == 0) + height = pic->height; + surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_VERTEXCOLOR), true); + e0 = Mod_Mesh_IndexForVertex(mod, surf, x , y , 0, 0, 0, -1, s1, t1, 0, 0, r1, g1, b1, a1); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y , 0, 0, 0, -1, s2, t2, 0, 0, r2, g2, b2, a2); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y + height, 0, 0, 0, -1, s4, t4, 0, 0, r4, g4, b4, a4); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x , y + height, 0, 0, 0, -1, s3, t3, 0, 0, r3, g3, b3, a3); + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); } -//[515]: this is old, delete void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags) { - _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha); - if(!r_draw2d.integer && !r_draw2d_force) - return; - - R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true); - - switch(vid.renderpath) + dp_model_t *mod = CL_Mesh_UI(); + msurface_t *surf; + int e0, e1, e2, e3; + float offsetx, offsety; + _DrawQ_Setup(); + // width is measured in real pixels + if (fabs(x2 - x1) > fabs(y2 - y1)) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: -#ifndef USE_GLES2 - CHECKGLERROR - - //qglLineWidth(width);CHECKGLERROR - - GL_Color(r,g,b,alpha); - CHECKGLERROR - qglBegin(GL_LINES); - qglVertex2f(x1, y1); - qglVertex2f(x2, y2); - qglEnd(); - CHECKGLERROR -#endif - break; - case RENDERPATH_D3D9: - //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_SOFT: - //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_GLES1: - case RENDERPATH_GLES2: - //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; + offsetx = 0; + offsety = width * vid_conheight.value / vid.height; } -} - -void DrawQ_Lines (float width, int numlines, int flags, qboolean hasalpha) -{ - _DrawQ_SetupAndProcessDrawFlag(flags, NULL, hasalpha ? 0.5f : 1.0f); - - if(!r_draw2d.integer && !r_draw2d_force) - return; - - switch(vid.renderpath) + else { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - CHECKGLERROR - - R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true); - - //qglLineWidth(width);CHECKGLERROR - - CHECKGLERROR - qglDrawArrays(GL_LINES, 0, numlines*2); - CHECKGLERROR - break; - case RENDERPATH_D3D9: - //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_SOFT: - //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_GLES1: - case RENDERPATH_GLES2: - //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; + offsetx = width * vid_conwidth.value / vid.width; + offsety = 0; } + surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_VERTEXCOLOR), true); + e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); + Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); } void DrawQ_SetClipArea(float x, float y, float width, float height) { int ix, iy, iw, ih; _DrawQ_Setup(); + DrawQ_FlushUI(); // We have to convert the con coords into real coords // OGL uses bottom to top (origin is in bottom left) @@ -1808,18 +1465,55 @@ void DrawQ_SetClipArea(float x, float y, float width, float height) void DrawQ_ResetClipArea(void) { + DrawQ_FlushUI(); _DrawQ_Setup(); GL_ScissorTest(false); } void DrawQ_Finish(void) { + DrawQ_FlushUI(); r_refdef.draw2dstage = 0; } void DrawQ_RecalcView(void) { + DrawQ_FlushUI(); if(r_refdef.draw2dstage) r_refdef.draw2dstage = -1; // next draw call will set viewport etc. again } +void DrawQ_FlushUI(void) +{ + int i; + dp_model_t *mod = CL_Mesh_UI(); + if (mod->num_surfaces == 0) + return; + + if (!r_draw2d.integer && !r_draw2d_force) + { + Mod_Mesh_Reset(mod); + return; + } + + // TODO: render the mesh using R_Q1BSP_Draw or similar, for full material support. + GL_DepthMask(false); + R_Mesh_PrepareVertices_Generic_Arrays(mod->surfmesh.num_vertices, mod->surfmesh.data_vertex3f, mod->surfmesh.data_lightmapcolor4f, mod->surfmesh.data_texcoordtexture2f); + for (i = 0; i < mod->num_surfaces; i++) + { + msurface_t *surf = mod->data_surfaces + i; + texture_t *tex = surf->texture; + if (tex->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) + GL_BlendFunc(tex->customblendfunc[0], tex->customblendfunc[1]); + else if (tex->currentmaterialflags & MATERIALFLAG_ADD) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + else if (tex->currentmaterialflags & MATERIALFLAG_ALPHA) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else + GL_BlendFunc(GL_ONE, GL_ZERO); + R_SetupShader_Generic(tex->currentskinframe->base, NULL, GL_MODULATE, 1, (tex->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) ? false : true, true, false); + R_Mesh_Draw(surf->num_firstvertex, surf->num_vertices, surf->num_firsttriangle, surf->num_triangles, mod->surfmesh.data_element3i, NULL, 0, mod->surfmesh.data_element3s, NULL, 0); + } + + Mod_Mesh_Reset(mod); +} diff --git a/gl_rmain.c b/gl_rmain.c index 36a45b0d..938d97f7 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -7438,9 +7438,6 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) R_TimeReport("explosions"); } - if (cl.csqc_loaded) - VM_CL_AddPolygonsToMeshQueue(CLVM_prog); - if (r_refdef.view.showdebug) { if (cl_locs_show.integer) @@ -8169,8 +8166,8 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT; if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD)) { - // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale - t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT; + // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale + t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT; for (q = 0; q < 3; q++) { t->render_glowmod[q] = rsurface.entity->glowmod[q]; @@ -8245,8 +8242,8 @@ texture_t *R_GetCurrentTexture(texture_t *t) for (q = 0; q < 3; q++) { t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale; - t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale; - t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale; + t->render_modellight_lightdir[q] = q == 2; + t->render_modellight_ambient[q] = 0; t->render_modellight_diffuse[q] = 0; t->render_modellight_specular[q] = 0; t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale; @@ -8257,6 +8254,30 @@ texture_t *R_GetCurrentTexture(texture_t *t) } } + if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR) + { + // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex + // attribute, we punt it to the lightmap path and hope for the best, + // but lighting doesn't work. + // + // FIXME: this is fine for effects but CSQC polygons should be subject + // to lighting. + t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT; + for (q = 0; q < 3; q++) + { + t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale; + t->render_modellight_lightdir[q] = q == 2; + t->render_modellight_ambient[q] = 0; + t->render_modellight_diffuse[q] = 0; + t->render_modellight_specular[q] = 0; + t->render_lightmap_ambient[q] = 0; + t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale; + t->render_lightmap_specular[q] = 0; + t->render_rtlight_diffuse[q] = 0; + t->render_rtlight_specular[q] = 0; + } + } + for (q = 0; q < 3; q++) { t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q]; diff --git a/model_alias.c b/model_alias.c index 9fdc0800..cdf0edee 100644 --- a/model_alias.c +++ b/model_alias.c @@ -944,7 +944,7 @@ void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, con Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf)); if(developer_extra.integer) Con_DPrintf("--> got %s from skin file\n", stripbuf); - Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL); break; } } @@ -963,7 +963,7 @@ void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, con if(developer_extra.integer) Con_DPrintf("--> using default\n"); Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf)); - Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL); } } @@ -1259,7 +1259,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j); else dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i); - if (!Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS)) + if (!Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL)) Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight)); datapointer += skinwidth * skinheight; totalskins++; @@ -1451,7 +1451,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->num_texturesperskin = loadmodel->num_surfaces; loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME) - Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL); } else { diff --git a/model_brush.c b/model_brush.c index e6451a05..eb37da16 100644 --- a/model_brush.c +++ b/model_brush.c @@ -1826,7 +1826,7 @@ static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb) // LordHavoc: backup the texture_t because q3 shader loading overwrites it backuptex = loadmodel->data_textures[i]; - if (name[0] && Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i, name, false, false, 0)) + if (name[0] && Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i, name, false, false, 0, MATERIALFLAG_WALL)) continue; loadmodel->data_textures[i] = backuptex; @@ -4439,7 +4439,7 @@ static void Mod_Q2BSP_LoadTexinfo(sizebuf_t *sb) int q2flags = out->q2flags; unsigned char *walfile = NULL; fs_offset_t walfilesize = 0; - Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, tx, filename, true, true, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, tx, filename, true, true, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL); // now read the .wal file to get metadata (even if a .tga was overriding it, we still need the wal data) walfile = FS_LoadFile(filename, tempmempool, true, &walfilesize); if (walfile) @@ -5309,7 +5309,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) { out[i].surfaceflags = LittleLong(in[i].surfaceflags); out[i].supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(LittleLong(in[i].contents)); - Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, out + i, in[i].name, true, true, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, out + i, in[i].name, true, true, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL); // restore the surfaceflags and supercontents out[i].surfaceflags = LittleLong(in[i].surfaceflags); out[i].supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(LittleLong(in[i].contents)); diff --git a/model_brush.h b/model_brush.h index 2eb38470..3b1d6162 100644 --- a/model_brush.h +++ b/model_brush.h @@ -127,6 +127,8 @@ mplane_t; #define MATERIALFLAG_ALPHAGEN_VERTEX 0x08000000 // use occlusion buffer for corona #define MATERIALFLAG_OCCLUDE 0x10000000 +// use vertex color instead of lighting (e.g. particles and other glowy stuff), use with MATERIALFLAG_FULLBRIGHT +#define MATERIALFLAG_VERTEXCOLOR 0x20000000 // combined mask of all attributes that require depth sorted rendering #define MATERIALFLAGMASK_DEPTHSORTED (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST) // combined mask of all attributes that cause some sort of transparency diff --git a/model_shared.c b/model_shared.c index 9d7d449d..5fea2298 100644 --- a/model_shared.c +++ b/model_shared.c @@ -2446,7 +2446,7 @@ texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(mempool_t *mempool, return shaderpass; } -qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags) +qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags, int defaultmaterialflags) { int texflagsmask, texflagsor; qboolean success = true; @@ -2613,6 +2613,9 @@ nothing GL_ZERO GL_ONE materiallayer = rgbgenvertexlayer; endofprelayers = rgbgenvertexlayer; firstpostlayer = rgbgenvertexlayer + 1; + // special case for rgbgen vertex if MATERIALFLAG_VERTEXCOLOR is expected on this material + if (defaultmaterialflags & MATERIALFLAG_VERTEXCOLOR) + texture->basematerialflags |= MATERIALFLAG_VERTEXCOLOR; } else if (rgbgendiffuselayer >= 0) { @@ -2777,17 +2780,17 @@ nothing GL_ZERO GL_ONE Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", modelname, texture->name); if (texture->surfaceflags & Q3SURFACEFLAG_NODRAW) { - texture->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW; + texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW; texture->supercontents = SUPERCONTENTS_SOLID; } else if (texture->surfaceflags & Q3SURFACEFLAG_SKY) { - texture->basematerialflags |= MATERIALFLAG_SKY; + texture->basematerialflags = MATERIALFLAG_SKY; texture->supercontents = SUPERCONTENTS_SKY; } else { - texture->basematerialflags |= MATERIALFLAG_WALL; + texture->basematerialflags = defaultmaterialflags; texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE; } if(cls.state == ca_dedicated) @@ -2797,9 +2800,10 @@ nothing GL_ZERO GL_ONE } else { - if (fallback) + skinframe_t *skinframe = R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false, fallback); + if (skinframe) { - texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false, true)); + texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, skinframe); if (texture->materialshaderpass->skinframes[0]->hasalpha) texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; if (texture->q2contents) @@ -4614,7 +4618,7 @@ void Mod_Mesh_Reset(dp_model_t *mod) mod->DrawAddWaterPlanes = NULL; // will be set if a texture needs it } -texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int addmaterialflags) +texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int defaultmaterialflags) { int i; texture_t *t; @@ -4631,8 +4635,7 @@ texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdra mod->data_surfaces[i].texture = mod->data_textures + (mod->data_surfaces[i].texture - oldtextures); } t = &mod->data_textures[mod->num_textures++]; - Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, false, true, defaulttexflags); - t->basematerialflags |= addmaterialflags; + Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, false, true, defaulttexflags, defaultmaterialflags); switch (defaultdrawflags & DRAWFLAG_MASK) { case DRAWFLAG_ADDITIVE: diff --git a/model_shared.h b/model_shared.h index 0d3914ed..9b5bf7b3 100644 --- a/model_shared.h +++ b/model_shared.h @@ -1183,7 +1183,7 @@ void Mod_CreateCollisionMesh(dp_model_t *mod); void Mod_FreeQ3Shaders(void); void Mod_LoadQ3Shaders(void); q3shaderinfo_t *Mod_LookupQ3Shader(const char *name); -qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags); +qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags, int defaultmaterialflags); texture_shaderpass_t *Mod_CreateShaderPass(mempool_t *mempool, skinframe_t *skinframe); texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(mempool_t *mempool, const char *modelname, q3shaderinfo_layer_t *layer, int layerindex, int texflags, const char *texturename); /// Sets up a material to render the provided skinframe. See also R_SkinFrame_LoadInternalBGRA. diff --git a/mvm_cmds.c b/mvm_cmds.c index a310b0e7..cc5d9c9f 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -1612,7 +1612,7 @@ void MVM_init_cmd(prvm_prog_t *prog) r_refdef_scene_t *scene; VM_Cmd_Init(prog); - VM_Polygons_Reset(prog); + prog->polygonbegin_model = NULL; scene = R_GetScenePointer( RST_MENU ); @@ -1634,5 +1634,5 @@ void MVM_reset_cmd(prvm_prog_t *prog) //VM_Cmd_Init(); VM_Cmd_Reset(prog); - VM_Polygons_Reset(prog); + prog->polygonbegin_model = NULL; } diff --git a/progsvm.h b/progsvm.h index 0a46d2aa..4188a8fa 100644 --- a/progsvm.h +++ b/progsvm.h @@ -116,43 +116,6 @@ typedef struct prvm_edict_s } fields; } prvm_edict_t; -#define VMPOLYGONS_MAXPOINTS 64 - -typedef struct vmpolygons_triangle_s -{ - rtexture_t *texture; - int drawflag; - qboolean hasalpha; - unsigned short elements[3]; -} vmpolygons_triangle_t; - -typedef struct vmpolygons_s -{ - mempool_t *pool; - qboolean initialized; - - int max_vertices; - int num_vertices; - float *data_vertex3f; - float *data_color4f; - float *data_texcoord2f; - - int max_triangles; - int num_triangles; - vmpolygons_triangle_t *data_triangles; - unsigned short *data_sortedelement3s; - - qboolean begin_active; - int begin_draw2d; - rtexture_t *begin_texture; - int begin_drawflag; - int begin_vertices; - float begin_vertex[VMPOLYGONS_MAXPOINTS][3]; - float begin_color[VMPOLYGONS_MAXPOINTS][4]; - float begin_texcoord[VMPOLYGONS_MAXPOINTS][2]; - qboolean begin_texture_hasalpha; -} vmpolygons_t; - extern prvm_eval_t prvm_badvalue; #define PRVM_alledictfloat(ed, fieldname) (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname)) @@ -634,9 +597,10 @@ typedef struct prvm_prog_s // buffer for storing all tempstrings created during one invocation of ExecuteProgram sizebuf_t tempstringsbuf; - // LordHavoc: moved this here to clean up things that relied on prvm_prog_list too much - // FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions? - vmpolygons_t vmpolygons; + // in csqc the polygonbegin,polygonvertex,polygonend sequencing is + // stateful, so this tracks the last polygonbegin's choice of + // CL_Mesh_CSQC or CL_Mesh_UI for this polygon + dp_model_t *polygonbegin_model; // copies of some vars that were former read from sv int num_edicts; diff --git a/r_lightning.c b/r_lightning.c index 5373e633..e3d05012 100644 --- a/r_lightning.c +++ b/r_lightning.c @@ -21,9 +21,7 @@ static void r_lightningbeams_start(void) static void CL_Beams_SetupExternalTexture(void) { - if (Mod_LoadTextureFromQ3Shader(r_main_mempool, "r_lightning.c", &cl_beams_externaltexture, "textures/particles/lightning", false, false, TEXF_ALPHA | TEXF_FORCELINEAR)) - cl_beams_externaltexture.basematerialflags = cl_beams_externaltexture.currentmaterialflags = MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE; - else + if (Mod_LoadTextureFromQ3Shader(r_main_mempool, "r_lightning.c", &cl_beams_externaltexture, "textures/particles/lightning", false, false, TEXF_ALPHA | TEXF_FORCELINEAR, MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE)) Cvar_SetValueQuick(&r_lightningbeam_qmbtexture, false); } @@ -77,7 +75,7 @@ static void CL_Beams_SetupBuiltinTexture(void) } skinframe = R_SkinFrame_LoadInternalBGRA("lightningbeam", TEXF_FORCELINEAR, data, texwidth, texheight, false); - Mod_LoadCustomMaterial(r_main_mempool, &cl_beams_builtintexture, "cl_beams_builtintexture", 0, MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE, skinframe); + Mod_LoadCustomMaterial(r_main_mempool, &cl_beams_builtintexture, "cl_beams_builtintexture", 0, MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_VERTEXCOLOR, skinframe); Mem_Free(data); } diff --git a/render.h b/render.h index 3663834a..d8fd0343 100644 --- a/render.h +++ b/render.h @@ -458,30 +458,30 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents); void RSurf_SetupDepthAndCulling(void); -void R_Mesh_ResizeArrays(int newvertices); - texture_t *R_GetCurrentTexture(texture_t *t); void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass); void R_AddWaterPlanes(entity_render_t *ent); void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass); void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass); -#define BATCHNEED_VERTEXMESH_VERTEX (1<< 1) // set up rsurface.batchvertexmesh -#define BATCHNEED_VERTEXMESH_NORMAL (1<< 2) // set up normals in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchnormal3f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_VECTOR (1<< 3) // set up vectors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchsvector3f and rsurface.batchtvector3f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_VERTEXCOLOR (1<< 4) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_TEXCOORD (1<< 5) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_LIGHTMAP (1<< 6) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_VERTEXMESH_SKELETAL (1<< 7) // set up skeletal index and weight data for vertex shader -#define BATCHNEED_ARRAY_VERTEX (1<< 8) // set up rsurface.batchvertex3f and optionally others -#define BATCHNEED_ARRAY_NORMAL (1<< 9) // set up normals in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchnormal3f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_VECTOR (1<<10) // set up vectors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchsvector3f and rsurface.batchtvector3f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_VERTEXCOLOR (1<<11) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_TEXCOORD (1<<12) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_LIGHTMAP (1<<13) // set up vertex colors in rsurface.batchvertexmesh if BATCHNEED_MESH, set up rsurface.batchlightmapcolor4f if BATCHNEED_ARRAYS -#define BATCHNEED_ARRAY_SKELETAL (1<<14) // set up skeletal index and weight data for vertex shader -#define BATCHNEED_NOGAPS (1<<15) // force vertex copying if firstvertex is not zero or there are gaps -#define BATCHNEED_ALLOWMULTIDRAW (1<<16) // allow multiple draws +#define BATCHNEED_VERTEXMESH_VERTEX (1<< 0) // set up positions in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_NORMAL (1<< 1) // set up normals in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_VECTOR (1<< 2) // set up tangent vectors in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_VERTEXTINTCOLOR (1<< 3) // set up vertex tint colors in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_VERTEXCOLOR (1<< 4) // set up vertex light colors in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_TEXCOORD (1<< 5) // set up surface texcoords in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_LIGHTMAP (1<< 6) // set up lightmap texcoords in rsurface.batchvertexmesh +#define BATCHNEED_VERTEXMESH_SKELETAL (1<< 7) // set up skeletal index and weight data for vertex shader +#define BATCHNEED_ARRAY_VERTEX (1<< 8) // set up rsurface.batchvertex3f +#define BATCHNEED_ARRAY_NORMAL (1<< 9) // set up rsurface.batchnormal3f +#define BATCHNEED_ARRAY_VECTOR (1<<10) // set up rsurface.batchsvector3f and rsurface.batchtvector3f +#define BATCHNEED_ARRAY_VERTEXTINTCOLOR (1<<11) // set up rsurface.batchvertexcolor4f +#define BATCHNEED_ARRAY_VERTEXCOLOR (1<<12) // set up rsurface.batchlightmapcolor4f +#define BATCHNEED_ARRAY_TEXCOORD (1<<13) // set up rsurface.batchtexcoordtexture2f +#define BATCHNEED_ARRAY_LIGHTMAP (1<<14) // set up rsurface.batchtexcoordlightmap2f +#define BATCHNEED_ARRAY_SKELETAL (1<<15) // set up skeletal index and weight data for vertex shader +#define BATCHNEED_NOGAPS (1<<16) // force vertex copying if firstvertex is not zero or there are gaps +#define BATCHNEED_ALLOWMULTIDRAW (1<<17) // allow multiple draws void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist); void RSurf_DrawBatch(void); @@ -604,7 +604,6 @@ void SCR_DrawConsole(void); void R_Shadow_EditLights_DrawSelectedLightProperties(void); void R_DecalSystem_Reset(decalsystem_t *decalsystem); void R_Shadow_UpdateBounceGridTexture(void); -void VM_CL_AddPolygonsToMeshQueue(struct prvm_prog_s *prog); void R_DrawPortals(void); void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); void R_Water_AddWaterPlane(msurface_t *surface, int entno); -- 2.39.2