[vulkan] Implement water surface rendering

They're unlit (fullbright, but that's nothing new for quake), but
working nicely. As a bonus, sort out the sky pass (forced to due to the
way command buffers are used).
This commit is contained in:
Bill Currie 2021-03-23 12:24:24 +09:00
parent 6e0312658d
commit 7e946a4de9
6 changed files with 173 additions and 78 deletions

View file

@ -73,7 +73,8 @@ typedef enum {
typedef enum {
QFV_bspDepth,
QFV_bspGBuffer,
QFV_bspTranslucent,
QFV_bspSky,
QFV_bspTurb,
QFV_bspNumPasses
} QFV_BspSubpass;
@ -146,6 +147,7 @@ typedef struct bspctx_s {
VkPipeline depth;
VkPipeline gbuf;
VkPipeline sky;
VkPipeline turb;
VkPipelineLayout layout;
size_t vertex_buffer_size;
size_t index_buffer_size;

View file

@ -313,6 +313,8 @@ bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag
bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc
bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag
bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc
bsp_turbf_src = $(vkshaderpath)/bsp_turb.frag
bsp_turbf_c = $(vkshaderpath)/bsp_turb.frag.spvc
lightingf_src = $(vkshaderpath)/lighting.frag
lightingf_c = $(vkshaderpath)/lighting.frag.spvc
composef_src = $(vkshaderpath)/compose.frag
@ -348,6 +350,8 @@ $(bsp_gbuff_c): $(bsp_gbuff_src)
$(bsp_skyf_c): $(bsp_skyf_src)
$(bsp_turbf_c): $(bsp_turbf_src)
$(lightingf_c): $(lightingf_src)
$(composef_c): $(composef_src)
@ -374,6 +378,7 @@ vkshader_c = \
$(bsp_gbufg_c) \
$(bsp_gbuff_c) \
$(bsp_skyf_c) \
$(bsp_turbf_c) \
$(lightingf_c) \
$(composef_c) \
$(aliasv_c) \

View file

@ -689,6 +689,43 @@
layout = quakebsp_layout;
//renderPass = renderpass;
};
bsp_turb = {
subpass = 1;
stages = (
{
stage = vertex;
name = main;
module = $builtin/quakebsp.vert;
},
{
stage = fragment;
name = main;
module = $builtin/bsp_turb.frag;
specializationInfo = {
mapEntries = (
{ size = 4; offset = 0; constantID = 0; },
{ size = 4; offset = 4; constantID = 1; },
);
data = <00000000ffffffff>;
};
},
);
vertexInput = $properties.vertexInput.brush;
inputAssembly = $properties.inputAssembly.brush;
viewport = $properties.viewport;
rasterization = $properties.rasterization.cw_cull_back;
multisample = $properties.multisample;
depthStencil = $properties.depthStencil.test_only;
colorBlend = {
logicOpEnable = false;
attachments = ($properties.attachmentBlendOp.disabled);
};
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = quakebsp_layout;
//renderPass = renderpass;
};
twod = {
subpass = 1;
stages = (

View file

@ -72,6 +72,8 @@ static
static
#include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/bsp_turb.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/lighting.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/compose.frag.spvc"
@ -104,6 +106,7 @@ static shaderdata_t builtin_shaders[] = {
{ "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) },
{ "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) },
{ "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) },
{ "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) },
{ "lighting.frag", lighting_frag, sizeof (lighting_frag) },
{ "compose.frag", compose_frag, sizeof (compose_frag) },
{ "alias.vert", alias_vert, sizeof (alias_vert) },

View file

@ -0,0 +1,52 @@
#version 450
layout (set = 0, binding = 1) uniform sampler2D Texture;
layout (push_constant) uniform PushConstants {
layout (offset = 64)
vec4 fog;
float time;
};
layout (location = 0) in vec4 tl_st;
layout (location = 1) in vec3 direction;
layout (location = 0) out vec4 frag_color;
const float PI = 3.14159265;
const float SPEED = 20.0;
const float CYCLE = 128.0;
const float FACTOR = PI * 2.0 / CYCLE;
const vec2 BIAS = vec2 (1.0, 1.0);
const float SCALE = 8.0;
vec2
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;
}
vec4
fogBlend (vec4 color)
{
float az = fog.a * gl_FragCoord.z / gl_FragCoord.w;
vec3 fog_color = fog.rgb;
float fog_factor = exp (-az * az);
return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a);
}
void
main (void)
{
vec4 c = vec4 (0);
vec4 e;
vec2 t_st = tl_st.xy;
vec2 l_st = tl_st.zw;
t_st = warp_st (t_st, time);
c = texture (Texture, t_st);
frag_color = c;//fogBlend (c);
}

View file

@ -72,13 +72,15 @@
static const char *bsp_pass_names[] = {
"depth",
"g-buffer",
"translucent",
"sky",
"turb",
};
static QFV_Subpass subpass_map[] = {
QFV_passDepth, // QFV_bspDepth
QFV_passGBuffer, // QFV_bspGBuffer
QFV_passTranslucent, // QFV_bspTranslucent
QFV_passTranslucent, // QFV_bspSky
QFV_passTranslucent, // QFV_bspTurb
};
static float identity[] = {
@ -968,58 +970,40 @@ bsp_end (vulkan_ctx_t *ctx)
bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx);
}
/*static void
turb_begin (bspctx_t *bctx)
static void
turb_begin (vulkan_ctx_t *ctx)
{
quat_t fog;
bspctx_t *bctx = ctx->bsp_context;
bctx->default_color[3] = bound (0, r_wateralpha->value, 1);
QuatCopy (bctx->default_color, bctx->last_color);
qfeglVertexAttrib4fv (quake_bsp.color.location, default_color);
Mat4Mult (glsl_projection, glsl_view, bsp_vp);
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
qfeglUseProgram (quake_turb.program);
qfeglEnableVertexAttribArray (quake_turb.vertex.location);
qfeglEnableVertexAttribArray (quake_turb.tlst.location);
qfeglDisableVertexAttribArray (quake_turb.color.location);
DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent],
bframe->cmdSet.a[QFV_bspTurb]);
qfeglVertexAttrib4fv (quake_turb.color.location, default_color);
//FIXME need per frame matrices
bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
bframe->imageInfo[0].imageView = ctx->default_magenta->view;
bframe->imageInfo[1].imageView = ctx->default_magenta->view;
bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap);
bframe->imageInfo[3].imageView = bctx->default_skysheet->view;
bframe->imageInfo[4].imageView = bctx->default_skybox->view;
glsl_Fog_GetColor (fog);
fog[3] = glsl_Fog_GetDensity () / 64.0;
fragconst_t frag_constants = { time: vr_data.realtime };
dfunc->vkCmdPushConstants (cmd, bctx->layout, VK_SHADER_STAGE_FRAGMENT_BIT,
64, sizeof (fragconst_t), &frag_constants);
qfeglUniform4fv (quake_turb.fog.location, 1, fog);
bsp_begin_subpass (QFV_bspTurb, bctx->turb, ctx);
}
qfeglUniform1i (quake_turb.palette.location, 1);
qfeglActiveTexture (GL_TEXTURE0 + 1);
qfeglEnable (GL_TEXTURE_2D);
qfeglBindTexture (GL_TEXTURE_2D, glsl_palette);
qfeglUniform1f (quake_turb.time.location, vr_data.realtime);
qfeglUniform1i (quake_turb.texture.location, 0);
qfeglActiveTexture (GL_TEXTURE0 + 0);
qfeglEnable (GL_TEXTURE_2D);
qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);
}*/
/*static void
turb_end (bspctx_t *bctx)
static void
turb_end (vulkan_ctx_t *ctx)
{
qfeglDisableVertexAttribArray (quake_turb.vertex.location);
qfeglDisableVertexAttribArray (quake_turb.tlst.location);
bspctx_t *bctx = ctx->bsp_context;
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
qfeglActiveTexture (GL_TEXTURE0 + 0);
qfeglDisable (GL_TEXTURE_2D);
qfeglActiveTexture (GL_TEXTURE0 + 1);
qfeglDisable (GL_TEXTURE_2D);
qfeglBindBuffer (GL_ARRAY_BUFFER, 0);
}*/
bsp_end_subpass (bframe->cmdSet.a[QFV_bspTurb], ctx);
}
static void
spin (mat4_t mat, bspctx_t *bctx)
@ -1057,9 +1041,8 @@ sky_begin (vulkan_ctx_t *ctx)
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
//FIXME where should skys go? g-buffer is overkill. Translucent pre-pass?
DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent],
bframe->cmdSet.a[QFV_bspTranslucent]);
bframe->cmdSet.a[QFV_bspSky]);
//FIXME need per frame matrices
bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
@ -1071,8 +1054,7 @@ sky_begin (vulkan_ctx_t *ctx)
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox);
//FIXME sky pass
bsp_begin_subpass (QFV_bspTranslucent, bctx->sky, ctx);
bsp_begin_subpass (QFV_bspSky, bctx->sky, ctx);
}
static void
@ -1081,8 +1063,7 @@ sky_end (vulkan_ctx_t *ctx)
bspctx_t *bctx = ctx->bsp_context;
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
//FIXME sky pass
bsp_end_subpass (bframe->cmdSet.a[QFV_bspTranslucent], ctx);
bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx);
}
static inline void
@ -1217,7 +1198,10 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx)
void
Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx)
{
/* bspctx_t *bctx = ctx->bsp_context;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context;
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
instsurf_t *is;
msurface_t *surf;
vulktex_t *tex = 0;
@ -1227,38 +1211,49 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx)
if (!bctx->waterchain)
return;
turb_begin (bctx);
turb_begin (ctx);
push_transform (identity, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
fragconst_t frag_constants = { time: vr_data.realtime };
push_fragconst (&frag_constants, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
for (is = bctx->waterchain; is; is = is->tex_chain) {
surf = is->surface;
if (tex != surf->texinfo->texture) {
if (tex != surf->texinfo->texture->render) {
if (tex) {
//XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
//for (ec = tex->elechain; ec; ec = ec->next)
// draw_elechain (ec, quake_turb.mvp_matrix.location,
// quake_turb.vertex.location,
// quake_turb.tlst.location,
// quake_turb.color.location);
bind_view (qfv_bsp_texture,
get_view (tex->tex, ctx->default_black),
bframe,
bframe->cmdSet.a[QFV_bspTurb],
bctx->layout, dfunc);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
reset_elechain (ec);
}
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;
}
tex = surf->texinfo->texture;
tex = surf->texinfo->texture->render;
}
add_surf_elements (tex, is, &ec, &el, bctx);
add_surf_elements (tex, is, &ec, &el, bctx, bframe);
}
if (tex) {
//XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
//for (ec = tex->elechain; ec; ec = ec->next)
// draw_elechain (ec, quake_turb.mvp_matrix.location,
// quake_turb.vertex.location,
// quake_turb.tlst.location,
// quake_turb.color.location);
bind_view (qfv_bsp_texture, get_view (tex->tex, ctx->default_black),
bframe, bframe->cmdSet.a[QFV_bspTurb],
bctx->layout, dfunc);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTurb]);
reset_elechain (ec);
}
tex->elechain = 0;
tex->elechain_tail = &tex->elechain;
}
turb_end (bctx);
turb_end (ctx);
bctx->waterchain = 0;
bctx->waterchain_tail = &bctx->waterchain;*/
bctx->waterchain_tail = &bctx->waterchain;
}
void
@ -1278,12 +1273,11 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
return;
sky_begin (ctx);
//FIXME sky pass
push_transform (identity, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTranslucent]);
bframe->cmdSet.a[QFV_bspSky]);
fragconst_t frag_constants = { time: vr_data.realtime };
push_fragconst (&frag_constants, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspTranslucent]);
bframe->cmdSet.a[QFV_bspSky]);
for (is = bctx->sky_chain; is; is = is->tex_chain) {
surf = is->surface;
if (tex != surf->texinfo->texture->render) {
@ -1291,11 +1285,11 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
bind_view (qfv_bsp_skysheet,
get_view (tex->tex, ctx->default_black),
bframe,
bframe->cmdSet.a[QFV_bspTranslucent],//FIXME
bframe->cmdSet.a[QFV_bspSky],
bctx->layout, dfunc);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,//FIXME
bframe->cmdSet.a[QFV_bspTranslucent]);
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspSky]);
reset_elechain (ec);
}
tex->elechain = 0;
@ -1307,11 +1301,11 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
}
if (tex) {
bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black),
bframe, bframe->cmdSet.a[QFV_bspTranslucent],//FIXME
bframe, bframe->cmdSet.a[QFV_bspSky],
bctx->layout, dfunc);
for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc,//FIXME
bframe->cmdSet.a[QFV_bspTranslucent]);
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspSky]);
reset_elechain (ec);
}
tex->elechain = 0;
@ -1488,6 +1482,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth");
bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf");
bctx->sky = Vulkan_CreatePipeline (ctx, "bsp_skysheet");
bctx->turb = Vulkan_CreatePipeline (ctx, "bsp_turb");
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
@ -1539,6 +1534,7 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0);
DARRAY_CLEAR (&bctx->texture_chains);
DARRAY_CLEAR (&bctx->frames);
QFV_DestroyStagingBuffer (bctx->light_stage);