95 lines
2.6 KiB
WebGPU Shading Language
95 lines
2.6 KiB
WebGPU Shading Language
@group(0) @binding(0)
|
|
var<uniform> viewProjectionMatrix : mat4x4<f32>;
|
|
|
|
@group(0) @binding(1)
|
|
var<storage, read> instancePositions : array<vec4<f32>>;
|
|
|
|
@group(0) @binding(2)
|
|
var<uniform> cameraPosition : vec3<f32>;
|
|
|
|
@group(0) @binding(3)
|
|
var myTextureArray: texture_2d_array<f32>;
|
|
|
|
@group(0) @binding(4)
|
|
var mySampler : sampler;
|
|
|
|
struct VertexOutput {
|
|
@builtin(position) position : vec4<f32>,
|
|
@location(0) worldPosition : vec3<f32>,
|
|
@location(1) worldNormal : vec3<f32>,
|
|
@location(2) uv : vec2<f32>,
|
|
};
|
|
|
|
@vertex
|
|
fn vertexEntryPoint(
|
|
@location(0) position : vec3<f32>,
|
|
@location(1) normal : vec3<f32>,
|
|
@location(2) uv : vec2<f32>,
|
|
@builtin(instance_index) instanceIndex : u32
|
|
) -> VertexOutput {
|
|
var output : VertexOutput;
|
|
|
|
let instanceOffset = instancePositions[instanceIndex].xyz;
|
|
let worldPosition = position + instanceOffset;
|
|
|
|
output.worldPosition = worldPosition;
|
|
output.worldNormal = normalize(normal);
|
|
output.position = viewProjectionMatrix * vec4<f32>(worldPosition, 1.0);
|
|
output.uv = uv;
|
|
|
|
return output;
|
|
}
|
|
@fragment
|
|
fn fragmentEntryPoint(
|
|
@location(0) worldPosition : vec3<f32>,
|
|
@location(1) worldNormal : vec3<f32>,
|
|
@location(2) uv : vec2<f32>
|
|
) -> @location(0) vec4<f32> {
|
|
|
|
// For test: encode UV as color (no texture sampling)
|
|
//let baseColor = vec3<f32>(uv, 0.0);
|
|
|
|
let baseColor = textureSampleLevel(myTextureArray, mySampler, uv, 0, 0).rgb;
|
|
|
|
|
|
|
|
let pi = 3.14159265;
|
|
let invPi = 0.318309886;
|
|
let N = normalize(worldNormal);
|
|
let V = normalize(cameraPosition - worldPosition);
|
|
let L = normalize(vec3<f32>(0.5, 1.0, 0.3));
|
|
let H = normalize(V + L);
|
|
|
|
let metallic = 0.2;
|
|
let roughness = 0.4;
|
|
let rough2 = roughness * roughness;
|
|
let lightColor = vec3<f32>(1.0);
|
|
|
|
let NdotV = max(dot(N, V), 0.001);
|
|
let NdotL = max(dot(N, L), 0.001);
|
|
let NdotH = max(dot(N, H), 0.001);
|
|
let HdotV = max(dot(H, V), 0.001);
|
|
|
|
let F0 = mix(vec3<f32>(0.04), baseColor, metallic);
|
|
let f = pow(1.0 - HdotV, 5.0);
|
|
let F = F0 + (1.0 - F0) * f;
|
|
|
|
let a2 = rough2 * rough2;
|
|
let NdotH2 = NdotH * NdotH;
|
|
let denom = NdotH2 * (a2 - 1.0) + 1.0;
|
|
let NDF = a2 / (pi * denom * denom);
|
|
|
|
let k = (roughness + 1.0);
|
|
let k2 = (k * k) / 8.0;
|
|
let Gv = NdotV / (NdotV * (1.0 - k2) + k2);
|
|
let Gl = NdotL / (NdotL * (1.0 - k2) + k2);
|
|
let G = Gv * Gl;
|
|
|
|
let spec = (NDF * G * F) / (4.0 * NdotV * NdotL + 0.001);
|
|
let kd = (vec3<f32>(1.0) - F) * (1.0 - metallic);
|
|
let diff = kd * baseColor * invPi;
|
|
|
|
let color = (diff + spec) * lightColor * NdotL + vec3<f32>(0.03) * baseColor;
|
|
|
|
return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), 1.0);
|
|
} |