This commit is contained in:
duck
2025-06-29 18:47:33 +05:00
parent 5987f9a44f
commit b2be9e3708
4 changed files with 154 additions and 70 deletions

View File

@@ -1,14 +1,10 @@
#version 450
layout(location = 0) in float vertexIndex;
layout(location = 1) in float depth;
layout(location = 0) in vec2 inUV;
layout(location = 0) out vec4 fragColor;
layout(set = 2, binding = 0) uniform sampler2D texture_sampler;
void main() {
fragColor = vec4(
depth,
cos(vertexIndex * 0.5) * 0.25 + 0.75,
sin(vertexIndex * 0.5) * 0.25 + 0.75,
1.0
);
fragColor = texture(texture_sampler, inUV);
}

View File

@@ -1,8 +1,8 @@
#version 450
layout(location = 0) in vec3 inCoord;
layout(location = 0) out float vertexIndex;
layout(location = 1) out float depth;
layout(location = 1) in vec2 inUV;
layout(location = 0) out vec2 outUV;
layout(set = 1, binding = 0) uniform Camera{
mat4 transform;
@@ -11,10 +11,7 @@ layout(set = 1, binding = 1) uniform Object{
mat4 transform;
} object;
void main() {
vertexIndex = gl_VertexIndex;
vec4 outPos = vec4(inCoord, 1.0) * object.transform * camera.transform;
depth = outPos.z / outPos.w;
gl_Position = outPos;
gl_Position = vec4(inCoord, 1.0) * object.transform * camera.transform;
outUV = inUV;
}

View File

@@ -8,50 +8,62 @@ const Graphics = @import("graphics.zig");
const Game = @import("game.zig");
const CUBE_MESH_DATA = [_]f32{
-0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
-0.5, 0.5, -0.5, 0.0, 0.0,
0.5, 0.5, -0.5, 0.0, 0.0,
-0.5, -0.5, -0.5, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0, 0.0,
-0.5, -0.5, -0.5, 0.0, 0.0,
0.5, 0.5, -0.5, 0.0, 0.0,
0.5, 0.5, -0.5, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0, 0.0,
0.5, -0.5, 0.5, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 0.0,
-0.5, 0.5, 0.5, 0.0, 0.0,
0.5, -0.5, 0.5, 0.0, 0.0,
-0.5, -0.5, 0.5, 0.0, 0.0,
0.5, -0.5, 0.5, 0.0, 0.0,
-0.5, 0.5, 0.5, 0.0, 0.0,
-0.5, 0.5, 0.5, 0.0, 0.0,
-0.5, 0.5, -0.5, 0.0, 0.0,
-0.5, -0.5, 0.5, 0.0, 0.0,
-0.5, -0.5, -0.5, 0.0, 0.0,
-0.5, -0.5, 0.5, 0.0, 0.0,
-0.5, 0.5, -0.5, 0.0, 0.0,
-0.5, 0.5, 0.5, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 0.0,
-0.5, 0.5, -0.5, 0.0, 0.0,
0.5, 0.5, -0.5, 0.0, 0.0,
-0.5, 0.5, -0.5, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 0.0,
-0.5, -0.5, -0.5, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0, 0.0,
-0.5, -0.5, 0.5, 0.0, 0.0,
0.5, -0.5, 0.5, 0.0, 0.0,
-0.5, -0.5, 0.5, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0, 0.0,
};
const PLANE_MESH_DATA = [_]f32{
-0.5, -0.5, 0,
0.5, 0.5, 0,
-0.5, 0.5, 0,
0.5, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
-0.5, -0.5, 0, 0.0, 1.0,
0.5, 0.5, 0, 1.0, 0.0,
-0.5, 0.5, 0, 0.0, 0.0,
0.5, 0.5, 0, 1.0, 0.0,
-0.5, -0.5, 0, 0.0, 1.0,
0.5, -0.5, 0, 1.0, 1.0,
};
// const TEXTURE_DATA = [_]u8{
// 255, 0, 0, 255,
// 0, 255, 0, 255,
// 0, 0, 255, 255,
// 0, 0, 0, 255,
// };
const TEXTURE_DATA = [_]u8{
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
0, 0, 0, 255,
};
pub const WorldTime = struct {
@@ -72,6 +84,7 @@ pub const PlayerState = union(enum) {
pub const Player = struct {
mesh: Graphics.Mesh,
texture: Graphics.Texture,
transform: Transform,
position: @Vector(2, i32),
state: PlayerState,
@@ -83,12 +96,14 @@ pub const Player = struct {
pub const Environment = struct {
mesh: Graphics.Mesh,
texture: Graphics.Texture,
transform: Transform,
};
pub fn init(controller: *Controller, graphics: *Graphics) !void {
controller.addResource(Player{
.mesh = try graphics.loadMesh(@ptrCast(&CUBE_MESH_DATA)),
.texture = try graphics.loadTexture(2, 2, @ptrCast(&TEXTURE_DATA)),
.transform = .{},
.position = .{ 0, 0 },
.state = .idle,
@@ -98,6 +113,7 @@ pub fn init(controller: *Controller, graphics: *Graphics) !void {
});
controller.addResource(Environment{
.mesh = try graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA)),
.texture = try graphics.loadTexture(2, 2, @ptrCast(&TEXTURE_DATA)),
.transform = .{
.position = .{ 0, 0, -1 },
.scale = @splat(5),
@@ -259,10 +275,10 @@ pub fn draw(
env.transform.rotation,
Transform.rotationByAxis(.{ 0, 0, 1 }, world_time.time.unitsSince(world_time.last_time) * std.math.pi),
);
try graphics.drawMesh(env.mesh, env.transform);
try graphics.drawMesh(env.mesh, Transform{
try graphics.drawMesh(env.mesh, env.texture, env.transform);
try graphics.drawMesh(env.mesh, env.texture, Transform{
.position = .{ 0, 0, -0.5 },
.scale = @splat(5),
});
try graphics.drawMesh(player.mesh, player.transform);
try graphics.drawMesh(player.mesh, player.texture, player.transform);
}

View File

@@ -11,6 +11,11 @@ pub const Mesh = struct {
vertex_count: usize,
};
pub const Texture = struct {
texture: *sdl.GPUTexture,
sampler: *sdl.GPUSampler,
};
window: *sdl.Window,
renderer: *sdl.Renderer,
device: *sdl.GPUDevice,
@@ -41,7 +46,7 @@ to_resize: ?[2]u32 = null,
const VERTEX_BUFFER_DEFAULT_CAPACITY = 1024;
const VERTEX_BUFFER_GROWTH_MULTIPLIER = 2;
const TRANSFER_BUFFER_DEFAULT_CAPACITY = 1024;
const BYTES_PER_VERTEX = 3 * 4;
const BYTES_PER_VERTEX = 5 * 4;
const Self = @This();
pub fn create() GameError!Self {
@@ -96,6 +101,7 @@ pub fn create() GameError!Self {
.entrypoint = "main",
.format = sdl.GPU_SHADERFORMAT_SPIRV,
.stage = sdl.GPU_SHADERSTAGE_FRAGMENT,
.num_samplers = 1,
},
);
errdefer sdl.ReleaseGPUShader(device, shader_frag);
@@ -132,18 +138,25 @@ pub fn create() GameError!Self {
.vertex_input_state = .{
.vertex_buffer_descriptions = &.{
.slot = 0,
// 3 Coordinates * 4 Bytes
.pitch = 3 * 4,
.pitch = 5 * 4,
.input_rate = sdl.GPU_VERTEXINPUTRATE_VERTEX,
},
.num_vertex_buffers = 1,
.vertex_attributes = &sdl.GPUVertexAttribute{
.offset = 0,
.location = 0,
.format = sdl.GPU_VERTEXELEMENTFORMAT_FLOAT3,
.buffer_slot = 0,
.vertex_attributes = &[2]sdl.GPUVertexAttribute{
sdl.GPUVertexAttribute{
.offset = 0,
.location = 0,
.format = sdl.GPU_VERTEXELEMENTFORMAT_FLOAT3,
.buffer_slot = 0,
},
sdl.GPUVertexAttribute{
.offset = 3 * 4,
.location = 1,
.format = sdl.GPU_VERTEXELEMENTFORMAT_FLOAT2,
.buffer_slot = 0,
},
},
.num_vertex_attributes = 1,
.num_vertex_attributes = 2,
},
.primitive_type = sdl.GPU_PRIMITIVETYPE_TRIANGLELIST,
.rasterizer_state = presets.RASTERIZER_CULL,
@@ -218,6 +231,64 @@ pub fn destroy(self: *Self) void {
sdl.DestroyGPUDevice(self.device);
}
pub fn loadTexture(self: *Self, width: u32, height: u32, texture_bytes: []const u8) GameError!Texture {
const target_format = sdl.SDL_GetGPUSwapchainTextureFormat(self.device, self.window);
const texture = sdl.CreateGPUTexture(self.device, &sdl.GPUTextureCreateInfo{
.format = target_format,
.layer_count_or_depth = 1,
.width = width,
.height = height,
.num_levels = 1,
.sample_count = sdl.GPU_SAMPLECOUNT_1,
.usage = sdl.GPU_TEXTUREUSAGE_SAMPLER,
}) orelse return GameError.SdlError;
errdefer sdl.ReleaseGPUTexture(self.device, texture);
const command_buffer = sdl.AcquireGPUCommandBuffer(self.device) orelse return GameError.SdlError;
{
errdefer _ = sdl.CancelGPUCommandBuffer(command_buffer);
const copy_pass = sdl.BeginGPUCopyPass(command_buffer) orelse return GameError.SdlError;
defer sdl.EndGPUCopyPass(copy_pass);
const map: [*]u8 = @ptrCast(sdl.MapGPUTransferBuffer(self.device, self.transfer_buffer, false) orelse return GameError.SdlError);
@memcpy(map, texture_bytes);
sdl.UnmapGPUTransferBuffer(self.device, self.transfer_buffer);
sdl.UploadToGPUTexture(copy_pass, &sdl.GPUTextureTransferInfo{
.offset = 0,
.pixels_per_row = width,
.rows_per_layer = height,
.transfer_buffer = self.transfer_buffer,
}, &sdl.GPUTextureRegion{
.texture = texture,
.mip_level = 0,
.layer = 0,
.x = 0,
.y = 0,
.z = 0,
.w = width,
.h = height,
.d = 1,
}, false);
}
if (!sdl.SubmitGPUCommandBuffer(command_buffer)) return GameError.SdlError;
const sampler = sdl.CreateGPUSampler(self.device, &sdl.GPUSamplerCreateInfo{
.address_mode_u = sdl.GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
.address_mode_v = sdl.GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
.address_mode_w = sdl.GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
.mag_filter = sdl.GPU_FILTER_NEAREST,
.min_filter = sdl.GPU_FILTER_LINEAR,
}) orelse return GameError.SdlError;
return Texture{
.texture = texture,
.sampler = sampler,
};
}
pub fn loadMesh(self: *Self, mesh_bytes: []const u8) GameError!Mesh {
std.debug.assert(mesh_bytes.len < self.transfer_buffer_capacity);
@@ -359,10 +430,14 @@ pub fn beginDraw(self: *Self) GameError!bool {
return true;
}
pub fn drawMesh(self: *Self, mesh: Mesh, transform: Transform) GameError!void {
pub fn drawMesh(self: *Self, mesh: Mesh, texture: Texture, transform: Transform) GameError!void {
if (self.render_pass == null) return;
sdl.PushGPUVertexUniformData(self.command_buffer, 1, &transform.matrix(), 16 * 4);
sdl.BindGPUFragmentSamplers(self.render_pass, 0, &sdl.GPUTextureSamplerBinding{
.texture = texture.texture,
.sampler = texture.sampler,
}, 1);
sdl.DrawGPUPrimitives(self.render_pass, @intCast(mesh.vertex_count), 1, @intCast(mesh.vertex_start), 0);
}