mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 09:52:21 +00:00
[vulkan] Implement deferred fog
It's not perfect (double fog on translucent surfaces, the scatter/absorption isn't right, and no local lighting on the fog itself), but it at least seems to look ok.
This commit is contained in:
parent
60cb5a922a
commit
8f20638cd9
9 changed files with 93 additions and 20 deletions
|
@ -36,7 +36,7 @@
|
|||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
|
||||
#define COMPOSE_IMAGE_INFOS 3
|
||||
#define COMPOSE_IMAGE_INFOS 4
|
||||
|
||||
typedef struct composeframe_s {
|
||||
VkDescriptorImageInfo imageInfo[COMPOSE_IMAGE_INFOS];
|
||||
|
|
|
@ -469,13 +469,13 @@ $(light_debug_c): $(light_debug_src) $(lighting_h)
|
|||
|
||||
$(light_oit_c): $(light_oit_src) $(lighting_h)
|
||||
|
||||
$(lighting_nonef_c): $(lighting_nonef_src) $(lighting_h) $(lighting_main)
|
||||
$(lighting_nonef_c): $(lighting_nonef_src) $(lighting_h) $(lighting_main) $(fog_h)
|
||||
|
||||
$(lighting_cascadef_c): $(lighting_cascadef_src) $(lighting_h) $(lighting_main)
|
||||
$(lighting_cascadef_c): $(lighting_cascadef_src) $(lighting_h) $(lighting_main) $(fog_h)
|
||||
|
||||
$(lighting_cubef_c): $(lighting_cubef_src) $(lighting_h) $(lighting_main)
|
||||
$(lighting_cubef_c): $(lighting_cubef_src) $(lighting_h) $(lighting_main) $(fog_h)
|
||||
|
||||
$(lighting_planef_c): $(lighting_planef_src) $(lighting_h) $(lighting_main)
|
||||
$(lighting_planef_c): $(lighting_planef_src) $(lighting_h) $(lighting_main) $(fog_h)
|
||||
|
||||
$(composef_c): $(composef_src) $(oit_blend) $(oit_h)
|
||||
|
||||
|
|
|
@ -708,6 +708,7 @@ properties = {
|
|||
lighting_attach, lighting_shadow);
|
||||
pushConstants = {
|
||||
fragment = {
|
||||
fog = vec4;
|
||||
CascadeDepths = vec4;
|
||||
queue = uint;
|
||||
};
|
||||
|
@ -724,6 +725,12 @@ properties = {
|
|||
};
|
||||
layout = {
|
||||
descriptorSets = (compose_attach, oit_set);
|
||||
pushConstants = {
|
||||
fragment = {
|
||||
fog = vec4;
|
||||
camera = vec4;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
output = {
|
||||
|
@ -1053,6 +1060,12 @@ descriptorSetLayouts = {
|
|||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
{
|
||||
binding = 3;
|
||||
descriptorType = input_attachment;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
particle_set = {
|
||||
|
@ -1884,6 +1897,7 @@ renderpasses = {
|
|||
color = shader_read_only_optimal;
|
||||
light = shader_read_only_optimal;
|
||||
emission = shader_read_only_optimal;
|
||||
position = shader_read_only_optimal;
|
||||
};
|
||||
color = {
|
||||
output = {
|
||||
|
@ -1891,7 +1905,7 @@ renderpasses = {
|
|||
blend = $additive_blend;
|
||||
};
|
||||
};
|
||||
preserve = (depth, normal, position);
|
||||
preserve = (depth, normal);
|
||||
};
|
||||
pipelines = {
|
||||
compose = {
|
||||
|
|
|
@ -5,24 +5,31 @@
|
|||
#define OIT_SET 1
|
||||
#include "oit_blend.finc"
|
||||
|
||||
#include "fog.finc"
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
vec4 fog;
|
||||
vec4 camera;
|
||||
};
|
||||
|
||||
layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput color;
|
||||
layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput light;
|
||||
layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput emission;
|
||||
layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput position;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
vec3 c;
|
||||
vec3 l;
|
||||
vec3 e;
|
||||
vec3 o;
|
||||
vec3 c = subpassLoad (color).rgb;
|
||||
vec3 l = subpassLoad (light).rgb;
|
||||
vec3 e = subpassLoad (emission).rgb;
|
||||
vec3 p = subpassLoad (position).xyz;
|
||||
vec3 o = max(BlendFrags (vec4 (c * l + e, 1)).xyz, vec3(0));
|
||||
|
||||
c = subpassLoad (color).rgb;
|
||||
l = subpassLoad (light).rgb;
|
||||
e = subpassLoad (emission).rgb;
|
||||
o = max(BlendFrags (vec4 (c * l + e, 1)).xyz, vec3(0));
|
||||
float d = length (p - camera.xyz);
|
||||
o = FogBlend (vec4(o,1), fog, d).xyz;
|
||||
o = pow (o, vec3(0.83));//FIXME make gamma correction configurable
|
||||
frag_color = vec4 (o, 1);
|
||||
}
|
||||
|
|
|
@ -7,3 +7,21 @@ FogBlend (vec4 color, vec4 fog)
|
|||
float fog_factor = exp (-az);
|
||||
return mix (fog_color, color, fog_factor);
|
||||
}
|
||||
|
||||
vec4
|
||||
FogBlend (vec4 color, vec4 fog, float dist)
|
||||
{
|
||||
float az = fog.a * dist;
|
||||
vec4 fog_color = vec4 (fog.rgb, 1.0);
|
||||
|
||||
float fog_factor = exp (-az);
|
||||
return mix (fog_color, color, fog_factor);
|
||||
}
|
||||
|
||||
vec4
|
||||
FogTransmit (vec4 color, vec4 fog, float dist)
|
||||
{
|
||||
float az = fog.a * dist;
|
||||
vec3 fog_color = exp (-az * fog.rgb);
|
||||
return vec4 (color.rgb * fog_color, color.a);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ layout (set = 1, binding = 4) buffer LightEntIds {
|
|||
};
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
vec4 fog;
|
||||
vec4 CascadeDepths;
|
||||
uint queue;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,8 @@ diffuse (vec3 incoming, vec3 normal)
|
|||
return clamp (lightdot, 0, 1);
|
||||
}
|
||||
|
||||
#include "fog.finc"
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
|
@ -61,6 +63,9 @@ main (void)
|
|||
if (bitfieldExtract(id_data, 31, 1) == 0) {
|
||||
col *= style[renderer[id].style];
|
||||
}
|
||||
if (fog.w > 0) {
|
||||
col = FogTransmit (col, fog, r[1]);
|
||||
}
|
||||
light += I * col.w * col.xyz;
|
||||
}
|
||||
//light = max (light, minLight);
|
||||
|
|
|
@ -87,11 +87,21 @@ compose_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
|||
cframe->imageInfo[0].imageView = fb->views[QFV_attachColor];
|
||||
cframe->imageInfo[1].imageView = fb->views[QFV_attachLight];
|
||||
cframe->imageInfo[2].imageView = fb->views[QFV_attachEmission];
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 1,
|
||||
cframe->descriptors, 0, 0);
|
||||
if (!color_only) {
|
||||
cframe->imageInfo[3].imageView = fb->views[QFV_attachPosition];
|
||||
if (color_only) {
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 1,
|
||||
cframe->descriptors, 0, 0);
|
||||
} else {
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS,
|
||||
cframe->descriptors, 0, 0);
|
||||
|
||||
vec4f_t fog = Fog_Get ();
|
||||
vec4f_t cam = r_refdef.camera[3];
|
||||
qfv_push_constants_t push_constants[] = {
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (fog), &fog },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(fog), sizeof (cam), &cam },
|
||||
};
|
||||
QFV_PushConstants (device, cmd, layout, 2, push_constants);
|
||||
}
|
||||
|
||||
VkDescriptorSet sets[] = {
|
||||
|
|
|
@ -1296,6 +1296,12 @@ lighting_draw_hulls (const exprval_t **params, exprval_t *result,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
vec4f_t fog;
|
||||
vec4f_t CascadeDepths;
|
||||
uint32_t queue;
|
||||
} light_push_constants_t;
|
||||
|
||||
static void
|
||||
lighting_draw_lights (const exprval_t **params, exprval_t *result,
|
||||
exprctx_t *ectx)
|
||||
|
@ -1317,15 +1323,27 @@ lighting_draw_lights (const exprval_t **params, exprval_t *result,
|
|||
return;
|
||||
}
|
||||
|
||||
vec4f_t fog = Fog_Get ();
|
||||
// convert scatter to transmission (FIXME ignoring absorbtion)
|
||||
fog = (vec4f_t) { 1, 1, 1, 0 } - fog;
|
||||
fog[3] = -fog[3];
|
||||
|
||||
//FIXME dup of z_range (sort of)
|
||||
vec4f_t depths = {
|
||||
r_nearclip / 32, r_nearclip / 256, r_nearclip / 1024, 0,
|
||||
};
|
||||
qfv_push_constants_t push_constants[] = {
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (depths), &depths },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(depths), sizeof(queue), &queue },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
field_offset (light_push_constants_t, fog),
|
||||
sizeof (fog), &fog },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
field_offset (light_push_constants_t, CascadeDepths),
|
||||
sizeof (depths), &depths },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
field_offset (light_push_constants_t, queue),
|
||||
sizeof (queue), &queue },
|
||||
};
|
||||
QFV_PushConstants (device, cmd, layout, 2, push_constants);
|
||||
QFV_PushConstants (device, cmd, layout, 3, push_constants);
|
||||
|
||||
dfunc->vkCmdDraw (cmd, 3, 1, 0, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue