[vulkan] Implement BSP surface transparency

Surfaces marked with SURF_DRAWALPHA but not SURF_DRAWTURB are put in a
separate queue for the water shader and run with a turb scale of 0.
Also, entities with colormod alpha < 1 are marked to go in the same
queue as SURF_DRAWALPHA surfaces (ie, no SURF_DRAWTURB unless the
model's texture indicated such).
This commit is contained in:
Bill Currie 2022-05-27 08:12:21 +09:00
parent a936336e84
commit 3603f90718
9 changed files with 51 additions and 16 deletions

View file

@ -110,6 +110,7 @@ typedef struct bsp_draw_s {
typedef struct bsp_drawset_s
DARRAY_TYPE (bsp_draw_t) bsp_drawset_t;
#define INST_ALPHA (1u<<31)
typedef struct instface_s {
uint32_t inst_id;
uint32_t face;

View file

@ -365,7 +365,7 @@
{
stageFlags = fragment;
offset = 0;
size = "4 * 4 + 4 + 4";
size = "4 * 4 + 4 + 4 + 4";
},
);
};

View file

@ -12,6 +12,7 @@ layout (location = 0) in vec4 tl_st;
layout (location = 1) in vec3 direction;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec4 position;
layout (location = 4) in vec4 color;
layout (location = 0) out vec4 frag_color;
layout (location = 1) out vec4 frag_emission;
@ -37,7 +38,7 @@ main (void)
vec3 e_st = vec3 (tl_st.xy, 1);
vec2 l_st = vec2 (tl_st.zw);
c = texture (Texture, t_st);
c = texture (Texture, t_st) * color;
e = texture (Texture, e_st);
frag_color = c;//fogBlend (c);
frag_emission = e;

View file

@ -11,11 +11,13 @@ layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
layout (location = 0) in vec4 v_tl_st[];
layout (location = 1) in vec3 v_direction[];
layout (location = 2) in vec4 v_color[];
layout (location = 0) out vec4 tl_st;
layout (location = 1) out vec3 direction;
layout (location = 2) out vec3 normal;
layout (location = 3) out vec4 position;
layout (location = 4) out vec4 color;
void
main()
@ -31,6 +33,7 @@ main()
gl_Position = Projection3d * (View * (p));
tl_st = v_tl_st[vert];
direction = v_direction[vert];
color = v_color[vert];
normal = n;
position = p;
EmitVertex ();

View file

@ -20,6 +20,7 @@ layout (location = 2) in uint entid;
layout (location = 0) out vec4 tl_st;
layout (location = 1) out vec3 direction;
layout (location = 2) out vec4 color;
void
main (void)
@ -29,4 +30,5 @@ main (void)
gl_Position = vec4 (vert, 1);
direction = (Sky * vertex).xyz;
tl_st = tl_uv;
color = entities[entid].color;
}

View file

@ -10,10 +10,12 @@ layout (push_constant) uniform PushConstants {
vec4 fog;
float time;
float alpha;
float turb_scale;
};
layout (location = 0) in vec4 tl_st;
layout (location = 1) in vec3 direction;
layout (location = 2) in vec4 color;
layout (location = 0) out vec4 frag_color;

View file

@ -6,10 +6,12 @@ layout (push_constant) uniform PushConstants {
vec4 fog;
float time;
float alpha;
float turb_scale;
};
layout (location = 0) in vec4 tl_st;
layout (location = 1) in vec3 direction;
layout (location = 2) in vec4 color;
layout (location = 0) out vec4 frag_color;
@ -25,7 +27,7 @@ warp_st (vec2 st, float time)
{
vec2 angle = st.ts * CYCLE / 2.0;
vec2 phase = vec2 (time, time) * SPEED;
return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE;
return st + turb_scale * (sin ((angle + phase) * FACTOR) + BIAS) / SCALE;
}
vec4
@ -48,7 +50,8 @@ main (void)
c = texture (Texture, t_st);
e = texture (Texture, e_st);
float a = c.a * e.a * alpha;
c += e;
c.a = alpha;
frag_color = c;//fogBlend (c);
c.a = a;
frag_color = c * color;//fogBlend (c);
}

View file

