continue;
if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size))
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
continue;
killdecal:
decal->typeindex = 0;
{
case pt_beam:
// beams have no culling
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
break;
default:
if(cl_particles_visculling.integer)
}
// anything else just has to be in front of the viewer and visible at this distance
if (DotProduct(p->org, r_refdef.view.forward) >= minparticledist_start && VectorDistance2(p->org, r_refdef.view.origin) < drawdist2 * (p->size * p->size))
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
break;
}
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(MESHQUEUE_SORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL);
}
/*polys->num_triangles = 0; // now done after rendering the scene,
cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
-cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
+cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
continue;
VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
}
}
vec3_t org;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
else
R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
}
center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
}
- R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
}
for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
{
VectorLerp(loc->mins, 0.5f, loc->maxs, center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
}
}
VectorAdd(center, portal->points[i].position, center);
f = ixtable[portal->numpoints];
VectorScale(center, f, center);
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, rsurface.rtlight);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, rsurface.rtlight);
}
}
}
center[1] += r_refdef.view.forward[1]*ent->transparent_offset;
center[2] += r_refdef.view.forward[2]*ent->transparent_offset;
}
- R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : ((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE), center, R_Q1BSP_DrawLight_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : ((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort), center, R_Q1BSP_DrawLight_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
continue;
}
int surfacenumber;
const rtlight_t *rtlight;
float dist;
- meshqueue_sortcategory_t category;
+ dptransparentsortcategory_t category;
}
meshqueue_t;
mqt_viewmaxdist = 0;
}
-void R_MeshQueue_AddTransparent(meshqueue_sortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_MeshQueue_AddTransparent(dptransparentsortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
{
meshqueue_t *mq;
if (mqt_count >= mqt_total || !mqt_array)
switch(mqt->category)
{
default:
- case MESHQUEUE_SORT_HUD:
+ case TRANSPARENTSORT_HUD:
hashindex = 0;
break;
- case MESHQUEUE_SORT_DISTANCE:
+ case TRANSPARENTSORT_DISTANCE:
// this could use a reduced range if we need more categories
hashindex = bound(0, (int)(bound(0, mqt->dist - r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
break;
- case MESHQUEUE_SORT_SKY:
+ case TRANSPARENTSORT_SKY:
hashindex = maxhashindex;
break;
}
// VorteX: seems this value is hardcoded in other several defines as it's changing makes mess
#define MESHQUEUE_TRANSPARENT_BATCHSIZE 256
-typedef enum meshqueue_sortcategory_e
-{
- MESHQUEUE_SORT_SKY,
- MESHQUEUE_SORT_DISTANCE,
- MESHQUEUE_SORT_HUD,
-}
-meshqueue_sortcategory_t;
-
void R_MeshQueue_BeginScene(void);
-void R_MeshQueue_AddTransparent(meshqueue_sortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
+void R_MeshQueue_AddTransparent(dptransparentsortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
void R_MeshQueue_RenderTransparent(void);
#endif
cvar_t mod_q3shader_default_polygonfactor = {0, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};
cvar_t mod_q3shader_default_polygonoffset = {0, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};
cvar_t mod_q3shader_force_addalpha = {0, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"};
+cvar_t mod_q3shader_force_terrain_alphaflag = {0, "mod_q3shader_force_terrain_alphaflag", "0", "for multilayered terrain shaders force TEXF_ALPHA flag on both layers"};
+
cvar_t mod_q1bsp_polygoncollisions = {0, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"};
cvar_t mod_collision_bih = {0, "mod_collision_bih", "1", "enables use of generated Bounding Interval Hierarchy tree instead of compiled bsp tree in collision code"};
cvar_t mod_recalculatenodeboxes = {0, "mod_recalculatenodeboxes", "1", "enables use of generated node bounding boxes based on BSP tree portal reconstruction, rather than the node boxes supplied by the map compiler"};
Cvar_RegisterVariable(&mod_q3shader_default_polygonfactor);
Cvar_RegisterVariable(&mod_q3shader_default_polygonoffset);
Cvar_RegisterVariable(&mod_q3shader_force_addalpha);
+ Cvar_RegisterVariable(&mod_q3shader_force_terrain_alphaflag);
Cvar_RegisterVariable(&mod_q1bsp_polygoncollisions);
Cvar_RegisterVariable(&mod_collision_bih);
Cvar_RegisterVariable(&mod_recalculatenodeboxes);
extern cvar_t mod_q3shader_default_polygonoffset;
extern cvar_t mod_q3shader_default_polygonfactor;
extern cvar_t mod_q3shader_force_addalpha;
+extern cvar_t mod_q3shader_force_terrain_alphaflag;
void Mod_LoadQ3Shaders(void)
{
int j;
shader.specularpowermod = 1;
shader.biaspolygonoffset = mod_q3shader_default_polygonoffset.value;
shader.biaspolygonfactor = mod_q3shader_default_polygonfactor.value;
+ shader.transparentsort = TRANSPARENTSORT_DISTANCE;
strlcpy(shader.name, com_token, sizeof(shader.name));
if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
{
// multilayer terrain shader or similar
shader.textureblendalpha = true;
+ if (mod_q3shader_force_terrain_alphaflag.integer)
+ shader.layers[0].texflags |= TEXF_ALPHA;
}
}
if(layer->blendfunc[0] == GL_ONE && layer->blendfunc[1] == GL_ONE)
layer->blendfunc[0] = GL_SRC_ALPHA;
}
-
+
layer->texflags = 0;
if (layer->alphatest)
layer->texflags |= TEXF_ALPHA;
shader.biaspolygonoffset = 0;
}
}
+ else if (!strcasecmp(parameter[0], "dptransparentsort") && numparameters >= 2)
+ {
+ shader.textureflags |= Q3TEXTUREFLAG_TRANSPARENTSORT;
+ if (!strcasecmp(parameter[1], "sky"))
+ shader.transparentsort = TRANSPARENTSORT_SKY;
+ else if (!strcasecmp(parameter[1], "distance"))
+ shader.transparentsort = TRANSPARENTSORT_DISTANCE;
+ else if (!strcasecmp(parameter[1], "hud"))
+ shader.transparentsort = TRANSPARENTSORT_HUD;
+ else
+ Con_DPrintf("%s parsing warning: unknown dptransparentsort category \"%s\", or not enough arguments\n", search->filenames[fileindex], parameter[1]);
+ }
else if (!strcasecmp(parameter[0], "dprefract") && numparameters >= 5)
{
shader.textureflags |= Q3TEXTUREFLAG_REFRACTION;
texture->basematerialflags |= MATERIALFLAG_CAMERA;
texture->customblendfunc[0] = GL_ONE;
texture->customblendfunc[1] = GL_ZERO;
+ texture->transparentsort = shader->transparentsort;
if (shader->numlayers > 0)
{
texture->customblendfunc[0] = shader->layers[0].blendfunc[0];
#define Q3TEXTUREFLAG_REFLECTION 512
#define Q3TEXTUREFLAG_WATERSHADER 1024
#define Q3TEXTUREFLAG_CAMERA 2048
+#define Q3TEXTUREFLAG_TRANSPARENTSORT 4096
#define Q3PATHLENGTH 64
#define TEXTURE_MAXFRAMES 64
OFFSETMAPPING_RELIEF // relief
}dpoffsetmapping_technique_t;
+typedef enum dptransparentsort_category_e
+{
+ TRANSPARENTSORT_SKY,
+ TRANSPARENTSORT_DISTANCE,
+ TRANSPARENTSORT_HUD,
+}dptransparentsortcategory_t;
typedef struct q3shaderinfo_s
{
// polygonoffset (only used if Q3TEXTUREFLAG_POLYGONOFFSET)
float biaspolygonoffset, biaspolygonfactor;
+ // transparent sort category
+ dptransparentsortcategory_t transparentsort;
+
// gloss
float specularscalemod;
float specularpowermod;
float offsetscale;
float offsetbias;
+ // transparent sort category
+ dptransparentsortcategory_t transparentsort;
+
// gloss
float specularscalemod;
float specularpowermod;
{
R_MoveExplosion(&explosion[i]);
if (explosion[i].alpha)
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
}
}
while (numexplosions > 0 && explosion[i-1].alpha <= 0)
dist = bound(0, dist, 1);
VectorLerp(start, dist, end, org);
// now we have the nearest point on the line, so sort with it
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
}
}
}
{
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light)
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
}
if (!r_editlights_lockcursor)
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
}
int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
return;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
- R_MeshQueue_AddTransparent((ent->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : ((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE), org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, rsurface.rtlight);
}