Basic vertex and index buffer

This commit is contained in:
Riyyi
2026-10-12 18:59:50 +02:00
parent 3549b0be95
commit 8b30fa4e7c
2 changed files with 120 additions and 16 deletions
+1 -3
View File
@@ -21,9 +21,7 @@ OS :: struct {
// Constructor / destructor // Constructor / destructor
os_init :: proc(settings: base.Settings) { os_init :: proc(settings: base.Settings) {
if !glfw.Init() { assert(cast(bool)glfw.Init(), "[glfw] init failure")
panic("[glfw] init failure")
}
// Set window properties // Set window properties
glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API) // do not create OpenGL context glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API) // do not create OpenGL context
+119 -13
View File
@@ -8,6 +8,16 @@ import "wgpu:wgpu"
import "sindri:base" import "sindri:base"
// -----------------------------------------
// Types
Vec3 :: [3]f32
Vertex :: struct #align (4) {
pos: Vec3,
col: Vec3,
}
// ----------------------------------------- // -----------------------------------------
// Variables // Variables
@@ -28,6 +38,10 @@ state: struct {
// ---------------------------------------- // ----------------------------------------
capabilities: wgpu.SurfaceCapabilities, capabilities: wgpu.SurfaceCapabilities,
vsync: bool, vsync: bool,
// ----------------------------------------
vertex_buffer: wgpu.Buffer,
index_buffer: wgpu.Buffer,
index_count: u32,
} }
// ----------------------------------------- // -----------------------------------------
@@ -64,6 +78,9 @@ instance_init :: proc(settings: base.Settings) {
} }
instance_destroy :: proc() { instance_destroy :: proc() {
wgpu.BufferRelease(state.vertex_buffer)
wgpu.BufferRelease(state.index_buffer)
wgpu.RenderPipelineRelease(state.pipeline) wgpu.RenderPipelineRelease(state.pipeline)
wgpu.PipelineLayoutRelease(state.pipeline_layout) wgpu.PipelineLayoutRelease(state.pipeline_layout)
wgpu.ShaderModuleRelease(state.module) wgpu.ShaderModuleRelease(state.module)
@@ -137,18 +154,36 @@ frame :: proc "c" () {
loadOp = .Clear, loadOp = .Clear,
storeOp = .Store, storeOp = .Store,
depthSlice = wgpu.DEPTH_SLICE_UNDEFINED, depthSlice = wgpu.DEPTH_SLICE_UNDEFINED,
clearValue = {0, 1, 0, 1}, clearValue = {55 / 255.0, 73 / 255.0, 73 / 255.0, 1},
}, },
}, },
) )
wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline) wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline)
wgpu.RenderPassEncoderDraw(
wgpu.RenderPassEncoderSetVertexBuffer(
render_pass_encoder, render_pass_encoder,
vertexCount = 3, slot = 0,
instanceCount = 1, buffer = state.vertex_buffer,
firstVertex = 0, offset = 0, // offset into buffer to start from
firstInstance = 0, size = wgpu.WHOLE_SIZE, // x bytes of the buffer to use
)
wgpu.RenderPassEncoderSetIndexBuffer(
render_pass_encoder,
buffer = state.index_buffer,
format = .Uint16, // type of each element in the buffer
offset = 0, // offset into buffer to start from
size = wgpu.WHOLE_SIZE, // x bytes of the buffer to use
)
wgpu.RenderPassEncoderDrawIndexed(
render_pass_encoder,
state.index_count,
instanceCount = 1, // draw x instance(s) of the mesh
firstIndex = 0, // offset into buffer to start from, useful for drawing sub-mesh
baseVertex = 0, // value added to index before vertex fetch, useful for multi-mesh vertex buffers
firstInstance = 0, // number to start instance index from
) )
wgpu.RenderPassEncoderEnd(render_pass_encoder) wgpu.RenderPassEncoderEnd(render_pass_encoder)
@@ -208,17 +243,31 @@ on_device :: proc "c" (
} }
wgpu.SurfaceConfigure(state.surface, &state.config) wgpu.SurfaceConfigure(state.surface, &state.config)
// ----------------------------------------
// Compile shader
shader :: ` shader :: `
struct VertexInput {
@location(0) pos: vec3<f32>,
@location(1) col: vec3<f32>,
};
struct VertexOutput {
@builtin(position) position: vec4<f32>,
@location(0) col: vec3<f32>,
};
@vertex @vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> { fn vs_main(in: VertexInput) -> VertexOutput {
let x = f32(i32(in_vertex_index) - 1); var out: VertexOutput;
let y = f32(i32(in_vertex_index & 1u) * 2 - 1); out.position = vec4<f32>(in.pos, 1.0);
return vec4<f32>(x, y, 0.0, 1.0); out.col = in.col;
return out;
} }
@fragment @fragment
fn fs_main() -> @location(0) vec4<f32> { fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0); return vec4<f32>(in.col, 1.0);
}` }`
state.module = wgpu.DeviceCreateShaderModule( state.module = wgpu.DeviceCreateShaderModule(
@@ -231,12 +280,46 @@ on_device :: proc "c" (
}, },
) )
// ----------------------------------------
// Buffer shape
// Fill vertex/index buffers
fill_buffers_with_quad()
vertex_attributes := [?]wgpu.VertexAttribute {
{
format = .Float32x3,
offset = cast(u64)offset_of(Vertex, pos),
shaderLocation = 0,
},
{
format = .Float32x3,
offset = cast(u64)offset_of(Vertex, col),
shaderLocation = 1,
},
}
vertex_layout := wgpu.VertexBufferLayout {
stepMode = .Vertex,
arrayStride = size_of(Vertex),
attributeCount = len(vertex_attributes),
attributes = raw_data(vertex_attributes[:]),
}
// ----------------------------------------
// Render pipeline
state.pipeline_layout = wgpu.DeviceCreatePipelineLayout(state.device, &{}) state.pipeline_layout = wgpu.DeviceCreatePipelineLayout(state.device, &{})
state.pipeline = wgpu.DeviceCreateRenderPipeline( state.pipeline = wgpu.DeviceCreateRenderPipeline(
state.device, state.device,
&{ &{
layout = state.pipeline_layout, layout = state.pipeline_layout,
vertex = {module = state.module, entryPoint = "vs_main"}, vertex = {
module = state.module,
entryPoint = "vs_main",
bufferCount = 1,
buffers = &vertex_layout,
},
fragment = &{ fragment = &{
module = state.module, module = state.module,
entryPoint = "fs_main", entryPoint = "fs_main",
@@ -290,3 +373,26 @@ pick_present_mode :: proc(vsync: bool) -> wgpu.PresentMode {
return .Fifo // Vsync On return .Fifo // Vsync On
} }
@(private = "file")
fill_buffers_with_quad :: proc() {
vertices := [?]Vertex {
{pos = {-0.5, -0.5, 0}, col = {1, 0, 0}}, // 0 bottom-left red
{pos = {+0.5, -0.5, 0}, col = {0, 1, 0}}, // 1 bottom-right green
{pos = {+0.5, +0.5, 0}, col = {0, 0, 1}}, // 2 top-right blue
{pos = {-0.5, +0.5, 0}, col = {1, 1, 0}}, // 3 top-left yellow
}
indices := [?]u16{0, 1, 2, 2, 3, 0}
state.vertex_buffer = wgpu.DeviceCreateBufferWithData(
state.device,
&{label = "quad vertices", usage = {.Vertex}},
vertices[:],
)
state.index_buffer = wgpu.DeviceCreateBufferWithData(
state.device,
&{label = "quad indices", usage = {.Index}},
indices[:],
)
state.index_count = cast(u32)len(indices)
}