parent
23da739650
commit
8d77ac2f8b
|
@ -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
|
Binary file not shown.
73
examples/custom-shader/shaders/noise.wgsl
Normal file
73
examples/custom-shader/shaders/noise.wgsl
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Vertex shader bindings
|
||||
|
||||
struct VertexOutput {
|
||||
[[location(0)]] tex_coord: vec2<f32>;
|
||||
[[builtin(position)]] position: vec4<f32>;
|
||||
};
|
||||
|
||||
let positions: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
|
||||
// Upper left triangle
|
||||
vec2<f32>(-1.0, -1.0),
|
||||
vec2<f32>(1.0, -1.0),
|
||||
vec2<f32>(-1.0, 1.0),
|
||||
|
||||
// Lower right triangle
|
||||
vec2<f32>(-1.0, 1.0),
|
||||
vec2<f32>(1.0, -1.0),
|
||||
vec2<f32>(1.0, 1.0),
|
||||
);
|
||||
|
||||
let uv: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
|
||||
// Upper left triangle
|
||||
vec2<f32>(0.0, 0.0),
|
||||
vec2<f32>(1.0, 0.0),
|
||||
vec2<f32>(0.0, 1.0),
|
||||
|
||||
// Lower right triangle
|
||||
vec2<f32>(0.0, 1.0),
|
||||
vec2<f32>(1.0, 0.0),
|
||||
vec2<f32>(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<f32>(positions[vertex_index], 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Fragment shader bindings
|
||||
|
||||
[[group(0), binding(0)]] var r_tex_color: texture_2d<f32>;
|
||||
[[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>) -> f32 {
|
||||
return random(dot(st, vec2<f32>(random_x, random_y)));
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn fs_main([[location(0)]] tex_coord: vec2<f32>) -> [[location(0)]] vec4<f32> {
|
||||
let sampled_color: vec4<f32> = textureSample(r_tex_color, r_tex_sampler, tex_coord);
|
||||
let noise_color: vec3<f32> = vec3<f32>(random_vec2(
|
||||
tex_coord.xy * vec2<f32>(r_locals.time % tau + bias)
|
||||
));
|
||||
|
||||
return vec4<f32>(sampled_color.rgb * noise_color, sampled_color.a);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
Binary file not shown.
|
@ -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 {
|
||||
|
|
|
@ -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
|
BIN
shaders/frag.spv
BIN
shaders/frag.spv
Binary file not shown.
53
shaders/scale.wgsl
Normal file
53
shaders/scale.wgsl
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Vertex shader bindings
|
||||
|
||||
struct VertexOutput {
|
||||
[[location(0)]] tex_coord: vec2<f32>;
|
||||
[[builtin(position)]] position: vec4<f32>;
|
||||
};
|
||||
|
||||
[[block]] struct Locals {
|
||||
transform: mat4x4<f32>;
|
||||
};
|
||||
[[group(0), binding(2)]] var r_locals: Locals;
|
||||
|
||||
let positions: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
|
||||
// Upper left triangle
|
||||
vec2<f32>(-1.0, -1.0),
|
||||
vec2<f32>(1.0, -1.0),
|
||||
vec2<f32>(-1.0, 1.0),
|
||||
|
||||
// Lower right triangle
|
||||
vec2<f32>(-1.0, 1.0),
|
||||
vec2<f32>(1.0, -1.0),
|
||||
vec2<f32>(1.0, 1.0),
|
||||
);
|
||||
|
||||
let uv: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
|
||||
// Upper left triangle
|
||||
vec2<f32>(0.0, 0.0),
|
||||
vec2<f32>(1.0, 0.0),
|
||||
vec2<f32>(0.0, 1.0),
|
||||
|
||||
// Lower right triangle
|
||||
vec2<f32>(0.0, 1.0),
|
||||
vec2<f32>(1.0, 0.0),
|
||||
vec2<f32>(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<f32>(positions[vertex_index], 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Fragment shader bindings
|
||||
|
||||
[[group(0), binding(0)]] var r_tex_color: texture_2d<f32>;
|
||||
[[group(0), binding(1)]] var r_tex_sampler: sampler;
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn fs_main([[location(0)]] tex_coord: vec2<f32>) -> [[location(0)]] vec4<f32> {
|
||||
return textureSample(r_tex_color, r_tex_sampler, tex_coord);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
BIN
shaders/vert.spv
BIN
shaders/vert.spv
Binary file not shown.
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue