mirror of
				https://github.com/encounter/dawn-cmake.git
				synced 2025-10-27 12:10:29 +00:00 
			
		
		
		
	These have been warnings for multiple months. Time to properly turn this on. Bug: tint:880 Change-Id: I3b38f672309b5acd48c12a38dc5a1675f3c62470 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/103480 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
		
			
				
	
	
		
			370 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			WebGPU Shading Language
		
	
	
	
	
	
			
		
		
	
	
			370 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			WebGPU Shading Language
		
	
	
	
	
	
| const GAMMA = 2.200000048;
 | |
| 
 | |
| fn linearTosRGB(linear : vec3<f32>) -> vec3<f32> {
 | |
|   let INV_GAMMA = (1.0 / GAMMA);
 | |
|   return pow(linear, vec3(INV_GAMMA));
 | |
| }
 | |
| 
 | |
| fn sRGBToLinear(srgb : vec3<f32>) -> vec3<f32> {
 | |
|   return pow(srgb, vec3(GAMMA));
 | |
| }
 | |
| 
 | |
| struct Camera {
 | |
|   projection : mat4x4<f32>,
 | |
|   inverseProjection : mat4x4<f32>,
 | |
|   view : mat4x4<f32>,
 | |
|   position : vec3<f32>,
 | |
|   time : f32,
 | |
|   outputSize : vec2<f32>,
 | |
|   zNear : f32,
 | |
|   zFar : f32,
 | |
| }
 | |
| 
 | |
| @binding(0) @group(0) var<uniform> camera : Camera;
 | |
| 
 | |
| struct ClusterLights {
 | |
|   offset : u32,
 | |
|   count : u32,
 | |
| }
 | |
| 
 | |
| struct ClusterLightGroup {
 | |
|   offset : u32,
 | |
|   lights : array<ClusterLights, 27648>,
 | |
|   indices : array<u32, 1769472>,
 | |
| }
 | |
| 
 | |
| @binding(1) @group(0) var<storage, read> clusterLights : ClusterLightGroup;
 | |
| 
 | |
| struct Light {
 | |
|   position : vec3<f32>,
 | |
|   range : f32,
 | |
|   color : vec3<f32>,
 | |
|   intensity : f32,
 | |
| }
 | |
| 
 | |
| struct GlobalLights {
 | |
|   ambient : vec3<f32>,
 | |
|   dirColor : vec3<f32>,
 | |
|   dirIntensity : f32,
 | |
|   dirDirection : vec3<f32>,
 | |
|   lightCount : u32,
 | |
|   lights : array<Light>,
 | |
| }
 | |
| 
 | |
| @binding(2) @group(0) var<storage, read> globalLights : GlobalLights;
 | |
| 
 | |
| const tileCount = vec3(32u, 18u, 48u);
 | |
| 
 | |
| fn linearDepth(depthSample : f32) -> f32 {
 | |
|   return ((camera.zFar * camera.zNear) / fma(depthSample, (camera.zNear - camera.zFar), camera.zFar));
 | |
| }
 | |
| 
 | |
| fn getTile(fragCoord : vec4<f32>) -> vec3<u32> {
 | |
|   let sliceScale = (f32(tileCount.z) / log2((camera.zFar / camera.zNear)));
 | |
|   let sliceBias = -(((f32(tileCount.z) * log2(camera.zNear)) / log2((camera.zFar / camera.zNear))));
 | |
|   let zTile = u32(max(((log2(linearDepth(fragCoord.z)) * sliceScale) + sliceBias), 0.0));
 | |
|   return vec3(u32((fragCoord.x / (camera.outputSize.x / f32(tileCount.x)))), u32((fragCoord.y / (camera.outputSize.y / f32(tileCount.y)))), zTile);
 | |
| }
 | |
| 
 | |
| fn getClusterIndex(fragCoord : vec4<f32>) -> u32 {
 | |
|   let tile = getTile(fragCoord);
 | |
|   return ((tile.x + (tile.y * tileCount.x)) + ((tile.z * tileCount.x) * tileCount.y));
 | |
| }
 | |
| 
 | |
| @binding(3) @group(0) var defaultSampler : sampler;
 | |
| 
 | |
| @binding(4) @group(0) var shadowTexture : texture_depth_2d;
 | |
| 
 | |
