|
|
@ -38,26 +38,17 @@ const Renderer = @This(); |
|
|
|
|
|
|
|
|
|
|
|
app: *App, |
|
|
|
app: *App, |
|
|
|
|
|
|
|
|
|
|
|
depth_texture: *gpu.Texture, |
|
|
|
|
|
|
|
depth_texture_view: *gpu.TextureView, |
|
|
|
|
|
|
|
pipeline: *gpu.RenderPipeline, |
|
|
|
pipeline: *gpu.RenderPipeline, |
|
|
|
scene_uniform_buffer: *gpu.Buffer, |
|
|
|
scene_uniform_buffer: *gpu.Buffer, |
|
|
|
scene_uniform_bind_group: *gpu.BindGroup, |
|
|
|
scene_uniform_bind_group: *gpu.BindGroup, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
depth_texture: ?*gpu.Texture = null, |
|
|
|
|
|
|
|
depth_texture_view: ?*gpu.TextureView = null, |
|
|
|
|
|
|
|
|
|
|
|
primitive_data: []PrimitiveData, |
|
|
|
primitive_data: []PrimitiveData, |
|
|
|
object_data: []ObjectData, |
|
|
|
object_data: []ObjectData, |
|
|
|
|
|
|
|
|
|
|
|
pub fn init(app: *App) !*Renderer { |
|
|
|
pub fn init(app: *App) !*Renderer { |
|
|
|
// Create a depth texture. This is used to ensure that when things are |
|
|
|
|
|
|
|
// rendered, an object behind another won't draw over one in front, simply |
|
|
|
|
|
|
|
// because it was rendered at a later point in time. |
|
|
|
|
|
|
|
const depth_texture = core.device.createTexture(&.{ |
|
|
|
|
|
|
|
.usage = .{ .render_attachment = true }, |
|
|
|
|
|
|
|
.size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, |
|
|
|
|
|
|
|
.format = .depth24_plus, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
const depth_texture_view = depth_texture.createView(null); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); |
|
|
|
const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); |
|
|
|
defer shader_module.release(); |
|
|
|
defer shader_module.release(); |
|
|
|
|
|
|
|
|
|
|
@ -167,14 +158,17 @@ pub fn init(app: *App) !*Renderer { |
|
|
|
const result = try app.allocator.create(Renderer); |
|
|
|
const result = try app.allocator.create(Renderer); |
|
|
|
result.* = .{ |
|
|
|
result.* = .{ |
|
|
|
.app = app, |
|
|
|
.app = app, |
|
|
|
.depth_texture = depth_texture, |
|
|
|
|
|
|
|
.depth_texture_view = depth_texture_view, |
|
|
|
|
|
|
|
.pipeline = pipeline, |
|
|
|
.pipeline = pipeline, |
|
|
|
.scene_uniform_buffer = scene_uniform.buffer, |
|
|
|
.scene_uniform_buffer = scene_uniform.buffer, |
|
|
|
.scene_uniform_bind_group = scene_uniform.bind_group, |
|
|
|
.scene_uniform_bind_group = scene_uniform.bind_group, |
|
|
|
.primitive_data = primitive_data, |
|
|
|
.primitive_data = primitive_data, |
|
|
|
.object_data = object_data, |
|
|
|
.object_data = object_data, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize the depth texture. |
|
|
|
|
|
|
|
// This is called also whenever the window is resized. |
|
|
|
|
|
|
|
result.recreateDepthTexture(); |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -183,8 +177,6 @@ pub fn deinit(self: *Renderer) void { |
|
|
|
// in the order they were created in `init`. |
|
|
|
// in the order they were created in `init`. |
|
|
|
defer self.app.allocator.destroy(self); |
|
|
|
defer self.app.allocator.destroy(self); |
|
|
|
|
|
|
|
|
|
|
|
defer self.depth_texture.release(); |
|
|
|
|
|
|
|
defer self.depth_texture_view.release(); |
|
|
|
|
|
|
|
defer self.pipeline.release(); |
|
|
|
defer self.pipeline.release(); |
|
|
|
defer self.scene_uniform_buffer.release(); |
|
|
|
defer self.scene_uniform_buffer.release(); |
|
|
|
defer self.scene_uniform_bind_group.release(); |
|
|
|
defer self.scene_uniform_bind_group.release(); |
|
|
@ -199,6 +191,15 @@ pub fn deinit(self: *Renderer) void { |
|
|
|
o.uniform_buffer.release(); |
|
|
|
o.uniform_buffer.release(); |
|
|
|
o.uniform_bind_group.release(); |
|
|
|
o.uniform_bind_group.release(); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defer if (self.depth_texture) |t| t.release(); |
|
|
|
|
|
|
|
defer if (self.depth_texture_view) |v| v.release(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn resize(self: *Renderer) void { |
|
|
|
|
|
|
|
// Recreate depth texture with the proper size, otherwise |
|
|
|
|
|
|
|
// the application may crash when the window is resized. |
|
|
|
|
|
|
|
self.recreateDepthTexture(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn update(self: *Renderer) void { |
|
|
|
pub fn update(self: *Renderer) void { |
|
|
@ -236,7 +237,7 @@ pub fn update(self: *Renderer) void { |
|
|
|
.store_op = .store, |
|
|
|
.store_op = .store, |
|
|
|
}}, |
|
|
|
}}, |
|
|
|
.depth_stencil_attachment = &.{ |
|
|
|
.depth_stencil_attachment = &.{ |
|
|
|
.view = self.depth_texture_view, |
|
|
|
.view = self.depth_texture_view.?, |
|
|
|
.depth_load_op = .clear, |
|
|
|
.depth_load_op = .clear, |
|
|
|
.depth_store_op = .store, |
|
|
|
.depth_store_op = .store, |
|
|
|
.depth_clear_value = 1.0, |
|
|
|
.depth_clear_value = 1.0, |
|
|
@ -285,6 +286,22 @@ pub fn update(self: *Renderer) void { |
|
|
|
core.queue.submit(&.{command}); |
|
|
|
core.queue.submit(&.{command}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Creates a depth texture. This is used to ensure that when things are |
|
|
|
|
|
|
|
/// rendered, an object behind another won't draw over one in front, simply |
|
|
|
|
|
|
|
/// because it was rendered at a later point in time. |
|
|
|
|
|
|
|
pub fn recreateDepthTexture(self: *Renderer) void { |
|
|
|
|
|
|
|
// Release previous depth butter and view, if any. |
|
|
|
|
|
|
|
if (self.depth_texture) |t| t.release(); |
|
|
|
|
|
|
|
if (self.depth_texture_view) |v| v.release(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.depth_texture = core.device.createTexture(&.{ |
|
|
|
|
|
|
|
.usage = .{ .render_attachment = true }, |
|
|
|
|
|
|
|
.size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, |
|
|
|
|
|
|
|
.format = .depth24_plus, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
self.depth_texture_view = self.depth_texture.?.createView(null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Creates a buffer on the GPU to store uniform parameter information as |
|
|
|
/// Creates a buffer on the GPU to store uniform parameter information as |
|
|
|
/// well as a bind group with the specified layout pointing to that buffer. |
|
|
|
/// well as a bind group with the specified layout pointing to that buffer. |
|
|
|
/// Additionally, immediately fills the buffer with the provided data. |
|
|
|
/// Additionally, immediately fills the buffer with the provided data. |
|
|
|