125 lines
3.3 KiB
WebGPU Shading Language
125 lines
3.3 KiB
WebGPU Shading Language
struct Configuration {
|
|
viewProj: mat4x4f,
|
|
lightViewProj: mat4x4f,
|
|
lightPosition: vec4f,
|
|
eyePosition: vec4f,
|
|
};
|
|
|
|
struct Particle {
|
|
position: vec4f,
|
|
value: vec4f,
|
|
};
|
|
|
|
struct ParticleConfiguration {
|
|
particle: vec4f,
|
|
circle: vec4f,
|
|
mouse: vec4f,
|
|
};
|
|
|
|
@group(0) @binding(0) var<uniform> config: Configuration;
|
|
@group(1) @binding(0) var<uniform> particleConfiguration: ParticleConfiguration;
|
|
@group(1) @binding(1) var<storage> particle: array<Particle>;
|
|
|
|
struct VertexInput {
|
|
@builtin(vertex_index) vertex_index: u32,
|
|
};
|
|
|
|
struct VertexOutput {
|
|
@builtin(position) position: vec4f,
|
|
@location(0) texture: vec2f,
|
|
};
|
|
|
|
const vertices = array(
|
|
vec2f(1.0, 0.0),
|
|
vec2f(0.0, 1.0),
|
|
vec2f(0.0, 0.0),
|
|
vec2f(1.0, 1.0),
|
|
);
|
|
|
|
@vertex
|
|
fn vertexMain(input: VertexInput) -> VertexOutput
|
|
{
|
|
let texture = vertices[input.vertex_index];
|
|
|
|
var output: VertexOutput;
|
|
output.position = vec4f(texture * 2.0 - 1.0, 0.0, 1.0);
|
|
output.texture = texture;
|
|
return output;
|
|
}
|
|
|
|
const pi: f32 = 3.14159274101257324219;
|
|
|
|
fn smoothing(radius: f32, distance: f32) -> f32
|
|
{
|
|
let volume = pi * pow(radius, 8) / 4;
|
|
let value = max(0, radius * radius - distance * distance);
|
|
return value * value * value / volume;
|
|
}
|
|
|
|
fn test(position: vec2f) -> f32
|
|
{
|
|
let x = position.x * 4 * pi;
|
|
let y = position.y * 4 * pi;
|
|
return cos(y - 3 + sin(x)) * 0.5 + 0.5;
|
|
}
|
|
|
|
fn positionDensity(position: vec2f, circleRadius: f32, particleCount: u32) -> f32
|
|
{
|
|
var density: f32 = 0.0;
|
|
for (var i: u32 = 0; i < u32(particleCount); i++) {
|
|
let distance = length(position - particle[i].position.xy);
|
|
let influence = smoothing(circleRadius, distance);
|
|
density += influence;
|
|
}
|
|
return density;
|
|
}
|
|
|
|
@fragment
|
|
fn fragmentMain(input: VertexOutput) -> @location(0) vec4f
|
|
{
|
|
var color: vec4f = vec4f(0.0, 0.0, 0.0, 0.0);
|
|
|
|
let particleCount = u32(particleConfiguration.particle.x);
|
|
let particleSize = particleConfiguration.particle.y;
|
|
let particleMass1 = particleConfiguration.particle.z;
|
|
let particleMass2 = particleConfiguration.particle.w;
|
|
|
|
let circleRadius = particleConfiguration.circle.x;
|
|
let circleThickness = particleConfiguration.circle.y;
|
|
let testIntensity = particleConfiguration.circle.z;
|
|
let mass12Mix = particleConfiguration.circle.w;
|
|
|
|
let circlePosition = particleConfiguration.mouse;
|
|
|
|
var property: f32 = 0.0;
|
|
|
|
for (var i: u32 = 0; i < particleCount; i++) {
|
|
let distance = length(input.texture.xy - particle[i].position.xy);
|
|
if (distance < particleSize) {
|
|
color.x = particle[i].value.x;
|
|
}
|
|
//let circleDistance = length(input.texture.xy - circlePosition.xy);
|
|
let influence = smoothing(circleRadius, distance);
|
|
//let particleDensity = positionDensity(particle[i].position.xy, circleRadius, particleCount);
|
|
let particleProperty = particle[i].value.x;
|
|
let particleDensity = particle[i].value.y;
|
|
|
|
let p1 = particleProperty * influence;
|
|
let p2 = p1 / particleDensity;
|
|
|
|
property += mix(p1, p2, mass12Mix);
|
|
}
|
|
color.z = property * mix(particleMass1, particleMass2, mass12Mix);
|
|
|
|
if (circlePosition.w != 0) {
|
|
let thickness = abs(length(input.texture.xy - circlePosition.xy) - circleRadius);
|
|
if (thickness < circleThickness) {
|
|
//color.y = 1.0;
|
|
}
|
|
}
|
|
|
|
let testColor = test(input.texture.xy);
|
|
return vec4(color.xz, testColor * testIntensity, 1.0);
|
|
//return vec4(color.x, 0, 0, 1.0);
|
|
}
|