| @binding(5) @group(0) var shadowSampler : sampler_comparison;
 | |
| 
 | |
| struct LightShadowTable {
 | |
|   light : array<i32>,
 | |
| }
 | |
| 
 | |
| @binding(6) @group(0) var<storage, read> lightShadowTable : LightShadowTable;
 | |
| 
 | |
| var<private> shadowSampleOffsets : array<vec2<f32>, 16> = array<vec2<f32>, 16>(vec2(-1.5, -1.5), vec2(-1.5, -0.5), vec2(-1.5, 0.5), vec2(-1.5, 1.5), vec2(-0.5, -1.5), vec2(-0.5, -0.5), vec2(-0.5, 0.5), vec2(-0.5, 1.5), vec2(0.5, -1.5), vec2(0.5, -0.5), vec2(0.5, 0.5), vec2(0.5, 1.5), vec2(1.5, -1.5), vec2(1.5, -0.5), vec2(1.5, 0.5), vec2(1.5, 1.5));
 | |
| 
 | |
| const shadowSampleCount = 16u;
 | |
| 
 | |
| struct ShadowProperties {
 | |
|   viewport : vec4<f32>,
 | |
|   viewProj : mat4x4<f32>,
 | |
| }
 | |
| 
 | |
| struct LightShadows {
 | |
|   properties : array<ShadowProperties>,
 | |
| }
 | |
| 
 | |
| @binding(7) @group(0) var<storage, read> shadow : LightShadows;
 | |
| 
 | |
| fn dirLightVisibility(worldPos : vec3<f32>) -> f32 {
 | |
|   let shadowIndex = lightShadowTable.light[0u];
 | |
|   if ((shadowIndex == -1)) {
 | |
|     return 1.0;
 | |
|   }
 | |
|   let viewport = shadow.properties[shadowIndex].viewport;
 | |
|   let lightPos = (shadow.properties[shadowIndex].viewProj * vec4(worldPos, 1.0));
 | |
|   let shadowPos = vec3((((lightPos.xy / lightPos.w) * vec2(0.5, -0.5)) + vec2(0.5, 0.5)), (lightPos.z / lightPos.w));
 | |
|   let viewportPos = vec2((viewport.xy + (shadowPos.xy * viewport.zw)));
 | |
|   let texelSize = (1.0 / vec2<f32>(textureDimensions(shadowTexture, 0)));
 | |
|   let clampRect = vec4((viewport.xy - texelSize), ((viewport.xy + viewport.zw) + texelSize));
 | |
|   var visibility = 0.0;
 | |
|   for(var i = 0u; (i < shadowSampleCount); i = (i + 1u)) {
 | |
|     visibility = (visibility + textureSampleCompareLevel(shadowTexture, shadowSampler, clamp((viewportPos + (shadowSampleOffsets[i] * texelSize)), clampRect.xy, clampRect.zw), (shadowPos.z - 0.003)));
 | |
|   }
 | |
|   return (visibility / f32(shadowSampleCount));
 | |
| }
 | |
| 
 | |
