Two colorful triangles

This commit is contained in:
2025-05-09 20:11:45 +03:00
commit 3701ab66dd
5 changed files with 239 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
sdlgpu
shaders/*.spv.*

17
build.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
set -e
set -x
for i in shaders/src/*; do
filename=$(basename $i)
basename=$(printf $filename | cut -d. -f1)
ext=$(printf $filename | cut -d. -f3)
glslc "$i" -o shaders/${basename}.spv.${ext}
done
# glslc shader.glsl.vert -o shader.spv.vert
# glslc shader.glsl.frag -o shader.spv.frag
odin build src -debug -out:sdlgpu
./sdlgpu

View File

@ -0,0 +1,9 @@
#version 460
layout(location=0) in vec3 color;
layout(location=0) out vec4 frag_color;
void main() {
frag_color = vec4(color, 1);
}

View File

@ -0,0 +1,16 @@
#version 460
layout(set=1, binding=0) uniform UBO {
mat4 mvp;
};
layout(location=0) in vec3 position;
layout(location=1) in vec3 color;
layout(location=0) out vec3 out_color;
void main() {
gl_Position = mvp * vec4(position, 1);
out_color = color;
}

195
src/main.odin Normal file
View File

@ -0,0 +1,195 @@
package main
import "core:log"
import "core:math/linalg"
import "core:mem"
import sdl "vendor:sdl3"
frag_shader_code := #load("../shaders/shader.spv.frag")
vert_shader_code := #load("../shaders/shader.spv.vert")
main :: proc() {
context.logger = log.create_console_logger()
sdl.SetLogPriorities(.VERBOSE)
ok := sdl.Init({.VIDEO});assert(ok)
window := sdl.CreateWindow("hi sdl", 800, 400, {});assert(window != nil)
gpu := sdl.CreateGPUDevice({.SPIRV}, true, nil);assert(gpu != nil)
ok = sdl.ClaimWindowForGPUDevice(gpu, window);assert(ok)
vert_shader := load_shader(gpu, vert_shader_code, .VERTEX, 1)
frag_shader := load_shader(gpu, frag_shader_code, .FRAGMENT, 0)
Vec3 :: [3]f32
Vertex :: struct {
pos: Vec3,
col: Vec3,
}
vertices := []Vertex {
{{-0.5, 0, 0}, {1, 0, 0}},
{{0, 1.0, 0}, {0, 1, 0}},
{{0.5, 0, 0}, {0, 0, 1}},
{{0.5, 0, 0}, {1, 1, 0}},
{{0, -0.5, 0}, {0, 1, 1}},
{{-0.5, -0, 0}, {1, 0, 1}},
}
vertices_byte_size := len(vertices) * size_of(vertices[0])
vertex_attrs := []sdl.GPUVertexAttribute {
{location = 0, format = .FLOAT3, offset = 0}, // Position
{location = 1, format = .FLOAT3, offset = size_of(Vec3)}, // Color
}
vertex_buf := sdl.CreateGPUBuffer(
gpu,
sdl.GPUBufferCreateInfo{usage = {.VERTEX}, size = u32(vertices_byte_size)},
)
transfer_buf := sdl.CreateGPUTransferBuffer(
gpu,
sdl.GPUTransferBufferCreateInfo{usage = .UPLOAD, size = u32(vertices_byte_size)},
)
{ // Copy verticies to the transfer buffer
transfer_mem := sdl.MapGPUTransferBuffer(
gpu,
transfer_buf,
false,
);assert(transfer_mem != nil)
defer sdl.UnmapGPUTransferBuffer(gpu, transfer_buf)
mem.copy(transfer_mem, raw_data(vertices), vertices_byte_size)
}
{ // Upload buffer to gpu
copy_cmd_buf := sdl.AcquireGPUCommandBuffer(gpu)
defer {ok = sdl.SubmitGPUCommandBuffer(copy_cmd_buf);assert(ok)}
copy_pass := sdl.BeginGPUCopyPass(copy_cmd_buf)
defer sdl.EndGPUCopyPass(copy_pass)
sdl.UploadToGPUBuffer(
copy_pass,
{transfer_buffer = transfer_buf},
{buffer = vertex_buf, size = u32(vertices_byte_size)},
false,
)
}
sdl.ReleaseGPUTransferBuffer(gpu, transfer_buf)
pipeline := sdl.CreateGPUGraphicsPipeline(
gpu,
{
vertex_shader = vert_shader,
fragment_shader = frag_shader,
vertex_input_state = {
num_vertex_buffers = 1,
vertex_buffer_descriptions = &sdl.GPUVertexBufferDescription {
slot = 0,
pitch = size_of(Vertex),
},
num_vertex_attributes = u32(len(vertex_attrs)),
vertex_attributes = raw_data(vertex_attrs),
},
primitive_type = .TRIANGLELIST,
target_info = {
num_color_targets = 1,
color_target_descriptions = &(sdl.GPUColorTargetDescription {
format = sdl.GetGPUSwapchainTextureFormat(gpu, window),
}),
},
},
)
sdl.ReleaseGPUShader(gpu, vert_shader)
sdl.ReleaseGPUShader(gpu, frag_shader)
wsize := [2]i32{}
ok = sdl.GetWindowSize(window, &wsize.x, &wsize.y);assert(ok)
rotation := f32(0)
proj := linalg.matrix4_perspective_f32(
linalg.to_radians(f32(30)),
f32(wsize.x) / f32(wsize.y),
0.001,
1000,
)
UBO :: struct {
mvp: matrix[4, 4]f32,
}
last_ticks := sdl.GetTicks()
loop: for {
new_ticks := sdl.GetTicks()
delta := f32(new_ticks - last_ticks) / 1000
last_ticks = new_ticks
ev: sdl.Event
for sdl.PollEvent(&ev) {
#partial switch ev.type {
case .QUIT:
break loop
case .KEY_DOWN:
if ev.key.scancode == .ESCAPE do break loop
}
}
cmd_buf := sdl.AcquireGPUCommandBuffer(gpu)
swaptex: ^sdl.GPUTexture
ok = sdl.WaitAndAcquireGPUSwapchainTexture(cmd_buf, window, &swaptex, nil, nil);assert(ok)
rotation += 1 * delta
model_mat :=
linalg.matrix4_translate_f32({0, 0, -5}) *
linalg.matrix4_rotate_f32(rotation, {0, 1, 0})
ubo := UBO{proj * model_mat}
if swaptex != nil {
color_target := sdl.GPUColorTargetInfo {
texture = swaptex,
load_op = .CLEAR,
clear_color = {0.3, 0.1, 0.7, 1},
store_op = .STORE,
}
render_pass := sdl.BeginGPURenderPass(cmd_buf, &color_target, 1, nil)
sdl.BindGPUGraphicsPipeline(render_pass, pipeline)
sdl.BindGPUVertexBuffers(
render_pass,
0,
&(sdl.GPUBufferBinding{buffer = vertex_buf}),
1,
)
sdl.PushGPUVertexUniformData(cmd_buf, 0, &ubo, size_of(ubo))
sdl.DrawGPUPrimitives(render_pass, u32(len(vertices)), 1, 0, 0)
sdl.EndGPURenderPass(render_pass)
}
ok = sdl.SubmitGPUCommandBuffer(cmd_buf)
}
}
load_shader :: proc(
gpu: ^sdl.GPUDevice,
code: []u8,
stage: sdl.GPUShaderStage,
num_uniforms: u32,
) -> ^sdl.GPUShader {
shader := sdl.CreateGPUShader(
gpu,
sdl.GPUShaderCreateInfo {
code_size = len(code),
code = raw_data(code),
entrypoint = "main",
format = {.SPIRV},
stage = stage,
num_uniform_buffers = num_uniforms,
},
)
return shader
}