Skip to content

Commit

Permalink
MODERN: Add support for alpha brushes.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsvensson committed Jan 7, 2025
1 parent a934fe5 commit dfcd53c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 12 deletions.
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
27 changes: 18 additions & 9 deletions src/glm_rsurf.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,15 +389,21 @@ 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) {
// See if previous batch has same texture & matrix, if so just continue
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 All @@ -417,7 +423,7 @@ static glm_worldmodel_req_t* GLM_NextBatchRequest(model_t* model, float alpha, i
}

// Try and continue the previous batch
if (worldmodel == req->worldmodel && !memcmp(req->mvMatrix, mvMatrix, sizeof(req->mvMatrix)) && polygonOffset == req->polygonOffset && req->flags == flags && req->isAlphaTested == isAlphaTested) {
if (worldmodel == req->worldmodel && !memcmp(req->mvMatrix, mvMatrix, sizeof(req->mvMatrix)) && polygonOffset == req->polygonOffset && req->flags == flags && req->isAlphaTested == isAlphaTested && req->alpha == alpha) {
if (num_textures == 0) {
// We don't care about materials, so can draw with previous batch
return req;
Expand Down Expand Up @@ -765,12 +771,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 +794,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 +848,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
5 changes: 3 additions & 2 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 @@ -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

0 comments on commit dfcd53c

Please sign in to comment.