| fn getCubeFace(v : vec3<f32>) -> i32 {
 | |
|   let vAbs = abs(v);
 | |
|   if (((vAbs.z >= vAbs.x) && (vAbs.z >= vAbs.y))) {
 | |
|     if ((v.z < 0.0)) {
 | |
|       return 5;
 | |
|     }
 | |
|     return 4;
 | |
|   }
 | |
|   if ((vAbs.y >= vAbs.x)) {
 | |
|     if ((v.y < 0.0)) {
 | |
|       return 3;
 | |
|     }
 | |
|     return 2;
 | |
|   }
 | |
|   if ((v.x < 0.0)) {
 | |
|     return 1;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| fn pointLightVisibility(lightIndex : u32, worldPos : vec3<f32>, pointToLight : vec3<f32>) -> f32 {
 | |
|   var shadowIndex = lightShadowTable.light[(lightIndex + 1u)];
 | |
|   if ((shadowIndex == -1)) {
 | |
|     return 1.0;
 | |
|   }
 | |
|   shadowIndex = (shadowIndex + getCubeFace((pointToLight * -1.0)));
 | |
|   let viewport = shadow.properties[shadowIndex].viewport;
 | |
|   let lightPos = (shadow.properties[shadowIndex].viewProj * vec4(worldPos, 1.0));
 | |
|   let shadowPos = vec3((((lightPos.xy / lightPos.w) * vec2(0.5, -0.5)) + vec2(0.5, 0.5)), (lightPos.z / lightPos.w));
 | |
|   let viewportPos = vec2((viewport.xy + (shadowPos.xy * viewport.zw)));
 | |
|   let texelSize = (1.0 / vec2<f32>(textureDimensions(shadowTexture, 0)));
 | |
|   let clampRect = vec4(viewport.xy, (viewport.xy + viewport.zw));
 | |
|   var visibility = 0.0;
 | |
|   for(var i = 0u; (i < shadowSampleCount); i = (i + 1u)) {
 | |
|     visibility = (visibility + textureSampleCompareLevel(shadowTexture, shadowSampler, clamp((viewportPos + (shadowSampleOffsets[i] * texelSize)), clampRect.xy, clampRect.zw), (shadowPos.z - 0.01)));
 | |
|   }
 | |
|   return (visibility / f32(shadowSampleCount));
 | |
| }
 | |
| 
 | |
| struct VertexOutput {
 | |
|   @builtin(position)
 | |
|   position : vec4<f32>,
 | |
|   @location(0)
 | |
|   worldPos : vec3<f32>,
 | |
|   @location(1)
 | |
|   view : vec3<f32>,
 | |
|   @location(2)
 | |
|   texcoord : vec2<f32>,
 | |
|   @location(3)
 | |
|   texcoord2 : vec2<f32>,
 | |
|   @location(4)
 | |
|   color : vec4<f32>,
 | |
|   @location(5)
 | |
|   instanceColor : vec4<f32>,
 | |
|   @location(6)
 | |
|   normal : vec3<f32>,
 | |
|   @location(7)
 | |
|   tangent : vec3<f32>,
 | |
|   @location(8)
 | |
|   bitangent : vec3<f32>,
 | |
| }
 | |
| 
 | |
| struct Material {
 | |
|   baseColorFactor : vec4<f32>,
 | |
|   emissiveFactor : vec3<f32>,
 | |
|   occlusionStrength : f32,
 | |
|   metallicRoughnessFactor : vec2<f32>,
 | |
|   alphaCutoff : f32,
 | |
| }
 | |
| 
 | |
| @binding(8) @group(0) var<uniform> material : Material;
 | |
| 
 | |
| @binding(9) @group(0) var baseColorTexture : texture_2d<f32>;
 | |
| 
 | |
| @binding(10) @group(0) var baseColorSampler : sampler;
 | |
| 
 | |
| @binding(11) @group(0) var normalTexture : texture_2d<f32>;
 | |
| 
 | |
| @binding(12) @group(0) var normalSampler : sampler;
 | |
| 
 | |
| @binding(13) @group(0) var metallicRoughnessTexture : texture_2d<f32>;
 | |
| 
 | |
| @binding(14) @group(0) var metallicRoughnessSampler : sampler;
 | |
| 
 | |
| @binding(15) @group(0) var occlusionTexture : texture_2d<f32>;
 | |
| 
 | |
| @binding(16) @group(0) var occlusionSampler : sampler;
 | |
| 
 | |
| @binding(17) @group(0) var emissiveTexture : texture_2d<f32>;
 | |
| 
 | |
| @binding(18) @group(0) var emissiveSampler : sampler;
 | |
| 
 | |
| struct SurfaceInfo {
 | |
|   baseColor : vec4<f32>,
 | |
|   albedo : vec3<f32>,
 | |
|   metallic : f32,
 | |
|   roughness : f32,
 | |
|   normal : vec3<f32>,
 | |
|   f0 : vec3<f32>,
 | |
|   ao : f32,
 | |
|   emissive : vec3<f32>,
 | |
|   v : vec3<f32>,
 | |
| }
 | |
| 
 | |
| fn GetSurfaceInfo(input : VertexOutput) -> SurfaceInfo {
 | |
|   var surface : SurfaceInfo;
 | |
|   surface.v = normalize(input.view);
 | |
|   let tbn = mat3x3(input.tangent, input.bitangent, input.normal);
 | |
|   let normalMap = textureSample(normalTexture, normalSampler, input.texcoord).rgb;
 | |
|   surface.normal = normalize((tbn * ((2.0 * normalMap) - vec3(1.0))));
 | |
|   let baseColorMap = textureSample(baseColorTexture, baseColorSampler, input.texcoord);
 | |
|   surface.baseColor = ((input.color * material.baseColorFactor) * baseColorMap);
 | |
|   if ((surface.baseColor.a < material.alphaCutoff)) {
 | |
|     // Violates uniformity analysis:
 | |
|     // discard;
 | |
|   }
 | |
|   surface.albedo = surface.baseColor.rgb;
 | |
|   let metallicRoughnessMap = textureSample(metallicRoughnessTexture, metallicRoughnessSampler, input.texcoord);
 | |
|   surface.metallic = (material.metallicRoughnessFactor.x * metallicRoughnessMap.b);
 | |
|   surface.roughness = (material.metallicRoughnessFactor.y * metallicRoughnessMap.g);
 | |
|   let dielectricSpec = vec3(0.039999999);
 | |
|   surface.f0 = mix(dielectricSpec, surface.albedo, vec3(surface.metallic));
 | |
|   let occlusionMap = textureSample(occlusionTexture, occlusionSampler, input.texcoord);
 | |
|   surface.ao = (material.occlusionStrength * occlusionMap.r);
 | |
|   let emissiveMap = textureSample(emissiveTexture, emissiveSampler, input.texcoord);
 | |
|   surface.emissive = (material.emissiveFactor * emissiveMap.rgb);
 | |
|   if ((input.instanceColor.a == 0.0)) {
 | |
|     surface.albedo = (surface.albedo + input.instanceColor.rgb);
 | |
|   } else {
 | |
|     surface.albedo = (surface.albedo * input.instanceColor.rgb);
 | |
|   }
 | |
|   return surface;
 | |
| }
 | |
| 
 | |
| const PI = 3.141592741;
 | |
| 
 | |
| const LightType_Point = 0u;
 | |
| 
 | |
| const LightType_Spot = 1u;
 | |
| 
 | |
| const LightType_Directional = 2u;
 | |
| 
 | |
| struct PuctualLight {
 | |
|   lightType : u32,
 | |
|   pointToLight : vec3<f32>,
 | |
|   range : f32,
 | |
|   color : vec3<f32>,
 | |
|   intensity : f32,
 | |
| }
 | |
| 
 | |
| fn FresnelSchlick(cosTheta : f32, F0 : vec3<f32>) -> vec3<f32> {
 | |
|   return (F0 + ((vec3(1.0) - F0) * pow((1.0 - cosTheta), 5.0)));
 | |
| }
 | |
| 
 | |
| fn DistributionGGX(N : vec3<f32>, H : vec3<f32>, roughness : f32) -> f32 {
 | |
|   let a = (roughness * roughness);
 | |
|   let a2 = (a * a);
 | |
|   let NdotH = max(dot(N, H), 0.0);
 | |
|   let NdotH2 = (NdotH * NdotH);
 | |
|   let num = a2;
 | |
|   let denom = ((NdotH2 * (a2 - 1.0)) + 1.0);
 | |
|   return (num / ((PI * denom) * denom));
 | |
| }
 | |
| 
 | |
| fn GeometrySchlickGGX(NdotV : f32, roughness : f32) -> f32 {
 | |
|   let r = (roughness + 1.0);
 | |
|   let k = ((r * r) / 8.0);
 | |
|   let num = NdotV;
 | |
|   let denom = ((NdotV * (1.0 - k)) + k);
 | |
|   return (num / denom);
 | |
| }
 | |
| 
 | |
| fn GeometrySmith(N : vec3<f32>, V : vec3<f32>, L : vec3<f32>, roughness : f32) -> f32 {
 | |
|   let NdotV = max(dot(N, V), 0.0);
 | |
|   let NdotL = max(dot(N, L), 0.0);
 | |
|   let ggx2 = GeometrySchlickGGX(NdotV, roughness);
 | |
|   let ggx1 = GeometrySchlickGGX(NdotL, roughness);
 | |
|   return (ggx1 * ggx2);
 | |
| }
 | |
| 
 | |
| fn lightAttenuation(light : PuctualLight) -> f32 {
 | |
|   if ((light.lightType == LightType_Directional)) {
 | |
|     return 1.0;
 | |
|   }
 | |
|   let distance = length(light.pointToLight);
 | |
|   if ((light.range <= 0.0)) {
 | |
|     return (1.0 / pow(distance, 2.0));
 | |
|   }
 | |
|   return (clamp((1.0 - pow((distance / light.range), 4.0)), 0.0, 1.0) / pow(distance, 2.0));
 | |
| }
 | |
| 
 | |
| fn lightRadiance(light : PuctualLight, surface : SurfaceInfo) -> vec3<f32> {
 | |
|   let L = normalize(light.pointToLight);
 | |
|   let H = normalize((surface.v + L));
 | |
|   let NDF = DistributionGGX(surface.normal, H, surface.roughness);
 | |
|   let G = GeometrySmith(surface.normal, surface.v, L, surface.roughness);
 | |
|   let F = FresnelSchlick(max(dot(H, surface.v), 0.0), surface.f0);
 | |
|   let kD = ((vec3(1.0) - F) * (1.0 - surface.metallic));
 | |
|   let NdotL = max(dot(surface.normal, L), 0.0);
 | |
|   let numerator = ((NDF * G) * F);
 | |
|   let denominator = max(((4.0 * max(dot(surface.normal, surface.v), 0.0)) * NdotL), 0.001);
 | |
|   let specular = (numerator / vec3(denominator));
 | |
|   let radiance = ((light.color * light.intensity) * lightAttenuation(light));
 | |
|   return (((((kD * surface.albedo) / vec3(PI)) + specular) * radiance) * NdotL);
 | |
| }
 | |
| 
 | |
| @binding(19) @group(0) var ssaoTexture : texture_2d<f32>;
 | |
| 
 | |
| struct FragmentOutput {
 | |
|   @location(0)
 | |
|   color : vec4<f32>,
 | |
|   @location(1)
 | |
|   emissive : vec4<f32>,
 | |
| }
 | |
| 
 | |
| @fragment
 | |
| fn fragmentMain(input : VertexOutput) -> FragmentOutput {
 | |
|   let surface = GetSurfaceInfo(input);
 | |
|   var Lo = vec3(0.0, 0.0, 0.0);
 | |
|   if ((globalLights.dirIntensity > 0.0)) {
 | |
|     var light : PuctualLight;
 | |
|     light.lightType = LightType_Directional;
 | |
|     light.pointToLight = globalLights.dirDirection;
 | |
|     light.color = globalLights.dirColor;
 | |
|     light.intensity = globalLights.dirIntensity;
 | |
|     let lightVis = dirLightVisibility(input.worldPos);
 | |
|     Lo = (Lo + (lightRadiance(light, surface) * lightVis));
 | |
|   }
 | |
|   let clusterIndex = getClusterIndex(input.position);
 | |
|   let lightOffset = clusterLights.lights[clusterIndex].offset;
 | |
|   let lightCount = clusterLights.lights[clusterIndex].count;
 | |
|   for(var lightIndex = 0u; (lightIndex < lightCount); lightIndex = (lightIndex + 1u)) {
 | |
|     let i = clusterLights.indices[(lightOffset + lightIndex)];
 | |
|     var light : PuctualLight;
 | |
|     light.lightType = LightType_Point;
 | |
|     light.pointToLight = (globalLights.lights[i].position.xyz - input.worldPos);
 | |
|     light.range = globalLights.lights[i].range;
 | |
|     light.color = globalLights.lights[i].color;
 | |
|     light.intensity = globalLights.lights[i].intensity;
 | |
|     let lightVis = pointLightVisibility(i, input.worldPos, light.pointToLight);
 | |
|     Lo = (Lo + (lightRadiance(light, surface) * lightVis));
 | |
|   }
 | |
|   let ssaoCoord = (input.position.xy / vec2<f32>(textureDimensions(ssaoTexture).xy));
 | |
|   let ssaoFactor = textureSample(ssaoTexture, defaultSampler, ssaoCoord).r;
 | |
|   let ambient = (((globalLights.ambient * surface.albedo) * surface.ao) * ssaoFactor);
 | |
|   let color = linearTosRGB(((Lo + ambient) + surface.emissive));
 | |
|   var out : FragmentOutput;
 | |
|   out.color = vec4(color, surface.baseColor.a);
 | |
|   out.emissive = vec4(surface.emissive, surface.baseColor.a);
 | |
|   return out;
 | |
| }
 |