Variable getIBLTransmissionConst
getIBLTransmission: "\nfn getVolumeTransmissionRay(normal: vec3f, viewDirection: vec3f, thickness: f32, ior: f32, modelScale: vec3f) -> vec3f {\n let refractionVector = refract(-viewDirection, normal, 1.0 / ior); \n return normalize(refractionVector) * thickness * modelScale;\n}\n\nfn applyIorToRoughness(roughness: f32, ior: f32) -> f32 {\n return roughness * saturate(ior * 2.0 - 2.0);\n}\n\nfn getTransmissionSample( fragCoord: vec2f, roughness: f32, ior: f32, transmissionSceneTexture: texture_2d<f32>, sampler: sampler ) -> vec4f {\n let transmissionSamplerSize: vec2f = vec2f(textureDimensions(transmissionSceneTexture));\n let lod: f32 = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n return textureSampleLevel( transmissionSceneTexture, sampler, fragCoord.xy, lod );\n}\n\nfn volumeAttenuation(transmissionDistance: f32, attenuationColor: vec3f, attenuationDistance: f32) -> vec3f {\n if (isinf(attenuationDistance)) {\n return vec3(1.0);\n } else {\n let attenuationCoefficient = -log(attenuationColor) / attenuationDistance;\n let transmittance = exp(-attenuationCoefficient * transmissionDistance);\n return transmittance;\n }\n}\n\nfn getIBLVolumeRefraction(\n normal: vec3f,\n viewDirection: vec3f,\n roughness: f32,\n diffuseColor: vec4f,\n specularColor: vec3f,\n specularF90: f32,\n position: vec3f,\n modelScale: vec3f,\n viewMatrix: mat4x4f,\n projMatrix: mat4x4f,\n dispersion: f32,\n ior: f32,\n thickness: f32,\n attenuationColor: vec3f,\n attenuationDistance: f32,\n transmissionBackgroundTexture: texture_2d<f32>,\n defaultSampler: sampler,\n) -> vec4f {\n // TODO dispersion\n var transmittedLight: vec4f;\n var transmissionRayLength: f32;\n var transmittance: vec3f;\n \n // Calculate the transmission ray\n let transmissionRay: vec3f = getVolumeTransmissionRay(normal, viewDirection, thickness, ior, modelScale);\n let refractedRayExit = position + transmissionRay;\n\n // Transform to NDC space\n let ndcPos = projMatrix * viewMatrix * vec4(refractedRayExit, 1.0);\n var refractionCoords = ndcPos.xy / ndcPos.w;\n refractionCoords = (refractionCoords + 1.0) / 2.0;\n refractionCoords = vec2(refractionCoords.x, 1.0 - refractionCoords.y); // webgpu Y flip\n\n // Sample the transmission texture\n transmittedLight = getTransmissionSample(refractionCoords, roughness, ior, transmissionBackgroundTexture, defaultSampler);\n\n // Compute transmittance\n transmittance = diffuseColor.rgb * volumeAttenuation(length(transmissionRay), attenuationColor, attenuationDistance);\n\n // Apply attenuation to transmitted light\n let attenuatedColor = transmittance * transmittedLight.rgb;\n\n // Compute Fresnel term using an environment BRDF\n let F = EnvironmentBRDF(normal, viewDirection, specularColor, specularF90, roughness);\n\n // Average the transmittance for a single factor\n let transmittanceFactor = (transmittance.r + transmittance.g + transmittance.b) / 3.0;\n\n // Combine results into the final color\n return vec4(\n (1.0 - F) * attenuatedColor,\n 1.0 - (1.0 - transmittedLight.a) * transmittanceFactor\n );\n}\n\nfn getIBLVolumeRefractionWithDispersion(\n normal: vec3f,\n viewDirection: vec3f,\n roughness: f32,\n diffuseColor: vec4f,\n specularColor: vec3f,\n specularF90: f32,\n position: vec3f,\n modelScale: vec3f,\n viewMatrix: mat4x4f,\n projMatrix: mat4x4f,\n dispersion: f32,\n ior: f32,\n thickness: f32,\n attenuationColor: vec3f,\n attenuationDistance: f32,\n transmissionBackgroundTexture: texture_2d<f32>,\n defaultSampler: sampler,\n) -> vec4f {\n var transmittedLight: vec4f;\n var transmissionRayLength: f32;\n var transmittance: vec3f;\n \n let halfSpread: f32 = (ior - 1.0) * 0.025 * dispersion;\n let iors: vec3f = vec3(ior - halfSpread, ior, ior + halfSpread);\n \n for(var i: i32 = 0; i < 3; i++) {\n let transmissionRay: vec3f = getVolumeTransmissionRay(normal, viewDirection, thickness, iors[i], modelScale);\n transmissionRayLength = length(transmissionRay);\n let refractedRayExit = position + transmissionRay;\n\n // Transform to NDC space\n let ndcPos = projMatrix * viewMatrix * vec4(refractedRayExit, 1.0);\n var refractionCoords = ndcPos.xy / ndcPos.w;\n refractionCoords = (refractionCoords + 1.0) / 2.0;\n refractionCoords = vec2(refractionCoords.x, 1.0 - refractionCoords.y); // webgpu Y flip\n \n let transmissionSample: vec4f = getTransmissionSample(refractionCoords, roughness, iors[i], transmissionBackgroundTexture, defaultSampler);\n \n transmittedLight[i] = transmissionSample[i];\n transmittedLight.a += transmissionSample.a;\n \n // Compute transmittance\n let diffuse: vec3f = diffuseColor.rgb;\n transmittance[i] = diffuse[i] * volumeAttenuation(length(transmissionRay), attenuationColor, attenuationDistance)[i];\n }\n \n transmittedLight.a /= 3.0;\n\n // Apply attenuation to transmitted light\n let attenuatedColor = transmittance * transmittedLight.rgb;\n\n // Compute Fresnel term using an environment BRDF\n let F = EnvironmentBRDF(normal, viewDirection, specularColor, specularF90, roughness);\n\n // Average the transmittance for a single factor\n let transmittanceFactor = (transmittance.r + transmittance.g + transmittance.b) / 3.0;\n\n // Combine results into the final color\n return vec4(\n (1.0 - F) * attenuatedColor,\n 1.0 - (1.0 - transmittedLight.a) * transmittanceFactor\n );\n}\n" = ...
WGSL functions to calculate the transmission effect of transmissive meshes using the renderer scene background texture.