Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - add some more pipelined-rendering shader examples #3041

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ anyhow = "1.0.4"
rand = "0.8.0"
ron = "0.7.0"
serde = { version = "1", features = ["derive"] }
bytemuck = "1.7"
# Needed to poll Task examples
futures-lite = "1.11.3"

Expand Down Expand Up @@ -418,6 +419,22 @@ path = "examples/shader/shader_defs.rs"
name = "shader_material"
path = "examples/shader/shader_material.rs"

[[example]]
name = "shader_material_glsl"
path = "examples/shader/shader_material_glsl.rs"

[[example]]
name = "shader_instancing"
path = "examples/shader/shader_instancing.rs"

[[example]]
name = "animate_shader"
path = "examples/shader/animate_shader.rs"

[[example]]
name = "compute_shader_game_of_life"
path = "examples/shader/compute_shader_game_of_life.rs"

# Tools
[[example]]
name = "bevymark"
Expand Down
72 changes: 72 additions & 0 deletions assets/shaders/animate_shader.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#import bevy_pbr::mesh_view_bind_group
#import bevy_pbr::mesh_struct

[[group(1), binding(0)]]
var<uniform> mesh: Mesh;

struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
};

struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] uv: vec2<f32>;
};

[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
let world_position = mesh.model * vec4<f32>(vertex.position, 1.0);

var out: VertexOutput;
out.clip_position = view.view_proj * world_position;
out.uv = vertex.uv;
return out;
}


struct Time {
time_since_startup: f32;
};
[[group(2), binding(0)]]
var<uniform> time: Time;


fn oklab_to_linear_srgb(c: vec3<f32>) -> vec3<f32> {
let L = c.x;
let a = c.y;
let b = c.z;

let l_ = L + 0.3963377774 * a + 0.2158037573 * b;
let m_ = L - 0.1055613458 * a - 0.0638541728 * b;
let s_ = L - 0.0894841775 * a - 1.2914855480 * b;

let l = l_*l_*l_;
let m = m_*m_*m_;
let s = s_*s_*s_;

return vec3<f32>(
4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s,
);
}

[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
let speed = 2.0;
let t_1 = sin(time.time_since_startup * speed) * 0.5 + 0.5;
let t_2 = cos(time.time_since_startup * speed);

let distance_to_center = distance(in.uv, vec2<f32>(0.5)) * 1.4;

// blending is done in a perceptual color space: https://bottosson.github.io/posts/oklab/
let red = vec3<f32>(0.627955, 0.224863, 0.125846);
let green = vec3<f32>(0.86644, -0.233887, 0.179498);
let blue = vec3<f32>(0.701674, 0.274566, -0.169156);
let white = vec3<f32>(1.0, 0.0, 0.0);
let mixed = mix(mix(red, blue, t_1), mix(green, white, t_2), distance_to_center);

return vec4<f32>(oklab_to_linear_srgb(mixed), 1.0);
}
11 changes: 11 additions & 0 deletions assets/shaders/custom_material.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#version 450

layout(location = 0) out vec4 o_Target;

layout(set = 1, binding = 0) uniform CustomMaterial {
vec4 Color;
};

void main() {
o_Target = Color;
}
26 changes: 26 additions & 0 deletions assets/shaders/custom_material.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#version 450

layout(location = 0) in vec3 Vertex_Position;
layout(location = 1) in vec3 Vertex_Normal;
layout(location = 2) in vec2 Vertex_Uv;

layout(set = 0, binding = 0) uniform CameraViewProj {
mat4 ViewProj;
mat4 InverseView;
mat4 Projection;
vec3 WorldPosition;
float near;
float far;
float width;
float height;
};

layout(set = 2, binding = 0) uniform Mesh {
mat4 Model;
mat4 InverseTransposeModel;
uint flags;
};

void main() {
gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
}
67 changes: 67 additions & 0 deletions assets/shaders/game_of_life.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
[[group(0), binding(0)]]
var texture: texture_storage_2d<rgba8unorm, read_write>;

fn hash(value: u32) -> u32 {
var state = value;
state = state ^ 2747636419u;
state = state * 2654435769u;
state = state ^ state >> 16u;
state = state * 2654435769u;
state = state ^ state >> 16u;
state = state * 2654435769u;
return state;
}
fn randomFloat(value: u32) -> f32 {
return f32(hash(value)) / 4294967295.0;
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

let randomNumber = randomFloat(invocation_id.y * num_workgroups.x + invocation_id.x);
let alive = randomNumber > 0.9;
let color = vec4<f32>(f32(alive));

textureStore(texture, location, color);
}


fn get(location: vec2<i32>, offset_x: i32, offset_y: i32) -> i32 {
let value: vec4<f32> = textureLoad(texture, location + vec2<i32>(offset_x, offset_y));
return i32(value.x);
}

fn count_alive(location: vec2<i32>) -> i32 {
return get(location, -1, -1) +
get(location, -1, 0) +
get(location, -1, 1) +
get(location, 0, -1) +
get(location, 0, 1) +
get(location, 1, -1) +
get(location, 1, 0) +
get(location, 1, 1);
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

let n_alive = count_alive(location);
let color = vec4<f32>(f32(n_alive) / 8.0);

var alive: bool;
if (n_alive == 3) {
alive = true;
} else if (n_alive == 2) {
let currently_alive = get(location, 0, 0);
alive = bool(currently_alive);
} else {
alive = false;
}

storageBarrier();

textureStore(texture, location, vec4<f32>(f32(alive)));
}
11 changes: 0 additions & 11 deletions assets/shaders/hot.frag

This file was deleted.

15 changes: 0 additions & 15 deletions assets/shaders/hot.vert

This file was deleted.

35 changes: 35 additions & 0 deletions assets/shaders/instancing.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#import bevy_pbr::mesh_view_bind_group
#import bevy_pbr::mesh_struct

[[group(1), binding(0)]]
var<uniform> mesh: Mesh;

struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;

[[location(3)]] i_pos_scale: vec4<f32>;
[[location(4)]] i_color: vec4<f32>;
};

struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] color: vec4<f32>;
};

[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
let position = vertex.position * vertex.i_pos_scale.w + vertex.i_pos_scale.xyz;
let world_position = mesh.model * vec4<f32>(position, 1.0);

var out: VertexOutput;
out.clip_position = view.view_proj * world_position;
out.color = vertex.i_color;
return out;
}

[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
return in.color;
}
4 changes: 4 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ Example | File | Description
Example | File | Description
--- | --- | ---
`shader_material` | [`shader/shader_material.rs`](./shader/shader_material.rs) | Illustrates creating a custom material and a shader that uses it
`shader_material_glsl` | [`shader/shader_material_glsl.rs`](./shader/shader_material_glsl.rs) | A custom shader using the GLSL shading language.
`shader_instancing` | [`shader/shader_instancing.rs`](./shader/shader_instancing.rs) | A custom shader showing off rendering a mesh multiple times in one draw call.
`animate_shader` | [`shader/animate_shader.rs`](./shader/animate_shader.rs) | Shows how to pass changing data like the time since startup into a shader.
`compute_shader_game_of_life` | [`shader/compute_shader_game_of_life.rs`](./shader/compute_shader_game_of_life.rs) | A compute shader simulating Conway's Game of Life
`shader_defs` | [`shader/shader_defs.rs`](./shader/shader_defs.rs) | Demonstrates creating a custom material that uses "shaders defs" (a tool to selectively toggle parts of a shader)

## Tests
Expand Down
Loading