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

Noise stuff #79

Closed
wants to merge 4 commits into from
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
16 changes: 16 additions & 0 deletions assets/materials/fbm.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#import bevy_vfx_bag::fbm

struct Material {
scale: f32,
offset_x: f32,
offset_y: f32,
};
@group(1) @binding(0)
var<uniform> material: Material;

@fragment
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
return vec4<f32>(vec3(fbm((material.scale * uv) + vec2(material.offset_x, material.offset_y))), 1.0);
}
17 changes: 17 additions & 0 deletions assets/materials/value_noise.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#import bevy_vfx_bag::value_noise

struct Material {
scale: f32,
offset_x: f32,
offset_y: f32,
};
@group(1) @binding(0)
var<uniform> material: Material;

@fragment
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
let noise = value_noise((material.scale * uv) + vec2(material.offset_x, material.offset_y));
return vec4<f32>(vec3(noise), 1.0);
}
83 changes: 83 additions & 0 deletions assets/materials/voronoi.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#import bevy_vfx_bag::math

struct Material {
scale: f32,
offset_x: f32,
offset_y: f32,
};
@group(1) @binding(0)
var<uniform> material: Material;

fn voronoi(
uv: vec2<f32>
) -> f32 {
var uv = uv * material.scale;
let id = vec2<i32>(floor(uv));

let cell_space = -0.5 + fract(uv);

var min_dist = 10.0;

for (var y: i32 = -1; y <= 1; y++) {
for (var x: i32 = -1; x <= 1; x++) {
let offset = vec2(x, y);

// Random 2D vector in range (-0.5, +0.5).
// Note that the strategy is to go from normal UVs (0,0) -> (1,1) to something scaled, like
// (0,0) -> (10,10) (for example).
// We floor that to get integer IDs.
// Then we add an offset in order to index our neighbours.
let neighbour_random_point = hash22f(vec2<u32>(id + offset)) / 2.;

// So now we have a random 2D point which is deterministic with regards
// to the ID of the cell.
// What we care about though is how far away this point is relative to _this_ cell.
// Therefore we have to add the offset of the cell with the point in question to realize
// that distance.
// var p = sin(random2d * vec2(material.offset_x, material.offset_y)) + vec2<f32>(offset);
// var p = sin(neighbour_random_point * vec2(material.offset_x, material.offset_y)) + vec2<f32>(offset);
var p = sin(neighbour_random_point) + vec2<f32>(offset);
// var p = random2d + vec2<f32>(offset);

// p += sin(vec2(material.offset_x, material.offset_y)) / 2.;

let dist = length(cell_space - p);

if (dist < min_dist) {
min_dist = dist;
}
}
}

// min_dist = 1. - min(1., min_dist);
min_dist = smoothstep(0.31, 1.0, min_dist);

return min_dist;
}

@fragment
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
// let v = voronoi(uv);
// return vec4<f32>(v * 0.1, v * 4., v, 1.0);

let uv = uv * 10.;

let xoff = sin(material.offset_x / 2.) / 2.1;
let yoff = cos(material.offset_x / 3.) / 2.1;
let off = vec2(xoff, yoff);

let a = vec2(3. + xoff);
let b = vec2(6., 6. + yoff);

let auv = -a + uv;
let ab = -a + b;

let h = clamp(dot(auv, normalize(ab)) / length(ab), 0., 1.);

let d = smoothstep(0.5, 0.6, length(-auv + h * ab));
// let d = length(h * ab);

return vec4<f32>(vec3(d), 1.0);
}
12 changes: 0 additions & 12 deletions assets/shaders/auto-update-shader.sh

This file was deleted.

30 changes: 30 additions & 0 deletions assets/shaders/fbm.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#define_import_path bevy_vfx_bag::fbm
#import bevy_vfx_bag::value_noise

/*
TODO:
- Expose parameters
- Consider if parameters should be shader preprocessor values
- The noise used should be defined by a shader preprocessor definition
*/

const NUM_OCTAVES: u32 = 8u;
const hurst: f32 = 1.0;

fn fbm(coords: vec2<f32>) -> f32 {
let gain = exp2(-hurst);
var result = 0.0;

var amplitude = 1.0;
var frequency = 1.0;

for (var i: u32 = 0u; i < NUM_OCTAVES; i++) {
let noise = value_noise(coords * frequency);
result += amplitude * noise;

amplitude *= gain;
frequency *= 2.041002312;
}

return result;
}
111 changes: 111 additions & 0 deletions assets/shaders/marble.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
From: https://www.shadertoy.com/view/Xs3fR4

// variant of Vorocracks: https://shadertoy.com/view/lsVyRy
// integrated with cracks here: https://www.shadertoy.com/view/Xd3fRN


float ofs = 0.;


float RATIO = 1., // stone length/width ratio
CRACK_depth = 2.,
CRACK_zebra_scale = 1., // fractal shape of the fault zebra
CRACK_zebra_amp = 0.34,
CRACK_profile = 1., // fault vertical shape 1. .2
CRACK_slope = 50., // 10. 1.4
CRACK_width = .001;


// === Voronoi =====================================================
// --- Base Voronoi. inspired by https://www.shadertoy.com/view/MslGD8

#define hash22(p) fract( 18.5453 * sin( p * mat2(127.1,311.7,269.5,183.3)) )


