kale, magnifying glass

This commit is contained in:
Hopeless Tyromancy 2026-05-13 10:33:28 -04:00
parent 6302d79dec
commit 4cb25b7757
14 changed files with 135 additions and 449 deletions

BIN
demo.mp4

Binary file not shown.

View File

@ -7,6 +7,6 @@ Pos=92,127
Size=195,279 Size=195,279
[Window][Kale Renderer] [Window][Kale Renderer]
Pos=60,60 Pos=62,56
Size=181,242 Size=181,242

View File

@ -5,15 +5,12 @@ layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D screen; layout(set = 2, binding = 0) uniform sampler2D screen;
layout(std140, set = 3, binding = 0) uniform UniformBlock { layout(std140, set = 3, binding = 0) uniform UniformBlock {
mat4 model; vec2 cam_pos;
mat4 view;
mat4 proj;
mat4 inv_view;
mat4 inv_proj;
vec4 cam_pos;
float time; float time;
float aspect;
int post_mode; int post_mode;
vec2 atlas_adjust; float zoom;
float radius;
}; };
float t(float x, float y) { return length(texture(screen, vec2(x, y)).xyz); } float t(float x, float y) { return length(texture(screen, vec2(x, y)).xyz); }
@ -83,7 +80,6 @@ void main() {
out_color = vec4(dither()); out_color = vec4(dither());
break; break;
} }
return;
out_color = out_color * 0.9 + out_color = out_color * 0.9 +
0.1*((t(uv.x, uv.y) > 0.01)? 0.1*((t(uv.x, uv.y) > 0.01)?

View File

@ -1,105 +1,30 @@
#version 450 #version 450
layout(location = 0) in vec2 uv; layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 out_color; layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D screen; layout(set = 2, binding = 0) uniform sampler2D sprites;
layout(set = 2, binding = 1) uniform sampler2D depth_tex;
layout(std140, set = 3, binding = 0) uniform UniformBlock { layout(std140, set = 3, binding = 0) uniform UniformBlock {
mat4 model; vec2 cam_pos;
mat4 view;
mat4 proj;
mat4 inv_view;
mat4 inv_proj;
vec4 cam_pos;
float time; float time;
float aspect;
int post_mode; int post_mode;
vec2 atlas_adjust; float zoom;
float radius;
}; };
const int MAX_MARCH_STEPS = 64;
const float EPS_DIST = 1e-6;
float sdf(vec3 point) {
vec3 p = point - cam_pos.xyz;
const float speed = 1.0 + exp(sin(time));
float t = speed * time;
const int N = 5;
float d = 1.0/EPS_DIST;
float orbit_radius = 0.4;
float radius = 0.03;
for(int i = 0; i < N; i++) {
float phase = ((3.14159 * 2.0) / float(N)) * float(i);
d = min(d, length(p - orbit_radius*vec3(sin(t + phase), 0.0, cos(t + phase))) - radius);
}
return d;
}
vec3 getnormal(vec3 p) {
float e = EPS_DIST;
return normalize(vec3(
sdf(p + vec3(e, 0.0, 0.0)) - sdf(p - vec3(e, 0.0, 0.0)),
sdf(p + vec3(0.0, e, 0.0)) - sdf(p - vec3(0.0, e, 0.0)),
sdf(p + vec3(0.0, 0.0, e)) - sdf(p - vec3(0.0, 0.0, e))
));
}
vec4 march(vec3 point, vec3 ray, float max_depth) {
float totaldist = 0.0;
int i;
for (i = 0; i < MAX_MARCH_STEPS && totaldist < max_depth; i += 1) {
float h = sdf(point);
if (h < EPS_DIST) {
totaldist += h;
return vec4(point, totaldist);
}
totaldist += h;
if (totaldist > max_depth)
break;
point += h * ray;
}
return vec4(-1.0);
}
vec3 camray() {
vec2 ndc = uv * 2.0 - 1.0;
ndc.y = -ndc.y;
vec4 view_pos = inv_proj * vec4(ndc, 1.0, 1.0);
view_pos /= view_pos.w;
return normalize((inv_view * vec4(normalize(view_pos.xyz), 0.0)).xyz);
}
vec4 kernel(float max_depth) {
max_depth = (max_depth > 0.0)? max_depth : 1000.0;
vec3 cam_ray = camray();
return march(cam_pos.xyz, cam_ray, max_depth);
}
float linearize_depth(vec2 uv) {
float d = texture(depth_tex, uv).r;
vec4 ndc = vec4(uv * 2.0 - 1.0, d * 2.0 - 1.0, 1.0);
vec4 view_pos = inv_proj * ndc;
view_pos /= view_pos.w;
return -view_pos.z; // view space, positive distance
}
void main() { void main() {
float max_depth = linearize_depth(uv); vec2 uv = 2.0 * v_uv - vec2(1.0);
vec4 hit = kernel(max_depth); uv.y *= -1.0;
uv.x *= aspect;
if (hit.w > 0.0) { float l = length(uv);
out_color = vec4(1.0);//out_color = vec4(getnormal(hit.xyz), 1.0); if(l < radius) {
} else { uv /= zoom;
out_color = texture(screen, uv);
} }
vec4 bg = texture(sprites, uv + cam_pos * 0.01);
out_color = bg;
} }

View File

@ -1,24 +0,0 @@
#version 460
layout(location = 0) in vec4 v_color;
layout(location = 1) in vec2 v_uv;
layout(location = 2) in vec3 v_normal_vs;
layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D atlas;
void main() {
vec3 light_dir = normalize(vec3(0.5, 1.0, 0.8));
float ambient = 0.2;
float diffuse = max(dot(v_normal_vs, light_dir), 0.0);
float lighting = ambient + (1.0 - ambient) * diffuse;
vec2 uv = vec2(v_uv.x, 1.0-v_uv.y);
out_color = texture(atlas, uv);// + v_color;
//out_color = v_color * vec4(v_normal_vs,1.0);
//out_color = vec4(v_color.rgb * lighting, v_color.a);
//out_color = vec4(1.0);
//out_color = vec4(viz(v_normal_vs), 1.0);
//out_color = vec4(lighting);
}

View File

@ -1,29 +0,0 @@
#version 460
layout(location = 0) in vec3 a_pos;
layout(location = 1) in vec2 a_uv;
layout(location = 2) in vec3 a_normal;
layout(location = 0) out vec4 v_color;
layout(location = 1) out vec2 v_uv;
layout(location = 2) out vec3 v_normal_vs; // view-space normal
layout(std140, set = 1, binding = 0) uniform UniformBlock {
mat4 model;
mat4 view;
mat4 proj;
mat4 inv_view;
mat4 inv_proj;
vec4 cam_pos;
float time;
int post_mode;
vec2 atlas_adjust;
};
void main() {
vec4 view_pos = view * model * vec4(a_pos, 1.0);
gl_Position = proj * view_pos;
v_color = vec4(a_uv, abs(sin(a_uv.x*a_uv.y)), 1.0);
v_uv = a_uv*atlas_adjust;
v_normal_vs = normalize(a_normal);
}

View File

@ -2,7 +2,6 @@
#include <SDL3/SDL_gamepad.h> #include <SDL3/SDL_gamepad.h>
#include <iostream> #include <iostream>
/* /*
I bought a very cheap ps4 knockoff controller and for some reason I bought a very cheap ps4 knockoff controller and for some reason
AXIS_RIGHTX and AXIS_RIGHTY are swapped with the triggers? AXIS_RIGHTX and AXIS_RIGHTY are swapped with the triggers?
@ -10,75 +9,62 @@
*/ */
#define WEIRD_JOYSTICK_BEHAVIOR 1 #define WEIRD_JOYSTICK_BEHAVIOR 1
vec3 Camera::dir() const {
return normalize(vec3(
cos(radians(yaw)) * cos(radians(pitch)),
sin(radians(pitch)),
sin(radians(yaw)) * cos(radians(pitch))
));
}
void Camera::update() { void Camera::update() {
if (look_up) pitch += look_speed; float speed = move_speed * (shifted ? 2.0f : 1.0f);
if (look_down) pitch -= look_speed; if(zoom >= 1.0f) {
if (look_left) yaw -= look_speed; speed /= zoom;
if (look_right) yaw += look_speed; }
pitch = clamp(pitch, -89.0f, 89.0f);
vec3 d = dir(); if (move_left) pos.x -= speed;
vec3 right = normalize(cross(d, up)); if (move_right) pos.x += speed;
target = pos + d; if (move_up) pos.y += speed;
if (move_down) pos.y -= speed;
float shift_speed = shifted? 10.0 : 1.0;
float speed = move_speed * shift_speed;
if (move_forward) { pos += d * speed; target += d * speed; }
if (move_backward) { pos -= d * speed; target -= d * speed; }
if (move_left) { pos -= right * speed; target -= right * speed; }
if (move_right) { pos += right * speed; target += right * speed; }
if (move_up) { pos += up * speed; target += up * speed; }
if (move_down) { pos -= up * speed; target -= up * speed; }
} }
void Camera::on_key(SDL_Scancode scancode, bool pressed) { void Camera::on_key(SDL_Scancode scancode, bool pressed) {
switch (scancode) { switch (scancode) {
case SDL_SCANCODE_W: move_forward = pressed; break; case SDL_SCANCODE_W:
case SDL_SCANCODE_S: move_backward = pressed; break; case SDL_SCANCODE_UP:
case SDL_SCANCODE_A: move_left = pressed; break; move_up = pressed;
case SDL_SCANCODE_D: move_right = pressed; break; break;
case SDL_SCANCODE_SPACE: move_up = pressed; break; case SDL_SCANCODE_S:
case SDL_SCANCODE_LCTRL: move_down = pressed; break; case SDL_SCANCODE_DOWN:
case SDL_SCANCODE_UP: look_up = pressed; break; move_down = pressed;
case SDL_SCANCODE_DOWN: look_down = pressed; break; break;
case SDL_SCANCODE_LEFT: look_left = pressed; break; case SDL_SCANCODE_A:
case SDL_SCANCODE_RIGHT: look_right = pressed; break; case SDL_SCANCODE_LEFT:
move_left = pressed;
break;
case SDL_SCANCODE_D:
case SDL_SCANCODE_RIGHT:
move_right = pressed;
break;
case SDL_SCANCODE_LSHIFT: case SDL_SCANCODE_LSHIFT:
case SDL_SCANCODE_RSHIFT: case SDL_SCANCODE_RSHIFT:
shifted = pressed; shifted = pressed;
break; break;
default: break; default:
break;
} }
} }
#ifndef WEIRD_JOYSTICK_BEHAVIOR #ifndef WEIRD_JOYSTICK_BEHAVIOR
#define WEIRD_JOYSTICK_BEHAVIOR 0 #define WEIRD_JOYSTICK_BEHAVIOR 0
#endif #endif
static float normalize_stick(SDL_Gamepad* gamepad, SDL_GamepadAxis axis) { static float normalize_stick(SDL_Gamepad* gamepad, SDL_GamepadAxis axis) {
if(axis == SDL_GAMEPAD_AXIS_COUNT || axis == SDL_GAMEPAD_AXIS_INVALID) if (axis == SDL_GAMEPAD_AXIS_COUNT || axis == SDL_GAMEPAD_AXIS_INVALID)
return 0.0f; return 0.0f;
float d = static_cast<float>(SDL_GetGamepadAxis(gamepad, axis)); float d = static_cast<float>(SDL_GetGamepadAxis(gamepad, axis));
bool reported_trigger = (axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER); bool reported_trigger = (axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
bool really_trigger = (WEIRD_JOYSTICK_BEHAVIOR)? (axis == SDL_GAMEPAD_AXIS_RIGHTX || axis == SDL_GAMEPAD_AXIS_RIGHTY) : reported_trigger; bool really_trigger = (WEIRD_JOYSTICK_BEHAVIOR) ? (axis == SDL_GAMEPAD_AXIS_RIGHTX || axis == SDL_GAMEPAD_AXIS_RIGHTY) : reported_trigger;
float min = (reported_trigger)? 0 : SDL_JOYSTICK_AXIS_MIN; float min = (reported_trigger) ? 0 : SDL_JOYSTICK_AXIS_MIN;
float max = SDL_JOYSTICK_AXIS_MAX; float max = SDL_JOYSTICK_AXIS_MAX;
float n = (d - min) / (max - min); float n = (d - min) / (max - min);
return really_trigger? n : ((n - 0.5) * 2.0); return really_trigger ? n : ((n - 0.5) * 2.0);
} }
void Camera::on_gamepad(SDL_Gamepad* gamepad) { void Camera::on_gamepad(SDL_Gamepad* gamepad) {
@ -86,63 +72,43 @@ void Camera::on_gamepad(SDL_Gamepad* gamepad) {
float lx = normalize_stick(gamepad, SDL_GAMEPAD_AXIS_LEFTX); float lx = normalize_stick(gamepad, SDL_GAMEPAD_AXIS_LEFTX);
float ly = normalize_stick(gamepad, SDL_GAMEPAD_AXIS_LEFTY); float ly = normalize_stick(gamepad, SDL_GAMEPAD_AXIS_LEFTY);
float ry = normalize_stick(gamepad, (WEIRD_JOYSTICK_BEHAVIOR)? SDL_GAMEPAD_AXIS_RIGHT_TRIGGER : SDL_GAMEPAD_AXIS_RIGHTY); float rx = normalize_stick(gamepad, (WEIRD_JOYSTICK_BEHAVIOR) ? SDL_GAMEPAD_AXIS_LEFT_TRIGGER : SDL_GAMEPAD_AXIS_RIGHTX);
float rx = normalize_stick(gamepad, (WEIRD_JOYSTICK_BEHAVIOR)? SDL_GAMEPAD_AXIS_LEFT_TRIGGER : SDL_GAMEPAD_AXIS_RIGHTX);
static uint8_t frame = 0;
if(frame++ == 64) {
std::cout << "lx: " << lx << " ly: " << ly << " rx: " << rx << " ry: " << ry << std::endl;
}
//float lt = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) / 32767.0f; static uint8_t frame = 0;
//float rt = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) / 32767.0f; if (frame++ == 64) {
std::cout << "lx: " << lx << " ly: " << ly << " rx: " << rx << std::endl;
}
const float dead = 0.1f; const float dead = 0.1f;
if (abs(lx) < dead) lx = 0.0f; if (abs(lx) < dead) lx = 0.0f;
if (abs(ly) < dead) ly = 0.0f; if (abs(ly) < dead) ly = 0.0f;
if (abs(rx) < dead) rx = 0.0f; if (abs(rx) < dead) rx = 0.0f;
if (abs(ry) < dead) ry = 0.0f;
// if (lt < dead) lt = 0.0f;
// if (rt < dead) rt = 0.0f;
float speed = move_speed * (shifted ? 2.0f : 1.0f);
if(zoom >= 1.0f) {
speed /= zoom;
}
// look — right stick only // Move with left stick
yaw += rx * look_speed; pos.x += lx * speed;
pitch -= ry * look_speed; pos.y += ly * speed;
pitch = clamp(pitch, -89.0f, 89.0f);
// Rotation with right stick x-axis
vec3 d = dir(); rotation += rx * 2.0f;
vec3 right = normalize(cross(d, up));
float speed = move_speed * (shifted ? 4.0f : 1.0f);
// move — left stick
pos += d * (-ly * speed);
pos += right * ( lx * speed);
// up/down — triggers
//pos += up * (rt - lt) * speed;
target = pos + d;
shifted = SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); shifted = SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER);
} }
void Camera::on_mouse_motion(float dx, float dy) { void Camera::on_mouse_motion(float dx, float dy) {
yaw += dx * look_speed * 0.1f; // Not used in 2D mode
pitch -= dy * look_speed * 0.1f; (void)dx;
pitch = clamp(pitch, -89.0f, 89.0f); (void)dy;
} }
CameraUBO Camera::ubo(float aspect) const { CameraUBO Camera::ubo(float aspect) const {
mat4 v = lookAt(pos, target, up); return CameraUBO{
mat4 p = perspective(radians(fov), aspect, 0.01f, 1000.0f); .cam_pos = vec4(pos.x, pos.y, 5.0f, 1.0f),
return CameraUBO {
.model = mat4(1.0f),
.view = v,
.proj = p,
.inv_view = inverse(v),
.inv_proj = inverse(p),
.cam_pos = vec4(pos, 1.0),
.time = (float)SDL_GetTicks() / 1000.0f, .time = (float)SDL_GetTicks() / 1000.0f,
.aspect = aspect
}; };
} }

View File

@ -4,25 +4,15 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
struct Camera { struct Camera {
vec3 pos = vec3(0.0f, 0.0f, 2.0f); vec2 pos = vec2(0.0f, 0.0f);
vec3 target = vec3(0.0f, 0.0f, 0.0f); float zoom = 1.0f;
vec3 up = vec3(0.0f, 1.0f, 0.0f); float move_speed = 5.0f;
float fov = 60.0f; float rotation = 0.0f;
float move_speed = 0.5f;
float look_speed = 1.0f;
float pitch = 0.0f;
float yaw = -90.0f;
bool move_forward = false;
bool move_backward = false;
bool move_left = false; bool move_left = false;
bool move_right = false; bool move_right = false;
bool move_up = false; bool move_up = false;
bool move_down = false; bool move_down = false;
bool look_up = false;
bool look_down = false;
bool look_left = false;
bool look_right = false;
bool shifted = false; bool shifted = false;
void update(); void update();
@ -30,7 +20,4 @@ struct Camera {
void on_mouse_motion(float dx, float dy); void on_mouse_motion(float dx, float dy);
void on_gamepad(SDL_Gamepad* gamepad); void on_gamepad(SDL_Gamepad* gamepad);
CameraUBO ubo(float aspect) const; CameraUBO ubo(float aspect) const;
private:
vec3 dir() const;
}; };

View File

@ -62,6 +62,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) {
SDL_AppResult SDL_AppIterate(void* appstate) { SDL_AppResult SDL_AppIterate(void* appstate) {
(void)appstate; (void)appstate;
camera.zoom = renderer.zoom;
camera.on_gamepad(renderer.gamepad); camera.on_gamepad(renderer.gamepad);
camera.update(); camera.update();

View File

@ -3,78 +3,10 @@
#include "types.h" #include "types.h"
#include <iostream> #include <iostream>
void ScenePipeline::create(SDL_GPUDevice* dev, SDL_Window* win) {
vert = load_shader(dev, "shaders/scene.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX, 0, 1);
frag = load_shader(dev, "shaders/scene.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 0);
SDL_GPUVertexBufferDescription vert_buf {
.slot = 0,
.pitch = sizeof(Vertex),
.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
.instance_step_rate = 0,
};
SDL_GPUVertexAttribute attrs[3] = {
{ .location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0 },
{ .location = 1, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, .offset = (uint32_t)offsetof(Vertex, uv) },
{ .location = 2, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = (uint32_t)offsetof(Vertex, norm) },
};
SDL_GPUColorTargetDescription color_tgt {
.format = SDL_GetGPUSwapchainTextureFormat(dev, win),
.blend_state = {
.src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
.dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.color_blend_op = SDL_GPU_BLENDOP_ADD,
.src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
.dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.alpha_blend_op = SDL_GPU_BLENDOP_ADD,
.enable_blend = false,
}
};
SDL_GPUGraphicsPipelineCreateInfo info {
.vertex_shader = vert,
.fragment_shader = frag,
.vertex_input_state = {
.vertex_buffer_descriptions = &vert_buf,
.num_vertex_buffers = 1,
.vertex_attributes = attrs,
.num_vertex_attributes = sizeof(attrs)/sizeof(attrs[0]),
},
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
.rasterizer_state = {
.fill_mode = SDL_GPU_FILLMODE_FILL,
.cull_mode = SDL_GPU_CULLMODE_NONE,
.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE,
},
.depth_stencil_state = {
.compare_op = SDL_GPU_COMPAREOP_LESS,
.enable_depth_test = true,
.enable_depth_write = true,
},
.target_info = {
.color_target_descriptions = &color_tgt,
.num_color_targets = 1,
.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT,
.has_depth_stencil_target = true,
},
};
pipeline = SDL_CreateGPUGraphicsPipeline(dev, &info);
if (!pipeline)
std::cerr << "Scene pipeline failed: " << SDL_GetError() << std::endl;
}
void ScenePipeline::destroy(SDL_GPUDevice* dev) {
if (pipeline) SDL_ReleaseGPUGraphicsPipeline(dev, pipeline);
if (vert) SDL_ReleaseGPUShader(dev, vert);
if (frag) SDL_ReleaseGPUShader(dev, frag);
}
void RayPipeline::create(SDL_GPUDevice* dev, SDL_Window* win) { void RayPipeline::create(SDL_GPUDevice* dev, SDL_Window* win) {
vert = load_shader(dev, "shaders/ray.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0); vert = load_shader(dev, "shaders/ray.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0);
frag = load_shader(dev, "shaders/ray.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT, 2, 1); frag = load_shader(dev, "shaders/ray.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);
SDL_GPUColorTargetDescription color_tgt { SDL_GPUColorTargetDescription color_tgt {
.format = SDL_GetGPUSwapchainTextureFormat(dev, win), .format = SDL_GetGPUSwapchainTextureFormat(dev, win),

View File

@ -1,15 +1,6 @@
#pragma once #pragma once
#include <SDL3/SDL_gpu.h> #include <SDL3/SDL_gpu.h>
struct ScenePipeline {
SDL_GPUGraphicsPipeline* pipeline = nullptr;
SDL_GPUShader* vert = nullptr;
SDL_GPUShader* frag = nullptr;
void create(SDL_GPUDevice* dev, SDL_Window* win);
void destroy(SDL_GPUDevice* dev);
};
struct RayPipeline { struct RayPipeline {
SDL_GPUGraphicsPipeline* pipeline = nullptr; SDL_GPUGraphicsPipeline* pipeline = nullptr;
SDL_GPUShader* vert = nullptr; SDL_GPUShader* vert = nullptr;

View File

@ -17,6 +17,17 @@
#include "imgui_impl_sdlgpu3.h" #include "imgui_impl_sdlgpu3.h"
static uint64_t visit_grid[64];
uint64_t simple_rand(uint64_t *s){
static uint64_t state = 0xDEADBEEF;
const uint64_t taps = 0x1BULL;
uint8_t out = state & 1;
state >>= 1;
if(out) state ^= taps << 60;
return state;
}
extern int post_mode; extern int post_mode;
extern vec2 atlas_adjust; extern vec2 atlas_adjust;
@ -27,12 +38,9 @@ bool Renderer::init(SDL_Window* w) {
SDL_ClaimWindowForGPUDevice(dev, win); SDL_ClaimWindowForGPUDevice(dev, win);
printf("LOAD BIN?\n"); load_sprites();
load_bin();
printf("BIN LOADED\n");
render_sampler = create_linear_sampler(dev); SDL_GPUSamplerCreateInfo sprite_sampler_info {
SDL_GPUSamplerCreateInfo depth_sampler_info {
.min_filter = SDL_GPU_FILTER_NEAREST, .min_filter = SDL_GPU_FILTER_NEAREST,
.mag_filter = SDL_GPU_FILTER_NEAREST, .mag_filter = SDL_GPU_FILTER_NEAREST,
.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST,
@ -42,68 +50,49 @@ bool Renderer::init(SDL_Window* w) {
.enable_compare = false, .enable_compare = false,
}; };
depth_sampler = SDL_CreateGPUSampler(dev, &depth_sampler_info); atlas_sampler = SDL_CreateGPUSampler(dev, &sprite_sampler_info);
atlas_sampler = SDL_CreateGPUSampler(dev, &depth_sampler_info); render_sampler = create_linear_sampler(dev);
resize_render_texture(960, 540); resize_render_texture(960, 540);
setup_imgui(); setup_imgui();
fprintf(stderr, "Pipeline creation...."); fprintf(stderr, "Pipeline creation....");
scene.create(dev, win);
ray.create(dev, win); ray.create(dev, win);
post.create(dev, win); post.create(dev, win);
fprintf(stderr, "finished\n"); fprintf(stderr, "finished\n");
return scene.pipeline && ray.pipeline; return post.pipeline && ray.pipeline;
} }
void Renderer::destroy() { void Renderer::destroy() {
if (render_tex) SDL_ReleaseGPUTexture(dev, render_tex);
if (post_tex) SDL_ReleaseGPUTexture(dev, post_tex); if (post_tex) SDL_ReleaseGPUTexture(dev, post_tex);
if (render_sampler) SDL_ReleaseGPUSampler(dev, render_sampler); if (render_sampler) SDL_ReleaseGPUSampler(dev, render_sampler);
if (vert_buff) SDL_ReleaseGPUBuffer(dev, vert_buff); if (vert_buff) SDL_ReleaseGPUBuffer(dev, vert_buff);
if (depth_tex) SDL_ReleaseGPUTexture(dev, depth_tex); if (atlas_tex) SDL_ReleaseGPUTexture(dev, atlas_tex);
if (gamepad) SDL_CloseGamepad(gamepad); if (gamepad) SDL_CloseGamepad(gamepad);
scene.destroy(dev);
ray.destroy(dev); ray.destroy(dev);
post.destroy(dev); post.destroy(dev);
SDL_DestroyGPUDevice(dev); SDL_DestroyGPUDevice(dev);
} }
bool Renderer::load_bin() { bool Renderer::load_sprites() {
const char* path = "assets/bin/hl1.bin";
const char* tex_path = "assets/bin/hl1.bin.png"; const char* tex_path = "assets/bin/hl1.bin.png";
/*if(!std::filesystem::exists(path) || !std::filesystem::exists(tex_path)) {
SDL_Log("Failed to find %s (or maybe %s)", path, tex_path);
return false;
}*/
size_t bin_size;
const uint8_t* bin_data = (uint8_t*)SDL_LoadFile(path, &bin_size);
if(!bin_data) {
SDL_Log("Failed to read %s %s", path, tex_path);
return false;
}
vertices.resize(bin_size/sizeof(Vertex));
memcpy(vertices.data(), bin_data, bin_size);
SDL_Log("File size: %zu, %zu vertices", bin_size, bin_size/3);
SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(dev); SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(dev);
SDL_GPUCopyPass *copy_pass = SDL_BeginGPUCopyPass(cmd); SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(cmd);
int w,h; int w,h;
atlas_tex = IMG_LoadGPUTexture(dev, copy_pass, tex_path, &w, &h); atlas_tex = IMG_LoadGPUTexture(dev, copy_pass, tex_path, &w, &h);
SDL_EndGPUCopyPass(copy_pass); SDL_EndGPUCopyPass(copy_pass);
SDL_SubmitGPUCommandBuffer(cmd); SDL_SubmitGPUCommandBuffer(cmd);
SDL_GPUBufferCreateInfo info {
.usage = SDL_GPU_BUFFERUSAGE_VERTEX, if(atlas_tex) {
.size = static_cast<uint32_t>(vertices.size() * sizeof(Vertex)), SDL_Log("Loaded sprite atlas: %s, size: %dx%d", tex_path, w, h);
}; } else {
vert_buff = SDL_CreateGPUBuffer(dev, &info); SDL_Log("Failed to load sprite atlas: %s, error: %s", tex_path, SDL_GetError());
upload_buffer(dev, vert_buff, vertices.data(), info.size); }
return true;
return !!atlas_tex;
} }
void Renderer::setup_imgui() { void Renderer::setup_imgui() {
@ -144,60 +133,14 @@ bool Renderer::load_bsp() {
void Renderer::resize_render_texture(uint32_t w, uint32_t h) { void Renderer::resize_render_texture(uint32_t w, uint32_t h) {
SDL_WaitForGPUIdle(dev); SDL_WaitForGPUIdle(dev);
if (render_tex) SDL_ReleaseGPUTexture(dev, render_tex);
if (post_tex) SDL_ReleaseGPUTexture(dev, post_tex); if (post_tex) SDL_ReleaseGPUTexture(dev, post_tex);
if (depth_tex) SDL_ReleaseGPUTexture(dev, depth_tex);
SDL_GPUTextureCreateInfo depth_info {
.type = SDL_GPU_TEXTURETYPE_2D,
.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT,
.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER,
.width = w,
.height = h,
.layer_count_or_depth = 1,
.num_levels = 1,
};
depth_tex = SDL_CreateGPUTexture(dev, &depth_info);
render_tex = create_render_texture(dev, win, w, h);
post_tex = create_render_texture(dev, win, w, h); post_tex = create_render_texture(dev, win, w, h);
render_w = w; render_w = w;
render_h = h; render_h = h;
} }
void Renderer::pass_scene(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo) {
SDL_PushGPUVertexUniformData(cmd, 0, &ubo, sizeof(ubo));
SDL_GPUColorTargetInfo tgt {
.texture = render_tex,
.clear_color = { 0.0, 0.0, 0.0, 1.0},
.load_op = SDL_GPU_LOADOP_CLEAR,
.store_op = SDL_GPU_STOREOP_STORE,
};
SDL_GPUDepthStencilTargetInfo depth_tgt {
.texture = depth_tex,
.clear_depth = 1.0f,
.load_op = SDL_GPU_LOADOP_CLEAR,
.store_op = SDL_GPU_STOREOP_STORE,
.stencil_load_op = SDL_GPU_LOADOP_DONT_CARE,
.stencil_store_op = SDL_GPU_STOREOP_STORE,
};
SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &tgt, 1, &depth_tgt);
SDL_BindGPUGraphicsPipeline(pass, scene.pipeline);
SDL_GPUBufferBinding binding { .buffer = vert_buff, .offset = 0 };
SDL_BindGPUVertexBuffers(pass, 0, &binding, 1);
SDL_GPUTextureSamplerBinding tex[1] = {
{ .texture = atlas_tex, .sampler = atlas_sampler },
};
SDL_BindGPUFragmentSamplers(pass, 0, tex, 1);
SDL_DrawGPUPrimitives(pass, vertices.size(), 1, 0, 0);
SDL_EndGPURenderPass(pass);
}
void Renderer::pass_ray(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo) { void Renderer::pass_ray(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo) {
SDL_PushGPUFragmentUniformData(cmd, 0, &ubo, sizeof(ubo)); SDL_PushGPUFragmentUniformData(cmd, 0, &ubo, sizeof(ubo));
@ -209,11 +152,11 @@ void Renderer::pass_ray(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo) {
SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &tgt, 1, NULL); SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &tgt, 1, NULL);
SDL_BindGPUGraphicsPipeline(pass, ray.pipeline); SDL_BindGPUGraphicsPipeline(pass, ray.pipeline);
SDL_GPUTextureSamplerBinding texs[2] = { SDL_GPUTextureSamplerBinding texs[1] = {
{ .texture = render_tex, .sampler = render_sampler }, { .texture = atlas_tex, .sampler = atlas_sampler },
{ .texture = depth_tex, .sampler = depth_sampler },
}; };
SDL_BindGPUFragmentSamplers(pass, 0, texs, 2);
SDL_BindGPUFragmentSamplers(pass, 0, texs, 1);
SDL_DrawGPUPrimitives(pass, 3, 1, 0, 0); SDL_DrawGPUPrimitives(pass, 3, 1, 0, 0);
SDL_EndGPURenderPass(pass); SDL_EndGPURenderPass(pass);
} }
@ -251,8 +194,10 @@ void Renderer::draw_imgui(SDL_GPUCommandBuffer* cmd, SDL_GPUTexture* tex) {
post_mode = 2; post_mode = 2;
ImGui::SliderFloat("Atlas du", &atlas_adjust.x, 0.1f, 100.0f); if(ImGui::CollapsingHeader("Magnification")) {
ImGui::SliderFloat("Atlas dv", &atlas_adjust.y, 0.1f, 100.0f); ImGui::SliderFloat("Zoom", &zoom, 0.1f, 100.0f);
ImGui::SliderFloat("Radius", &radius, 0.1f, 1.0f);
}
ImGui::End(); ImGui::End();
@ -282,7 +227,8 @@ void Renderer::draw_imgui(SDL_GPUCommandBuffer* cmd, SDL_GPUTexture* tex) {
void Renderer::draw(CameraUBO& ubo) { void Renderer::draw(CameraUBO& ubo) {
ubo.post_mode = post_mode; ubo.post_mode = post_mode;
ubo.atlas_adjust = atlas_adjust; ubo.zoom = zoom;
ubo.radius = radius;
static std::array<float, 25> frame_times; static std::array<float, 25> frame_times;
static float last_time = (float)SDL_GetPerformanceCounter()/(float)SDL_GetPerformanceFrequency(); static float last_time = (float)SDL_GetPerformanceCounter()/(float)SDL_GetPerformanceFrequency();
@ -312,7 +258,6 @@ void Renderer::draw(CameraUBO& ubo) {
if (sw_w != render_w || sw_h != render_h) if (sw_w != render_w || sw_h != render_h)
resize_render_texture(sw_w, sw_h); resize_render_texture(sw_w, sw_h);
pass_scene(cmd, ubo);
pass_ray(cmd, ubo); pass_ray(cmd, ubo);
pass_post(cmd, swapchain, ubo); pass_post(cmd, swapchain, ubo);
draw_imgui(cmd, swapchain); draw_imgui(cmd, swapchain);

View File

@ -10,26 +10,26 @@ struct Renderer {
SDL_Window* win = nullptr; SDL_Window* win = nullptr;
SDL_Gamepad* gamepad = nullptr; SDL_Gamepad* gamepad = nullptr;
ScenePipeline scene;
RayPipeline ray; RayPipeline ray;
PostPipeline post; PostPipeline post;
SDL_GPUBuffer* vert_buff = nullptr; SDL_GPUBuffer* vert_buff = nullptr;
SDL_GPUTexture* render_tex = nullptr;
SDL_GPUTexture* post_tex = nullptr; SDL_GPUTexture* post_tex = nullptr;
SDL_GPUTexture* depth_tex = nullptr; SDL_GPUTexture* sprite_tex = nullptr;
SDL_GPUTexture* atlas_tex = nullptr; SDL_GPUTexture* atlas_tex = nullptr;
SDL_GPUSampler* render_sampler = nullptr; SDL_GPUSampler* render_sampler = nullptr;
SDL_GPUSampler* depth_sampler = nullptr; SDL_GPUSampler* sprite_sampler = nullptr;
SDL_GPUSampler* atlas_sampler = nullptr; SDL_GPUSampler* atlas_sampler = nullptr;
uint32_t render_w = 0, render_h = 0; uint32_t render_w = 0, render_h = 0;
uint64_t frame = 0; uint64_t frame = 0;
bool in_menu = 0; bool in_menu = 0;
float fps = 0.0; float fps = 0.0;
/* imgui controlled */ /* imgui controlled */
int post_mode = 0; int post_mode = 0;
vec2 atlas_adjust = vec2(0); float zoom = 1.0f;
float radius = 0.1f;
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
@ -39,13 +39,12 @@ struct Renderer {
void draw(CameraUBO& ubo); void draw(CameraUBO& ubo);
private: private:
bool load_bin(); bool load_sprites();
bool load_bsp(); bool load_bsp();
void setup_imgui(); void setup_imgui();
void draw_imgui(SDL_GPUCommandBuffer* cmd, SDL_GPUTexture* tex); void draw_imgui(SDL_GPUCommandBuffer* cmd, SDL_GPUTexture* tex);
void add_gol_layer(); void add_gol_layer();
void resize_render_texture(uint32_t w, uint32_t h); void resize_render_texture(uint32_t w, uint32_t h);
void pass_scene(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo);
void pass_ray(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo); void pass_ray(SDL_GPUCommandBuffer* cmd, const CameraUBO& ubo);
void pass_post(SDL_GPUCommandBuffer* cmd, SDL_GPUTexture* swapchain, const CameraUBO& ubo); void pass_post(SDL_GPUCommandBuffer* cmd, SDL_GPUTexture* swapchain, const CameraUBO& ubo);
}; };

View File

@ -10,13 +10,10 @@ struct Vertex {
}; };
struct CameraUBO { struct CameraUBO {
mat4 model; vec2 cam_pos;
mat4 view;
mat4 proj;
mat4 inv_view;
mat4 inv_proj;
vec4 cam_pos;
float time; float time;
float aspect;
int post_mode; int post_mode;
vec2 atlas_adjust; float zoom;
float radius;
}; };