Skip to content

Commit 1e0482b

Browse files
authored
Merge pull request #988 from qw-ctf/alpha-brushes
2 parents 3ecbeda + d7f3e38 commit 1e0482b

9 files changed

+48
-19
lines changed

CMakeLists.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ option(USE_SYSTEM_LIBS "Use system libraries instead of VCPKG" ON
1010
option(RENDERER_MODERN_OPENGL "Enable modern OpenGL renderer" ON)
1111
option(RENDERER_CLASSIC_OPENGL "Enable classic OpenGL renderer" ON)
1212
option(DEBUG_MEMORY_ALLOCATIONS "Enable debug prints for memory allocations" OFF)
13-
option(RENDERING_TRACE "Enable tracing of the rendering pipeline" OFF)
1413
option(ENABLE_SANDBOX "Enables application sandboxing (macOS)" ON)
1514
option(ENABLE_LTO "Enable Link Time Optimization" ON)
1615

@@ -838,7 +837,7 @@ target_compile_definitions(ezquake PRIVATE
838837
WITH_NQPROGS
839838

840839
$<$<BOOL:${DEBUG_MEMORY_ALLOCATIONS}>:DEBUG_MEMORY_ALLOCATIONS>
841-
$<$<BOOL:${RENDERING_TRACE}>:WITH_RENDERING_TRACE>
840+
$<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:WITH_RENDERING_TRACE>
842841

843842
$<$<PLATFORM_ID:Darwin>:GL_SILENCE_DEPRECATION>
844843

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_aliasmodel.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ static void GLM_RenderPreparedEntities(aliasmodel_draw_type_t type)
502502
renderer.TextureUnitBind(TEXTURE_UNIT_MATERIAL, shelltexture);
503503
}
504504

505-
if (translucent && !shells) {
505+
// Depth pre-pass to make viewmodel look good.
506+
if (type == aliasmodel_draw_postscene) {
506507
GLM_StateBeginAliasModelZPassBatch();
507508
for (i = 0; i < instr->num_calls; ++i) {
508509
GL_MultiDrawArraysIndirect(

src/glm_local.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ typedef struct uniform_block_frame_constants_s {
6464
// [4-byte break]
6565
int r_width;
6666
int r_height;
67-
float r_inv_width;
68-
float r_inv_height;
6967
float r_zFar;
7068
float r_zNear;
7169

@@ -79,6 +77,8 @@ typedef struct uniform_block_frame_constants_s {
7977
// camangles [0]
8078

8179
float camangles[3]; // [1] [2]
80+
float r_inv_width;
81+
float r_inv_height;
8282
} uniform_block_frame_constants_t;
8383

8484
#define MAX_WORLDMODEL_BATCH 64

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/common.glsl

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ layout(std140, binding=EZQ_GL_BINDINGPOINT_FRAMECONSTANTS) uniform GlobalState {
6060
// [4-byte break]
6161
int r_width;
6262
int r_height;
63-
float r_inv_width;
64-
float r_inv_height;
6563
float r_zFar;
6664
float r_zNear;
6765

@@ -75,6 +73,8 @@ layout(std140, binding=EZQ_GL_BINDINGPOINT_FRAMECONSTANTS) uniform GlobalState {
7573
// camAngles.x
7674

7775
vec3 camAngles; // camAngles.yz
76+
float r_inv_width;
77+
float r_inv_height;
7878
};
7979

8080
struct WorldDrawInfo {

src/glsl/draw_world.fragment.glsl

+4-3
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
@@ -139,9 +140,9 @@ void main()
139140
if ((Flags & EZQ_SURFACE_ALPHATEST) == EZQ_SURFACE_ALPHATEST && texColor.a < 0.5) {
140141
discard;
141142
}
143+
#endif
142144
// Avoid black artifacts at border between texture and transparency visible in fog
143145
texColor = vec4(texColor.rgb, 1.0);
144-
#endif
145146

146147
turbType = Flags & EZQ_SURFACE_TYPE;
147148
if (turbType != 0) {
@@ -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

src/r_states.c

+1
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ static void R_InitialiseEntityStates(void)
382382
state->blendingEnabled = false;
383383

384384
state = R_CopyRenderingState(r_state_aliasmodel_translucent_batch, r_state_aliasmodel_opaque_batch, "aliasModelTranslucentBatchState");
385+
state->depth.mask_enabled = false;
385386
state->blendFunc = r_blendfunc_premultiplied_alpha;
386387
state->blendingEnabled = true;
387388

0 commit comments

Comments
 (0)