// --- Voronoi distance to borders. inspired by https://www.shadertoy.com/view/ldl3W8
vec3 voronoiB( vec2 u ) // returns len + id
{
vec2 iu = floor(u), C, P;
float m = 1e9,d;

for( int k=0; k < 9; k++ ) {
vec2 p = iu + vec2(k%3-1,k/3-1),

o = hash22(p),
r = p - u + o;
d = dot(r,r);
if( d < m ) m = d, C = p-iu, P = r;
}

m = 1e9;

for( int k=0; k < 25; k++ ) {
vec2 p = iu+C + vec2(k%5-2,k/5-2),
o = hash22(p),
r = p-u + o;

if( dot(P-r,P-r)>1e-5 )
m = min( m, .5*dot( (P+r), normalize(r-P) ) );
}

return vec3( m, P+u );
}

// === pseudo Perlin noise =============================================
#define rot(a) mat2(cos(a),-sin(a),sin(a),cos(a))
int MOD = 1; // type of Perlin noise

// --- 2D
#define hash21(p) fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453123)
float noise2(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p); f = f*f*(3.-2.*f); // smoothstep

float v= mix( mix(hash21(i+vec2(0,0)),hash21(i+vec2(1,0)),f.x),
mix(hash21(i+vec2(0,1)),hash21(i+vec2(1,1)),f.x), f.y);
return MOD==0 ? v
: MOD==1 ? 2.*v-1.
: MOD==2 ? abs(2.*v-1.)
: 1.-abs(2.*v-1.);
}


#define noise22(p) vec2(noise2(p),noise2(p+17.7))
vec2 fbm22(vec2 p) {
vec2 v = vec2(0);
float a = .5;
mat2 R = rot(0.5);

for (int i = 0; i < 6; i++, p*=2.,a/=2.)
p *= R,
v += a * noise22(p);

return v;
}


// ======================================================

void mainImage( out vec4 O, vec2 U )
{
U *= 3./iResolution.y;
U.x += iTime; // for demo

vec3 H0;
O-=O;

for(float i=0.; i<CRACK_depth ; i++) {
vec2 V = U / vec2(RATIO,2), // voronoi cell shape
D = CRACK_zebra_amp * fbm22(U/CRACK_zebra_scale) * CRACK_zebra_scale;
vec3 H = voronoiB( V + D ); if (i==0.) H0=H;
float d = H.x; // distance to cracks
// cracks
d = min( 1., CRACK_slope * pow(max(0.,d-CRACK_width),CRACK_profile) );

O += vec4(1.-d) / exp2(i);
U *= 1.5 * rot(.37);
}
}

*/
49 changes: 49 additions & 0 deletions assets/shaders/math.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#define_import_path bevy_vfx_bag::math

// See Mark Jarzynski and Marc Olano, Hash Functions for GPU Rendering, Journal of Computer
// Graphics Techniques (JCGT), vol. 9, no. 3, 20–38, 2020
fn pcg3d(v: vec3<u32>) -> vec3<u32> {
var v = v * 1664525u + 1013904223u;

v.x += v.y * v.z;
v.y += v.z * v.x;
v.z += v.x * v.y;

v = v ^ (v >> 16u);

v.x += v.y*v.z;
v.y += v.z*v.x;
v.z += v.x*v.y;

return v;
}

// https://github.com/gfx-rs/naga/issues/1908
fn ldexp_workaround(v: f32, e: f32) -> f32 {
return v * exp2(e);
}
fn ldexp_workaround2(v: vec2<f32>, e: f32) -> vec2<f32> {
return v * exp2(e);
}

fn hash21(point: vec2<u32>) -> u32 {
return pcg3d(vec3<u32>(point.xy, 0u)).x;
}

fn hash21f(point: vec2<u32>) -> f32 {
// https://www.pcg-random.org/using-pcg-c.html
// We get a random value in a u32's range.
// Divide it by 1/2^32 to produce a value in the [0, 1) range.
// Then massage it to get the desired [-1, 1) range.
let noise = ldexp_workaround(f32(hash21(point)), -32.0);
return -1.0 + 2.0 * noise;
}

fn hash22(point: vec2<u32>) -> vec2<u32> {
return pcg3d(vec3<u32>(point.xy, 0u)).xy;
}

fn hash22f(point: vec2<u32>) -> vec2<f32> {
let noise = ldexp_workaround2(vec2<f32>(hash22(point)), -32.0);
return vec2(-1.0) + (2.0 * noise);
}
27 changes: 27 additions & 0 deletions assets/shaders/value_noise.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#define_import_path bevy_vfx_bag::value_noise
#import bevy_vfx_bag::math

fn value_noise(coords: vec2<f32>) -> f32 {
let index = vec2<u32>(floor(coords));
let frac = fract(coords);

// Sometimes a smoothstepped frac is used instead.
let interpolant = frac;

let noise_xy00 = hash21f(index + vec2(0u, 0u));
let noise_xy10 = hash21f(index + vec2(1u, 0u));
let noise_xy01 = hash21f(index + vec2(0u, 1u));
let noise_xy11 = hash21f(index + vec2(1u, 1u));

// Gives us the noise at the correct point in the x direction
// between the upper corners
let noise_x0_lerp = mix(f32(noise_xy00), f32(noise_xy10), interpolant.x);

// x direction lower corners
let noise_x1_lerp = mix(f32(noise_xy01), f32(noise_xy11), interpolant.x);

// Lastly lerp between the values found in the y direction.
let noise = mix(noise_x0_lerp, noise_x1_lerp, interpolant.y);

return noise;
}
8 changes: 7 additions & 1 deletion examples/examples_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,13 @@ mod shapes {

// ground plane
commands.spawn(PbrBundle {
mesh: meshes.add(shape::Plane { size: 50. }.into()),
mesh: meshes.add(
shape::Plane {
size: 50.,
..default()
}
.into(),
),
material: materials.add(Color::SILVER.into()),
..default()
});
Expand Down
Loading