Refactor shaders

This commit is contained in:
Maximilian Ammann 2021-12-28 14:24:34 +01:00
parent 2d12d79f3e
commit 36fc5f9f5e
7 changed files with 198 additions and 83 deletions

View File

@ -1,5 +1,4 @@
mod piplines;
mod shader;
mod shader_ffi;
mod tesselation;
mod texture;
@ -7,3 +6,4 @@ mod platform_constants;
mod camera;
pub mod state;
mod shaders;

View File

@ -1,80 +0,0 @@
use wgpu::{
ColorTargetState, FragmentState, ShaderModule, ShaderModuleDescriptor, VertexAttribute,
VertexBufferLayout, VertexState,
};
use super::platform_constants::COLOR_TEXTURE_FORMAT;
use super::shader_ffi::GpuVertexUniform;
const VERTEX_SHADER_ARGUMENTS: [VertexAttribute; 3] = [
wgpu::VertexAttribute {
offset: 0,
format: wgpu::VertexFormat::Float32x2,
shader_location: 0,
},
wgpu::VertexAttribute {
offset: wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32x2,
shader_location: 1,
},
wgpu::VertexAttribute {
offset: 2 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Uint32,
shader_location: 2,
},
];
const VERTEX_SHADER_BUFFERS: [VertexBufferLayout; 1] = [wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &VERTEX_SHADER_ARGUMENTS,
}];
const DEFAULT_FRAGMENT_COLOR_TARGETS: [ColorTargetState; 1] = [wgpu::ColorTargetState {
format: COLOR_TEXTURE_FORMAT,
blend: None,
write_mask: wgpu::ColorWrites::ALL,
}];
const NO_COLOR_FRAGMENT_COLOR_TARGETS: [ColorTargetState; 1] = [wgpu::ColorTargetState {
format: COLOR_TEXTURE_FORMAT,
blend: None,
write_mask: wgpu::ColorWrites::empty(),
}];
pub fn create_vertex_module_descriptor<'a>() -> ShaderModuleDescriptor<'a> {
wgpu::ShaderModuleDescriptor {
label: Some("Geometry vs"),
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/vertex.wgsl").into()),
}
}
pub fn create_fragment_module_descriptor<'a>() -> ShaderModuleDescriptor<'a> {
wgpu::ShaderModuleDescriptor {
label: Some("Geometry fs"),
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/fragment.wgsl").into()),
}
}
pub fn create_vertex_state(vertex_shader_module: &ShaderModule) -> VertexState {
wgpu::VertexState {
module: vertex_shader_module,
entry_point: "main",
buffers: &VERTEX_SHADER_BUFFERS,
}
}
pub fn create_fragment_state(
fragment_shader_module: &ShaderModule,
disable_color: bool,
) -> FragmentState {
wgpu::FragmentState {
module: fragment_shader_module,
entry_point: "main",
targets: if disable_color {
&NO_COLOR_FRAGMENT_COLOR_TARGETS
} else {
&DEFAULT_FRAGMENT_COLOR_TARGETS
},
}
}

151
src/render/shaders/mod.rs Normal file
View File

@ -0,0 +1,151 @@
use wgpu::{BufferAddress, ColorTargetState, Device, FragmentState, ShaderModule, ShaderModuleDescriptor, VertexAttribute, VertexBufferLayout, VertexState, VertexStepMode};
pub struct FragmentShaderState {
source: &'static str,
targets: &'static [ColorTargetState],
module: Option<ShaderModule>,
}
pub struct VertexShaderState {
source: &'static str,
buffers: &'static [VertexBufferLayout<'static>],
module: Option<ShaderModule>,
}
impl FragmentShaderState {
pub const fn new(source: &'static str, targets: &'static [ColorTargetState]) -> Self {
Self {
source,
targets,
module: None,
}
}
pub fn create_fragment_state(
&mut self, device: &Device,
) -> FragmentState {
self.module = Some(device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("fragment shader"),
source: wgpu::ShaderSource::Wgsl(self.source.into()),
}));
wgpu::FragmentState {
module: self.module.as_ref().unwrap(),
entry_point: "main",
targets: self.targets,
}
}
}
impl VertexShaderState {
pub const fn new(source: &'static str,
buffers: &'static [VertexBufferLayout<'static>]) -> Self {
Self {
source,
buffers,
module: None,
}
}
pub fn create_vertex_state(&mut self, device: &Device) -> VertexState {
self.module = Some(device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("vertex shader"),
source: wgpu::ShaderSource::Wgsl(self.source.into()),
}));
wgpu::VertexState {
module: self.module.as_ref().unwrap(),
entry_point: "main",
buffers: self.buffers,
}
}
}
pub mod tile {
use crate::render::platform_constants::COLOR_TEXTURE_FORMAT;
use crate::render::shader_ffi::GpuVertexUniform;
use super::{VertexShaderState, ColorTargetState, FragmentShaderState};
pub const VERTEX: VertexShaderState = VertexShaderState::new(
include_str!("tile.vertex.wgsl"), &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
format: wgpu::VertexFormat::Float32x2,
shader_location: 0,
},
wgpu::VertexAttribute {
offset: wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32x2,
shader_location: 1,
},
wgpu::VertexAttribute {
offset: 2 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Uint32,
shader_location: 2,
},
],
}],
);
pub const FRAGMENT: FragmentShaderState = FragmentShaderState::new(
include_str!("tile.fragment.wgsl"), &[wgpu::ColorTargetState {
format: COLOR_TEXTURE_FORMAT,
blend: None,
write_mask: wgpu::ColorWrites::ALL,
}],
);
}
pub mod tile_mask {
use crate::render::platform_constants::COLOR_TEXTURE_FORMAT;
use crate::render::shader_ffi::GpuVertexUniform;
use super::{VertexShaderState, ColorTargetState, FragmentShaderState};
pub const VERTEX: VertexShaderState = VertexShaderState::new(
include_str!("tile_mask.vertex.wgsl"), &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
format: wgpu::VertexFormat::Float32x2,
shader_location: 0,
},
wgpu::VertexAttribute {
offset: wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32x2,
shader_location: 1,
},
wgpu::VertexAttribute {
offset: 2 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Uint32,
shader_location: 2,
},
],
},
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
format: wgpu::VertexFormat::Float32x2,
shader_location: 4,
},
],
}],
);
pub const FRAGMENT: FragmentShaderState = FragmentShaderState::new(
include_str!("tile_mask.fragment.wgsl"), &[wgpu::ColorTargetState {
format: COLOR_TEXTURE_FORMAT,
blend: None,
write_mask: wgpu::ColorWrites::ALL,
}]);
}

View File

@ -41,8 +41,7 @@ fn main(
var prim: PrimitiveUniform = u_primitives.primitives[a_prim_id];
var z = 0.0;
var mask_offset = vec2<f32>(f32(instance_idx) * 4096.0, 0.0);
var world_pos = a_position + mask_offset + prim.translate + a_normal * prim.width;
var world_pos = a_position + prim.translate + a_normal * prim.width;
var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0);

View File

@ -0,0 +1,9 @@
struct Output {
[[location(0)]] out_color: vec4<f32>;
};
[[stage(fragment)]]
fn main() -> Output {
return Output(vec4<f32>(1.0,1.0,1.0,1.0));
}

View File

@ -0,0 +1,36 @@
struct CameraUniform {
view_proj: mat4x4<f32>;
view_position: vec4<f32>;
};
struct GlobalsUniform {
camera: CameraUniform;
};
[[group(0), binding(0)]] var<uniform> globals: GlobalsUniform;
struct VertexOutput {
[[builtin(position)]] position: vec4<f32>;
};
[[stage(vertex)]]
fn main(
[[location(0)]] a_position: vec2<f32>,
[[location(4)]] mask_offset: vec2<f32>,
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput {
var z = 0.0;
var world_pos = a_position + mask_offset;
if (instance_idx == u32(1)) {
if (a_position.x == 0.0) {
world_pos.x = 0.0;
}
}
var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0);
return VertexOutput(position);
}