Two colorful triangles
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
sdlgpu
|
||||
shaders/*.spv.*
|
17
build.sh
Executable file
17
build.sh
Executable 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
|
9
shaders/src/shader.glsl.frag
Normal file
9
shaders/src/shader.glsl.frag
Normal 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);
|
||||
}
|
16
shaders/src/shader.glsl.vert
Normal file
16
shaders/src/shader.glsl.vert
Normal 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
195
src/main.odin
Normal 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
|
||||
}
|
||||
|
Reference in New Issue
Block a user