Skip to content

Commit

Permalink
Merge pull request #988 from qw-ctf/alpha-brushes
Browse files Browse the repository at this point in the history
  • Loading branch information
dsvensson authored Jan 8, 2025
2 parents 3ecbeda + d7f3e38 commit 1e0482b
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 19 deletions.
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ option(USE_SYSTEM_LIBS "Use system libraries instead of VCPKG" ON
option(RENDERER_MODERN_OPENGL "Enable modern OpenGL renderer" ON)
option(RENDERER_CLASSIC_OPENGL "Enable classic OpenGL renderer" ON)
option(DEBUG_MEMORY_ALLOCATIONS "Enable debug prints for memory allocations" OFF)
option(RENDERING_TRACE "Enable tracing of the rendering pipeline" OFF)
option(ENABLE_SANDBOX "Enables application sandboxing (macOS)" ON)
option(ENABLE_LTO "Enable Link Time Optimization" ON)

Expand Down Expand Up @@ -838,7 +837,7 @@ target_compile_definitions(ezquake PRIVATE
WITH_NQPROGS

$<$<BOOL:${DEBUG_MEMORY_ALLOCATIONS}>:DEBUG_MEMORY_ALLOCATIONS>
$<$<BOOL:${RENDERING_TRACE}>:WITH_RENDERING_TRACE>
$<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:WITH_RENDERING_TRACE>

$<$<PLATFORM_ID:Darwin>:GL_SILENCE_DEPRECATION>

Expand Down
16 changes: 15 additions & 1 deletion src/cl_ents.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,18 @@ void CL_AddEntityToList(visentlist_t* list, visentlist_entrytype_t vistype, enti

ent = &list->list[cl_visents.count].ent;
list->list[cl_visents.count].type = type;
list->list[cl_visents.count].distance = VectorDistanceQuick(cl.simorg, ent->origin);
if (vistype == visent_alpha) {
// Sort transparent entities based on closest point for stable back-to-front rendering.
vec3_t distance;
int i;
for (i = 0; i < 3; i++) {
distance[i] = r_refdef.vieworg[i] - ent->origin[i];
distance[i] -= bound(ent->model->mins[i], distance[i], ent->model->maxs[i]);
}
list->list[cl_visents.count].distance = DotProduct(distance, distance);
} else {
list->list[cl_visents.count].distance = VectorDistanceQuick(cl.simorg, ent->origin);
}
list->list[cl_visents.count].draw[vistype] = true;

ent->outlineScale = 0.5f * (r_refdef2.outlineBase + DotProduct(ent->origin, r_refdef2.outline_vpn));
Expand Down Expand Up @@ -233,6 +244,9 @@ void CL_AddEntity(entity_t *ent)
vistype = visent_firstpass;
ent->renderfx |= RF_NOSHADOW;
}
else if (ent->alpha > 0.0f && ent->alpha < 1.0f) {
vistype = visent_alpha;
}
else {
vistype = visent_normal;
}
Expand Down
3 changes: 2 additions & 1 deletion src/glm_aliasmodel.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,8 @@ static void GLM_RenderPreparedEntities(aliasmodel_draw_type_t type)
renderer.TextureUnitBind(TEXTURE_UNIT_MATERIAL, shelltexture);
}

if (translucent && !shells) {
// Depth pre-pass to make viewmodel look good.
if (type == aliasmodel_draw_postscene) {
GLM_StateBeginAliasModelZPassBatch();
for (i = 0; i < instr->num_calls; ++i) {
GL_MultiDrawArraysIndirect(
Expand Down
4 changes: 2 additions & 2 deletions src/glm_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ typedef struct uniform_block_frame_constants_s {
// [4-byte break]
int r_width;
int r_height;
float r_inv_width;
float r_inv_height;
float r_zFar;
float r_zNear;

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

float camangles[3]; // [1] [2]
float r_inv_width;
float r_inv_height;
} uniform_block_frame_constants_t;

#define MAX_WORLDMODEL_BATCH 64
Expand Down
27 changes: 19 additions & 8 deletions src/glm_rsurf.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,15 +389,23 @@ static glm_worldmodel_req_t* GLM_NextBatchRequest(model_t* model, float alpha, i
glm_brushmodel_drawcall_t* drawcall = &drawcalls[current_drawcall];
float mvMatrix[16];

glm_brushmodel_drawcall_type desired_type = alpha == 0.0f ? opaque_world : alpha_surfaces;

R_GetModelviewMatrix(mvMatrix);

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

// See if previous batch has same texture & matrix, if so just continue
if (drawcall->batch_count) {
if (drawcall->type != desired_type) {
drawcall = GL_FlushWorldModelBatch();
drawcall->type = desired_type;
}
else if (drawcall->batch_count && drawcall->type == opaque_world) {
// See if previous request has same texture & matrix, if so just continue
// as long as drawcall is not alpha as such requests must be drawn in the
// predetermined order.
req = &drawcall->worldmodel_requests[drawcall->batch_count - 1];

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

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

if (model->drawflat_chain) {
req = GLM_NextBatchRequest(model, 1.0f, 0, 0, false, false, false, false);
req = GLM_NextBatchRequest(model, ent->alpha, 0, 0, false, false, false, false);

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

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

req = GLM_NextBatchRequest(model, 1.0f, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
req = GLM_NextBatchRequest(model, ent->alpha, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
tex = R_TextureAnimation(ent, tex);
if (!GLM_AssignTexture(i, tex)) {
req = GLM_NextBatchRequest(model, 1.0f, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
req = GLM_NextBatchRequest(model, ent->alpha, 1, i, polygonOffset, caustics, false, tex->isAlphaTested);
GLM_AssignTexture(i, tex);
}

Expand Down Expand Up @@ -842,12 +850,15 @@ static void GL_SortDrawCalls(glm_brushmodel_drawcall_t* drawcall)
}
}

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

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

drawcall->calls[i].alpha = thisReq->alpha;
drawcall->calls[i].alpha = thisReq->alpha == 0.0f ? 1.0f : thisReq->alpha;
drawcall->calls[i].flags = thisReq->flags;
memcpy(drawcall->calls[i].modelMatrix, thisReq->mvMatrix, sizeof(drawcall->calls[i].modelMatrix));
drawcall->calls[i].samplerBase = thisReq->samplerMappingBase;
Expand Down
4 changes: 2 additions & 2 deletions src/glsl/common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ layout(std140, binding=EZQ_GL_BINDINGPOINT_FRAMECONSTANTS) uniform GlobalState {
// [4-byte break]
int r_width;
int r_height;
float r_inv_width;
float r_inv_height;
float r_zFar;
float r_zNear;

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

vec3 camAngles; // camAngles.yz
float r_inv_width;
float r_inv_height;
};

struct WorldDrawInfo {
Expand Down
7 changes: 4 additions & 3 deletions src/glsl/draw_world.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ in vec4 UnClipped;

in float mix_floor;
in float mix_wall;
in float alpha;

layout(location=0) out vec4 frag_colour;
#ifdef DRAW_GEOMETRY
Expand Down Expand Up @@ -139,9 +140,9 @@ void main()
if ((Flags & EZQ_SURFACE_ALPHATEST) == EZQ_SURFACE_ALPHATEST && texColor.a < 0.5) {
discard;
}
#endif
// Avoid black artifacts at border between texture and transparency visible in fog
texColor = vec4(texColor.rgb, 1.0);
#endif

turbType = Flags & EZQ_SURFACE_TYPE;
if (turbType != 0) {
Expand Down Expand Up @@ -232,11 +233,11 @@ void main()
texColor = vec4(mix(texColor.rgb, texColor.rgb + lumaColor.rgb, min(1, Flags & EZQ_SURFACE_HAS_LUMA)), texColor.a);
#endif
texColor = applyColorTinting(texColor);
frag_colour = vec4(lmColor.rgb, 1) * texColor;
frag_colour = vec4(lmColor.rgb * alpha, alpha) * texColor;
#if defined(DRAW_LUMA_TEXTURES) && defined(DRAW_LUMA_TEXTURES_FB)
lumaColor = applyColorTinting(lumaColor);
frag_colour = vec4(mix(frag_colour.rgb, frag_colour.rgb + lumaColor.rgb, min(1, Flags & EZQ_SURFACE_HAS_LUMA)), frag_colour.a);
frag_colour = vec4(mix(frag_colour.rgb, lumaColor.rgb, min(1, Flags & EZQ_SURFACE_HAS_FB) * lumaColor.a), frag_colour.a);
frag_colour = vec4(mix(frag_colour.rgb, lumaColor.rgb * alpha, min(1, Flags & EZQ_SURFACE_HAS_FB) * lumaColor.a), frag_colour.a);
#elif !defined(DRAW_LUMA_TEXTURES) && defined(DRAW_LUMA_TEXTURES_FB)
// GL_DECAL
lumaColor = applyColorTinting(lumaColor);
Expand Down
2 changes: 2 additions & 0 deletions src/glsl/draw_world.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ layout(std140, binding = EZQ_GL_BINDINGPOINT_WORLDMODEL_SURFACES) buffer surface

out float mix_floor;
out float mix_wall;
out float alpha;

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

gl_Position = projectionMatrix * drawInfo[_instanceId].mvMatrix * vec4(position, 1.0);
#ifdef DRAW_GEOMETRY
Expand Down
1 change: 1 addition & 0 deletions src/r_states.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ static void R_InitialiseEntityStates(void)
state->blendingEnabled = false;

state = R_CopyRenderingState(r_state_aliasmodel_translucent_batch, r_state_aliasmodel_opaque_batch, "aliasModelTranslucentBatchState");
state->depth.mask_enabled = false;
state->blendFunc = r_blendfunc_premultiplied_alpha;
state->blendingEnabled = true;

Expand Down

0 comments on commit 1e0482b

Please sign in to comment.