Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MODERN: Add support for alpha brushes. #988

Merged
merged 5 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading