summaryrefslogtreecommitdiff
path: root/c2.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2025-01-06 22:05:05 +1100
committerquou <quou@disroot.org>2025-01-06 22:07:10 +1100
commitce6efd3b28b5cec813c715a57a884199fa3b3ce1 (patch)
tree239e6e9b4b376f9b2cc294d564f69ae0e501e778 /c2.cpp
parent1006ccf490c473447498a5c1a290e4dd9b55b7c2 (diff)
environment mapping
Diffstat (limited to 'c2.cpp')
-rw-r--r--c2.cpp176
1 files changed, 173 insertions, 3 deletions
diff --git a/c2.cpp b/c2.cpp
index 0c231eb..5268117 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -230,10 +230,34 @@ struct Sky {
Sampler_Id sampler,
const Camera& cam
) {
+ Texture_Id backbuffer_id = d->get_backbuffer();
+ Texture& backbuffer = d->get_texture(backbuffer_id);
Cbuffer* cb = (Cbuffer*)config.map(d);
cb->iview = cam.get_view().inverse();
cb->iprojection = cam.get_proj().inverse();
config.unmap(d);
+ render_imp(
+ d,
+ a,
+ pass,
+ sampler,
+ config.gpuonly,
+ 0,
+ backbuffer.w,
+ backbuffer.h
+ );
+ }
+
+ void render_imp(
+ Device* d,
+ Arena* a,
+ Render_Pass& pass,
+ Sampler_Id sampler,
+ Buffer_Id cbuffer,
+ int offset,
+ int w,
+ int h
+ ) {
Context& ctx = d->get_ctx();
Pipeline_Builder pb(a, d);
pb.begin();
@@ -244,7 +268,9 @@ struct Sky {
texture,
sampler
);
- pb.cbuffer(cfg_binding, config.gpuonly);
+ pb.viewport(0, 0, w, h);
+ pb.scissor(0, 0, w, h);
+ pb.cbuffer(cfg_binding, cbuffer, offset, sizeof(Cbuffer));
pb.depth(true, false, Depth_Mode::equal);
Pipeline& pip = pb.build();
@@ -263,6 +289,143 @@ struct Sky {
}
};
+struct Env_Probe {
+ Texture_Id cubemap;
+ Texture_Id cubemap_depth;
+ Texture_Id faces[6];
+ Sampler_Id sampler;
+ int cubemap_res;
+ Staged_Buffer config;
+
+ void init(Device* dev, Asset_Arena* assets, int res) {
+ int i;
+ Sampler_State s{};
+ cubemap_res = res;
+ s.min = Filter_Mode::linear;
+ s.mag = Filter_Mode::linear;
+ s.address_u = Address_Mode::repeat;
+ s.address_v = Address_Mode::repeat;
+ sampler = dev->create_sampler("env probe sampler", s);
+ cubemap_depth = dev->create_texture(
+ "env cubemap depth",
+ texture_format_d16,
+ Texture_Flags::sampleable | Texture_Flags::depth_stencil_target,
+ res,
+ res,
+ 1,
+ 1,
+ 1,
+ 0
+ );
+ cubemap = dev->create_texture(
+ "env cubemap",
+ texture_format_rgba16f,
+ Texture_Flags::cubemap |
+ Texture_Flags::colour_target |
+ Texture_Flags::sampleable,
+ res,
+ res,
+ 1,
+ 1,
+ 1,
+ Buffer_Id(0)
+ );
+ for (i = 0; i < 6; i++) {
+ faces[i] = dev->alias_texture(
+ cubemap,
+ "env cubemap face",
+ texture_format_rgba16f,
+ Texture_Flags::colour_target |
+ Texture_Flags::sampleable,
+ res,
+ res,
+ 1,
+ 1,
+ 1,
+ 0,
+ i
+ );
+ }
+ config.init(
+ dev,
+ "env probe sky cbuffer",
+ sizeof(Sky::Cbuffer) * 6,
+ Buffer_Flags::constant_buffer
+ );
+ }
+
+ void destroy(Device* dev) {
+ int i;
+ for (i = 0; i < 6; i++) {
+ dev->destroy_texture(faces[i]);
+ }
+ dev->destroy_texture(cubemap_depth);
+ dev->destroy_sampler(sampler);
+ dev->destroy_texture(cubemap);
+ config.destroy(dev);
+ }
+
+ void update_cbuffer(Device* dev) {
+ int i;
+ Context& ctx = dev->get_ctx();
+ Sky::Cbuffer* bufs = (Sky::Cbuffer*)config.map(dev);
+ m4f iproj = m4f::pers(
+ 90.0f,
+ 1.0f,
+ 0.1f,
+ 1000.0f
+ ).inverse();
+ v3f dirs[] = {
+ v3f( 1.0f, 0.0f, 0.0f),
+ v3f(-1.0f, 0.0f, 0.0f),
+ v3f( 0.0f, 1.0f, 0.0f),
+ v3f( 0.0f, -1.0f, 0.0f),
+ v3f( 0.0f, 0.0f, -1.0f),
+ v3f( 0.0f, 0.0f, 1.0f)
+ };
+ v3f ups[] = {
+ v3f(0.0f, 1.0f, 0.0f),
+ v3f(0.0f, 1.0f, 0.0f),
+ v3f(0.0f, 0.0f, 1.0f),
+ v3f(0.0f, 0.0f, -1.0f),
+ v3f(0.0f, 1.0f, 0.0f),
+ v3f(0.0f, 1.0f, 0.0f)
+ };
+ for (i = 0; i < 6; i++) {
+ Sky::Cbuffer& buf = bufs[i];
+ m4f view = m4f::lookat(v3f(0.0f), dirs[i], ups[i]);
+ buf.iview = view.inverse();
+ buf.iprojection = iproj;
+ }
+ config.unmap(dev);
+ config.update(ctx);
+ }
+
+ void render(Device* dev, Arena* a, Sky& sky) {
+ int i;
+ Pipeline_Builder pb(a, dev);
+ Context& ctx = dev->get_ctx();
+ update_cbuffer(dev);
+ for (i = 0; i < 6; i++) {
+ ctx.transition(faces[i], Resource_State::render_target);
+ pb.begin_rp();
+ pb.rp_target(faces[i], Clear_Mode::discard);
+ pb.rp_depth_target(cubemap_depth, 1.0f);
+ sky.render_imp(
+ dev,
+ a,
+ pb.build_rp(),
+ sampler,
+ config.gpuonly,
+ i * sizeof(Sky::Cbuffer),
+ cubemap_res,
+ cubemap_res
+ );
+ ctx.transition(faces[i], Resource_State::shader_read);
+ }
+ }
+};
+
struct Config_Buffer {
float offset[2];
};
@@ -286,6 +449,7 @@ extern "C" int entrypoint() {
Model_Scene scene;
Orbit_Cam camera;
Sky sky;
+ Env_Probe eprobe;
Buffer_Id vbo, cbuf;
Sampler_Id clamped_linear;
C2* app = App::create<C2>("c2");
@@ -350,6 +514,7 @@ extern "C" int entrypoint() {
(Model*)assets.load("monkey.mdl")
);
sky.init(dev, &assets);
+ eprobe.init(dev, &assets, 256);
camera.init();
while (app->running) {
Arena frame_arena;
@@ -428,6 +593,10 @@ extern "C" int entrypoint() {
pb.rp_depth_target(dev->get_depth_target(), Clear_Mode::restore);
Render_Pass& sky_pass = pb.build_rp();
+ ctx.debug_push("environment cube");
+ eprobe.render(dev, &frame_arena, sky);
+ ctx.debug_pop();
+
Texture& bb = dev->get_texture(dev->get_backbuffer());
monkey->transform = m4f::translate(
m4f::identity(),
@@ -450,10 +619,10 @@ extern "C" int entrypoint() {
scene.update(camera, dev);
ctx.debug_push("scene");
ctx.debug_push("depth prepass");
- scene.render(dev, &frame_arena, depth_prepass, clamped_linear);
+ scene.render(dev, &frame_arena, depth_prepass, 0, clamped_linear);
ctx.debug_pop();
ctx.debug_push("forward");
- scene.render(dev, &frame_arena, pass2, clamped_linear);
+ scene.render(dev, &frame_arena, pass2, eprobe.cubemap, clamped_linear);
ctx.debug_pop();
ctx.debug_pop();
@@ -479,6 +648,7 @@ extern "C" int entrypoint() {
}
scene.destroy(dev);
sky.destroy(dev);
+ eprobe.destroy(dev);
ui->destroy();
assets.destroy();
dev->destroy_texture(default_texture);