summaryrefslogtreecommitdiff
path: root/src/gpu/effects
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/effects')
-rw-r--r--src/gpu/effects/shader_composer.cc33
-rw-r--r--src/gpu/effects/shader_composer.h23
-rw-r--r--src/gpu/effects/shaders.cc81
3 files changed, 137 insertions, 0 deletions
diff --git a/src/gpu/effects/shader_composer.cc b/src/gpu/effects/shader_composer.cc
new file mode 100644
index 0000000..61da6e6
--- /dev/null
+++ b/src/gpu/effects/shader_composer.cc
@@ -0,0 +1,33 @@
+// This file is part of the 64k demo project.
+// It implements the ShaderComposer class.
+
+#include "gpu/effects/shader_composer.h"
+#include <sstream>
+
+ShaderComposer& ShaderComposer::Get() {
+ static ShaderComposer instance;
+ return instance;
+}
+
+void ShaderComposer::RegisterSnippet(const std::string& name, const std::string& code) {
+ snippets_[name] = code;
+}
+
+std::string ShaderComposer::Compose(const std::vector<std::string>& dependencies, const std::string& main_code) {
+ std::stringstream ss;
+ ss << "// Generated by ShaderComposer\n\n";
+
+ for (const auto& dep : dependencies) {
+ auto it = snippets_.find(dep);
+ if (it != snippets_.end()) {
+ ss << "// --- Snippet: " << dep << " ---\n";
+ ss << it->second << "\n";
+ }
+ }
+
+ ss << "// --- Main Code ---\n";
+ ss << main_code;
+
+ return ss.str();
+}
+
diff --git a/src/gpu/effects/shader_composer.h b/src/gpu/effects/shader_composer.h
new file mode 100644
index 0000000..7d918a9
--- /dev/null
+++ b/src/gpu/effects/shader_composer.h
@@ -0,0 +1,23 @@
+// This file is part of the 64k demo project.
+// It defines the ShaderComposer class for managing WGSL snippets.
+
+#pragma once
+
+#include <string>
+#include <map>
+#include <vector>
+
+class ShaderComposer {
+public:
+ static ShaderComposer& Get();
+
+ // Register a snippet (e.g. "common_math", "sdf_primitives")
+ void RegisterSnippet(const std::string& name, const std::string& code);
+
+ // Assemble a final shader string by prepending required snippets
+ std::string Compose(const std::vector<std::string>& dependencies, const std::string& main_code);
+
+private:
+ ShaderComposer() = default;
+ std::map<std::string, std::string> snippets_;
+};
diff --git a/src/gpu/effects/shaders.cc b/src/gpu/effects/shaders.cc
index ac0bba9..6d86d2b 100644
--- a/src/gpu/effects/shaders.cc
+++ b/src/gpu/effects/shaders.cc
@@ -3,6 +3,87 @@
#include "../demo_effects.h"
+#include "gpu/effects/shader_composer.h"
+
+void InitShaderComposer() {
+ auto& sc = ShaderComposer::Get();
+
+ sc.RegisterSnippet("common_uniforms", R"(
+struct GlobalUniforms {
+ view_proj: mat4x4<f32>,
+ camera_pos_time: vec4<f32>,
+ params: vec4<f32>,
+};
+struct ObjectData {
+ model: mat4x4<f32>,
+ inv_model: mat4x4<f32>,
+ color: vec4<f32>,
+ params: vec4<f32>,
+};
+struct ObjectsBuffer {
+ objects: array<ObjectData>,
+};
+)");
+
+ sc.RegisterSnippet("sdf_primitives", R"(
+fn sdSphere(p: vec3<f32>, r: f32) -> f32 {
+ return length(p) - r;
+}
+fn sdBox(p: vec3<f32>, b: vec3<f32>) -> f32 {
+ let q = abs(p) - b;
+ return length(max(q, vec3<f32>(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0);
+}
+fn sdTorus(p: vec3<f32>, t: vec2<f32>) -> f32 {
+ let q = vec2<f32>(length(p.xz) - t.x, p.y);
+ return length(q) - t.y;
+}
+fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
+ return dot(p, n) + h;
+}
+ sc.RegisterSnippet("lighting", R"(
+fn get_normal_basic(p: vec3<f32>, obj_type: f32) -> vec3<f32> {
+ if (obj_type == 1.0) { return normalize(p); }
+ let e = vec2<f32>(0.001, 0.0);
+ return normalize(vec3<f32>(
+ get_dist(p + e.xyy, obj_type) - get_dist(p - e.xyy, obj_type),
+ get_dist(p + e.yxy, obj_type) - get_dist(p - e.yxy, obj_type),
+ get_dist(p + e.yyx, obj_type) - get_dist(p - e.yyx, obj_type)
+ ));
+}
+
+fn calc_shadow(ro: vec3<f32>, rd: vec3<f32>, tmin: f32, tmax: f32, skip_idx: u32) -> f32 {
+ var res = 1.0;
+ var t = tmin;
+ if (t < 0.05) { t = 0.05; }
+ for (var i = 0; i < 32; i = i + 1) {
+ let h = map_scene(ro + rd * t, skip_idx);
+ if (h < 0.001) { return 0.0; }
+ res = min(res, 16.0 * h / t);
+ t = t + clamp(h, 0.02, 0.4);
+ if (t > tmax) { break; }
+ }
+ return clamp(res, 0.0, 1.0);
+}
+ sc.RegisterSnippet("ray_box", R"(
+struct RayBounds {
+ t_entry: f32,
+ t_exit: f32,
+ hit: bool,
+};
+
+fn ray_box_intersection(ro: vec3<f32>, rd: vec3<f32>, extent: vec3<f32>) -> RayBounds {
+ let inv_rd = 1.0 / rd;
+ let t0 = (-extent - ro) * inv_rd;
+ let t1 = (extent - ro) * inv_rd;
+ let tmin_vec = min(t0, t1);
+ let tmax_vec = max(t0, t1);
+ let t_entry = max(0.0, max(tmin_vec.x, max(tmin_vec.y, tmin_vec.z)));
+ let t_exit = min(tmax_vec.x, min(tmax_vec.y, tmax_vec.z));
+ return RayBounds(t_entry, t_exit, t_entry <= t_exit);
+}
+)");
+}
+
const char* main_shader_wgsl = R"(
struct Uniforms {
audio_peak: f32,