From f9798743b8dca628c2273c818b28d82ffb31a785 Mon Sep 17 00:00:00 2001 From: nullprop Date: Sat, 11 Nov 2023 17:31:04 +0200 Subject: [PATCH] Pass roughness & metalness factors to shader --- res/shaders/globals.wgsl | 7 +++++++ res/shaders/pbr.wgsl | 10 ++++++---- src/core/material.rs | 30 ++++++++++++++++++++++++------ src/core/state.rs | 13 +++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/res/shaders/globals.wgsl b/res/shaders/globals.wgsl index 772670b..70eaf6b 100644 --- a/res/shaders/globals.wgsl +++ b/res/shaders/globals.wgsl @@ -27,6 +27,13 @@ struct GlobalUniforms { @group(0) @binding(2) var global_uniforms: GlobalUniforms; +struct MaterialUniform { + metallic_factor: f32, + rougness_factor: f32, + _padding1: f32, + _padding2: f32, +} + struct VertexInput { @location(0) position: vec3, @location(1) tex_coords: vec2, diff --git a/res/shaders/pbr.wgsl b/res/shaders/pbr.wgsl index ab4fc71..85677f1 100644 --- a/res/shaders/pbr.wgsl +++ b/res/shaders/pbr.wgsl @@ -67,6 +67,9 @@ var t_roughness_metalness: texture_2d; @group(2) @binding(5) var s_roughness_metalness: sampler; +@group(2) @binding(6) +var material_uniform: MaterialUniform; + @fragment fn fs_main(vert: VertexOutput) -> @location(0) vec4 { // textures @@ -76,10 +79,9 @@ fn fs_main(vert: VertexOutput) -> @location(0) vec4 { t_roughness_metalness, s_roughness_metalness, vert.tex_coords); let albedo = object_color.xyz; - // TODO: pass factors to shader - let roughness = object_roughness_metalness.y * 1.0; - let metalness = object_roughness_metalness.z * 1.0; - + let roughness = object_roughness_metalness.y * material_uniform.rougness_factor; + let metalness = object_roughness_metalness.z * material_uniform.metallic_factor; + var total_radiance: vec3; let in_light = sample_direct_light(vert.world_position); diff --git a/src/core/material.rs b/src/core/material.rs index 34e782b..071c64f 100644 --- a/src/core/material.rs +++ b/src/core/material.rs @@ -1,3 +1,4 @@ +use wgpu::util::DeviceExt; use crate::core::texture::Texture; pub struct Material { @@ -5,13 +6,17 @@ pub struct Material { pub diffuse_texture: Texture, pub normal_texture: Texture, pub metallic_roughness_texture: Texture, - // TODO pass to shader - pub metallic_factor: f32, - // TODO pass to shader - pub roughness_factor: f32, + pub material_uniform: MaterialUniform, pub bind_group: wgpu::BindGroup, } +#[repr(C)] +#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +pub struct MaterialUniform { + // metallic, roughness, none, none + pub factors: [f32; 4], +} + impl Material { pub fn new( device: &wgpu::Device, @@ -23,6 +28,15 @@ impl Material { roughness_factor: f32, layout: &wgpu::BindGroupLayout, ) -> Self { + let material_uniform = MaterialUniform { + factors: [metallic_factor, roughness_factor, 0.0, 0.0] + }; + let material_uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Material Uniform UB"), + contents: bytemuck::cast_slice(&[material_uniform]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { layout, entries: &[ @@ -53,6 +67,11 @@ impl Material { binding: 5, resource: wgpu::BindingResource::Sampler(&metallic_roughness_texture.sampler), }, + // uniform + wgpu::BindGroupEntry { + binding: 6, + resource: material_uniform_buffer.as_entire_binding(), + } ], label: None, }); @@ -62,8 +81,7 @@ impl Material { diffuse_texture, normal_texture, metallic_roughness_texture, - metallic_factor, - roughness_factor, + material_uniform, bind_group, } } diff --git a/src/core/state.rs b/src/core/state.rs index d1c7cfd..7ecb3f0 100644 --- a/src/core/state.rs +++ b/src/core/state.rs @@ -5,6 +5,7 @@ use std::time::Duration; use wgpu::util::DeviceExt; use winit::{event::*, window::Window}; +use crate::core::material::MaterialUniform; use super::camera::{Camera, CameraController, CameraUniform}; use super::instance::{Instance, InstanceRaw}; @@ -305,6 +306,7 @@ impl State { let geometry_depth_bind_group = State::create_geometry_depth_bind_group(&device, &geometry_depth_bind_group_layout, &geometry_depth_texture); + let material_uniform_size = mem::size_of::() as u64; let texture_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[ @@ -359,6 +361,17 @@ impl State { ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, }, + // material uniform + wgpu::BindGroupLayoutEntry { + binding: 6, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: wgpu::BufferSize::new(material_uniform_size), + }, + count: None, + }, ], label: Some("texture_bind_group_layout"), });