summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile17
-rw-r--r--build.ninja9
-rw-r--r--c2.cpp71
-rw-r--r--configure.lua1
-rw-r--r--intermediate/surface.glsl59
-rw-r--r--intermediate/ts.glsl148
-rw-r--r--lighting.cpp49
-rw-r--r--lighting.hpp6
-rw-r--r--model.cpp2
-rw-r--r--model.hpp1
-rw-r--r--renderer.cpp180
-rw-r--r--renderer.hpp36
-rw-r--r--video.cpp2
13 files changed, 450 insertions, 131 deletions
diff --git a/Makefile b/Makefile
index 4a1b27e..fe8d568 100644
--- a/Makefile
+++ b/Makefile
@@ -118,15 +118,18 @@ data/tonemap.csh: intermediate/tonemap.glsl shadercompiler | data
data/triangle.csh: intermediate/triangle.glsl shadercompiler | data
cpp -MMD -MF data/triangle.d -MT data/triangle.csh -Iintermediate intermediate/triangle.glsl > /dev/null
./shadercompiler intermediate/triangle.glsl data/triangle.csh
+data/ts.csh: intermediate/ts.glsl shadercompiler | data
+ cpp -MMD -MF data/ts.d -MT data/ts.csh -Iintermediate intermediate/ts.glsl > /dev/null
+ ./shadercompiler intermediate/ts.glsl data/ts.csh
data/ui.csh: intermediate/ui.glsl shadercompiler | data
cpp -MMD -MF data/ui.d -MT data/ui.csh -Iintermediate intermediate/ui.glsl > /dev/null
./shadercompiler intermediate/ui.glsl data/ui.csh
-data/monkey.mdl: convmodel intermediate/monkey.glb data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh | data
+data/monkey.mdl: convmodel intermediate/monkey.glb data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh | data
./convmodel data intermediate/monkey.glb data/monkey.mdl
-data/cube.mdl: convmodel intermediate/cube.glb data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh | data
+data/cube.mdl: convmodel intermediate/cube.glb data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh | data
./convmodel data intermediate/cube.glb data/cube.mdl
-data/scene.mdl: convmodel intermediate/scene.glb data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh | data
+data/scene.mdl: convmodel intermediate/scene.glb data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh | data
./convmodel data intermediate/scene.glb data/scene.mdl
data/22.tex: convtexture intermediate/22.bmp | data
@@ -149,16 +152,16 @@ data/plastic.mat: convmaterial intermediate/plastic.mat | data
data/greybox.mat: convmaterial intermediate/greybox.mat | data
./convmaterial intermediate/greybox.mat data/greybox.mat
-pack: packer data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh data/monkey.mdl data/cube.mdl data/scene.mdl data/22.tex data/kita.tex data/brick_albedo.tex data/brick_ao.tex data/brick_normal.tex data/sky.tex data/bricks.mat data/plastic.mat data/greybox.mat
- ./packer pack data debug.csh mip_spec.csh sky.csh surface.csh surface_depthonly.csh tonemap.csh triangle.csh ui.csh monkey.mdl cube.mdl scene.mdl 22.tex kita.tex brick_albedo.tex brick_ao.tex brick_normal.tex sky.tex bricks.mat plastic.mat greybox.mat
+pack: packer data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh data/monkey.mdl data/cube.mdl data/scene.mdl data/22.tex data/kita.tex data/brick_albedo.tex data/brick_ao.tex data/brick_normal.tex data/sky.tex data/bricks.mat data/plastic.mat data/greybox.mat
+ ./packer pack data debug.csh mip_spec.csh sky.csh surface.csh surface_depthonly.csh tonemap.csh triangle.csh ts.csh ui.csh monkey.mdl cube.mdl scene.mdl 22.tex kita.tex brick_albedo.tex brick_ao.tex brick_normal.tex sky.tex bricks.mat plastic.mat greybox.mat
data:
mkdir -p data
--include qstd/memory.d qstd/plat.d qstd/str.d qstd/pack.d cfg/cfgparse.d sc/sc.d sc/includer.d app.d asset.d c2.d camera.d debugdraw.d editor.d lighting.d maths.d model.d physics.d pipeline.d renderer.d scene.d ui.d video.d world.d convtexture.d convmodel.d convmaterial.d packer.d data/debug.d data/mip_spec.d data/sky.d data/surface.d data/surface_depthonly.d data/tonemap.d data/triangle.d data/ui.d
+-include qstd/memory.d qstd/plat.d qstd/str.d qstd/pack.d cfg/cfgparse.d sc/sc.d sc/includer.d app.d asset.d c2.d camera.d debugdraw.d editor.d lighting.d maths.d model.d physics.d pipeline.d renderer.d scene.d ui.d video.d world.d convtexture.d convmodel.d convmaterial.d packer.d data/debug.d data/mip_spec.d data/sky.d data/surface.d data/surface_depthonly.d data/tonemap.d data/triangle.d data/ts.d data/ui.d
clean:
- rm -f qstd/memory.o qstd/plat.o qstd/str.o qstd/pack.o cfg/cfgparse.o sc/sc.o sc/includer.o app.o asset.o c2.o camera.o debugdraw.o editor.o lighting.o maths.o model.o physics.o pipeline.o renderer.o scene.o ui.o video.o world.o convtexture.o convmodel.o convmaterial.o packer.o qstd/memory.d qstd/plat.d qstd/str.d qstd/pack.d cfg/cfgparse.d sc/sc.d sc/includer.d app.d asset.d c2.d camera.d debugdraw.d editor.d lighting.d maths.d model.d physics.d pipeline.d renderer.d scene.d ui.d video.d world.d convtexture.d convmodel.d convmaterial.d packer.d data/debug.d data/mip_spec.d data/sky.d data/surface.d data/surface_depthonly.d data/tonemap.d data/triangle.d data/ui.d data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh data/monkey.mdl data/cube.mdl data/scene.mdl data/22.tex data/kita.tex data/brick_albedo.tex data/brick_ao.tex data/brick_normal.tex data/sky.tex data/bricks.mat data/plastic.mat data/greybox.mat
+ rm -f qstd/memory.o qstd/plat.o qstd/str.o qstd/pack.o cfg/cfgparse.o sc/sc.o sc/includer.o app.o asset.o c2.o camera.o debugdraw.o editor.o lighting.o maths.o model.o physics.o pipeline.o renderer.o scene.o ui.o video.o world.o convtexture.o convmodel.o convmaterial.o packer.o qstd/memory.d qstd/plat.d qstd/str.d qstd/pack.d cfg/cfgparse.d sc/sc.d sc/includer.d app.d asset.d c2.d camera.d debugdraw.d editor.d lighting.d maths.d model.d physics.d pipeline.d renderer.d scene.d ui.d video.d world.d convtexture.d convmodel.d convmaterial.d packer.d data/debug.d data/mip_spec.d data/sky.d data/surface.d data/surface_depthonly.d data/tonemap.d data/triangle.d data/ts.d data/ui.d data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh data/monkey.mdl data/cube.mdl data/scene.mdl data/22.tex data/kita.tex data/brick_albedo.tex data/brick_ao.tex data/brick_normal.tex data/sky.tex data/bricks.mat data/plastic.mat data/greybox.mat
rm -f shadercompiler
rmdir data
rm -f c2
diff --git a/build.ninja b/build.ninja
index 0d15a5e..8635232 100644
--- a/build.ninja
+++ b/build.ninja
@@ -83,11 +83,12 @@ build data/surface.csh: shadercompiler intermediate/surface.glsl | shadercompile
build data/surface_depthonly.csh: shadercompiler intermediate/surface_depthonly.glsl | shadercompiler.exe
build data/tonemap.csh: shadercompiler intermediate/tonemap.glsl | shadercompiler.exe
build data/triangle.csh: shadercompiler intermediate/triangle.glsl | shadercompiler.exe
+build data/ts.csh: shadercompiler intermediate/ts.glsl | shadercompiler.exe
build data/ui.csh: shadercompiler intermediate/ui.glsl | shadercompiler.exe
-build data/monkey.mdl: convmodel intermediate/monkey.glb | convmodel.exe data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh
-build data/cube.mdl: convmodel intermediate/cube.glb | convmodel.exe data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh
-build data/scene.mdl: convmodel intermediate/scene.glb | convmodel.exe data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh
+build data/monkey.mdl: convmodel intermediate/monkey.glb | convmodel.exe data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh
+build data/cube.mdl: convmodel intermediate/cube.glb | convmodel.exe data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh
+build data/scene.mdl: convmodel intermediate/scene.glb | convmodel.exe data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh
build data/bricks.mat: convmaterial intermediate/bricks.mat | convmaterial.exe
build data/plastic.mat: convmaterial intermediate/plastic.mat | convmaterial.exe
@@ -106,5 +107,5 @@ build data/brick_normal.tex: convtexture intermediate/brick_normal.bmp | convtex
build data/sky.tex: convtexture intermediate/sky.hdr | convtexture.exe
format = rgba16f
-build pack: packer data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ui.csh data/monkey.mdl data/cube.mdl data/scene.mdl data/bricks.mat data/plastic.mat data/greybox.mat data/22.tex data/kita.tex data/brick_albedo.tex data/brick_ao.tex data/brick_normal.tex data/sky.tex | packer.exe
+build pack: packer data/debug.csh data/mip_spec.csh data/sky.csh data/surface.csh data/surface_depthonly.csh data/tonemap.csh data/triangle.csh data/ts.csh data/ui.csh data/monkey.mdl data/cube.mdl data/scene.mdl data/bricks.mat data/plastic.mat data/greybox.mat data/22.tex data/kita.tex data/brick_albedo.tex data/brick_ao.tex data/brick_normal.tex data/sky.tex | packer.exe
diff --git a/c2.cpp b/c2.cpp
index ac9e7d4..3867280 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -162,61 +162,6 @@ struct Orbit_Cam {
}
};
-struct Fullscreen_Quad {
- Buffer_Id vb;
-
- void init(Device* d) {
- float verts[] = {
- -1.0f, -1.0f, 0.0f, 0.0f,
- -1.0f, 3.0f, 0.0f, 2.0f,
- 3.0f, -1.0f, 2.0f, 0.0f
- };
- Buffer_Id stage;
- void* mem;
- stage = d->create_buffer(
- "sky vb stage",
- sizeof verts,
- Buffer_Flags::cpu_readwrite |
- Buffer_Flags::copy_src
- );
- mem = d->map_buffer(stage, 0, sizeof verts);
- memcpy(mem, verts, sizeof verts);
- d->unmap_buffer(stage);
- vb = d->create_buffer(
- "fullscreen quad",
- sizeof verts,
- Buffer_Flags::copy_dst |
- Buffer_Flags::vertex_buffer
- );
- Context& ctx = d->acquire();
- ctx.copy(vb, stage);
- d->submit(ctx);
- d->destroy_bufferi(stage);
- }
-
- void destroy(Device* d) {
- d->destroy_buffer(vb);
- }
-
- void render(
- Context& ctx,
- Pipeline& pip,
- Render_Pass& pass,
- int bind
- ) {
- Vertex_Buffer_Binding vbb[] = {{
- .id = vb,
- .offset = 0,
- .target = bind
- }, {}};
- Draw draw{};
- draw.verts = vbb;
- draw.vertex_count = 3;
- draw.instance_count = 1;
- ctx.submit(draw, pip, pass);
- }
-};
-
struct Sky {
Staged_Buffer config;
Texture_Id texture;
@@ -647,7 +592,6 @@ struct C2 : public App {
Lighting lighting;
Camera_Id camera;
Orbit_Cam orbit_cam;
- Fullscreen_Quad quad;
Sky sky;
Env_Probe eprobe;
Tonemap tonemap;
@@ -703,7 +647,6 @@ struct C2 : public App {
ui_shader = (Shader*)assets.load("ui.csh");
texture = (Texture*)assets.load("22.tex");
texture2 = (Texture*)assets.load("kita.tex");
- quad.init(dev);
cbuf = dev->create_buffer(
"config buffer",
sizeof(Config_Buffer),
@@ -715,7 +658,7 @@ struct C2 : public App {
per_frame_memory_size
);
clamped_linear = create_clamped_linear(dev);
- renderer.init(arena, dev);
+ renderer.init(arena, dev, assets);
world = (World*)arena_alloc(arena, sizeof *world);
world->init(arena);
ui = UI::create(this, &ui_arena);
@@ -726,7 +669,7 @@ struct C2 : public App {
ui->layout(w, h);
fps_label = ui->create_element<UI::Label>(ui->root, "");
scene.init(&scene_arena, 32, clamped_linear);
- lighting.init(dev);
+ lighting.init(dev, w, h);
sky.init(dev, &assets);
eprobe.init(dev, &assets, 256);
tonemap.init(dev, &assets);
@@ -884,7 +827,7 @@ struct C2 : public App {
Render_Pass& tonemap_pass = pb.build_rp();
ctx.debug_push("environment cube");
- eprobe.render(dev, &frame_arena, quad, sky);
+ eprobe.render(dev, &frame_arena, renderer.quad, sky);
ctx.debug_pop();
renderer.env_cubemap = eprobe.get_cubemap();
@@ -911,7 +854,7 @@ struct C2 : public App {
sky.render(
dev,
&frame_arena,
- quad,
+ renderer.quad,
sky_pass,
clamped_linear,
pcam,
@@ -925,7 +868,7 @@ struct C2 : public App {
tonemap.render(
dev,
&frame_arena,
- quad,
+ renderer.quad,
tonemap_pass,
hdr_target,
clamped_linear
@@ -959,7 +902,7 @@ struct C2 : public App {
clamped_linear
);
Pipeline& ui_pip = pb.build();
- quad.render(
+ renderer.quad.render(
ctx,
ui_pip,
ui_pass,
@@ -1001,7 +944,6 @@ struct C2 : public App {
}
void on_destroy() override {
- quad.destroy(dev);
scene.destroy(dev);
sky.destroy(dev);
lighting.destroy(dev, renderer);
@@ -1030,6 +972,7 @@ struct C2 : public App {
dev->destroy_buffer(ui_buffer);
make_hdr_target();
make_ui_texture();
+ lighting.recreate(dev, w, h);
}
void make_hdr_target() {
diff --git a/configure.lua b/configure.lua
index 9bfe342..d944308 100644
--- a/configure.lua
+++ b/configure.lua
@@ -50,6 +50,7 @@ config = {
"surface_depthonly",
"tonemap",
"triangle",
+ "ts",
"ui",
},
materials = {
diff --git a/intermediate/surface.glsl b/intermediate/surface.glsl
index 71a4307..82bf2f6 100644
--- a/intermediate/surface.glsl
+++ b/intermediate/surface.glsl
@@ -29,6 +29,9 @@ type: vec2
name: uv
type: vec2
[interpolator]
+name: screen
+type: vec4
+[interpolator]
name: position
type: vec4
[interpolator]
@@ -114,7 +117,7 @@ dimension: cube
[texture]
name: shadowmaps
stage: fragment
-dimension: shadowArray
+dimension: array
[target]
name: colour
@@ -133,7 +136,9 @@ void main() {
interpolator.uv = uv;
interpolator.position = pos;
interpolator.tbn = mat3(t, b, n);
- gl_Position = c_vp.view_projection * pos;
+ pos = c_vp.view_projection * pos;
+ interpolator.screen = pos;
+ gl_Position = pos;
}
#endif
@@ -170,54 +175,10 @@ float specular_brdf(vec2 uv, vec3 ref, vec3 l, vec3 v, vec3 n) {
return (D * F * G) / (4.0 * ndl * ndv + 0.001);
}
-vec2 poissonDisk[16] = vec2[](
- vec2(-0.94201624, -0.39906216),
- vec2(0.94558609, -0.76890725),
- vec2(-0.094184101, -0.92938870),
- vec2(0.34495938, 0.29387760),
- vec2(-0.91588581, 0.45771432),
- vec2(-0.81544232, -0.87912464),
- vec2(-0.38277543, 0.27676845),
- vec2(0.97484398, 0.75648379),
- vec2(0.44323325, -0.97511554),
- vec2(0.53742981, -0.47373420),
- vec2(-0.26496911, -0.41893023),
- vec2(0.79197514, 0.19090188),
- vec2(-0.24188840, 0.99706507),
- vec2(-0.81409955, 0.91437590),
- vec2(0.19984126, 0.78641367),
- vec2(0.14383161, -0.14100790)
-);
-
-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(Light l, 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[l.caster_id];
- vec4 surf = caster.projection * 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)) % 16;
- vec2 coord = surf.xy + poissonDisk[index] * m;
- vec4 vec = vec4(coord, float(l.caster_id), surf.z);
- d += texture(shadowmaps, vec).r * w;
- }
- return d;
-}
-
void main() {
int i;
vec2 uv = interpolator.uv;
+ vec2 suv = (interpolator.screen.xy / interpolator.screen.w) * 0.5 + 0.5;
vec3 p = interpolator.position.xyz;
vec3 nrmsample = texture(normal, uv).rgb;
@@ -251,9 +212,7 @@ void main() {
spec_col *
specular_brdf(uv, ref, light_dir, view_dir, nrm) *
cos_theta_i;
- float shadow = 1.0f;
- if (l.caster_id >= 0)
- shadow = get_shadow(l, p);
+ float shadow = texture(shadowmaps, vec3(suv, float(l.caster_id))).r;
light += (diffuse + spec) * l.brightness * l.colour * shadow;
}
diff --git a/intermediate/ts.glsl b/intermediate/ts.glsl
new file mode 100644
index 0000000..23195f6
--- /dev/null
+++ b/intermediate/ts.glsl
@@ -0,0 +1,148 @@
+#ifdef DESC
+[program]
+type: graphics
+vertex: main
+fragment: main
+#endif
+
+#include "forward.h"
+
+#ifdef DESC
+
+[binding]
+name: verts
+rate: vertex
+[attribute]
+name: position
+type: vec2
+[attribute]
+name: uv
+type: vec2
+
+[interpolator]
+name: uv
+type: vec2
+
+[texture]
+name: shadowmaps
+stage: fragment
+dimension: shadowArray
+[texture]
+name: previous
+stage: fragment
+dimension: 2
+[texture]
+name: depthmap
+stage: fragment
+dimension: 2
+
+[struct]
+name: Config
+[variable]
+name: inv_view
+type: mat4
+[variable]
+name: inv_proj
+type: mat4
+[variable]
+name: prev_vp
+type: mat4
+
+[struct]
+name: Caster_Config
+[variable]
+name: index
+type: int
+
+[cbuffer]
+name: config
+type: Config
+stage: fragment
+
+[cbuffer]
+name: caster_config
+type: Caster_Config
+stage: fragment
+
+[sbuffer]
+name: casters
+type: Caster
+stage: fragment
+
+[target]
+name: shadow_amount
+type: float
+
+#endif
+
+#ifdef VERTEX_SHADER
+void main() {
+ interpolator.uv = uv;
+ gl_Position = vec4(position, 1.0, 1.0);
+}
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+vec2 poissonDisk[16] = vec2[](
+ vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790)
+);
+
+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) {
+ 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);
+ 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;
+ vec2 coord = surf.xy + poissonDisk[index] * m;
+ vec4 vec = vec4(coord, float(id), surf.z);
+ d += texture(shadowmaps, vec).r * w;
+ }
+ return d;
+}
+
+vec3 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;
+}
+
+void main() {
+ vec2 uv = interpolator.uv;
+ float d = texture(depthmap, uv).r;
+ vec3 wpos = get_world_pos(d, uv);
+ float prev = texture(previous, uv).r;
+ float current = get_shadow(caster_config.index, wpos);
+ shadow_amount = (prev + current) * 0.5;
+}
+#endif
diff --git a/lighting.cpp b/lighting.cpp
index 0e41ddd..4f1fdfb 100644
--- a/lighting.cpp
+++ b/lighting.cpp
@@ -20,7 +20,7 @@ struct GPU_Caster {
m4f projection;
};
-void Lighting::init(Device* dev) {
+void Lighting::init(Device* dev, int w, int h) {
int i;
Sampler_State ss{};
lights.init(
@@ -46,6 +46,9 @@ void Lighting::init(Device* dev) {
max_shadows,
0
);
+ zero(ss_shadows, sizeof ss_shadows);
+ zero(ss_shadow_slices, sizeof ss_shadow_slices);
+ recreate(dev, w, h);
for (i = 0; i < max_shadows; i++) {
cameras[i] = 0;
shadow_slices[i] = dev->alias_texture(
@@ -85,6 +88,50 @@ void Lighting::destroy(Device* dev, Renderer& r) {
r.destroy_camera(cameras[i]);
}
dev->destroy_texture(shadows);
+ destroy_ss(dev);
+}
+
+void Lighting::destroy_ss(Device* dev) {
+ int i, j;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < max_shadows; j++)
+ if (ss_shadow_slices[i][j])
+ dev->destroy_texture(ss_shadow_slices[i][j]);
+ if (ss_shadows[i])
+ dev->destroy_texture(ss_shadows[i]);
+ }
+}
+
+void Lighting::recreate(Device* dev, int w, int h) {
+ int i, j;
+ destroy_ss(dev);
+ for (i = 0; i < 2; i++) {
+ ss_shadows[i] = dev->create_texture(
+ "Shadow accumulation buffer",
+ texture_format_r8i,
+ Texture_Flags::sampleable | Texture_Flags::colour_target,
+ w,
+ h,
+ 1,
+ 1,
+ max_shadows,
+ 0
+ );
+ for (j = 0; j < max_shadows; j++)
+ ss_shadow_slices[i][j] = dev->alias_texture(
+ ss_shadows[i],
+ "Shadow accumulation buffer slice",
+ texture_format_r8i,
+ Texture_Flags::colour_target,
+ shadow_res,
+ shadow_res,
+ 1,
+ 1,
+ 1,
+ 0,
+ j
+ );
+ }
}
void Lighting::write_bufs(
diff --git a/lighting.hpp b/lighting.hpp
index ccd08d3..0d331d7 100644
--- a/lighting.hpp
+++ b/lighting.hpp
@@ -19,10 +19,14 @@ struct Lighting {
Staged_Buffer casters;
Texture_Id shadows;
Texture_Id shadow_slices[max_shadows];
+ Texture_Id ss_shadows[2];
+ Texture_Id ss_shadow_slices[2][max_shadows];
Sampler_Id shadow_sampler;
Camera_Id cameras[max_shadows];
int light_count, caster_count;
- void init(Device* dev);
+ 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);
void update(
Device* dev,
diff --git a/model.cpp b/model.cpp
index f24c0eb..5806655 100644
--- a/model.cpp
+++ b/model.cpp
@@ -388,7 +388,7 @@ void Model_Instance::render(
pb.shader(mesh.shader);
pb.sbuffer(mesh.light_binding, lighting->lights.gpuonly);
pb.sbuffer(mesh.casters_binding, lighting->casters.gpuonly);
- pb.texture(mesh.shadowmaps_binding, lighting->shadows, lighting->shadow_sampler);
+ pb.texture(mesh.shadowmaps_binding, res.shadows, res.sampler);
mesh.material->use(pb, res.sampler, dev->get_shader(mesh.shader));
pb.cbuffer(
mesh.mat_binding,
diff --git a/model.hpp b/model.hpp
index 7417e51..022ec27 100644
--- a/model.hpp
+++ b/model.hpp
@@ -97,6 +97,7 @@ struct Material_Loader : public Asset_Loader {
struct Model_Resources {
Texture_Id env_cubemap;
+ Texture_Id shadows;
Sampler_Id sampler;
Buffer_Id vp;
Buffer_Id globals;
diff --git a/renderer.cpp b/renderer.cpp
index d8c4895..ffc0a3c 100644
--- a/renderer.cpp
+++ b/renderer.cpp
@@ -5,10 +5,23 @@ extern "C" {
#include "memory.h"
}
+#include <string.h>
+
struct VP_Cbuffer {
m4f view_projection;
};
+struct TS_Cbuffer {
+ m4f inv_view;
+ m4f inv_proj;
+ m4f prev_vp;
+};
+
+struct TS_Caster_Config {
+ int index;
+ char pad[60];
+};
+
struct Global_Cbuffer {
v3f camera_pos;
int light_count;
@@ -36,7 +49,22 @@ void init_drawlist(
);
}
-void Renderer::init(Arena* arena, Device* d) {
+void Renderer::make_ts_sampler(Device* d) {
+ Sampler_State s{};
+ s.min = Filter_Mode::point;
+ s.mag = Filter_Mode::point;
+ s.mip = Filter_Mode::point;
+ s.address_u = Address_Mode::border;
+ s.address_v = Address_Mode::border;
+ s.border[0] = 0.0f;
+ ts_sampler = d->create_sampler("temporal shadow sampler", s);
+}
+
+void Renderer::init(
+ Arena* arena,
+ Device* d,
+ Asset_Arena& assets
+) {
int i;
auto id = [&](int did, int cap) {
init_drawlist(&drawlists[did], d, arena, cap);
@@ -52,6 +80,37 @@ void Renderer::init(Arena* arena, Device* d) {
sizeof(Global_Cbuffer),
Buffer_Flags::constant_buffer
);
+ ts_config.init(
+ d,
+ "Temporal shadow cbuffer",
+ sizeof(TS_Cbuffer),
+ Buffer_Flags::constant_buffer
+ );
+ ts_config2.init(
+ d,
+ "Temporal shadow casters",
+ sizeof(TS_Caster_Config) * Lighting::max_shadows,
+ Buffer_Flags::constant_buffer
+ );
+ quad.init(d);
+ ts_shader = (Shader*)assets.load("ts.csh");
+ ts_shadowmap_binding = ts_shader->descriptor_binding("shadowmaps");
+ ts_depthmap_binding = ts_shader->descriptor_binding("depthmap");
+ ts_prev_binding = ts_shader->descriptor_binding("previous");
+ ts_vert_binding = ts_shader->binding_index("verts");
+ ts_config_binding = ts_shader->descriptor_binding("config");
+ 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");
+ assert(ts_shadowmap_binding >= 0);
+ assert(ts_depthmap_binding >= 0);
+ assert(ts_prev_binding >= 0);
+ assert(ts_vert_binding >= 0);
+ assert(ts_config_binding >= 0);
+ assert(ts_caster_config_binding >= 0);
+ assert(ts_casters_binding >= 0);
+ assert(ts_globals_binding >= 0);
+ make_ts_sampler(d);
frame = 0;
}
@@ -60,6 +119,10 @@ void Renderer::destroy(Device* d) {
for (i = 0; i < drawlist_count; i++)
drawlists[i].vp.destroy(d);
globals.destroy(d);
+ ts_config.destroy(d);
+ ts_config2.destroy(d);
+ quad.destroy(d);
+ d->destroy_sampler(ts_sampler);
}
void Renderer::set_camera(Camera_Id cam, int drawlist) {
@@ -81,6 +144,7 @@ void Drawlist::render(
vpc->view_projection = cam.get_proj() * cam.get_view();
vp.unmap(dev);
vp.update(dev->get_ctx());
+ res.shadows = l->ss_shadows[r.frame & 1];
res.sampler = r.clamped_linear;
res.env_cubemap = r.env_cubemap;
res.vp = vp.gpuonly;
@@ -106,6 +170,67 @@ void Renderer::update_globals(
globals.update(ctx);
}
+void Renderer::temporal_shadows(
+ Device* dev,
+ Context& ctx,
+ const Lighting* l,
+ Pipeline_Builder& pb
+) {
+ 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);
+ for (i = 0; i < c; i++) {
+ casters[i].index = i;
+ }
+ cbuf->inv_view = cam.get_view().inverse();
+ cbuf->inv_proj = cam.get_proj().inverse();
+ ts_config.unmap(dev);
+ ts_config2.unmap(dev);
+ ctx.debug_push("temporal shadows");
+ ts_config.update(ctx);
+ ts_config2.update(ctx);
+ for (i = 0; i < c; i++) {
+ int ind = frame & 1;
+ auto& pass = pb
+ .begin_rp()
+ .rp_target(l->ss_shadow_slices[ind][i], Clear_Mode::discard)
+ .build_rp();
+ auto& pip = pb
+ .begin()
+ .shader(ts_shader->id)
+ .vertex_format(ts_shader->vf)
+ .texture(
+ ts_shadowmap_binding,
+ l->shadows,
+ l->shadow_sampler)
+ .texture(
+ ts_prev_binding,
+ l->ss_shadow_slices[!ind][i],
+ ts_sampler)
+ .texture(
+ ts_depthmap_binding,
+ dev->get_depth_target(),
+ ts_sampler)
+ .cbuffer(ts_config_binding, ts_config.gpuonly)
+ .cbuffer(
+ ts_caster_config_binding,
+ ts_config2.gpuonly,
+ i * sizeof(TS_Caster_Config),
+ sizeof(TS_Caster_Config))
+ .cbuffer(ts_globals_binding, globals.gpuonly)
+ .sbuffer(ts_casters_binding, l->casters.gpuonly)
+ .build();
+ quad.render(
+ ctx,
+ pip,
+ pass,
+ ts_vert_binding
+ );
+ }
+ ctx.debug_pop();
+}
+
void Renderer::render(
Device* dev,
Arena* a, Texture_Id hdr_target,
@@ -154,6 +279,8 @@ void Renderer::render(
}
ctx.debug_pop();
+ temporal_shadows(dev, ctx, l, pb);
+
ctx.debug_push("forward");
drawlists[FORWARD].render(*this, dev, a, l, forward_pass, 0);
ctx.debug_pop();
@@ -210,3 +337,54 @@ void Renderer::setcam(int did, Camera_Id cam) {
assert(cam.index);
drawlists[did].camera = cam;
}
+
+void Fullscreen_Quad::init(Device* d) {
+ float verts[] = {
+ -1.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, 3.0f, 0.0f, 2.0f,
+ 3.0f, -1.0f, 2.0f, 0.0f
+ };
+ Buffer_Id stage;
+ void* mem;
+ stage = d->create_buffer(
+ "sky vb stage",
+ sizeof verts,
+ Buffer_Flags::cpu_readwrite |
+ Buffer_Flags::copy_src
+ );
+ mem = d->map_buffer(stage, 0, sizeof verts);
+ memcpy(mem, verts, sizeof verts);
+ d->unmap_buffer(stage);
+ vb = d->create_buffer(
+ "fullscreen quad",
+ sizeof verts,
+ Buffer_Flags::copy_dst |
+ Buffer_Flags::vertex_buffer
+ );
+ Context& ctx = d->acquire();
+ ctx.copy(vb, stage);
+ d->submit(ctx);
+ d->destroy_bufferi(stage);
+}
+
+void Fullscreen_Quad::destroy(Device* d) {
+ d->destroy_buffer(vb);
+}
+
+void Fullscreen_Quad::render(
+ Context& ctx,
+ Pipeline& pip,
+ Render_Pass& pass,
+ int bind
+) {
+ Vertex_Buffer_Binding vbb[] = {{
+ .id = vb,
+ .offset = 0,
+ .target = bind
+ }, {}};
+ Draw draw{};
+ draw.verts = vbb;
+ draw.vertex_count = 3;
+ draw.instance_count = 1;
+ ctx.submit(draw, pip, pass);
+}
diff --git a/renderer.hpp b/renderer.hpp
index c49c804..46f5331 100644
--- a/renderer.hpp
+++ b/renderer.hpp
@@ -12,6 +12,7 @@ enum {
SHADOW_MAP_END = SHADOW_MAP_START + Lighting::max_shadows,
drawlist_count = SHADOW_MAP_END };
+struct Asset_Arena;
struct Model_Instance;
struct Renderer;
@@ -32,26 +33,59 @@ struct Drawlist {
);
};
+struct Fullscreen_Quad {
+ Buffer_Id vb;
+
+ void init(Device* d);
+ void destroy(Device* d);
+ void render(
+ Context& ctx,
+ Pipeline& pip,
+ Render_Pass& pass,
+ int bind
+ );
+};
+
struct Renderer {
static constexpr int max_cameras = 16;
Hash_Map<Camera_Id, Camera, max_cameras> cameras;
Drawlist drawlists[drawlist_count];
Staged_Buffer globals;
+ Fullscreen_Quad quad;
int camera_count;
int frame;
+ Shader* ts_shader;
+ int ts_shadowmap_binding;
+ int ts_depthmap_binding;
+ int ts_prev_binding;
+ int ts_vert_binding;
+ int ts_config_binding;
+ int ts_caster_config_binding;
+ int ts_casters_binding;
+ int ts_globals_binding;
+ Sampler_Id ts_sampler;
+ Staged_Buffer ts_config, ts_config2;
+
Sampler_Id clamped_linear;
Texture_Id env_cubemap;
- void init(Arena* arena, Device* d);
+ void init(Arena* arena, Device* d, Asset_Arena& assets);
void destroy(Device* d);
void set_camera(Camera_Id cam, int drawlist);
+ void make_ts_sampler(Device* d);
void render(
Device* dev,
Arena* a,
Texture_Id hdr_target,
const Lighting* l
);
+ void temporal_shadows(
+ Device* dev,
+ Context& ctx,
+ const Lighting* l,
+ Pipeline_Builder& pb
+ );
void add_model(int drawlist, Model_Instance* m);
void rem_model(int drawlist, Model_Instance* m);
diff --git a/video.cpp b/video.cpp
index fa98813..28df58b 100644
--- a/video.cpp
+++ b/video.cpp
@@ -1386,7 +1386,7 @@ void Device_Vk::create_depth(int w, int h) {
destroy_texture(depth);
depth = create_texture(
"default depth",
- texture_format_d24s8,
+ texture_format_d32,
Texture_Flags::sampleable | Texture_Flags::depth_stencil_target,
w,
h,