UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

77 lines 5.62 kB
// Do not edit. import { ShaderStore } from "../Engines/shaderStore.js"; import "./ShadersInclude/helperFunctions.js"; import "./ShadersInclude/fibonacci.js"; import "./ShadersInclude/subSurfaceScatteringFunctions.js"; import "./ShadersInclude/diffusionProfile.js"; const name = "subSurfaceScatteringPixelShader"; const shader = `#include<helperFunctions> #include<fibonacci> #include<subSurfaceScatteringFunctions> #include<diffusionProfile> varying vUV: vec2f;uniform texelSize: vec2f;var textureSamplerSampler: sampler;var textureSampler: texture_2d<f32>;var irradianceSamplerSampler: sampler;var irradianceSampler: texture_2d<f32>;var depthSamplerSampler: sampler;var depthSampler: texture_2d<f32>;var albedoSamplerSampler: sampler;var albedoSampler: texture_2d<f32>;uniform viewportSize: vec2f;uniform metersPerUnit: f32;const LOG2_E=1.4426950408889634;const SSS_PIXELS_PER_SAMPLE=4.;const _SssSampleBudget=40u; #define SSS_BILATERAL_FILTER true fn EvalBurleyDiffusionProfile(r: f32,S: vec3f)->vec3f {let exp_13=exp2(((LOG2_E*(-1.0/3.0))*r)*S); let expSum=exp_13*(1.+exp_13*exp_13); return (S*rcp(8.*PI))*expSum; } fn SampleBurleyDiffusionProfile(u_: f32,rcpS: f32)->vec2f {let u=1.-u_; let g=1.+(4.*u)*(2.*u+sqrt(1.+(4.*u)*u));let n=exp2(log2(g)*(-1.0/3.0)); let p=(g*n)*n; let c=1.+p+n; let d=(3./LOG2_E*2.)+(3./LOG2_E)*log2(u); let x=(3./LOG2_E)*log2(c)-d; let rcpExp=((c*c)*c)*rcp((4.*u)*((c*c)+(4.*u)*(4.*u)));let r=x*rcpS;let rcpPdf=(8.*PI*rcpS)*rcpExp; return vec2f(r,rcpPdf);} fn ComputeBilateralWeight(xy2: f32,z_: f32,mmPerUnit: f32,S: vec3f,rcpPdf: f32)->vec3f { #ifndef SSS_BILATERAL_FILTER let z=0.; #else let z=z_; #endif let r=sqrt(xy2+(z*mmPerUnit)*(z*mmPerUnit));let area=rcpPdf; #ifdef SSS_CLAMP_ARTIFACT return clamp(EvalBurleyDiffusionProfile(r,S)*area,vec3f(0.0),vec3f(1.0)); #else return EvalBurleyDiffusionProfile(r,S)*area; #endif } fn EvaluateSample(i: u32,n: u32,S: vec3f,d: f32,centerPosVS: vec3f,mmPerUnit: f32,pixelsPerMm: f32, phase: f32,totalIrradiance: ptr<function,vec3f>,totalWeight: ptr<function,vec3f>) {let scale =rcp(f32(n));let offset=rcp(f32(n))*0.5;let sinPhase=sin(phase);let cosPhase=cos(phase);let bdp=SampleBurleyDiffusionProfile(f32(i)*scale+offset,d);let r=bdp.x;let rcpPdf=bdp.y;let phi=SampleDiskGolden(i,n).y;let sinPhi=sin(phi);let cosPhi=cos(phi);let sinPsi=cosPhase*sinPhi+sinPhase*cosPhi; let cosPsi=cosPhase*cosPhi-sinPhase*sinPhi; let vec=r*vec2f(cosPsi,sinPsi);let position=fragmentInputs.vUV+round((pixelsPerMm*r)*vec2(cosPsi,sinPsi))*uniforms.texelSize;let xy2 =r*r;let textureRead=textureSampleLevel(irradianceSampler,irradianceSamplerSampler,position,0.);let viewZ=textureSampleLevel(depthSampler,depthSamplerSampler,position,0.).r;let irradiance =textureRead.rgb;if (testLightingForSSS(textureRead.a)) {let relZ=viewZ-centerPosVS.z;let weight=ComputeBilateralWeight(xy2,relZ,mmPerUnit,S,rcpPdf);*totalIrradiance+=weight*irradiance;*totalWeight +=weight;} else {}} #define CUSTOM_FRAGMENT_DEFINITIONS @fragment fn main(input: FragmentInputs)->FragmentOutputs {let irradianceAndDiffusionProfile =textureSampleLevel(irradianceSampler,irradianceSamplerSampler,fragmentInputs.vUV,0.);let centerIrradiance=irradianceAndDiffusionProfile.rgb;let diffusionProfileIndex=u32(round(irradianceAndDiffusionProfile.a*255.));var centerDepth =0.;let inputColor=textureSampleLevel(textureSampler,textureSamplerSampler,fragmentInputs.vUV,0.);let passedStencilTest=testLightingForSSS(irradianceAndDiffusionProfile.a);if (passedStencilTest) {centerDepth=textureSampleLevel(depthSampler,depthSamplerSampler,fragmentInputs.vUV,0.).r;} if (!passedStencilTest) { fragmentOutputs.color=inputColor;return fragmentOutputs;} let distScale =1.;let S =uniforms.diffusionS[diffusionProfileIndex];let d =uniforms.diffusionD[diffusionProfileIndex];let filterRadius=uniforms.filterRadii[diffusionProfileIndex];let centerPosNDC=fragmentInputs.vUV;let cornerPosNDC=fragmentInputs.vUV+0.5*uniforms.texelSize;let centerPosVS =vec3f(centerPosNDC*uniforms.viewportSize,1.0)*centerDepth; let cornerPosVS =vec3f(cornerPosNDC*uniforms.viewportSize,1.0)*centerDepth; let mmPerUnit =1000.*(uniforms.metersPerUnit*rcp(distScale));let unitsPerMm=rcp(mmPerUnit);let unitsPerPixel=2.*abs(cornerPosVS.x-centerPosVS.x);let pixelsPerMm =rcp(unitsPerPixel)*unitsPerMm;let filterArea =PI*square(filterRadius*pixelsPerMm);let sampleCount =u32(filterArea*rcp(SSS_PIXELS_PER_SAMPLE));let sampleBudget=_SssSampleBudget;let albedo =textureSampleLevel(albedoSampler,albedoSamplerSampler,fragmentInputs.vUV,0.).rgb;if (distScale==0. || sampleCount<1) { #ifdef DEBUG_SSS_SAMPLES let green=vec3f(0.,1.,0.);fragmentOutputs.color=vec4f(green,1.0);return fragmentOutputs; #endif fragmentOutputs.color=vec4f(inputColor.rgb+albedo*centerIrradiance,1.0);return fragmentOutputs;} #ifdef DEBUG_SSS_SAMPLES let red =vec3f(1.,0.,0.);let blue=vec3f(0.,0.,1.);fragmentOutputs.color=vec4f(mix(blue,red,clamp(f32(sampleCount)/f32(sampleBudget),0.0,1.0)),1.0);return fragmentOutputs; #endif let phase=0.;let n=min(sampleCount,sampleBudget);var totalIrradiance=vec3f(0.);var totalWeight =vec3f(0.);for (var i=0u; i<n; i++) {EvaluateSample(i,n,S,d,centerPosVS,mmPerUnit,pixelsPerMm, phase,&totalIrradiance,&totalWeight);} totalWeight=max(totalWeight,vec3f(HALF_MIN));fragmentOutputs.color=vec4f(inputColor.rgb+albedo*max(totalIrradiance/totalWeight,vec3f(0.0)),1.);} `; // Sideeffect if (!ShaderStore.ShadersStoreWGSL[name]) { ShaderStore.ShadersStoreWGSL[name] = shader; } /** @internal */ export const subSurfaceScatteringPixelShaderWGSL = { name, shader }; //# sourceMappingURL=subSurfaceScattering.fragment.js.map