feat(renderer): add ORM and emissive texture map support to PBR pipeline
- Extended bind group 1: albedo + normal + ORM + emissive (8 bindings) - pbr_shader.wgsl: ORM sampling (R=AO, G=roughness, B=metallic) + emissive - deferred_gbuffer.wgsl: ORM + emissive luminance in material_data.w - deferred_lighting.wgsl: emissive contribution from G-Buffer - All 5 PBR examples updated with default ORM/emissive textures - Backward compatible: old 4-binding layout preserved Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,10 @@ struct MaterialUniform {
|
|||||||
@group(1) @binding(1) var s_albedo: sampler;
|
@group(1) @binding(1) var s_albedo: sampler;
|
||||||
@group(1) @binding(2) var t_normal: texture_2d<f32>;
|
@group(1) @binding(2) var t_normal: texture_2d<f32>;
|
||||||
@group(1) @binding(3) var s_normal: sampler;
|
@group(1) @binding(3) var s_normal: sampler;
|
||||||
|
@group(1) @binding(4) var t_orm: texture_2d<f32>;
|
||||||
|
@group(1) @binding(5) var s_orm: sampler;
|
||||||
|
@group(1) @binding(6) var t_emissive: texture_2d<f32>;
|
||||||
|
@group(1) @binding(7) var s_emissive: sampler;
|
||||||
|
|
||||||
@group(2) @binding(0) var<uniform> material: MaterialUniform;
|
@group(2) @binding(0) var<uniform> material: MaterialUniform;
|
||||||
|
|
||||||
@@ -84,11 +88,21 @@ fn fs_main(in: VertexOutput) -> GBufferOutput {
|
|||||||
let TBN = mat3x3<f32>(T, B, N_geom);
|
let TBN = mat3x3<f32>(T, B, N_geom);
|
||||||
let N = normalize(TBN * tangent_normal);
|
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<f32>(0.299, 0.587, 0.114));
|
||||||
|
|
||||||
var out: GBufferOutput;
|
var out: GBufferOutput;
|
||||||
out.position = vec4<f32>(in.world_pos, 1.0);
|
out.position = vec4<f32>(in.world_pos, 1.0);
|
||||||
out.normal = vec4<f32>(N * 0.5 + 0.5, 1.0);
|
out.normal = vec4<f32>(N * 0.5 + 0.5, 1.0);
|
||||||
out.albedo = vec4<f32>(albedo, material.base_color.a * tex_color.a);
|
out.albedo = vec4<f32>(albedo, material.base_color.a * tex_color.a);
|
||||||
out.material_data = vec4<f32>(material.metallic, material.roughness, material.ao, 1.0);
|
out.material_data = vec4<f32>(metallic, roughness, ao, emissive_lum);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||||||
let metallic = mat_sample.r;
|
let metallic = mat_sample.r;
|
||||||
let roughness = mat_sample.g;
|
let roughness = mat_sample.g;
|
||||||
let ao = mat_sample.b;
|
let ao = mat_sample.b;
|
||||||
|
let emissive_lum = mat_sample.w;
|
||||||
|
|
||||||
let V = normalize(camera_uniform.camera_pos - world_pos);
|
let V = normalize(camera_uniform.camera_pos - world_pos);
|
||||||
|
|
||||||
@@ -306,7 +307,10 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||||||
let ambient = (diffuse_ibl + specular_ibl) * ao * ssgi_ao + ssgi_indirect;
|
let ambient = (diffuse_ibl + specular_ibl) * ao * ssgi_ao + ssgi_indirect;
|
||||||
|
|
||||||
// Output raw HDR linear colour; tonemap is applied in a separate tonemap pass.
|
// 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<f32>(color, alpha);
|
return vec4<f32>(color, alpha);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 light::{CameraUniform, LightUniform, LightData, LightsUniform, MAX_LIGHTS, LIGHT_DIRECTIONAL, LIGHT_POINT, LIGHT_SPOT};
|
||||||
pub use mesh::Mesh;
|
pub use mesh::Mesh;
|
||||||
pub use camera::{Camera, FpsController};
|
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 material::MaterialUniform;
|
||||||
pub use sphere::generate_sphere;
|
pub use sphere::generate_sphere;
|
||||||
pub use pbr_pipeline::create_pbr_pipeline;
|
pub use pbr_pipeline::create_pbr_pipeline;
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ struct MaterialUniform {
|
|||||||
@group(1) @binding(1) var s_diffuse: sampler;
|
@group(1) @binding(1) var s_diffuse: sampler;
|
||||||
@group(1) @binding(2) var t_normal: texture_2d<f32>;
|
@group(1) @binding(2) var t_normal: texture_2d<f32>;
|
||||||
@group(1) @binding(3) var s_normal: sampler;
|
@group(1) @binding(3) var s_normal: sampler;
|
||||||
|
@group(1) @binding(4) var t_orm: texture_2d<f32>;
|
||||||
|
@group(1) @binding(5) var s_orm: sampler;
|
||||||
|
@group(1) @binding(6) var t_emissive: texture_2d<f32>;
|
||||||
|
@group(1) @binding(7) var s_emissive: sampler;
|
||||||
|
|
||||||
@group(2) @binding(0) var<uniform> material: MaterialUniform;
|
@group(2) @binding(0) var<uniform> material: MaterialUniform;
|
||||||
|
|
||||||
@@ -250,9 +254,15 @@ fn sample_environment(direction: vec3<f32>, roughness: f32) -> vec3<f32> {
|
|||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let tex_color = textureSample(t_diffuse, s_diffuse, in.uv);
|
let tex_color = textureSample(t_diffuse, s_diffuse, in.uv);
|
||||||
let albedo = material.base_color.rgb * tex_color.rgb;
|
let albedo = material.base_color.rgb * tex_color.rgb;
|
||||||
let metallic = material.metallic;
|
|
||||||
let roughness = material.roughness;
|
// Sample ORM texture: R=AO, G=Roughness, B=Metallic; multiply with material params
|
||||||
let ao = material.ao;
|
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
|
// Normal mapping via TBN matrix
|
||||||
let T = normalize(in.world_tangent);
|
let T = normalize(in.world_tangent);
|
||||||
@@ -304,7 +314,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||||||
|
|
||||||
let ambient = (diffuse_ibl + specular_ibl) * ao;
|
let ambient = (diffuse_ibl + specular_ibl) * ao;
|
||||||
|
|
||||||
var color = ambient + Lo;
|
var color = ambient + Lo + emissive;
|
||||||
|
|
||||||
// Reinhard tone mapping
|
// Reinhard tone mapping
|
||||||
color = color / (color + vec3<f32>(1.0));
|
color = color / (color + vec3<f32>(1.0));
|
||||||
|
|||||||
@@ -155,6 +155,15 @@ impl GpuTexture {
|
|||||||
Self::from_rgba(device, queue, 1, 1, &[255, 255, 255, 255], layout)
|
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 {
|
pub fn bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: Some("TextureBindGroupLayout"),
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use voltex_renderer::{
|
|||||||
gbuffer_camera_bind_group_layout,
|
gbuffer_camera_bind_group_layout,
|
||||||
lighting_gbuffer_bind_group_layout, lighting_lights_bind_group_layout,
|
lighting_gbuffer_bind_group_layout, lighting_lights_bind_group_layout,
|
||||||
lighting_shadow_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,
|
SsgiResources, SsgiUniform,
|
||||||
ssgi_gbuffer_bind_group_layout, ssgi_data_bind_group_layout, create_ssgi_pipeline,
|
ssgi_gbuffer_bind_group_layout, ssgi_data_bind_group_layout, create_ssgi_pipeline,
|
||||||
RtAccel, RtInstance, BlasMeshData, RtShadowResources, RtShadowUniform,
|
RtAccel, RtInstance, BlasMeshData, RtShadowResources, RtShadowUniform,
|
||||||
@@ -119,6 +119,8 @@ struct AppState {
|
|||||||
// Keep textures alive
|
// Keep textures alive
|
||||||
_albedo_tex: GpuTexture,
|
_albedo_tex: GpuTexture,
|
||||||
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
||||||
|
_orm_tex: GpuTexture,
|
||||||
|
_emissive_tex: GpuTexture,
|
||||||
_shadow_map: ShadowMap,
|
_shadow_map: ShadowMap,
|
||||||
_ibl: IblResources,
|
_ibl: IblResources,
|
||||||
_shadow_uniform_buffer: wgpu::Buffer,
|
_shadow_uniform_buffer: wgpu::Buffer,
|
||||||
@@ -171,7 +173,7 @@ impl ApplicationHandler for DeferredDemoApp {
|
|||||||
// G-Buffer pass bind group layouts
|
// G-Buffer pass bind group layouts
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
let gbuf_cam_layout = gbuffer_camera_bind_group_layout(&gpu.device);
|
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);
|
let mat_layout = MaterialUniform::bind_group_layout(&gpu.device);
|
||||||
|
|
||||||
// Camera dynamic uniform buffer (one CameraUniform per sphere)
|
// 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 old_tex_layout = GpuTexture::bind_group_layout(&gpu.device);
|
||||||
let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout);
|
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 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,
|
&gpu.device,
|
||||||
&pbr_tex_layout,
|
&pbr_tex_layout,
|
||||||
&albedo_tex.view,
|
&albedo_tex.view,
|
||||||
&albedo_tex.sampler,
|
&albedo_tex.sampler,
|
||||||
&normal_tex.1,
|
&normal_tex.1,
|
||||||
&normal_tex.2,
|
&normal_tex.2,
|
||||||
|
&orm_tex.view,
|
||||||
|
&orm_tex.sampler,
|
||||||
|
&emissive_tex.view,
|
||||||
|
&emissive_tex.sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Material bind group (dynamic offset, group 2)
|
// Material bind group (dynamic offset, group 2)
|
||||||
@@ -581,6 +589,8 @@ impl ApplicationHandler for DeferredDemoApp {
|
|||||||
shadow_layout,
|
shadow_layout,
|
||||||
_albedo_tex: albedo_tex,
|
_albedo_tex: albedo_tex,
|
||||||
_normal_tex: normal_tex,
|
_normal_tex: normal_tex,
|
||||||
|
_orm_tex: orm_tex,
|
||||||
|
_emissive_tex: emissive_tex,
|
||||||
_shadow_map: shadow_map,
|
_shadow_map: shadow_map,
|
||||||
_ibl: ibl,
|
_ibl: ibl,
|
||||||
_shadow_uniform_buffer: shadow_uniform_buffer,
|
_shadow_uniform_buffer: shadow_uniform_buffer,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use voltex_renderer::{
|
|||||||
GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData,
|
GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData,
|
||||||
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline,
|
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline,
|
||||||
ShadowMap, ShadowUniform,
|
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;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
@@ -36,6 +36,8 @@ struct AppState {
|
|||||||
camera_light_bind_group: wgpu::BindGroup,
|
camera_light_bind_group: wgpu::BindGroup,
|
||||||
_albedo_tex: GpuTexture,
|
_albedo_tex: GpuTexture,
|
||||||
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
||||||
|
_orm_tex: GpuTexture,
|
||||||
|
_emissive_tex: GpuTexture,
|
||||||
pbr_texture_bind_group: wgpu::BindGroup,
|
pbr_texture_bind_group: wgpu::BindGroup,
|
||||||
material_bind_group: wgpu::BindGroup,
|
material_bind_group: wgpu::BindGroup,
|
||||||
shadow_bind_group: wgpu::BindGroup,
|
shadow_bind_group: wgpu::BindGroup,
|
||||||
@@ -138,7 +140,7 @@ impl ApplicationHandler for IblDemoApp {
|
|||||||
|
|
||||||
// Bind group layouts
|
// Bind group layouts
|
||||||
let cl_layout = camera_light_bind_group_layout(&gpu.device);
|
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);
|
let mat_layout = MaterialUniform::bind_group_layout(&gpu.device);
|
||||||
|
|
||||||
// Camera+Light bind group
|
// 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 old_tex_layout = GpuTexture::bind_group_layout(&gpu.device);
|
||||||
let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout);
|
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 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,
|
&gpu.device,
|
||||||
&pbr_tex_layout,
|
&pbr_tex_layout,
|
||||||
&albedo_tex.view,
|
&albedo_tex.view,
|
||||||
&albedo_tex.sampler,
|
&albedo_tex.sampler,
|
||||||
&normal_tex.1,
|
&normal_tex.1,
|
||||||
&normal_tex.2,
|
&normal_tex.2,
|
||||||
|
&orm_tex.view,
|
||||||
|
&orm_tex.sampler,
|
||||||
|
&emissive_tex.view,
|
||||||
|
&emissive_tex.sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
// IBL resources
|
// IBL resources
|
||||||
@@ -240,6 +248,8 @@ impl ApplicationHandler for IblDemoApp {
|
|||||||
camera_light_bind_group,
|
camera_light_bind_group,
|
||||||
_albedo_tex: albedo_tex,
|
_albedo_tex: albedo_tex,
|
||||||
_normal_tex: normal_tex,
|
_normal_tex: normal_tex,
|
||||||
|
_orm_tex: orm_tex,
|
||||||
|
_emissive_tex: emissive_tex,
|
||||||
pbr_texture_bind_group,
|
pbr_texture_bind_group,
|
||||||
material_bind_group,
|
material_bind_group,
|
||||||
shadow_bind_group,
|
shadow_bind_group,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use voltex_renderer::{
|
|||||||
GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData,
|
GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData,
|
||||||
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, obj,
|
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, obj,
|
||||||
ShadowMap, ShadowUniform,
|
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;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
@@ -35,6 +35,8 @@ struct AppState {
|
|||||||
camera_light_bind_group: wgpu::BindGroup,
|
camera_light_bind_group: wgpu::BindGroup,
|
||||||
_albedo_tex: GpuTexture,
|
_albedo_tex: GpuTexture,
|
||||||
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
||||||
|
_orm_tex: GpuTexture,
|
||||||
|
_emissive_tex: GpuTexture,
|
||||||
pbr_texture_bind_group: wgpu::BindGroup,
|
pbr_texture_bind_group: wgpu::BindGroup,
|
||||||
material_bind_group: wgpu::BindGroup,
|
material_bind_group: wgpu::BindGroup,
|
||||||
shadow_bind_group: wgpu::BindGroup,
|
shadow_bind_group: wgpu::BindGroup,
|
||||||
@@ -149,7 +151,7 @@ impl ApplicationHandler for MultiLightApp {
|
|||||||
|
|
||||||
// Bind group layouts
|
// Bind group layouts
|
||||||
let cl_layout = camera_light_bind_group_layout(&gpu.device);
|
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);
|
let mat_layout = MaterialUniform::bind_group_layout(&gpu.device);
|
||||||
|
|
||||||
// Camera+Light bind group
|
// 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 old_tex_layout = GpuTexture::bind_group_layout(&gpu.device);
|
||||||
let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout);
|
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 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,
|
&gpu.device,
|
||||||
&pbr_tex_layout,
|
&pbr_tex_layout,
|
||||||
&albedo_tex.view,
|
&albedo_tex.view,
|
||||||
&albedo_tex.sampler,
|
&albedo_tex.sampler,
|
||||||
&normal_tex.1,
|
&normal_tex.1,
|
||||||
&normal_tex.2,
|
&normal_tex.2,
|
||||||
|
&orm_tex.view,
|
||||||
|
&orm_tex.sampler,
|
||||||
|
&emissive_tex.view,
|
||||||
|
&emissive_tex.sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
// IBL resources
|
// IBL resources
|
||||||
@@ -252,6 +260,8 @@ impl ApplicationHandler for MultiLightApp {
|
|||||||
camera_light_bind_group,
|
camera_light_bind_group,
|
||||||
_albedo_tex: albedo_tex,
|
_albedo_tex: albedo_tex,
|
||||||
_normal_tex: normal_tex,
|
_normal_tex: normal_tex,
|
||||||
|
_orm_tex: orm_tex,
|
||||||
|
_emissive_tex: emissive_tex,
|
||||||
pbr_texture_bind_group,
|
pbr_texture_bind_group,
|
||||||
material_bind_group,
|
material_bind_group,
|
||||||
shadow_bind_group,
|
shadow_bind_group,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use voltex_renderer::{
|
|||||||
GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData,
|
GpuContext, Camera, FpsController, CameraUniform, LightsUniform, LightData,
|
||||||
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline,
|
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline,
|
||||||
ShadowMap, ShadowUniform,
|
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;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
@@ -36,6 +36,8 @@ struct AppState {
|
|||||||
camera_light_bind_group: wgpu::BindGroup,
|
camera_light_bind_group: wgpu::BindGroup,
|
||||||
_albedo_tex: GpuTexture,
|
_albedo_tex: GpuTexture,
|
||||||
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
||||||
|
_orm_tex: GpuTexture,
|
||||||
|
_emissive_tex: GpuTexture,
|
||||||
pbr_texture_bind_group: wgpu::BindGroup,
|
pbr_texture_bind_group: wgpu::BindGroup,
|
||||||
material_bind_group: wgpu::BindGroup,
|
material_bind_group: wgpu::BindGroup,
|
||||||
shadow_bind_group: wgpu::BindGroup,
|
shadow_bind_group: wgpu::BindGroup,
|
||||||
@@ -134,7 +136,7 @@ impl ApplicationHandler for PbrDemoApp {
|
|||||||
|
|
||||||
// Bind group layouts
|
// Bind group layouts
|
||||||
let cl_layout = camera_light_bind_group_layout(&gpu.device);
|
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);
|
let mat_layout = MaterialUniform::bind_group_layout(&gpu.device);
|
||||||
|
|
||||||
// Camera+Light bind group
|
// 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 old_tex_layout = GpuTexture::bind_group_layout(&gpu.device);
|
||||||
let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout);
|
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 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,
|
&gpu.device,
|
||||||
&pbr_tex_layout,
|
&pbr_tex_layout,
|
||||||
&albedo_tex.view,
|
&albedo_tex.view,
|
||||||
&albedo_tex.sampler,
|
&albedo_tex.sampler,
|
||||||
&normal_tex.1,
|
&normal_tex.1,
|
||||||
&normal_tex.2,
|
&normal_tex.2,
|
||||||
|
&orm_tex.view,
|
||||||
|
&orm_tex.sampler,
|
||||||
|
&emissive_tex.view,
|
||||||
|
&emissive_tex.sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
// IBL resources
|
// IBL resources
|
||||||
@@ -236,6 +244,8 @@ impl ApplicationHandler for PbrDemoApp {
|
|||||||
camera_light_bind_group,
|
camera_light_bind_group,
|
||||||
_albedo_tex: albedo_tex,
|
_albedo_tex: albedo_tex,
|
||||||
_normal_tex: normal_tex,
|
_normal_tex: normal_tex,
|
||||||
|
_orm_tex: orm_tex,
|
||||||
|
_emissive_tex: emissive_tex,
|
||||||
pbr_texture_bind_group,
|
pbr_texture_bind_group,
|
||||||
material_bind_group,
|
material_bind_group,
|
||||||
shadow_bind_group,
|
shadow_bind_group,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use voltex_renderer::{
|
|||||||
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, obj,
|
Mesh, GpuTexture, MaterialUniform, generate_sphere, create_pbr_pipeline, obj,
|
||||||
ShadowMap, ShadowUniform, ShadowPassUniform, SHADOW_MAP_SIZE,
|
ShadowMap, ShadowUniform, ShadowPassUniform, SHADOW_MAP_SIZE,
|
||||||
create_shadow_pipeline, shadow_pass_bind_group_layout,
|
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;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
@@ -39,6 +39,8 @@ struct AppState {
|
|||||||
camera_light_bind_group: wgpu::BindGroup,
|
camera_light_bind_group: wgpu::BindGroup,
|
||||||
_albedo_tex: GpuTexture,
|
_albedo_tex: GpuTexture,
|
||||||
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
_normal_tex: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
|
||||||
|
_orm_tex: GpuTexture,
|
||||||
|
_emissive_tex: GpuTexture,
|
||||||
pbr_texture_bind_group: wgpu::BindGroup,
|
pbr_texture_bind_group: wgpu::BindGroup,
|
||||||
material_bind_group: wgpu::BindGroup,
|
material_bind_group: wgpu::BindGroup,
|
||||||
// Shadow resources
|
// Shadow resources
|
||||||
@@ -188,7 +190,7 @@ impl ApplicationHandler for ShadowDemoApp {
|
|||||||
|
|
||||||
// Bind group layouts
|
// Bind group layouts
|
||||||
let cl_layout = camera_light_bind_group_layout(&gpu.device);
|
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);
|
let mat_layout = MaterialUniform::bind_group_layout(&gpu.device);
|
||||||
|
|
||||||
// Camera+Light bind group
|
// 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 old_tex_layout = GpuTexture::bind_group_layout(&gpu.device);
|
||||||
let albedo_tex = GpuTexture::white_1x1(&gpu.device, &gpu.queue, &old_tex_layout);
|
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 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,
|
&gpu.device,
|
||||||
&pbr_tex_layout,
|
&pbr_tex_layout,
|
||||||
&albedo_tex.view,
|
&albedo_tex.view,
|
||||||
&albedo_tex.sampler,
|
&albedo_tex.sampler,
|
||||||
&normal_tex.1,
|
&normal_tex.1,
|
||||||
&normal_tex.2,
|
&normal_tex.2,
|
||||||
|
&orm_tex.view,
|
||||||
|
&orm_tex.sampler,
|
||||||
|
&emissive_tex.view,
|
||||||
|
&emissive_tex.sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
// IBL resources
|
// IBL resources
|
||||||
@@ -311,6 +319,8 @@ impl ApplicationHandler for ShadowDemoApp {
|
|||||||
camera_light_bind_group,
|
camera_light_bind_group,
|
||||||
_albedo_tex: albedo_tex,
|
_albedo_tex: albedo_tex,
|
||||||
_normal_tex: normal_tex,
|
_normal_tex: normal_tex,
|
||||||
|
_orm_tex: orm_tex,
|
||||||
|
_emissive_tex: emissive_tex,
|
||||||
pbr_texture_bind_group,
|
pbr_texture_bind_group,
|
||||||
material_bind_group,
|
material_bind_group,
|
||||||
shadow_map,
|
shadow_map,
|
||||||
|
|||||||
Reference in New Issue
Block a user