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 pixels::wgpu::{self, util::DeviceExt};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
pub(crate) struct NoiseRenderer {
|
pub(crate) struct NoiseRenderer {
|
||||||
bind_group: wgpu::BindGroup,
|
bind_group: wgpu::BindGroup,
|
||||||
|
@ -8,8 +9,13 @@ pub(crate) struct NoiseRenderer {
|
||||||
|
|
||||||
impl NoiseRenderer {
|
impl NoiseRenderer {
|
||||||
pub(crate) fn new(device: &wgpu::Device, texture_view: &wgpu::TextureView) -> Self {
|
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 shader = wgpu::ShaderModuleDescriptor {
|
||||||
let fs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/frag.spv"));
|
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
|
// Create a texture sampler with nearest neighbor
|
||||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
|
@ -103,7 +109,7 @@ impl NoiseRenderer {
|
||||||
layout: Some(&pipeline_layout),
|
layout: Some(&pipeline_layout),
|
||||||
vertex: wgpu::VertexState {
|
vertex: wgpu::VertexState {
|
||||||
module: &vs_module,
|
module: &vs_module,
|
||||||
entry_point: "main",
|
entry_point: "vs_main",
|
||||||
buffers: &[],
|
buffers: &[],
|
||||||
},
|
},
|
||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
|
@ -111,7 +117,7 @@ impl NoiseRenderer {
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
fragment: Some(wgpu::FragmentState {
|
fragment: Some(wgpu::FragmentState {
|
||||||
module: &fs_module,
|
module: &fs_module,
|
||||||
entry_point: "main",
|
entry_point: "fs_main",
|
||||||
targets: &[wgpu::ColorTargetState {
|
targets: &[wgpu::ColorTargetState {
|
||||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
blend: Some(wgpu::BlendState {
|
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 crate::SurfaceSize;
|
||||||
|
use std::borrow::Cow;
|
||||||
use ultraviolet::Mat4;
|
use ultraviolet::Mat4;
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
|
@ -21,8 +22,13 @@ impl ScalingRenderer {
|
||||||
surface_size: &SurfaceSize,
|
surface_size: &SurfaceSize,
|
||||||
render_texture_format: wgpu::TextureFormat,
|
render_texture_format: wgpu::TextureFormat,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let vs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/vert.spv"));
|
let shader = wgpu::ShaderModuleDescriptor {
|
||||||
let fs_module = device.create_shader_module(&wgpu::include_spirv!("../shaders/frag.spv"));
|
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
|
// Create a texture sampler with nearest neighbor
|
||||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
|
@ -121,7 +127,7 @@ impl ScalingRenderer {
|
||||||
layout: Some(&pipeline_layout),
|
layout: Some(&pipeline_layout),
|
||||||
vertex: wgpu::VertexState {
|
vertex: wgpu::VertexState {
|
||||||
module: &vs_module,
|
module: &vs_module,
|
||||||
entry_point: "main",
|
entry_point: "vs_main",
|
||||||
buffers: &[],
|
buffers: &[],
|
||||||
},
|
},
|
||||||
primitive: wgpu::PrimitiveState::default(),
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
|
@ -129,7 +135,7 @@ impl ScalingRenderer {
|
||||||
multisample: wgpu::MultisampleState::default(),
|
multisample: wgpu::MultisampleState::default(),
|
||||||
fragment: Some(wgpu::FragmentState {
|
fragment: Some(wgpu::FragmentState {
|
||||||
module: &fs_module,
|
module: &fs_module,
|
||||||
entry_point: "main",
|
entry_point: "fs_main",
|
||||||
targets: &[wgpu::ColorTargetState {
|
targets: &[wgpu::ColorTargetState {
|
||||||
format: render_texture_format,
|
format: render_texture_format,
|
||||||
blend: Some(wgpu::BlendState {
|
blend: Some(wgpu::BlendState {
|
||||||
|
|
Loading…
Reference in a new issue