diff --git a/examples/custom-shader/shaders/README.md b/examples/custom-shader/shaders/README.md deleted file mode 100644 index 5be4ff8..0000000 --- a/examples/custom-shader/shaders/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Shaders - -The GLSL shader source is not compiled as part of the normal cargo build process. This was a conscious decision sparked by the current state of the ecosystem; compiling GLSL-to-SPIR-V requires a C++ toolchain including CMake, which is an unacceptable constraint for a simple crate providing a pixel buffer. - -If you need to modify the GLSL sources, you must also recompile the SPIR-V as well. This can be done with `glslang`, `glslc`, etc. - -Compile shaders with `glslangValidator`: - -```bash -glslangValidator -V shader.frag && glslangValidator -V shader.vert -``` - -For more information, see https://github.com/parasyte/pixels/issues/9 diff --git a/examples/custom-shader/shaders/frag.spv b/examples/custom-shader/shaders/frag.spv deleted file mode 100644 index aee9847..0000000 Binary files a/examples/custom-shader/shaders/frag.spv and /dev/null differ diff --git a/examples/custom-shader/shaders/noise.wgsl b/examples/custom-shader/shaders/noise.wgsl new file mode 100644 index 0000000..cdde83c --- /dev/null +++ b/examples/custom-shader/shaders/noise.wgsl @@ -0,0 +1,73 @@ +// Vertex shader bindings + +struct VertexOutput { + [[location(0)]] tex_coord: vec2; + [[builtin(position)]] position: vec4; +}; + +let positions: array, 6> = array, 6>( + // Upper left triangle + vec2(-1.0, -1.0), + vec2(1.0, -1.0), + vec2(-1.0, 1.0), + + // Lower right triangle + vec2(-1.0, 1.0), + vec2(1.0, -1.0), + vec2(1.0, 1.0), +); + +let uv: array, 6> = array, 6>( + // Upper left triangle + vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + + // Lower right triangle + vec2(0.0, 1.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0), +); + +[[stage(vertex)]] +fn vs_main([[builtin(vertex_index)]] vertex_index: u32) -> VertexOutput { + var out: VertexOutput; + out.tex_coord = uv[vertex_index]; + out.position = vec4(positions[vertex_index], 0.0, 1.0); + return out; +} + +// Fragment shader bindings + +[[group(0), binding(0)]] var r_tex_color: texture_2d; +[[group(0), binding(1)]] var r_tex_sampler: sampler; +[[block]] struct Locals { + time: f32; +}; +[[group(0), binding(2)]] var r_locals: Locals; + +let tau: f32 = 6.283185307179586476925286766559; +let bias: f32 = 0.2376; // Offset the circular time input so it is never 0 + +// Random functions based on https://thebookofshaders.com/10/ +let random_scale: f32 = 43758.5453123; +let random_x: f32 = 12.9898; +let random_y: f32 = 78.233; + +fn random(x: f32) -> f32 { + return fract(sin(x) * random_scale); +} + +fn random_vec2(st: vec2) -> f32 { + return random(dot(st, vec2(random_x, random_y))); +} + +[[stage(fragment)]] +fn fs_main([[location(0)]] tex_coord: vec2) -> [[location(0)]] vec4 { + let sampled_color: vec4 = textureSample(r_tex_color, r_tex_sampler, tex_coord); + let noise_color: vec3 = vec3(random_vec2( + tex_coord.xy * vec2(r_locals.time % tau + bias) + )); + + return vec4(sampled_color.rgb * noise_color, sampled_color.a); +} diff --git a/examples/custom-shader/shaders/shader.frag b/examples/custom-shader/shaders/shader.frag deleted file mode 100644 index 6308c43..0000000 --- a/examples/custom-shader/shaders/shader.frag +++ /dev/null @@ -1,38 +0,0 @@ -// IMPORTANT: This shader needs to be compiled out-of-band to SPIR-V -// See: https://github.com/parasyte/pixels/issues/9 - -#version 450 - -layout(location = 0) in vec2 v_TexCoord; -layout(location = 0) out vec4 outColor; -layout(set = 0, binding = 0) uniform texture2D t_Color; -layout(set = 0, binding = 1) uniform sampler s_Color; -layout(set = 0, binding = 2) uniform Locals { - float u_Time; -}; - -#define PI 3.1415926535897932384626433832795 -#define TAU PI * 2.0 - -// Offset the circular time input so it is never 0 -#define BIAS 0.2376 - -// Random functions based on https://thebookofshaders.com/10/ -#define RANDOM_SCALE 43758.5453123 -#define RANDOM_X 12.9898 -#define RANDOM_Y 78.233 - -float random(float x) { - return fract(sin(x) * RANDOM_SCALE); -} - -float random_vec2(vec2 st) { - return random(dot(st.xy, vec2(RANDOM_X, RANDOM_Y))); -} - -void main() { - vec4 sampledColor = texture(sampler2D(t_Color, s_Color), v_TexCoord.xy); - vec3 noiseColor = vec3(random_vec2(v_TexCoord.xy * vec2(mod(u_Time, TAU) + BIAS))); - - outColor = vec4(sampledColor.rgb * noiseColor, sampledColor.a); -} diff --git a/examples/custom-shader/shaders/shader.vert b/examples/custom-shader/shaders/shader.vert deleted file mode 100644 index 8804d9d..0000000 --- a/examples/custom-shader/shaders/shader.vert +++ /dev/null @@ -1,39 +0,0 @@ -// IMPORTANT: This shader needs to be compiled out-of-band to SPIR-V -// See: https://github.com/parasyte/pixels/issues/9 - -#version 450 - -out gl_PerVertex { - vec4 gl_Position; -}; - -layout(location = 0) out vec2 v_TexCoord; - -const vec2 positions[6] = vec2[6]( - // Upper left triangle - vec2(-1.0, -1.0), - vec2(1.0, -1.0), - vec2(-1.0, 1.0), - - // Lower right triangle - vec2(-1.0, 1.0), - vec2(1.0, -1.0), - vec2(1.0, 1.0) -); - -const vec2 uv[6] = vec2[6]( - // Upper left triangle - vec2(0.0, 0.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - - // Lower right triangle - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(1.0, 1.0) -); - -void main() { - v_TexCoord = uv[gl_VertexIndex]; - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); -} diff --git a/examples/custom-shader/shaders/vert.spv b/examples/custom-shader/shaders/vert.spv deleted file mode 100644 index ec125ed..0000000 Binary files a/examples/custom-shader/shaders/vert.spv and /dev/null differ diff --git a/examples/custom-shader/src/renderers.rs b/examples/custom-shader/src/renderers.rs index 705314a..ebc7d71 100644 --- a/examples/custom-shader/src/renderers.rs +++ b/examples/custom-shader/src/renderers.rs @@ -1,4 +1,5 @@ use pixels::wgpu::{self, util::DeviceExt}; +use std::borrow::Cow; pub(crate) struct NoiseRenderer { bind_group: wgpu::BindGroup, @@ -8,8 +9,13 @@ pub(crate) struct NoiseRenderer { impl NoiseRenderer { pub(crate) fn new(device: &wgpu::Device, texture_view: &wgpu::TextureView) -> Self { - let vs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/vert.spv")); - let fs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/frag.spv")); + let shader = wgpu::ShaderModuleDescriptor { + label: Some("custom_noise_shader"), + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("../shaders/noise.wgsl"))), + flags: wgpu::ShaderFlags::VALIDATION, + }; + let vs_module = device.create_shader_module(&shader); + let fs_module = device.create_shader_module(&shader); // Create a texture sampler with nearest neighbor let sampler = device.create_sampler(&wgpu::SamplerDescriptor { @@ -103,7 +109,7 @@ impl NoiseRenderer { layout: Some(&pipeline_layout), vertex: wgpu::VertexState { module: &vs_module, - entry_point: "main", + entry_point: "vs_main", buffers: &[], }, primitive: wgpu::PrimitiveState::default(), @@ -111,7 +117,7 @@ impl NoiseRenderer { multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { module: &fs_module, - entry_point: "main", + entry_point: "fs_main", targets: &[wgpu::ColorTargetState { format: wgpu::TextureFormat::Bgra8UnormSrgb, blend: Some(wgpu::BlendState { diff --git a/shaders/README.md b/shaders/README.md deleted file mode 100644 index 5be4ff8..0000000 --- a/shaders/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Shaders - -The GLSL shader source is not compiled as part of the normal cargo build process. This was a conscious decision sparked by the current state of the ecosystem; compiling GLSL-to-SPIR-V requires a C++ toolchain including CMake, which is an unacceptable constraint for a simple crate providing a pixel buffer. - -If you need to modify the GLSL sources, you must also recompile the SPIR-V as well. This can be done with `glslang`, `glslc`, etc. - -Compile shaders with `glslangValidator`: - -```bash -glslangValidator -V shader.frag && glslangValidator -V shader.vert -``` - -For more information, see https://github.com/parasyte/pixels/issues/9 diff --git a/shaders/frag.spv b/shaders/frag.spv deleted file mode 100644 index 46bcca4..0000000 Binary files a/shaders/frag.spv and /dev/null differ diff --git a/shaders/scale.wgsl b/shaders/scale.wgsl new file mode 100644 index 0000000..f716c90 --- /dev/null +++ b/shaders/scale.wgsl @@ -0,0 +1,53 @@ +// Vertex shader bindings + +struct VertexOutput { + [[location(0)]] tex_coord: vec2; + [[builtin(position)]] position: vec4; +}; + +[[block]] struct Locals { + transform: mat4x4; +}; +[[group(0), binding(2)]] var r_locals: Locals; + +let positions: array, 6> = array, 6>( + // Upper left triangle + vec2(-1.0, -1.0), + vec2(1.0, -1.0), + vec2(-1.0, 1.0), + + // Lower right triangle + vec2(-1.0, 1.0), + vec2(1.0, -1.0), + vec2(1.0, 1.0), +); + +let uv: array, 6> = array, 6>( + // Upper left triangle + vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + + // Lower right triangle + vec2(0.0, 1.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0), +); + +[[stage(vertex)]] +fn vs_main([[builtin(vertex_index)]] vertex_index: u32) -> VertexOutput { + var out: VertexOutput; + out.tex_coord = uv[vertex_index]; + out.position = r_locals.transform * vec4(positions[vertex_index], 0.0, 1.0); + return out; +} + +// Fragment shader bindings + +[[group(0), binding(0)]] var r_tex_color: texture_2d; +[[group(0), binding(1)]] var r_tex_sampler: sampler; + +[[stage(fragment)]] +fn fs_main([[location(0)]] tex_coord: vec2) -> [[location(0)]] vec4 { + return textureSample(r_tex_color, r_tex_sampler, tex_coord); +} diff --git a/shaders/shader.frag b/shaders/shader.frag deleted file mode 100644 index 65853cf..0000000 --- a/shaders/shader.frag +++ /dev/null @@ -1,13 +0,0 @@ -// IMPORTANT: This shader needs to be compiled out-of-band to SPIR-V -// See: https://github.com/parasyte/pixels/issues/9 - -#version 450 - -layout(location = 0) in vec2 v_TexCoord; -layout(location = 0) out vec4 outColor; -layout(set = 0, binding = 0) uniform texture2D t_Color; -layout(set = 0, binding = 1) uniform sampler s_Color; - -void main() { - outColor = texture(sampler2D(t_Color, s_Color), v_TexCoord); -} diff --git a/shaders/shader.vert b/shaders/shader.vert deleted file mode 100644 index 3e1d026..0000000 --- a/shaders/shader.vert +++ /dev/null @@ -1,43 +0,0 @@ -// IMPORTANT: This shader needs to be compiled out-of-band to SPIR-V -// See: https://github.com/parasyte/pixels/issues/9 - -#version 450 - -out gl_PerVertex { - vec4 gl_Position; -}; - -layout(location = 0) out vec2 v_TexCoord; - -layout(set = 0, binding = 2) uniform Locals { - mat4 u_Transform; -}; - -const vec2 positions[6] = vec2[6]( - // Upper left triangle - vec2(-1.0, -1.0), - vec2(1.0, -1.0), - vec2(-1.0, 1.0), - - // Lower right triangle - vec2(-1.0, 1.0), - vec2(1.0, -1.0), - vec2(1.0, 1.0) -); - -const vec2 uv[6] = vec2[6]( - // Upper left triangle - vec2(0.0, 0.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - - // Lower right triangle - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(1.0, 1.0) -); - -void main() { - v_TexCoord = uv[gl_VertexIndex]; - gl_Position = u_Transform * vec4(positions[gl_VertexIndex], 0.0, 1.0); -} diff --git a/shaders/vert.spv b/shaders/vert.spv deleted file mode 100644 index 9c8f317..0000000 Binary files a/shaders/vert.spv and /dev/null differ diff --git a/src/renderers.rs b/src/renderers.rs index 7d1f510..11d7ed3 100644 --- a/src/renderers.rs +++ b/src/renderers.rs @@ -1,4 +1,5 @@ use crate::SurfaceSize; +use std::borrow::Cow; use ultraviolet::Mat4; use wgpu::util::DeviceExt; @@ -21,8 +22,13 @@ impl ScalingRenderer { surface_size: &SurfaceSize, render_texture_format: wgpu::TextureFormat, ) -> Self { - let vs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/vert.spv")); - let fs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/frag.spv")); + let shader = wgpu::ShaderModuleDescriptor { + label: Some("pixels_scaling_renderer_shader"), + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("../shaders/scale.wgsl"))), + flags: wgpu::ShaderFlags::VALIDATION, + }; + let vs_module = device.create_shader_module(&shader); + let fs_module = device.create_shader_module(&shader); // Create a texture sampler with nearest neighbor let sampler = device.create_sampler(&wgpu::SamplerDescriptor { @@ -121,7 +127,7 @@ impl ScalingRenderer { layout: Some(&pipeline_layout), vertex: wgpu::VertexState { module: &vs_module, - entry_point: "main", + entry_point: "vs_main", buffers: &[], }, primitive: wgpu::PrimitiveState::default(), @@ -129,7 +135,7 @@ impl ScalingRenderer { multisample: wgpu::MultisampleState::default(), fragment: Some(wgpu::FragmentState { module: &fs_module, - entry_point: "main", + entry_point: "fs_main", targets: &[wgpu::ColorTargetState { format: render_texture_format, blend: Some(wgpu::BlendState {