webgpu-app/flat.wgsl

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);
}