@ -20,6 +20,7 @@ layout (location = 2) in uint entid;
layout (location = 0) out vec4 tl_st;
layout (location = 1) out vec3 direction;
layout (location = 2) out vec4 color;
void
main (void)
@ -28,4 +29,5 @@ main (void)
gl_Position = Projection3d * (View * vec4 (vert, 1));
direction = (Sky * vertex).xyz;
tl_st = tl_uv;
color = entities[entid].color;
}

View file

@ -51,6 +51,7 @@
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/math/bitop.h"
#include "QF/scene/entity.h"
#include "QF/Vulkan/qf_bsp.h"
@ -79,6 +80,7 @@ typedef struct bsp_push_constants_s {
quat_t fog;
float time;
float alpha;
float turb_scale;
} bsp_push_constants_t;
static const char * __attribute__((used)) bsp_pass_names[] = {
@ -604,6 +606,7 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx)
pass->ent_frame = e->animation.frame & 1;
pass->inst_id = model->render_id;
pass->inst_id |= e->renderer.colormod[3] < 1 ? INST_ALPHA : 0;
if (!pass->instances[model->render_id].entities.size) {
bsp_model_t *m = &bctx->models[model->render_id];
bsp_face_t *face = &bctx->faces[m->first_face];
@ -767,8 +770,11 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout,
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (bsp_push_constants_t, alpha),
sizeof (constants->alpha), &constants->alpha },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (bsp_push_constants_t, turb_scale),
sizeof (constants->turb_scale), &constants->turb_scale },
};
QFV_PushConstants (device, cmd, layout, 3, push_constants);
QFV_PushConstants (device, cmd, layout, 4, push_constants);
}
static void
@ -956,6 +962,10 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe)
__auto_type is = queue->a[j];
__auto_type f = bctx->faces[is.face];
f.flags |= ((is.inst_id & INST_ALPHA)
>> (BITOP_LOG2(INST_ALPHA)
- BITOP_LOG2(SURF_DRAWALPHA))) & SURF_DRAWALPHA;
is.inst_id &= ~INST_ALPHA;
if (pass->instances[is.inst_id].first_instance == -1) {
uint32_t count = pass->instances[is.inst_id].entities.size;
pass->instances[is.inst_id].first_instance = pass->entid_count;
@ -966,12 +976,15 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe)
}
int dq = 0;
if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) {
if (f.flags & SURF_DRAWSKY) {
dq = 1;
}
if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) {
if (f.flags & SURF_DRAWALPHA) {
dq = 2;
}
if (f.flags & SURF_DRAWTURB) {
dq = 3;
}
size_t dq_size = pass->draw_queues[dq].size;
bsp_draw_t *draw = &pass->draw_queues[dq].a[dq_size - 1];
@ -1138,22 +1151,30 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
bspctx_t *bctx = ctx->bsp_context;
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
if (!bctx->main_pass.draw_queues[2].size)
if (!bctx->main_pass.draw_queues[3].size)
return;
turb_begin (rFrame);
bsp_push_constants_t frag_constants = {
.time = vr_data.realtime,
.alpha = r_wateralpha
};
push_fragconst (&frag_constants, bctx->layout, device,
bframe->cmdSet.a[QFV_bspTurb]);
VkPipelineLayout layout = bctx->layout;
bsp_push_constants_t frag_constants = {
.time = vr_data.realtime,
.alpha = 1,
.turb_scale = 0,
};
push_fragconst (&frag_constants, layout, device,
bframe->cmdSet.a[QFV_bspTurb]);
__auto_type pass = &bctx->main_pass;
pass->textures = &bctx->registered_textures;
draw_queue (pass, 2, layout, device, bframe->cmdSet.a[QFV_bspTurb]);
frag_constants.alpha = r_wateralpha;
frag_constants.turb_scale = 1;
push_fragconst (&frag_constants, bctx->layout, device,
bframe->cmdSet.a[QFV_bspTurb]);
draw_queue (pass, 3, layout, device, bframe->cmdSet.a[QFV_bspTurb]);
turb_end (ctx);
}
@ -1379,7 +1400,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
DARRAY_INIT (&bctx->registered_textures, 64);
bctx->main_pass.num_queues = 3;//solid, sky, water
bctx->main_pass.num_queues = 4;//solid, sky, water, transparent
bctx->main_pass.draw_queues = malloc (bctx->main_pass.num_queues
* sizeof (bsp_drawset_t));
for (int i = 0; i < bctx->main_pass.num_queues; i++) {