summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c2.cpp1
-rw-r--r--intermediate/forward.h6
-rw-r--r--intermediate/ts.glsl54
-rw-r--r--lighting.cpp78
-rw-r--r--lighting.hpp21
-rw-r--r--model.cpp4
-rw-r--r--renderer.cpp47
-rw-r--r--renderer.hpp5
-rw-r--r--sc/sc.cpp2
-rw-r--r--src/guy.blendbin0 -> 483196 bytes
-rw-r--r--video.cpp17
-rw-r--r--video.hpp1
12 files changed, 162 insertions, 74 deletions
diff --git a/c2.cpp b/c2.cpp
index 3a14ea5..f53d59d 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -841,7 +841,6 @@ struct C2 : public App {
pcam.update();
lighting.update(dev, ctx, *world, renderer, scene);
update_scene(scene, dev, *world);
- lr.add_box(scene.bound);
ctx.debug_push("scene");
renderer.render(
dev,
diff --git a/intermediate/forward.h b/intermediate/forward.h
index 7c4c9d3..156a185 100644
--- a/intermediate/forward.h
+++ b/intermediate/forward.h
@@ -22,6 +22,9 @@ name: Caster
[variable]
name: projection
type: mat4
+[variable]
+name: jittered
+type: mat4
[struct]
name: Globals
@@ -41,4 +44,7 @@ type: Globals
stage: fragment
#endif
+
+#define max_casters 16
+
#endif
diff --git a/intermediate/ts.glsl b/intermediate/ts.glsl
index 61dd728..d80d6e4 100644
--- a/intermediate/ts.glsl
+++ b/intermediate/ts.glsl
@@ -35,6 +35,10 @@ dimension: 2
name: depthmap
stage: fragment
dimension: 2
+[texture]
+name: prev_occlusion
+stage: fragment
+dimension: 2
[struct]
name: Config
@@ -72,6 +76,9 @@ stage: fragment
[target]
name: shadow_amount
type: float
+[target]
+name: occlusion
+type: float
#endif
@@ -103,25 +110,25 @@ vec2 poissonDisk[16] = vec2[](
vec2(0.14383161, -0.14100790)
);
-float random(vec3 seed, int i){
- vec4 seed4 = vec4(seed,i);
+float random(vec3 seed, int i) {
+ vec4 seed4 = vec4(seed, i);
float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
return fract(sin(dot_product) * 43758.5453);
}
-float get_shadow(int id, vec3 wpos) {
+float get_shadow(int id, mat4 proj, vec3 wpos) {
const int taps = 4;
const float w = 1.0 / float(taps);
const float m = 1.0 / 1000.0;
int i;
float d = 0.0f;
- Caster caster = casters[id];
- vec4 surf = caster.projection * vec4(wpos, 1.0);
+ vec4 surf = proj * vec4(wpos, 1.0);
surf /= surf.w;
surf.xy = surf.xy * 0.5 + 0.5;
surf.z -= 0.005;
for (i = 0; i < taps; i++) {
- int index = int(16.0 * random(floor(wpos.xyz * 1000.0), i + globals.frame)) % 16;
+ float r = random(floor(wpos.xyz * 1000.0), i + globals.frame);
+ int index = int(16.0 * r) % 16;
vec2 coord = surf.xy + poissonDisk[index] * m;
vec4 vec = vec4(coord, float(id), surf.z);
d += texture(shadowmaps, vec).r * w;
@@ -129,31 +136,44 @@ float get_shadow(int id, vec3 wpos) {
return d;
}
-vec3 get_world_pos(float depth, vec2 uv) {
+vec4 get_world_pos(float depth, vec2 uv) {
float z = depth;
vec4 clip = vec4(uv * 2.0 - 1.0, z, 1.0);
vec4 view = config.inv_proj * clip;
view /= view.w;
- return (config.inv_view * view).xyz;
+ return config.inv_view * view;
}
void main() {
- float w_prev = 0.9;
- float w_cur = 0.1;
+ float w_prev = 0.99;
+ float w_cur = 0.01;
+ Caster caster = casters[caster_config.index];
vec2 uv = interpolator.uv;
float d = texture(depthmap, uv).r;
- vec3 wpos = get_world_pos(d, uv);
- vec4 prev_pos = config.prev_vp * vec4(wpos, 1.0);
+ float o = texture(prev_occlusion, uv).r;
+ vec4 wpos = get_world_pos(d, uv);
+ vec4 prev_pos = config.prev_vp * vec4(wpos.xyz, 1.0);
vec2 prev_uv = (prev_pos.xy / prev_pos.w) * 0.5 + 0.5;
float prev = texture(previous, prev_uv).r;
- float current = get_shadow(caster_config.index, wpos);
+ float base = get_shadow(
+ caster_config.index,
+ caster.projection,
+ wpos.xyz
+ );
+ float jittered = get_shadow(
+ caster_config.index + max_casters,
+ caster.jittered,
+ wpos.xyz
+ );
if (
prev_uv.x < 0.0 || prev_uv.x > 1.0 ||
- prev_uv.y < 0.0 || prev_uv.y > 1.0
+ prev_uv.y < 0.0 || prev_uv.y > 1.0 ||
+ abs(d - o) > 0.001
) {
- w_prev = 0.0;
- w_cur = 1.0;
+ shadow_amount = base;
+ } else {
+ shadow_amount = prev * w_prev + jittered * w_cur;
}
- shadow_amount = (prev * w_prev + current * w_cur);
+ occlusion = d;
}
#endif
diff --git a/lighting.cpp b/lighting.cpp
index 1eb4298..9f154cb 100644
--- a/lighting.cpp
+++ b/lighting.cpp
@@ -8,6 +8,8 @@ extern "C" {
#include "plat.h"
}
+#include <random>
+
/* needs to match surface shader */
struct GPU_Light {
v3f dir;
@@ -18,18 +20,19 @@ struct GPU_Light {
struct GPU_Caster {
m4f projection;
+ m4f jittered;
};
void Lighting::init(Device* dev, int w, int h) {
int i;
Sampler_State ss{};
- lights.init(
+ gpu_lights.init(
dev,
"Light buffer",
max_lights * sizeof(GPU_Light),
Buffer_Flags::storage_buffer
);
- casters.init(
+ gpu_casters.init(
dev,
"Caster buffer",
max_shadows * sizeof(GPU_Caster),
@@ -43,13 +46,14 @@ void Lighting::init(Device* dev, int w, int h) {
shadow_res,
1,
1,
- max_shadows,
+ shadowmap_count,
0
);
zero(ss_shadows, sizeof ss_shadows);
zero(ss_shadow_slices, sizeof ss_shadow_slices);
+ zero(occlusion, sizeof occlusion);
recreate(dev, w, h);
- for (i = 0; i < max_shadows; i++) {
+ for (i = 0; i < shadowmap_count; i++) {
cameras[i] = 0;
shadow_slices[i] = dev->alias_texture(
shadows,
@@ -80,10 +84,10 @@ void Lighting::init(Device* dev, int w, int h) {
void Lighting::destroy(Device* dev, Renderer& r) {
int i;
- lights.destroy(dev);
- casters.destroy(dev);
+ gpu_lights.destroy(dev);
+ gpu_casters.destroy(dev);
dev->destroy_sampler(shadow_sampler);
- for (i = 0; i < max_shadows; i++) {
+ for (i = 0; i < shadowmap_count; i++) {
dev->destroy_texture(shadow_slices[i]);
r.destroy_camera(cameras[i]);
}
@@ -99,6 +103,8 @@ void Lighting::destroy_ss(Device* dev) {
dev->destroy_texture(ss_shadow_slices[i][j]);
if (ss_shadows[i])
dev->destroy_texture(ss_shadows[i]);
+ if (occlusion[i])
+ dev->destroy_texture(occlusion[i]);
}
}
@@ -131,7 +137,28 @@ void Lighting::recreate(Device* dev, int w, int h) {
0,
j
);
+ occlusion[i] = dev->create_texture(
+ "Occlusion buffer",
+ texture_format_r32f,
+ Texture_Flags::sampleable | Texture_Flags::colour_target,
+ w,
+ h,
+ 1,
+ 1,
+ 1,
+ 0
+ );
+ }
+}
+
+Camera_Id Lighting::gm_cam(Renderer& r) {
+ int id = cam_count++;
+ Camera_Id cid = cameras[id];
+ if (!cid) {
+ cid = r.create_camera();
+ cameras[id] = cid;
}
+ return cid;
}
void Lighting::write_bufs(
@@ -144,6 +171,10 @@ void Lighting::write_bufs(
GPU_Light* ldst = (GPU_Light*)lptr;
GPU_Caster* cdst = (GPU_Caster*)cptr;
int count = 0, ccount = 0;
+ cam_count = 0;
+ std::random_device dev;
+ std::mt19937 rng(dev());
+ std::uniform_real_distribution<float> dist6(-0.01f, 0.01f);
for (auto v : w.view<Sun_Light>()) {
GPU_Light gl;
Sun_Light& l = v.get<Sun_Light>();
@@ -155,15 +186,22 @@ void Lighting::write_bufs(
gl.colour = l.colour;
gl.dir = l.dir;
if (l.caster && ccount < max_shadows) {
+ Camera* cam[2];
int cid = ccount++;
- GPU_Caster& c = cdst[cid];
- Camera_Id camid = cameras[cid];
- if (!camid)
- camid = r.create_camera();
- Camera& cam = r.get_camera(camid);
- cam.init_shadow(l.dir, s.bound.min, s.bound.max);
- c.projection = cam.get_proj() * cam.get_view();
- cameras[cid] = camid;
+ Caster& caster = casters[cid];
+ GPU_Caster& gc = cdst[cid];
+ v3f jitter(
+ dist6(rng),
+ dist6(rng),
+ dist6(rng)
+ );
+ caster = Caster { gm_cam(r), gm_cam(r) };
+ cam[0] = &r.get_camera(caster.reality);
+ cam[1] = &r.get_camera(caster.jittered);
+ cam[0]->init_shadow(l.dir, s.bound.min, s.bound.max);
+ cam[1]->init_shadow(l.dir + jitter, s.bound.min, s.bound.max);
+ gc.projection = cam[0]->get_proj() * cam[0]->get_view();
+ gc.jittered = cam[1]->get_proj() * cam[1]->get_view();
gl.caster_id = cid;
} else
gl.caster_id = -1;
@@ -181,10 +219,10 @@ void Lighting::update(
Model_Scene& s
) {
light_count = 0;
- write_bufs(lights.map(dev), casters.map(dev), w, r, s);
- casters.unmap(dev);
- lights.unmap(dev);
- lights.update(ctx);
- casters.update(ctx);
+ write_bufs(gpu_lights.map(dev), gpu_casters.map(dev), w, r, s);
+ gpu_casters.unmap(dev);
+ gpu_lights.unmap(dev);
+ gpu_lights.update(ctx);
+ gpu_casters.update(ctx);
}
diff --git a/lighting.hpp b/lighting.hpp
index 0d331d7..ac2d2c5 100644
--- a/lighting.hpp
+++ b/lighting.hpp
@@ -11,23 +11,32 @@ struct Model_Scene;
struct Renderer;
struct World;
+struct Caster {
+ Camera_Id reality;
+ Camera_Id jittered;
+};
+
struct Lighting {
static constexpr int max_lights = 128;
static constexpr int max_shadows = 16;
+ static constexpr int shadowmap_count = max_shadows * 2;
static constexpr int shadow_res = 2048;
- Staged_Buffer lights;
- Staged_Buffer casters;
+ Staged_Buffer gpu_lights;
+ Staged_Buffer gpu_casters;
Texture_Id shadows;
- Texture_Id shadow_slices[max_shadows];
+ Texture_Id shadow_slices[shadowmap_count];
Texture_Id ss_shadows[2];
- Texture_Id ss_shadow_slices[2][max_shadows];
+ Texture_Id ss_shadow_slices[2][shadowmap_count];
+ Texture_Id occlusion[2];
Sampler_Id shadow_sampler;
- Camera_Id cameras[max_shadows];
- int light_count, caster_count;
+ Caster casters[max_shadows];
+ Camera_Id cameras[shadowmap_count];
+ int light_count, caster_count, cam_count;
void init(Device* dev, int w, int h);
void destroy_ss(Device* dev);
void recreate(Device* dev, int w, int h);
void destroy(Device* dev, Renderer& r);
+ Camera_Id gm_cam(Renderer& r);
void update(
Device* dev,
Context& ctx,
diff --git a/model.cpp b/model.cpp
index 5806655..aa65898 100644
--- a/model.cpp
+++ b/model.cpp
@@ -386,8 +386,8 @@ void Model_Instance::render(
} else {
pb.depth(true, false, Depth_Mode::equal);
pb.shader(mesh.shader);
- pb.sbuffer(mesh.light_binding, lighting->lights.gpuonly);
- pb.sbuffer(mesh.casters_binding, lighting->casters.gpuonly);
+ pb.sbuffer(mesh.light_binding, lighting->gpu_lights.gpuonly);
+ pb.sbuffer(mesh.casters_binding, lighting->gpu_casters.gpuonly);
pb.texture(mesh.shadowmaps_binding, res.shadows, res.sampler);
mesh.material->use(pb, res.sampler, dev->get_shader(mesh.shader));
pb.cbuffer(
diff --git a/renderer.cpp b/renderer.cpp
index a9d590a..8bc2d94 100644
--- a/renderer.cpp
+++ b/renderer.cpp
@@ -71,6 +71,8 @@ void Renderer::init(
id(FORWARD, 512);
for (i = SHADOW_MAP_START; i < SHADOW_MAP_END; i++)
id(i, 512);
+ for (i = SHADOW_JIT_START; i < SHADOW_JIT_END; i++)
+ id(i, 512);
camera_count = 1;
cameras.init();
globals.init(
@@ -101,6 +103,7 @@ void Renderer::init(
ts_caster_config_binding = ts_shader->descriptor_binding("caster_config");
ts_casters_binding = ts_shader->descriptor_binding("casters");
ts_globals_binding = ts_shader->descriptor_binding("globals");
+ ts_prev_occlusion_binding = ts_shader->descriptor_binding("prev_occlusion");
assert(ts_shadowmap_binding >= 0);
assert(ts_depthmap_binding >= 0);
assert(ts_prev_binding >= 0);
@@ -109,6 +112,7 @@ void Renderer::init(
assert(ts_caster_config_binding >= 0);
assert(ts_casters_binding >= 0);
assert(ts_globals_binding >= 0);
+ assert(ts_prev_occlusion_binding >= 0);
make_ts_sampler(d);
frame = 0;
}
@@ -178,7 +182,7 @@ void Renderer::temporal_shadows(
int i, c = l->caster_count;
Camera& cam = get_camera(drawlists[FORWARD].camera);
TS_Cbuffer* cbuf = (TS_Cbuffer*)ts_config.map(dev);
- TS_Caster_Config* casters = (TS_Caster_Config*)ts_config.map(dev);
+ TS_Caster_Config* casters = (TS_Caster_Config*)ts_config2.map(dev);
for (i = 0; i < c; i++) {
casters[i].index = i;
}
@@ -195,6 +199,7 @@ void Renderer::temporal_shadows(
auto& pass = pb
.begin_rp()
.rp_target(l->ss_shadow_slices[ind][i], Clear_Mode::discard)
+ .rp_target(l->occlusion[ind], Clear_Mode::discard)
.build_rp();
auto& pip = pb
.begin()
@@ -212,6 +217,10 @@ void Renderer::temporal_shadows(
ts_depthmap_binding,
dev->get_depth_target(),
ts_sampler)
+ .texture(
+ ts_prev_occlusion_binding,
+ l->occlusion[!ind],
+ ts_sampler)
.cbuffer(ts_config_binding, ts_config.gpuonly)
.cbuffer(
ts_caster_config_binding,
@@ -219,7 +228,7 @@ void Renderer::temporal_shadows(
i * sizeof(TS_Caster_Config),
sizeof(TS_Caster_Config))
.cbuffer(ts_globals_binding, globals.gpuonly)
- .sbuffer(ts_casters_binding, l->casters.gpuonly)
+ .sbuffer(ts_casters_binding, l->gpu_casters.gpuonly)
.build();
quad.render(
ctx,
@@ -251,11 +260,11 @@ void Renderer::render(
.rp_target(hdr_target, Clear_Mode::restore)
.rp_depth_target(dev->get_depth_target(), Clear_Mode::restore)
.build_rp();
- Render_Pass* shadow_passes[Lighting::max_shadows];
- for (i = 0; i < Lighting::max_shadows; i++) {
+ Render_Pass* shadow_passes[drawlist_count];
+ for (i = SHADOW_MAP_START, j = 0; i < SHADOW_JIT_END; i++, j++) {
shadow_passes[i] = &pb
.begin_rp()
- .rp_depth_target(l->shadow_slices[i], 1.0f)
+ .rp_depth_target(l->shadow_slices[j], 1.0f)
.build_rp();
}
@@ -263,20 +272,22 @@ void Renderer::render(
drawlists[FORWARD].render(*this, dev, a, l, depth_prepass, 0);
ctx.debug_pop();
+ auto shadows = [&]<typename T>(int s, T cam) {
+ for (i = s, j = 0; j < l->caster_count; i++, j++) {
+ auto o = [](Pipeline_Builder& pb) {
+ pb.cull(Cull_Mode::front);
+ };
+ setcam(i, l->casters[j].*cam);
+ ctx.debug_push("shadow map");
+ drawlists[i].render(*this, dev, a, l, *shadow_passes[i], o);
+ ctx.debug_pop();
+ }
+ };
ctx.debug_push("shadow maps");
- for (
- i = SHADOW_MAP_START, j = 0;
- i < SHADOW_MAP_END && j < l->caster_count;
- i++, j++
- ) {
- auto o = [](Pipeline_Builder& pb) {
- pb.cull(Cull_Mode::front);
- };
- setcam(i, l->cameras[j]);
- ctx.debug_push("shadow map");
- drawlists[i].render(*this, dev, a, l, *shadow_passes[j], o);
- ctx.debug_pop();
- }
+ shadows(SHADOW_MAP_START, &Caster::reality);
+ ctx.debug_pop();
+ ctx.debug_push("jittered shadow maps");
+ shadows(SHADOW_JIT_START, &Caster::jittered);
ctx.debug_pop();
temporal_shadows(dev, ctx, l, pb);
diff --git a/renderer.hpp b/renderer.hpp
index 387032d..20c7f98 100644
--- a/renderer.hpp
+++ b/renderer.hpp
@@ -10,7 +10,9 @@ enum {
FORWARD,
SHADOW_MAP_START,
SHADOW_MAP_END = SHADOW_MAP_START + Lighting::max_shadows,
- drawlist_count = SHADOW_MAP_END };
+ SHADOW_JIT_START = SHADOW_MAP_END,
+ SHADOW_JIT_END = SHADOW_JIT_START + Lighting::max_shadows,
+ drawlist_count = SHADOW_JIT_END };
struct Asset_Arena;
struct Model_Instance;
@@ -64,6 +66,7 @@ struct Renderer {
int ts_caster_config_binding;
int ts_casters_binding;
int ts_globals_binding;
+ int ts_prev_occlusion_binding;
Sampler_Id ts_sampler;
Staged_Buffer ts_config, ts_config2;
diff --git a/sc/sc.cpp b/sc/sc.cpp
index 9232e10..1f7ccba 100644
--- a/sc/sc.cpp
+++ b/sc/sc.cpp
@@ -601,7 +601,7 @@ struct Desc {
size_t i, l = trgts.size();
for (i = 0; i < l; i++) {
auto& attr = trgts[i];
- ss << "layout (location = 0) out ";
+ ss << "layout (location = " << i << ") out ";
ss << attr.tname << " ";
ss << attr.name << ";\n";
}
diff --git a/src/guy.blend b/src/guy.blend
new file mode 100644
index 0000000..a3b14ce
--- /dev/null
+++ b/src/guy.blend
Binary files differ
diff --git a/video.cpp b/video.cpp
index 28df58b..3e960be 100644
--- a/video.cpp
+++ b/video.cpp
@@ -1628,8 +1628,8 @@ void Renderpass_Vk::init(
const Rpo_Key& rpk
) {
VkRenderPassCreateInfo ri{};
- VkAttachmentDescription ads[2];
- VkAttachmentReference car, dar;
+ VkAttachmentDescription ads[max_colour_attachments + 1];
+ VkAttachmentReference cars[max_colour_attachments], dar;
VkSubpassDescription sd{};
VkResult r;
auto& rp = rpk.rpo;
@@ -1637,10 +1637,12 @@ void Renderpass_Vk::init(
bool has_depth = rp.depth.id;
int count = 0, i, c = rp.colour_count;
zero(ads, sizeof ads);
+ zero(cars, sizeof cars);
for (i = 0; i < c; i++) {
int index = count++;
auto& colour = rp.colours[i];
auto& ad = ads[index];
+ auto& car = cars[index];
ad.format = get_vk_format(colour.fmt);
ad.samples = VK_SAMPLE_COUNT_1_BIT;
ad.loadOp = load_op_from_mode(colour.mode);
@@ -1677,7 +1679,7 @@ void Renderpass_Vk::init(
sd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
sd.colorAttachmentCount = rp.colour_count;
- sd.pColorAttachments = &car;
+ sd.pColorAttachments = cars;
sd.pDepthStencilAttachment = has_depth? &dar: 0;
ri.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
@@ -1704,7 +1706,7 @@ void Framebuffer_Vk::init(
) {
bool has_depth = rp.depth.id;
int i, count = 0;
- VkImageView atts[2];
+ VkImageView atts[max_colour_attachments + 1];
VkResult r;
VkFramebufferCreateInfo fbi{};
for (i = 0; i < rp.colour_count; i++) {
@@ -2880,12 +2882,11 @@ void Pipeline_Vk::init_blending(
zero(&bi, sizeof bi);
if (rp.colour_count) {
int i, c = rp.colour_count;
- abs =
- (VkPipelineColorBlendAttachmentState*)arena_alloc(
+ abs = (VkPipelineColorBlendAttachmentState*)arena_alloc(
&scope,
- sizeof abs * c
+ sizeof *abs * c
);
- zero(abs, sizeof *abs);
+ zero(abs, sizeof *abs * c);
for (i = 0; i < c; i++) {
auto& ab = abs[i];
ab.colorWriteMask =
diff --git a/video.hpp b/video.hpp
index 5aa25bc..4289685 100644
--- a/video.hpp
+++ b/video.hpp
@@ -553,6 +553,7 @@ struct Context {
void submit(const Render_Pass& rp);
void copy(Buffer_Id dst, Buffer_Id src);
void copy(Texture_Id dst, Buffer_Id src);
+ void copy(Texture_Id dst, Texture_Id src);
void transition(Texture_Id id, Resource_State state);
void debug_push(const char* name);
void debug_pop();