Skip to content

Commit d7f3e38

Browse files
committed
MODERN: Add support for alpha brushes.
Fixes #630.
1 parent a934fe5 commit d7f3e38

File tree

4 files changed

+39
-11
lines changed

4 files changed

+39
-11
lines changed

src/cl_ents.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,18 @@ void CL_AddEntityToList(visentlist_t* list, visentlist_entrytype_t vistype, enti
181181

182182
ent = &list->list[cl_visents.count].ent;
183183
list->list[cl_visents.count].type = type;
184-
list->list[cl_visents.count].distance = VectorDistanceQuick(cl.simorg, ent->origin);
184+
if (vistype == visent_alpha) {
185+
// Sort transparent entities based on closest point for stable back-to-front rendering.
186+
vec3_t distance;
187+
int i;
188+
for (i = 0; i < 3; i++) {
189+
distance[i] = r_refdef.vieworg[i] - ent->origin[i];
190+
distance[i] -= bound(ent->model->mins[i], distance[i], ent->model->maxs[i]);
191+
}
192+
list->list[cl_visents.count].distance = DotProduct(distance, distance);
193+
} else {
194+
list->list[cl_visents.count].distance = VectorDistanceQuick(cl.simorg, ent->origin);
195+
}
185196
list->list[cl_visents.count].draw[vistype] = true;
186197

187198
ent->outlineScale = 0.5f * (r_refdef2.outlineBase + DotProduct(ent->origin, r_refdef2.outline_vpn));
@@ -233,6 +244,9 @@ void CL_AddEntity(entity_t *ent)
233244
vistype = visent_firstpass;
234245
ent->renderfx |= RF_NOSHADOW;
235246
}
247+
else if (ent->alpha > 0.0f && ent->alpha < 1.0f) {
248+
vistype = visent_alpha;
249+
}
236250
else {
237251
vistype = visent_normal;
238252
}

src/glm_rsurf.c

+19-8
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,23 @@ static glm_worldmodel_req_t* GLM_NextBatchRequest(model_t* model, float alpha, i
389389
glm_brushmodel_drawcall_t* drawcall = &drawcalls[current_drawcall];
390390
float mvMatrix[16];
391391

392+
glm_brushmodel_drawcall_type desired_type = alpha == 0.0f ? opaque_world : alpha_surfaces;
393+
392394
R_GetModelviewMatrix(mvMatrix);
393395

394396
// If user has switched off caustics (or no texture), ignore
395397
if (caustics) {
396398
caustics &= ((R_ProgramCustomOptions(r_program_brushmodel) & DRAW_CAUSTIC_TEXTURES) == DRAW_CAUSTIC_TEXTURES);
397399
}
398400

399-
// See if previous batch has same texture & matrix, if so just continue
400-
if (drawcall->batch_count) {
401+
if (drawcall->type != desired_type) {
402+
drawcall = GL_FlushWorldModelBatch();
403+
drawcall->type = desired_type;
404+
}
405+
else if (drawcall->batch_count && drawcall->type == opaque_world) {
406+
// See if previous request has same texture & matrix, if so just continue
407+
// as long as drawcall is not alpha as such requests must be drawn in the
408+
// predetermined order.
401409
req = &drawcall->worldmodel_requests[drawcall->batch_count - 1];
402410

403411
if (allow_duplicate && model == req->model && req->samplerMappingCount == num_textures && req->firstTexture == first_texture && drawcall->batch_count < MAX_WORLDMODEL_BATCH && isAlphaTested == req->isAlphaTested) {
@@ -765,12 +773,12 @@ void GLM_DrawBrushModel(entity_t* ent, qbool polygonOffset, qbool caustics)
765773
glm_worldmodel_req_t* req = NULL;
766774
model_t* model = ent->model;
767775

768-
if (GLM_DuplicatePreviousRequest(model, 1.0f, model->last_texture_chained - model->first_texture_chained + 1, model->first_texture_chained, polygonOffset, caustics)) {
776+
if (GLM_DuplicatePreviousRequest(model, ent->alpha, model->last_texture_chained - model->first_texture_chained + 1, model->first_texture_chained, polygonOffset, caustics)) {
769777
return;
770778
}
771779

772780
if (model->drawflat_chain) {
773-
req = GLM_NextBatchRequest(model, 1.0f, 0, 0, false, false, false, false);
781+
req = GLM_NextBatchRequest(model, ent->alpha, 0, 0, false, false, false, false);
774782

775783
req = GLM_DrawFlatChain(req, model->drawflat_chain);
776784

@@ -788,10 +796,10 @@ void GLM_DrawBrushModel(entity_t* ent, qbool polygonOffset, qbool caustics)
788796
continue;
789797
}
790798

791-
req = GLM_NextBatchRequest(model, 1.0f, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
799+
req = GLM_NextBatchRequest(model, ent->alpha, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
792800
tex = R_TextureAnimation(ent, tex);
793801
if (!GLM_AssignTexture(i, tex)) {
794-
req = GLM_NextBatchRequest(model, 1.0f, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
802+
req = GLM_NextBatchRequest(model, ent->alpha, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
795803
GLM_AssignTexture(i, tex);
796804
}
797805

@@ -842,12 +850,15 @@ static void GL_SortDrawCalls(glm_brushmodel_drawcall_t* drawcall)
842850
}
843851
}
844852

845-
qsort(drawcall->worldmodel_requests, drawcall->batch_count, sizeof(drawcall->worldmodel_requests[0]), GL_DrawCallComparison);
853+
// Translucent bmodels are put into requests based on their distance from view and sorting here will break that order.
854+
if (drawcall->type == opaque_world) {
855+
qsort(drawcall->worldmodel_requests, drawcall->batch_count, sizeof(drawcall->worldmodel_requests[0]), GL_DrawCallComparison);
856+
}
846857

847858
for (i = 0; i < drawcall->batch_count; ++i) {
848859
glm_worldmodel_req_t* thisReq = &drawcall->worldmodel_requests[i];
849860

850-
drawcall->calls[i].alpha = thisReq->alpha;
861+
drawcall->calls[i].alpha = thisReq->alpha == 0.0f ? 1.0f : thisReq->alpha;
851862
drawcall->calls[i].flags = thisReq->flags;
852863
memcpy(drawcall->calls[i].modelMatrix, thisReq->mvMatrix, sizeof(drawcall->calls[i].modelMatrix));
853864
drawcall->calls[i].samplerBase = thisReq->samplerMappingBase;

src/glsl/draw_world.fragment.glsl

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ in vec4 UnClipped;
4545

4646
in float mix_floor;
4747
in float mix_wall;
48+
in float alpha;
4849

4950
layout(location=0) out vec4 frag_colour;
5051
#ifdef DRAW_GEOMETRY
@@ -232,11 +233,11 @@ void main()
232233
texColor = vec4(mix(texColor.rgb, texColor.rgb + lumaColor.rgb, min(1, Flags & EZQ_SURFACE_HAS_LUMA)), texColor.a);
233234
#endif
234235
texColor = applyColorTinting(texColor);
235-
frag_colour = vec4(lmColor.rgb, 1) * texColor;
236+
frag_colour = vec4(lmColor.rgb * alpha, alpha) * texColor;
236237
#if defined(DRAW_LUMA_TEXTURES) && defined(DRAW_LUMA_TEXTURES_FB)
237238
lumaColor = applyColorTinting(lumaColor);
238239
frag_colour = vec4(mix(frag_colour.rgb, frag_colour.rgb + lumaColor.rgb, min(1, Flags & EZQ_SURFACE_HAS_LUMA)), frag_colour.a);
239-
frag_colour = vec4(mix(frag_colour.rgb, lumaColor.rgb, min(1, Flags & EZQ_SURFACE_HAS_FB) * lumaColor.a), frag_colour.a);
240+
frag_colour = vec4(mix(frag_colour.rgb, lumaColor.rgb * alpha, min(1, Flags & EZQ_SURFACE_HAS_FB) * lumaColor.a), frag_colour.a);
240241
#elif !defined(DRAW_LUMA_TEXTURES) && defined(DRAW_LUMA_TEXTURES_FB)
241242
// GL_DECAL
242243
lumaColor = applyColorTinting(lumaColor);

src/glsl/draw_world.vertex.glsl

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ layout(std140, binding = EZQ_GL_BINDINGPOINT_WORLDMODEL_SURFACES) buffer surface
3636

3737
out float mix_floor;
3838
out float mix_wall;
39+
out float alpha;
3940

4041
layout(std140, binding=EZQ_GL_BINDINGPOINT_BRUSHMODEL_DRAWDATA) buffer WorldCvars {
4142
WorldDrawInfo drawInfo[];
@@ -51,6 +52,7 @@ void main()
5152
float materialArrayIndex = samplerMapping[drawInfo[_instanceId].samplerBase + materialNumber].layer;
5253
int drawCallFlags = drawInfo[_instanceId].drawFlags;
5354
int textureFlags = samplerMapping[drawInfo[_instanceId].samplerBase + materialNumber].flags;
55+
alpha = drawInfo[_instanceId].alpha;
5456

5557
gl_Position = projectionMatrix * drawInfo[_instanceId].mvMatrix * vec4(position, 1.0);
5658
#ifdef DRAW_GEOMETRY

0 commit comments

Comments
 (0)