|
// A fragment shader which lights textured geometry with point lights. |
|
|
|
// Lights from a storage buffer binding. |
|
struct PointLight { |
|
position: vec3f, |
|
color: vec3f, |
|
} |
|
|
|
struct LightStorage { |
|
pointCount: u32, |
|
point: array<PointLight>, |
|
} |
|
|
|
@group(0) @binding(0) var<storage> lights: LightStorage; |
|
|
|
// Texture and sampler. |
|
@group(1) @binding(0) var baseColorSampler: sampler; |
|
@group(1) @binding(1) var baseColorTexture: texture_2d<f32>; |
|
|
|
// Function arguments are values from the vertex shader. |
|
// Instead of putting @location(), you have to order them manually. First arg is @location(0), 2nd is @location(1) and so on... |
|
// The function signature would be "(vec3f, vec3f, vec2f) -> (vec4f)" |
|
// With builtin: |
|
// fragment fragmentMain(foo: [vertex_index]) -> vec4f {} |
|
// fragment fragmentMain() -> [position] {} |
|
fragment fragmentMain(worldPos: vec3f, normal: vec3f, uv: vec2f) -> vec4f { |
|
// Sample the base color of the surface from a texture. |
|
// We use "const" here to specify that it is constant. Who though "let" is a good idea? |
|
// Yeah ok I know this is computed at runtime, but I'm sure the compiler is smart enough to determine this is runtime |
|
// variable, right? |
|
const baseColor = textureSample(baseColorTexture, baseColorSampler, uv); |
|
|
|
const N = normalize(normal); |
|
var surfaceColor = vec3f(0); |
|
|
|
// Loop over the scene point lights. |
|
for (var i = 0u; i < lights.pointCount; i++) { |
|
const worldToLight = lights.point[i].position - worldPos; |
|
const dist = length(worldToLight); |
|
const dir = normalize(worldToLight); |
|
|
|
// Determine the contribution of this light to the surface color. |
|
const radiance = lights.point[i].color * (1 / pow(dist, 2)); |
|
const nDotL = max(dot(N, dir), 0); |
|
|
|
// Accumulate light contribution to the surface color. |
|
surfaceColor += baseColor.rgb * radiance * nDotL; |
|
} |
|
|
|
// Return the accumulated surface color. |
|
return vec4(surfaceColor, baseColor.a); |
|
} |