diff --git a/crates/voltex_renderer/src/deferred_gbuffer.wgsl b/crates/voltex_renderer/src/deferred_gbuffer.wgsl index c4397da..db646ab 100644 --- a/crates/voltex_renderer/src/deferred_gbuffer.wgsl +++ b/crates/voltex_renderer/src/deferred_gbuffer.wgsl @@ -20,6 +20,10 @@ struct MaterialUniform { @group(1) @binding(1) var s_albedo: sampler; @group(1) @binding(2) var t_normal: texture_2d; @group(1) @binding(3) var s_normal: sampler; +@group(1) @binding(4) var t_orm: texture_2d; +@group(1) @binding(5) var s_orm: sampler; +@group(1) @binding(6) var t_emissive: texture_2d; +@group(1) @binding(7) var s_emissive: sampler; @group(2) @binding(0) var material: MaterialUniform; @@ -84,11 +88,21 @@ fn fs_main(in: VertexOutput) -> GBufferOutput { let TBN = mat3x3(T, B, N_geom); let N = normalize(TBN * tangent_normal); + // Sample ORM texture: R=AO, G=Roughness, B=Metallic; multiply with material params + let orm_sample = textureSample(t_orm, s_orm, in.uv); + let ao = orm_sample.r * material.ao; + let roughness = orm_sample.g * material.roughness; + let metallic = orm_sample.b * material.metallic; + + // Sample emissive texture and compute luminance + let emissive = textureSample(t_emissive, s_emissive, in.uv).rgb; + let emissive_lum = dot(emissive, vec3(0.299, 0.587, 0.114)); + var out: GBufferOutput; out.position = vec4(in.world_pos, 1.0); out.normal = vec4(N * 0.5 + 0.5, 1.0); out.albedo = vec4(albedo, material.base_color.a * tex_color.a); - out.material_data = vec4(material.metallic, material.roughness, material.ao, 1.0); + out.material_data = vec4(metallic, roughness, ao, emissive_lum); return out; } diff --git a/crates/voltex_renderer/src/deferred_lighting.wgsl b/crates/voltex_renderer/src/deferred_lighting.wgsl index 905ea66..a04d9e4 100644 --- a/crates/voltex_renderer/src/deferred_lighting.wgsl +++ b/crates/voltex_renderer/src/deferred_lighting.wgsl @@ -260,6 +260,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { let metallic = mat_sample.r; let roughness = mat_sample.g; let ao = mat_sample.b; + let emissive_lum = mat_sample.w; let V = normalize(camera_uniform.camera_pos - world_pos); @@ -306,7 +307,10 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { let ambient = (diffuse_ibl + specular_ibl) * ao * ssgi_ao + ssgi_indirect; // Output raw HDR linear colour; tonemap is applied in a separate tonemap pass. - let color = ambient + Lo; + var color = ambient + Lo; + + // Add emissive contribution (luminance stored in G-Buffer, modulated by albedo) + color += albedo * emissive_lum; return vec4(color, alpha); } diff --git a/crates/voltex_renderer/src/lib.rs b/crates/voltex_renderer/src/lib.rs index a025d21..50c081b 100644 --- a/crates/voltex_renderer/src/lib.rs +++ b/crates/voltex_renderer/src/lib.rs @@ -32,7 +32,7 @@ pub use gpu::{GpuContext, DEPTH_FORMAT}; pub use light::{CameraUniform, LightUniform, LightData, LightsUniform, MAX_LIGHTS, LIGHT_DIRECTIONAL, LIGHT_POINT, LIGHT_SPOT}; pub use mesh::Mesh; pub use camera::{Camera, FpsController}; -pub use texture::{GpuTexture, pbr_texture_bind_group_layout, create_pbr_texture_bind_group}; +pub use texture::{GpuTexture, pbr_texture_bind_group_layout, create_pbr_texture_bind_group, pbr_full_texture_bind_group_layout, create_pbr_full_texture_bind_group}; pub use material::MaterialUniform; pub use sphere::generate_sphere; pub use pbr_pipeline::create_pbr_pipeline; diff --git a/crates/voltex_renderer/src/pbr_shader.wgsl b/crates/voltex_renderer/src/pbr_shader.wgsl index 66830fc..3407367 100644 --- a/crates/voltex_renderer/src/pbr_shader.wgsl +++ b/crates/voltex_renderer/src/pbr_shader.wgsl @@ -36,6 +36,10 @@ struct MaterialUniform { @group(1) @binding(1) var s_diffuse: sampler; @group(1) @binding(2) var t_normal: texture_2d; @group(1) @binding(3) var s_normal: sampler; +@group(1) @binding(4) var t_orm: texture_2d; +@group(1) @binding(5) var s_orm: sampler; +@group(1) @binding(6) var t_emissive: texture_2d; +@group(1) @binding(7) var s_emissive: sampler; @group(2) @binding(0) var material: MaterialUniform; @@ -250,9 +254,15 @@ fn sample_environment(direction: vec3, roughness: f32) -> vec3 { fn fs_main(in: VertexOutput) -> @location(0) vec4 { let tex_color = textureSample(t_diffuse, s_diffuse, in.uv); let albedo = material.base_color.rgb * tex_color.rgb; - let metallic = material.metallic; - let roughness = material.roughness; - let ao = material.ao; + + // Sample ORM texture: R=AO, G=Roughness, B=Metallic; multiply with material params + let orm_sample = textureSample(t_orm, s_orm, in.uv); + let ao = orm_sample.r * material.ao; + let roughness = orm_sample.g * material.roughness; + let metallic = orm_sample.b * material.metallic; + + // Sample emissive texture + let emissive = textureSample(t_emissive, s_emissive, in.uv).rgb; // Normal mapping via TBN matrix let T = normalize(in.world_tangent); @@ -304,7 +314,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { let ambient = (diffuse_ibl + specular_ibl) * ao; - var color = ambient + Lo; + var color = ambient + Lo + emissive; // Reinhard tone mapping color = color / (color + vec3(1.0)); diff --git a/crates/voltex_renderer/src/texture.rs b/crates/voltex_renderer/src/texture.rs index 965ead5..5b88f37 100644 --- a/crates/voltex_renderer/src/texture.rs +++ b/crates/voltex_renderer/src/texture.rs @@ -155,6 +155,15 @@ impl GpuTexture { Self::from_rgba(device, queue, 1, 1, &[255, 255, 255, 255], layout) } + /// Create a 1x1 black texture (RGBA 0,0,0,255). Used as default emissive (no emission). + pub fn black_1x1( + device: &wgpu::Device, + queue: &wgpu::Queue, + layout: &wgpu::BindGroupLayout, + ) -> Self { + Self::from_rgba(device, queue, 1, 1, &[0, 0, 0, 255], layout) + } + pub fn bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("TextureBindGroupLayout"), @@ -316,6 +325,140 @@ pub fn create_pbr_texture_bind_group( }) } +/// Bind group layout for full PBR textures: albedo (0-1) + normal (2-3) + ORM (4-5) + emissive (6-7). +pub fn pbr_full_texture_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("PBR Full Texture Bind Group Layout"), + entries: &[ + // binding 0: albedo texture + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, + }, + // binding 1: albedo sampler + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + // binding 2: normal map texture + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, + }, + // binding 3: normal map sampler + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + // binding 4: ORM texture (AO/Roughness/Metallic) + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, + }, + // binding 5: ORM sampler + wgpu::BindGroupLayoutEntry { + binding: 5, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + // binding 6: emissive texture + wgpu::BindGroupLayoutEntry { + binding: 6, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, + }, + // binding 7: emissive sampler + wgpu::BindGroupLayoutEntry { + binding: 7, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + ], + }) +} + +/// Create a bind group for full PBR textures (albedo + normal + ORM + emissive). +pub fn create_pbr_full_texture_bind_group( + device: &wgpu::Device, + layout: &wgpu::BindGroupLayout, + albedo_view: &wgpu::TextureView, + albedo_sampler: &wgpu::Sampler, + normal_view: &wgpu::TextureView, + normal_sampler: &wgpu::Sampler, + orm_view: &wgpu::TextureView, + orm_sampler: &wgpu::Sampler, + emissive_view: &wgpu::TextureView, + emissive_sampler: &wgpu::Sampler, +) -> wgpu::BindGroup { + device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("PBR Full Texture Bind Group"), + layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(albedo_view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(albedo_sampler), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(normal_view), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::Sampler(normal_sampler), + }, + wgpu::BindGroupEntry { + binding: 4, + resource: wgpu::BindingResource::TextureView(orm_view), + }, + wgpu::BindGroupEntry { + binding: 5, + resource: wgpu::BindingResource::Sampler(orm_sampler), + }, + wgpu::BindGroupEntry { + binding: 6, + resource: wgpu::BindingResource::TextureView(emissive_view), + }, + wgpu::BindGroupEntry { + binding: 7, + resource: wgpu::BindingResource::Sampler(emissive_sampler), + }, + ], + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/examples/deferred_demo/src/main.rs b/examples/deferred_demo/src/main.rs index 782a5bd..fe2364d 100644 --- a/examples/deferred_demo/src/main.rs +++ b/examples/deferred_demo/src/main.rs @@ -16,7 +16,7 @@ use voltex_renderer::{ gbuffer_camera_bind_group_layout, lighting_gbuffer_bind_group_layout, lighting_lights_bind_group_layout, lighting_shadow_bind_group_layout, - pbr_texture_bind_group_layout, create_pbr_texture_bind_group, + pbr_full_texture_bind_group_layout, create_pbr_full_texture_bind_group, SsgiResources, SsgiUniform, ssgi_gbuffer_bind_group_layout, ssgi_data_bind_group_layout, create_ssgi_pipeline, RtAccel, RtInstance, BlasMeshData, RtShadowResources, RtShadowUniform, @@ -119,6 +119,8 @@ struct AppState { // Keep textures alive _albedo_tex: GpuTexture, _normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler), + _orm_tex: GpuTexture, + _emissive_tex: GpuTexture, _shadow_map: ShadowMap, _ibl: IblResources, _shadow_uniform_buffer: wgpu::Buffer, @@ -171,7 +173,7 @@ impl ApplicationHandler for DeferredDemoApp { // G-Buffer pass bind group layouts // --------------------------------------------------------------- let gbuf_cam_layout = gbuffer_camera_bind_group_layout(&gpu.device); - let pbr_tex_layout = pbr_texture_bind_group_layout(&gpu.device); + let pbr_tex_layout = pbr_full_texture_bind_group_layout(&gpu.device); let mat_layout = MaterialUniform::bind_group_layout(&gpu.device); // Camera dynamic uniform buffer (one CameraUniform per sphere) @@ -204,17 +206,23 @@ impl ApplicationHandler for DeferredDemoApp { }], }); - // PBR textures: white albedo + flat normal + // PBR textures: white albedo + flat normal + ORM + emissive let old_tex_layout = GpuTexture::bind_group_layout(&gpu.device); let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); let normal_tex = GpuTexture::flat_normal_1x1(&gpu.device, &gpu.queue); - let pbr_texture_bind_group = create_pbr_texture_bind_group( + let orm_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let emissive_tex = GpuTexture::black_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let pbr_texture_bind_group = create_pbr_full_texture_bind_group( &gpu.device, &pbr_tex_layout, &albedo_tex.view, &albedo_tex.sampler, &normal_tex.1, &normal_tex.2, + &orm_tex.view, + &orm_tex.sampler, + &emissive_tex.view, + &emissive_tex.sampler, ); // Material bind group (dynamic offset, group 2) @@ -581,6 +589,8 @@ impl ApplicationHandler for DeferredDemoApp { shadow_layout, _albedo_tex: albedo_tex, _normal_tex: normal_tex, + _orm_tex: orm_tex, + _emissive_tex: emissive_tex, _shadow_map: shadow_map, _ibl: ibl, _shadow_uniform_buffer: shadow_uniform_buffer, diff --git a/examples/ibl_demo/src/main.rs b/examples/ibl_demo/src/main.rs index ee5e180..74978f5 100644 --- a/examples/ibl_demo/src/main.rs +++ b/examples/ibl_demo/src/main.rs @@ -11,7 +11,7 @@ use voltex_renderer::{ GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData, Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, ShadowMap, ShadowUniform, - IblResources, pbr_texture_bind_group_layout, create_pbr_texture_bind_group, + IblResources, pbr_full_texture_bind_group_layout, create_pbr_full_texture_bind_group, }; use wgpu::util::DeviceExt; @@ -36,6 +36,8 @@ struct AppState { camera_light_bind_group: wgpu::BindGroup, _albedo_tex: GpuTexture, _normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler), + _orm_tex: GpuTexture, + _emissive_tex: GpuTexture, pbr_texture_bind_group: wgpu::BindGroup, material_bind_group: wgpu::BindGroup, shadow_bind_group: wgpu::BindGroup, @@ -138,7 +140,7 @@ impl ApplicationHandler for IblDemoApp { // Bind group layouts let cl_layout = camera_light_bind_group_layout(&gpu.device); - let pbr_tex_layout = pbr_texture_bind_group_layout(&gpu.device); + let pbr_tex_layout = pbr_full_texture_bind_group_layout(&gpu.device); let mat_layout = MaterialUniform::bind_group_layout(&gpu.device); // Camera+Light bind group @@ -163,17 +165,23 @@ impl ApplicationHandler for IblDemoApp { ], }); - // PBR texture bind group (albedo + normal) + // PBR texture bind group (albedo + normal + ORM + emissive) let old_tex_layout = GpuTexture::bind_group_layout(&gpu.device); let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); let normal_tex = GpuTexture::flat_normal_1x1(&gpu.device, &gpu.queue); - let pbr_texture_bind_group = create_pbr_texture_bind_group( + let orm_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let emissive_tex = GpuTexture::black_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let pbr_texture_bind_group = create_pbr_full_texture_bind_group( &gpu.device, &pbr_tex_layout, &albedo_tex.view, &albedo_tex.sampler, &normal_tex.1, &normal_tex.2, + &orm_tex.view, + &orm_tex.sampler, + &emissive_tex.view, + &emissive_tex.sampler, ); // IBL resources @@ -240,6 +248,8 @@ impl ApplicationHandler for IblDemoApp { camera_light_bind_group, _albedo_tex: albedo_tex, _normal_tex: normal_tex, + _orm_tex: orm_tex, + _emissive_tex: emissive_tex, pbr_texture_bind_group, material_bind_group, shadow_bind_group, diff --git a/examples/multi_light_demo/src/main.rs b/examples/multi_light_demo/src/main.rs index 7d96b1e..b935597 100644 --- a/examples/multi_light_demo/src/main.rs +++ b/examples/multi_light_demo/src/main.rs @@ -11,7 +11,7 @@ use voltex_renderer::{ GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData, Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, obj, ShadowMap, ShadowUniform, - IblResources, pbr_texture_bind_group_layout, create_pbr_texture_bind_group, + IblResources, pbr_full_texture_bind_group_layout, create_pbr_full_texture_bind_group, }; use wgpu::util::DeviceExt; @@ -35,6 +35,8 @@ struct AppState { camera_light_bind_group: wgpu::BindGroup, _albedo_tex: GpuTexture, _normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler), + _orm_tex: GpuTexture, + _emissive_tex: GpuTexture, pbr_texture_bind_group: wgpu::BindGroup, material_bind_group: wgpu::BindGroup, shadow_bind_group: wgpu::BindGroup, @@ -149,7 +151,7 @@ impl ApplicationHandler for MultiLightApp { // Bind group layouts let cl_layout = camera_light_bind_group_layout(&gpu.device); - let pbr_tex_layout = pbr_texture_bind_group_layout(&gpu.device); + let pbr_tex_layout = pbr_full_texture_bind_group_layout(&gpu.device); let mat_layout = MaterialUniform::bind_group_layout(&gpu.device); // Camera+Light bind group @@ -174,17 +176,23 @@ impl ApplicationHandler for MultiLightApp { ], }); - // PBR texture bind group (albedo + normal) + // PBR texture bind group (albedo + normal + ORM + emissive) let old_tex_layout = GpuTexture::bind_group_layout(&gpu.device); let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); let normal_tex = GpuTexture::flat_normal_1x1(&gpu.device, &gpu.queue); - let pbr_texture_bind_group = create_pbr_texture_bind_group( + let orm_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let emissive_tex = GpuTexture::black_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let pbr_texture_bind_group = create_pbr_full_texture_bind_group( &gpu.device, &pbr_tex_layout, &albedo_tex.view, &albedo_tex.sampler, &normal_tex.1, &normal_tex.2, + &orm_tex.view, + &orm_tex.sampler, + &emissive_tex.view, + &emissive_tex.sampler, ); // IBL resources @@ -252,6 +260,8 @@ impl ApplicationHandler for MultiLightApp { camera_light_bind_group, _albedo_tex: albedo_tex, _normal_tex: normal_tex, + _orm_tex: orm_tex, + _emissive_tex: emissive_tex, pbr_texture_bind_group, material_bind_group, shadow_bind_group, diff --git a/examples/pbr_demo/src/main.rs b/examples/pbr_demo/src/main.rs index 6ab0efc..838bf89 100644 --- a/examples/pbr_demo/src/main.rs +++ b/examples/pbr_demo/src/main.rs @@ -11,7 +11,7 @@ use voltex_renderer::{ GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData, Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, ShadowMap, ShadowUniform, - IblResources, pbr_texture_bind_group_layout, create_pbr_texture_bind_group, + IblResources, pbr_full_texture_bind_group_layout, create_pbr_full_texture_bind_group, }; use wgpu::util::DeviceExt; @@ -36,6 +36,8 @@ struct AppState { camera_light_bind_group: wgpu::BindGroup, _albedo_tex: GpuTexture, _normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler), + _orm_tex: GpuTexture, + _emissive_tex: GpuTexture, pbr_texture_bind_group: wgpu::BindGroup, material_bind_group: wgpu::BindGroup, shadow_bind_group: wgpu::BindGroup, @@ -134,7 +136,7 @@ impl ApplicationHandler for PbrDemoApp { // Bind group layouts let cl_layout = camera_light_bind_group_layout(&gpu.device); - let pbr_tex_layout = pbr_texture_bind_group_layout(&gpu.device); + let pbr_tex_layout = pbr_full_texture_bind_group_layout(&gpu.device); let mat_layout = MaterialUniform::bind_group_layout(&gpu.device); // Camera+Light bind group @@ -159,17 +161,23 @@ impl ApplicationHandler for PbrDemoApp { ], }); - // PBR texture bind group (albedo + normal) + // PBR texture bind group (albedo + normal + ORM + emissive) let old_tex_layout = GpuTexture::bind_group_layout(&gpu.device); let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); let normal_tex = GpuTexture::flat_normal_1x1(&gpu.device, &gpu.queue); - let pbr_texture_bind_group = create_pbr_texture_bind_group( + let orm_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let emissive_tex = GpuTexture::black_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let pbr_texture_bind_group = create_pbr_full_texture_bind_group( &gpu.device, &pbr_tex_layout, &albedo_tex.view, &albedo_tex.sampler, &normal_tex.1, &normal_tex.2, + &orm_tex.view, + &orm_tex.sampler, + &emissive_tex.view, + &emissive_tex.sampler, ); // IBL resources @@ -236,6 +244,8 @@ impl ApplicationHandler for PbrDemoApp { camera_light_bind_group, _albedo_tex: albedo_tex, _normal_tex: normal_tex, + _orm_tex: orm_tex, + _emissive_tex: emissive_tex, pbr_texture_bind_group, material_bind_group, shadow_bind_group, diff --git a/examples/shadow_demo/src/main.rs b/examples/shadow_demo/src/main.rs index 7cc4f26..ab4673d 100644 --- a/examples/shadow_demo/src/main.rs +++ b/examples/shadow_demo/src/main.rs @@ -12,7 +12,7 @@ use voltex_renderer::{ Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, obj, ShadowMap, ShadowUniform, ShadowPassUniform, SHADOW_MAP_SIZE, create_shadow_pipeline, shadow_pass_bind_group_layout, - IblResources, pbr_texture_bind_group_layout, create_pbr_texture_bind_group, + IblResources, pbr_full_texture_bind_group_layout, create_pbr_full_texture_bind_group, }; use wgpu::util::DeviceExt; @@ -39,6 +39,8 @@ struct AppState { camera_light_bind_group: wgpu::BindGroup, _albedo_tex: GpuTexture, _normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler), + _orm_tex: GpuTexture, + _emissive_tex: GpuTexture, pbr_texture_bind_group: wgpu::BindGroup, material_bind_group: wgpu::BindGroup, // Shadow resources @@ -188,7 +190,7 @@ impl ApplicationHandler for ShadowDemoApp { // Bind group layouts let cl_layout = camera_light_bind_group_layout(&gpu.device); - let pbr_tex_layout = pbr_texture_bind_group_layout(&gpu.device); + let pbr_tex_layout = pbr_full_texture_bind_group_layout(&gpu.device); let mat_layout = MaterialUniform::bind_group_layout(&gpu.device); // Camera+Light bind group @@ -211,17 +213,23 @@ impl ApplicationHandler for ShadowDemoApp { ], }); - // PBR texture bind group (albedo + normal) + // PBR texture bind group (albedo + normal + ORM + emissive) let old_tex_layout = GpuTexture::bind_group_layout(&gpu.device); let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); let normal_tex = GpuTexture::flat_normal_1x1(&gpu.device, &gpu.queue); - let pbr_texture_bind_group = create_pbr_texture_bind_group( + let orm_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let emissive_tex = GpuTexture::black_1x1(&gpu.device, &gpu.queue, &old_tex_layout); + let pbr_texture_bind_group = create_pbr_full_texture_bind_group( &gpu.device, &pbr_tex_layout, &albedo_tex.view, &albedo_tex.sampler, &normal_tex.1, &normal_tex.2, + &orm_tex.view, + &orm_tex.sampler, + &emissive_tex.view, + &emissive_tex.sampler, ); // IBL resources @@ -311,6 +319,8 @@ impl ApplicationHandler for ShadowDemoApp { camera_light_bind_group, _albedo_tex: albedo_tex, _normal_tex: normal_tex, + _orm_tex: orm_tex, + _emissive_tex: emissive_tex, pbr_texture_bind_group, material_bind_group, shadow_map,