feat(render): time-based rotation in shaders

This commit is contained in:
Chance 2025-04-27 17:22:05 -04:00
parent 22a58044d5
commit 0e8209f9b9
Signed by: caznix
GPG key ID: 489D213143D753FD
3 changed files with 55 additions and 12 deletions

View file

@ -3,7 +3,7 @@ use naga::{
ShaderStage,
back::spv::{self, WriterFlags},
front::glsl::{self, Options as GlslOptions, ParseErrors},
valid::{ValidationError, ValidationFlags, Validator},
valid::{Capabilities, ValidationError, ValidationFlags, Validator},
};
use std::{
env, fs,
@ -62,9 +62,12 @@ fn compile_shader(path: &Path, out_dir: &Path) -> Result<(), BuildError> {
let module = glsl::Frontend::default()
.parse(&GlslOptions::from(stage), &src)
.map_err(|e| (ext.clone(), e))?;
let info = Validator::new(ValidationFlags::all(), Default::default())
.validate(&module)
.map_err(|e| (ext.clone(), e.into_inner()))?;
let info = Validator::new(
ValidationFlags::all(),
Capabilities::default().union(Capabilities::PUSH_CONSTANT),
)
.validate(&module)
.map_err(|e| (ext.clone(), e.into_inner()))?;
let mut writer = spv::Writer::new(&spv::Options {
flags: WriterFlags::empty(),
..Default::default()

View file

@ -6,13 +6,26 @@ layout(location = 2) in vec3 normal_in;
layout(location = 3) in vec2 tex_coords;
layout(location = 0) out vec2 tex_coord;
layout(location = 1) out vec3 normal;
layout(push_constant) uniform float TIME;
layout(set = 0, binding = 0) uniform UniformBufferObject {
mat4x4 projection;
} view;
mat4 rotation(float lerp) {
return mat4(cos(lerp), -sin(lerp), 0., 0.,
sin(lerp), cos(lerp), 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.);
}
void main() {
gl_Position = view.projection * vec4(position, 1.0);
float sum_val = sin(TIME / 5);
gl_Position = view.projection * transpose(mat4(
1.0, 0.0, 0.0, sum_val,
0.0, 1.0, 0.0, sum_val,
0.0, 0.0, 1.0, sum_val,
0.0, 0.0, 0.0, 1.0) * mat4((sin(TIME) + 1.0) / 2, 0.0, 0.0, 0.0,
0.0, (sin(TIME) + 1.0) / 2, 0.0, 0.0,
0.0, 0.0, (sin(TIME) + 1.0) / 2, 0.0,
0.0, 0.0, 0.0, 1) * rotation(TIME * 2.5)) * vec4(position, 1.0);
tex_coord = tex_coords;
normal = normal_in;
// gl_Position
// out_color = color;
}

View file

@ -6,7 +6,8 @@ use std::time::Instant;
use tracing::info;
use wgpu::util::DeviceExt;
use wgpu::{
Backends, FragmentState, IndexFormat, Instance, InstanceDescriptor, PipelineCompilationOptions,
Backends, Features, FragmentState, IndexFormat, Instance, InstanceDescriptor, Limits,
PipelineCompilationOptions, PushConstantRange, ShaderStages,
};
use winit::application::ApplicationHandler;
use winit::event::{ElementState, MouseButton};
@ -48,6 +49,9 @@ struct WgpuRenderer<'surface> {
camera_bind_group: wgpu::BindGroup,
pumpkin: model::Model,
delta: f32,
time_elapsed: f32,
start_time: Instant,
last_frame_time: Instant,
default_texture: wgpu::BindGroup,
}
@ -85,6 +89,11 @@ impl WgpuRenderer<'_> {
});
rpass.set_pipeline(&self.render_pipeline);
rpass.set_bind_group(0, &self.camera_bind_group, &[]);
rpass.set_push_constants(
ShaderStages::VERTEX,
0,
&bytemuck::cast_slice(&[self.time_elapsed]),
);
for mesh in &self.pumpkin.meshes {
let bind_group = mesh
@ -99,9 +108,12 @@ impl WgpuRenderer<'_> {
}
}
self.queue.submit(Some(encoder.finish()));
let elapsed_time = std::time::Instant::elapsed(&self.start_time);
self.time_elapsed = elapsed_time.as_secs_f32();
info!("{}", self.time_elapsed);
let delta_time = std::time::Instant::now() - self.last_frame_time;
self.delta = delta_time.as_secs_f32();
info!("{}", self.delta);
// info!("{}", self.delta);
surface_texture.present();
self.last_frame_time = std::time::Instant::now();
}
@ -159,11 +171,19 @@ impl WgpuState {
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: Some(&surface),
..Default::default()
})
.await
.unwrap();
let device_descriptor = wgpu::DeviceDescriptor::default();
let device_descriptor = wgpu::DeviceDescriptor {
required_features: Features::PUSH_CONSTANTS,
required_limits: Limits {
max_push_constant_size: 4,
..Default::default()
},
..Default::default()
};
let (device, queue) = adapter.request_device(&device_descriptor).await.unwrap();
let size = window.inner_size();
@ -212,7 +232,10 @@ impl WgpuState {
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Pipeline Layout"),
bind_group_layouts: &[&camera_bind_group_layout, &texture_bind_group_layout],
push_constant_ranges: &[],
push_constant_ranges: &[PushConstantRange {
stages: ShaderStages::VERTEX,
range: 0..4,
}],
});
let vert_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
@ -373,6 +396,7 @@ impl WgpuState {
let render_pipeline = device.create_render_pipeline(&pipeline_descriptor);
WgpuRenderer {
time_elapsed: 0.0,
surface,
surface_config,
depth_texture,
@ -386,6 +410,8 @@ impl WgpuState {
depth_texture_view,
pumpkin,
default_texture,
start_time: std::time::Instant::now(),
delta: 0f32,
last_frame_time: Instant::now(),
}
@ -429,7 +455,8 @@ impl ApplicationHandler for App<'_> {
match event {
winit::event::WindowEvent::RedrawRequested => {
let window_ctx = self.windows.get_mut(&window_id).unwrap();
window_ctx.renderer.draw()
window_ctx.renderer.draw();
window_ctx.request_redraw();
}
winit::event::WindowEvent::CloseRequested => {
let _ = self.windows.remove(&window_id);