From: havoc Date: Sat, 16 Oct 2004 11:29:13 +0000 (+0000) Subject: now parses more of q3 shaders to guess at proper rendering settings for surfaces... X-Git-Tag: xonotic-v0.1.0preview~5474 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=0b1a551c92c502e09d5d8590c76db227d249b1b1;p=xonotic%2Fdarkplaces.git now parses more of q3 shaders to guess at proper rendering settings for surfaces, now implemented are additive blend, deformvertexes autosprite (and autosprite2), nomipmaps, nopicmip, cull twosided/none/disable, surfaceparm nomipmap now assumes that a q3 texture is not transparent unless it has a shader saying it is (yes shaders are now required to enable transparency in q3bsp) now loads the texture used in the first pass of the shader if there is no texture of the same name as the shader itself what this all means: quake3 maps look 99% correct (other than lack of animation and various shader effects) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4648 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_rsurf.c b/gl_rsurf.c index 9e53d693..7db260b7 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1931,7 +1931,7 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber) rmeshstate_t m; R_Mesh_Matrix(&ent->matrix); memset(&m, 0, sizeof(m)); - if (ent->effects & EF_ADDITIVE) + if ((ent->effects & EF_ADDITIVE) || (face->texture->textureflags & Q3TEXTUREFLAG_ADDITIVE)) GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); else GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1979,13 +1979,60 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber) } m.pointer_color = varray_color4f; } - m.pointer_vertex = face->data_vertex3f; + if (face->texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) + { + int i, j; + float f, center[3], center2[3], forward[3], right[3], up[3], v[4][3]; + matrix4x4_t matrix1, imatrix1; + R_Mesh_Matrix(&r_identitymatrix); + // a single autosprite surface can contain multiple sprites... + for (j = 0;j < face->num_vertices - 3;j += 4) + { + VectorClear(center); + for (i = 0;i < 4;i++) + VectorAdd(center, face->data_vertex3f + (j+i) * 3, center); + VectorScale(center, 0.25f, center); + Matrix4x4_Transform(&ent->matrix, center, center2); + // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out? + Matrix4x4_FromVectors(&matrix1, face->data_normal3f + j*3, face->data_svector3f + j*3, face->data_tvector3f + j*3, center); + Matrix4x4_Invert_Simple(&imatrix1, &matrix1); + for (i = 0;i < 4;i++) + Matrix4x4_Transform(&imatrix1, face->data_vertex3f + (j+i)*3, v[i]); + if (face->texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2) + { + CL_SparkShower (center, vec3_origin, 1); + forward[0] = r_vieworigin[0] - center2[0]; + forward[1] = r_vieworigin[1] - center2[1]; + forward[2] = 0; + VectorNormalize(forward); + right[0] = forward[1]; + right[1] = -forward[0]; + right[2] = 0; + up[0] = 0; + up[1] = 0; + up[2] = 1; + } + else + { + VectorCopy(r_viewforward, forward); + VectorCopy(r_viewright, right); + VectorCopy(r_viewup, up); + } + for (i = 0;i < 4;i++) + VectorMAMAMAM(1, center2, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (i+j) * 3); + } + m.pointer_vertex = varray_vertex3f; + } + else + m.pointer_vertex = face->data_vertex3f; R_Mesh_State(&m); - qglDisable(GL_CULL_FACE); + if (face->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglDisable(GL_CULL_FACE); GL_LockArrays(0, face->num_vertices); R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i); GL_LockArrays(0, 0); - qglEnable(GL_CULL_FACE); + if (face->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglEnable(GL_CULL_FACE); } void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumfaces, q3msurface_t **texturefacelist) @@ -2063,6 +2110,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf GL_DepthMask(true); GL_DepthTest(true); GL_BlendFunc(GL_ONE, GL_ZERO); + qglDisable(GL_CULL_FACE); memset(&m, 0, sizeof(m)); for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++) { @@ -2082,6 +2130,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i); GL_LockArrays(0, 0); } + qglEnable(GL_CULL_FACE); return; } // anything else is a typical wall, lightmap * texture + glow @@ -2091,6 +2140,8 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf GL_DepthTest(true); GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(1, 1, 1, 1); + if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglDisable(GL_CULL_FACE); memset(&m, 0, sizeof(m)); m.tex[0] = R_GetTexture(t->skin.base); for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++) @@ -2119,8 +2170,12 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf GL_LockArrays(0, 0); } } + if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglEnable(GL_CULL_FACE); return; } + if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglDisable(GL_CULL_FACE); if (r_lightmapintensity <= 0) { GL_DepthMask(true); @@ -2252,6 +2307,8 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf GL_LockArrays(0, 0); } } + if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglEnable(GL_CULL_FACE); } void R_Q3BSP_DrawFaces(entity_render_t *ent, int skyfaces) @@ -2424,16 +2481,34 @@ void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa { if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS) && !(surface->texture->surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NODRAW)) && surface->num_triangles) { - for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3) + if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) { - v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3) { - SETPVSBIT(outsurfacepvs, surfaceindex); - outsurfacelist[outnumsurfaces++] = surfaceindex; - break; + v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; + v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; + v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; + if (lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + { + SETPVSBIT(outsurfacepvs, surfaceindex); + outsurfacelist[outnumsurfaces++] = surfaceindex; + break; + } + } + } + else + { + for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3) + { + v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; + v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; + v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; + if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + { + SETPVSBIT(outsurfacepvs, surfaceindex); + outsurfacelist[outnumsurfaces++] = surfaceindex; + break; + } } } } @@ -2475,7 +2550,7 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, { surface = model->brushq3.data_faces + surfacelist[surfacelistindex]; // FIXME: check some manner of face->rendermode here? - if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS)) + if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && !(surface->texture->surfaceparms & (Q3SURFACEPARM_SKY | Q3SURFACEPARM_TRANS)) && !(surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)) R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs); } R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist); @@ -2507,7 +2582,13 @@ void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->data_vertex3f, surface->data_svector3f, surface->data_tvector3f, surface->data_normal3f, surface->data_texcoordtexture2f, surface->num_triangles, surface->data_element3i); } else if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->num_triangles) + { + if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglDisable(GL_CULL_FACE); R_Shadow_RenderLighting(surface->num_vertices, surface->num_triangles, surface->data_element3i, surface->data_vertex3f, surface->data_svector3f, surface->data_tvector3f, surface->data_normal3f, surface->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, surface->texture->skin.base, surface->texture->skin.nmap, surface->texture->skin.gloss, lightcubemap, LIGHTING_DIFFUSE | LIGHTING_SPECULAR); + if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglEnable(GL_CULL_FACE); + } } } } diff --git a/model_brush.c b/model_brush.c index 2cb005c4..5f432355 100644 --- a/model_brush.c +++ b/model_brush.c @@ -3597,9 +3597,11 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) fssearch_t *search; char *f; const char *text; - int flags; + int flags, flags2, numparameters, passnumber; char shadername[Q3PATHLENGTH]; char sky[Q3PATHLENGTH]; + char firstpasstexturename[Q3PATHLENGTH]; + char parameter[4][Q3PATHLENGTH]; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -3617,7 +3619,6 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) out->surfaceflags = LittleLong(in->surfaceflags); out->nativecontents = LittleLong(in->contents); out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, out->nativecontents); - Mod_LoadSkinFrame(&out->skin, out->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, true, true); out->surfaceparms = -1; } @@ -3633,7 +3634,10 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) { strlcpy (shadername, com_token, sizeof (shadername)); flags = 0; + flags2 = 0; sky[0] = 0; + passnumber = 0; + firstpasstexturename[0] = 0; if (COM_ParseToken(&text, false) && !strcasecmp(com_token, "{")) { while (COM_ParseToken(&text, false)) @@ -3646,103 +3650,152 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) { if (!strcasecmp(com_token, "}")) break; + if (!strcasecmp(com_token, "\n")) + continue; + numparameters = 0; + for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++) + { + if (j < 4) + { + strlcpy(parameter[j], com_token, sizeof(parameter[j])); + numparameters = j + 1; + } + if (!COM_ParseToken(&text, true)) + break; + } + Con_Printf("%s %i: ", shadername, passnumber); + for (j = 0;j < numparameters;j++) + Con_Printf(" %s", parameter[j]); + Con_Print("\n"); + if (passnumber == 0 && numparameters >= 1) + { + if (!strcasecmp(parameter[0], "blendfunc")) + { + Con_Printf("!\n"); + if (numparameters == 2 && !strcasecmp(parameter[1], "add")) + flags2 |= Q3TEXTUREFLAG_ADDITIVE; + else if (numparameters == 3 && !strcasecmp(parameter[1], "gl_one") && !strcasecmp(parameter[2], "gl_one")) + flags2 |= Q3TEXTUREFLAG_ADDITIVE; + else if (numparameters == 3 && !strcasecmp(parameter[1], "gl_src_alpha") && !strcasecmp(parameter[2], "gl_one")) + flags2 |= Q3TEXTUREFLAG_ADDITIVE; + } + else if (numparameters >= 2 && (!strcasecmp(parameter[0], "map") || !strcasecmp(parameter[0], "clampmap"))) + strlcpy(firstpasstexturename, parameter[1], sizeof(firstpasstexturename)); + else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap")) + strlcpy(firstpasstexturename, parameter[2], sizeof(firstpasstexturename)); + } + // break out a level if it was } + if (!strcasecmp(com_token, "}")) + break; } + passnumber++; + continue; } - else if (!strcasecmp(com_token, "surfaceparm")) + numparameters = 0; + for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++) { - if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n")) + if (j < 4) { - if (!strcasecmp(com_token, "alphashadow")) - flags |= Q3SURFACEPARM_ALPHASHADOW; - else if (!strcasecmp(com_token, "areaportal")) - flags |= Q3SURFACEPARM_AREAPORTAL; - else if (!strcasecmp(com_token, "clusterportal")) - flags |= Q3SURFACEPARM_CLUSTERPORTAL; - else if (!strcasecmp(com_token, "detail")) - flags |= Q3SURFACEPARM_DETAIL; - else if (!strcasecmp(com_token, "donotenter")) - flags |= Q3SURFACEPARM_DONOTENTER; - else if (!strcasecmp(com_token, "fog")) - flags |= Q3SURFACEPARM_FOG; - else if (!strcasecmp(com_token, "lava")) - flags |= Q3SURFACEPARM_LAVA; - else if (!strcasecmp(com_token, "lightfilter")) - flags |= Q3SURFACEPARM_LIGHTFILTER; - else if (!strcasecmp(com_token, "metalsteps")) - flags |= Q3SURFACEPARM_METALSTEPS; - else if (!strcasecmp(com_token, "nodamage")) - flags |= Q3SURFACEPARM_NODAMAGE; - else if (!strcasecmp(com_token, "nodlight")) - flags |= Q3SURFACEPARM_NODLIGHT; - else if (!strcasecmp(com_token, "nodraw")) - flags |= Q3SURFACEPARM_NODRAW; - else if (!strcasecmp(com_token, "nodrop")) - flags |= Q3SURFACEPARM_NODROP; - else if (!strcasecmp(com_token, "noimpact")) - flags |= Q3SURFACEPARM_NOIMPACT; - else if (!strcasecmp(com_token, "nolightmap")) - flags |= Q3SURFACEPARM_NOLIGHTMAP; - else if (!strcasecmp(com_token, "nomarks")) - flags |= Q3SURFACEPARM_NOMARKS; - else if (!strcasecmp(com_token, "nomipmaps")) - flags |= Q3SURFACEPARM_NOMIPMAPS; - else if (!strcasecmp(com_token, "nonsolid")) - flags |= Q3SURFACEPARM_NONSOLID; - else if (!strcasecmp(com_token, "origin")) - flags |= Q3SURFACEPARM_ORIGIN; - else if (!strcasecmp(com_token, "playerclip")) - flags |= Q3SURFACEPARM_PLAYERCLIP; - else if (!strcasecmp(com_token, "sky")) - flags |= Q3SURFACEPARM_SKY; - else if (!strcasecmp(com_token, "slick")) - flags |= Q3SURFACEPARM_SLICK; - else if (!strcasecmp(com_token, "slime")) - flags |= Q3SURFACEPARM_SLIME; - else if (!strcasecmp(com_token, "structural")) - flags |= Q3SURFACEPARM_STRUCTURAL; - else if (!strcasecmp(com_token, "trans")) - flags |= Q3SURFACEPARM_TRANS; - else if (!strcasecmp(com_token, "water")) - flags |= Q3SURFACEPARM_WATER; - else - Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], com_token); - if (!COM_ParseToken(&text, true) || strcasecmp(com_token, "\n")) - { - Con_Printf("%s parsing error: surfaceparm only takes one parameter.\n", search->filenames[i]); - goto parseerror; - } + strlcpy(parameter[j], com_token, sizeof(parameter[j])); + numparameters = j + 1; } + if (!COM_ParseToken(&text, true)) + break; + } + if (i == 0 && !strcasecmp(com_token, "}")) + break; + Con_Printf("%s: ", shadername); + for (j = 0;j < numparameters;j++) + Con_Printf(" %s", parameter[j]); + Con_Print("\n"); + if (numparameters < 1) + continue; + if (!strcasecmp(parameter[0], "surfaceparm") && numparameters >= 2) + { + if (!strcasecmp(parameter[1], "alphashadow")) + flags |= Q3SURFACEPARM_ALPHASHADOW; + else if (!strcasecmp(parameter[1], "areaportal")) + flags |= Q3SURFACEPARM_AREAPORTAL; + else if (!strcasecmp(parameter[1], "clusterportal")) + flags |= Q3SURFACEPARM_CLUSTERPORTAL; + else if (!strcasecmp(parameter[1], "detail")) + flags |= Q3SURFACEPARM_DETAIL; + else if (!strcasecmp(parameter[1], "donotenter")) + flags |= Q3SURFACEPARM_DONOTENTER; + else if (!strcasecmp(parameter[1], "fog")) + flags |= Q3SURFACEPARM_FOG; + else if (!strcasecmp(parameter[1], "lava")) + flags |= Q3SURFACEPARM_LAVA; + else if (!strcasecmp(parameter[1], "lightfilter")) + flags |= Q3SURFACEPARM_LIGHTFILTER; + else if (!strcasecmp(parameter[1], "metalsteps")) + flags |= Q3SURFACEPARM_METALSTEPS; + else if (!strcasecmp(parameter[1], "nodamage")) + flags |= Q3SURFACEPARM_NODAMAGE; + else if (!strcasecmp(parameter[1], "nodlight")) + flags |= Q3SURFACEPARM_NODLIGHT; + else if (!strcasecmp(parameter[1], "nodraw")) + flags |= Q3SURFACEPARM_NODRAW; + else if (!strcasecmp(parameter[1], "nodrop")) + flags |= Q3SURFACEPARM_NODROP; + else if (!strcasecmp(parameter[1], "noimpact")) + flags |= Q3SURFACEPARM_NOIMPACT; + else if (!strcasecmp(parameter[1], "nolightmap")) + flags |= Q3SURFACEPARM_NOLIGHTMAP; + else if (!strcasecmp(parameter[1], "nomarks")) + flags |= Q3SURFACEPARM_NOMARKS; + else if (!strcasecmp(parameter[1], "nomipmaps")) + flags |= Q3SURFACEPARM_NOMIPMAPS; + else if (!strcasecmp(parameter[1], "nonsolid")) + flags |= Q3SURFACEPARM_NONSOLID; + else if (!strcasecmp(parameter[1], "origin")) + flags |= Q3SURFACEPARM_ORIGIN; + else if (!strcasecmp(parameter[1], "playerclip")) + flags |= Q3SURFACEPARM_PLAYERCLIP; + else if (!strcasecmp(parameter[1], "sky")) + flags |= Q3SURFACEPARM_SKY; + else if (!strcasecmp(parameter[1], "slick")) + flags |= Q3SURFACEPARM_SLICK; + else if (!strcasecmp(parameter[1], "slime")) + flags |= Q3SURFACEPARM_SLIME; + else if (!strcasecmp(parameter[1], "structural")) + flags |= Q3SURFACEPARM_STRUCTURAL; + else if (!strcasecmp(parameter[1], "trans")) + flags |= Q3SURFACEPARM_TRANS; + else if (!strcasecmp(parameter[1], "water")) + flags |= Q3SURFACEPARM_WATER; else - { - Con_Printf("%s parsing error: surfaceparm expects a parameter.\n", search->filenames[i]); - goto parseerror; - } + Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], parameter[1]); } - else if (!strcasecmp(com_token, "sky")) + else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2) + strlcpy(sky, parameter[1], sizeof(sky)); + else if (!strcasecmp(parameter[0], "skyparms") && numparameters >= 2) { - if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n")) - if (strlen(com_token) < sizeof(sky)) - strcpy(sky, com_token); + if (!atoi(parameter[1]) && strcasecmp(parameter[1], "-")) + strlcpy(sky, parameter[1], sizeof(sky)); } - else if (!strcasecmp(com_token, "skyparms")) + else if (!strcasecmp(parameter[0], "cull") && numparameters >= 2) { - if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n")) - { - if (strlen(com_token) < sizeof(sky) && !atoi(com_token) && strcasecmp(com_token, "-")) - strcpy(sky, com_token); - if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n")) - COM_ParseToken(&text, true); - } + if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "twosided")) + flags2 |= Q3TEXTUREFLAG_TWOSIDED; } - else + else if (!strcasecmp(parameter[0], "nomipmaps")) + flags2 |= Q3TEXTUREFLAG_NOMIPMAPS; + else if (!strcasecmp(parameter[0], "nopicmip")) + flags2 |= Q3TEXTUREFLAG_NOPICMIP; + else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2) { - // look for linebreak or } - while(COM_ParseToken(&text, true) && strcasecmp(com_token, "\n") && strcasecmp(com_token, "}")); - // break out to top level if it was } - if (!strcasecmp(com_token, "}")) - break; + if (!strcasecmp(parameter[1], "autosprite") && numparameters == 2) + flags2 |= Q3TEXTUREFLAG_AUTOSPRITE; + if (!strcasecmp(parameter[1], "autosprite2") && numparameters == 2) + flags2 |= Q3TEXTUREFLAG_AUTOSPRITE2; } } + // force transparent render path for a number of odd + // shader effects to avoid bogging down the normal + // render path unnecessarily + if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) + flags |= Q3SURFACEPARM_TRANS; // add shader to list (shadername and flags) // actually here we just poke into the texture settings for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++) @@ -3750,6 +3803,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) if (!strcasecmp(out->name, shadername)) { out->surfaceparms = flags; + out->textureflags = flags2; + strlcpy(out->firstpasstexturename, firstpasstexturename, sizeof(out->firstpasstexturename)); if ((flags & Q3SURFACEPARM_SKY) && sky[0]) { // quake3 seems to append a _ to the skybox name, so this must do so as well @@ -3779,14 +3834,16 @@ parseerror: Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name); out->surfaceparms = 0; // these are defaults - if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk") - || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw")) - out->surfaceparms |= Q3SURFACEPARM_NODRAW; if (!strncmp(out->name, "textures/skies/", 15)) out->surfaceparms |= Q3SURFACEPARM_SKY; - if (R_TextureHasAlpha(out->skin.base)) - out->surfaceparms |= Q3SURFACEPARM_TRANS; + //if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk") + // || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw")) + // out->surfaceparms |= Q3SURFACEPARM_NODRAW; + //if (R_TextureHasAlpha(out->skin.base)) + // out->surfaceparms |= Q3SURFACEPARM_TRANS; } + if (!Mod_LoadSkinFrame(&out->skin, out->name, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true)) + Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true); } Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c); } diff --git a/model_shared.h b/model_shared.h index 2c3630ea..830428d7 100644 --- a/model_shared.h +++ b/model_shared.h @@ -327,14 +327,24 @@ model_brushq2_t; #define Q3SURFACEPARM_TRANS 16777216 #define Q3SURFACEPARM_WATER 33554432 +// various flags from shaders +#define Q3TEXTUREFLAG_TWOSIDED 1 +#define Q3TEXTUREFLAG_ADDITIVE 2 +#define Q3TEXTUREFLAG_NOMIPMAPS 4 +#define Q3TEXTUREFLAG_NOPICMIP 8 +#define Q3TEXTUREFLAG_AUTOSPRITE 16 +#define Q3TEXTUREFLAG_AUTOSPRITE2 32 + struct q3msurface_s; typedef struct q3mtexture_s { char name[Q3PATHLENGTH]; + char firstpasstexturename[Q3PATHLENGTH]; int surfaceflags; int nativecontents; int supercontents; int surfaceparms; + int textureflags; int number; skinframe_t skin;