@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.
189 lines • 12 kB
JavaScript
// Do not edit.
import { ShaderStore } from "../Engines/shaderStore.js";
const name = "iblShadowVoxelTracingPixelShader";
const shader = `precision highp sampler2D;precision highp sampler3D;
varying vec2 vUV;
uniform sampler2D depthSampler;uniform sampler2D worldNormalSampler;uniform sampler2D blueNoiseSampler;uniform sampler2D icdfSampler;uniform sampler3D voxelGridSampler;
uniform samplerCube iblSampler;
uniform vec4 shadowParameters;
uniform vec4 voxelBiasParameters;
uniform vec4 sssParameters;
uniform vec4 shadowOpacity;uniform mat4 projMtx;uniform mat4 viewMtx;uniform mat4 invProjMtx;uniform mat4 invViewMtx;uniform mat4 wsNormalizationMtx;uniform mat4 invVPMtx;
struct AABB3f {vec3 m_min;vec3 m_max;};struct Ray {vec3 orig;vec3 dir;vec3 dir_rcp;float t_min;float t_max;};Ray make_ray(const vec3 origin,const vec3 direction,const float tmin,
const float tmax) {Ray ray;ray.orig=origin;ray.dir=direction;ray.dir_rcp=1.0f/direction;ray.t_min=tmin;ray.t_max=tmax;return ray;}
bool ray_box_intersection(const in AABB3f aabb,const in Ray ray,
out float distance_near,out float distance_far) {vec3 tbot=ray.dir_rcp*(aabb.m_min-ray.orig);vec3 ttop=ray.dir_rcp*(aabb.m_max-ray.orig);vec3 tmin=min(ttop,tbot);vec3 tmax=max(ttop,tbot);distance_near=max(ray.t_min,max(tmin.x,max(tmin.y,tmin.z)));distance_far=min(ray.t_max,min(tmax.x,min(tmax.y,tmax.z)));return distance_near<=distance_far;}
struct VoxelMarchDiagnosticInfo {float heat;ivec3 voxel_intersect_coords;};
uint hash(uint i) {i ^= i>>16u;i*=0x7FEB352Du;i ^= i>>15u;i*=0x846CA68Bu;i ^= i>>16u;return i;}
float uint2float(uint i) {return uintBitsToFloat(0x3F800000u | (i>>9u))-1.0;}
vec3 uv_to_normal(vec2 uv) {vec3 N;vec2 uvRange=uv;float theta=uvRange.x*2.0*PI;float phi=uvRange.y*PI;N.x=cos(theta)*sin(phi);N.z=sin(theta)*sin(phi);N.y=cos(phi);return N;}
vec2 plasticSequence(const uint rstate) {return vec2(uint2float(rstate*3242174889u),
uint2float(rstate*2447445414u));}
float goldenSequence(const uint rstate) {return uint2float(rstate*2654435769u);}
float distanceSquared(vec2 a,vec2 b) {vec2 diff=a-b;return dot(diff,diff);}
void genTB(const vec3 N,out vec3 T,out vec3 B) {float s=N.z<0.0 ? -1.0 : 1.0;float a=-1.0/(s+N.z);float b=N.x*N.y*a;T=vec3(1.0+s*N.x*N.x*a,s*b,-s*N.x);B=vec3(b,s+N.y*N.y*a,-N.y);}
int stack[24];
bool anyHitVoxels(const Ray ray_vs,
out VoxelMarchDiagnosticInfo voxel_march_diagnostic_info) {
bool anyHitVoxels(const Ray ray_vs) {
vec3 invD=ray_vs.dir_rcp;vec3 D=ray_vs.dir;vec3 O=ray_vs.orig;ivec3 negD=ivec3(lessThan(D,vec3(0,0,0)));int voxel0=negD.x | negD.y<<1 | negD.z<<2;vec3 t0=-O*invD,t1=(vec3(1.0)-O)*invD;int maxLod=int(highestMipLevel);int stackLevel=0;
uint steps=0u;
PUSH(maxLod<<24);while (stackLevel>0) {int elem=POP();ivec4 Coords =
ivec4(elem & 0xFF,elem>>8 & 0xFF,elem>>16 & 0xFF,elem>>24);if (Coords.w==0) {
voxel_march_diagnostic_info.heat=float(steps)/24.0;
return true;}
++steps;
float invRes=exp2(float(Coords.w-maxLod));vec3 bbmin=invRes*vec3(Coords.xyz+negD);vec3 bbmax=invRes*vec3(Coords.xyz-negD+ivec3(1));vec3 mint=mix(t0,t1,bbmin);vec3 maxt=mix(t0,t1,bbmax);vec3 midt=0.5*(mint+maxt);mint.x=max(0.0,mint.x);midt.x=max(0.0,midt.x);int nodeMask=int(
round(texelFetch(voxelGridSampler,Coords.xyz,Coords.w).x*255.0));Coords.w--;int voxelBit=voxel0;Coords.xyz=(Coords.xyz<<1)+negD;int packedCoords =
Coords.x | Coords.y<<8 | Coords.z<<16 | Coords.w<<24;if (max(mint.x,max(mint.y,mint.z))<min(midt.x,min(midt.y,midt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x1;packedCoords ^= 0x00001;if (max(midt.x,max(mint.y,mint.z))<min(maxt.x,min(midt.y,midt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x2;packedCoords ^= 0x00100;if (max(midt.x,max(midt.y,mint.z))<min(maxt.x,min(maxt.y,midt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x1;packedCoords ^= 0x00001;if (max(mint.x,max(midt.y,mint.z))<min(midt.x,min(maxt.y,midt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x4;packedCoords ^= 0x10000;if (max(mint.x,max(midt.y,midt.z))<min(midt.x,min(maxt.y,maxt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x1;packedCoords ^= 0x00001;if (max(midt.x,max(midt.y,midt.z))<min(maxt.x,min(maxt.y,maxt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x2;packedCoords ^= 0x00100;if (max(midt.x,max(mint.y,midt.z))<min(maxt.x,min(midt.y,maxt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);voxelBit ^= 0x1;packedCoords ^= 0x00001;if (max(mint.x,max(mint.y,midt.z))<min(midt.x,min(midt.y,maxt.z)) &&
(1<<voxelBit & nodeMask) != 0)
PUSH(packedCoords);}
voxel_march_diagnostic_info.heat=float(steps)/24.0;
return false;}
float linearizeDepth(float depth,float near,float far) {return (near*far)/(far-depth*(far-near));}
float screenSpaceShadow(vec3 csOrigin,vec3 csDirection,vec2 csZBufferSize,
float nearPlaneZ,float farPlaneZ,float noise) {
float csZDir=-1.0;
float csZDir=1.0;
float ssSamples=SSSsamples;float ssMaxDist=SSSmaxDistance;float ssStride=SSSstride;float ssThickness=SSSthickness;float rayLength =
csZDir*(csOrigin.z+ssMaxDist*csDirection.z)<csZDir*nearPlaneZ
?
(nearPlaneZ-csOrigin.z)/csDirection.z
: ssMaxDist;vec3 csEndPoint=csOrigin+rayLength*csDirection;vec4 H0=projMtx*vec4(csOrigin,1.0);vec4 H1=projMtx*vec4(csEndPoint,1.0);vec2 Z0=vec2(csOrigin.z ,1.0)/H0.w;vec2 Z1=vec2(csEndPoint.z,1.0)/H1.w;vec2 P0=csZBufferSize*(0.5*H0.xy*Z0.y+0.5);vec2 P1=csZBufferSize*(0.5*H1.xy*Z1.y+0.5);P1+=vec2(distanceSquared(P0,P1)<0.0001 ? 0.01 : 0.0);vec2 delta=P1-P0;bool permute=false;if (abs(delta.x)<abs(delta.y)) {permute=true;P0=P0.yx;P1=P1.yx;delta=delta.yx;}
float stepDirection=sign(delta.x);float invdx=stepDirection/delta.x;vec2 dP=ssStride*vec2(stepDirection,invdx*delta.y);vec2 dZ=ssStride*invdx*(Z1-Z0);float opacity=0.0;vec2 P=P0+noise*dP;vec2 Z=Z0+noise*dZ;float end=P1.x*stepDirection;float rayZMax=csZDir*Z.x/Z.y;float sceneDepth=rayZMax;Z+=dZ;for (float stepCount=0.0;opacity<1.0 && P.x*stepDirection<end && sceneDepth>0.0 && stepCount<ssSamples;stepCount++,P+=dP,
Z+=dZ) {
ivec2 coords=ivec2(permute ? P.yx : P);sceneDepth=texelFetch(depthSampler,coords,0).x;sceneDepth=linearizeDepth(sceneDepth,nearPlaneZ,farPlaneZ);sceneDepth=csZDir*sceneDepth;if (sceneDepth<=0.0) {break;}
float rayZMin=rayZMax;rayZMax=csZDir*Z.x/Z.y;opacity+=max(opacity,step(rayZMax,sceneDepth+ssThickness)*step(sceneDepth,rayZMin));}
return opacity;}
float voxelShadow(vec3 wsOrigin,vec3 wsDirection,vec3 wsNormal,
vec2 DitherNoise,
out VoxelMarchDiagnosticInfo voxel_march_diagnostic_info) {
float voxelShadow(vec3 wsOrigin,vec3 wsDirection,vec3 wsNormal,
vec2 DitherNoise) {
float vxResolution=float(textureSize(voxelGridSampler,0).x);vec3 T,B;genTB(wsDirection,T,B);vec2 DitherXY=sqrt(DitherNoise.x)*vec2(cos(2.0*PI*DitherNoise.y),
sin(2.0*PI*DitherNoise.y));float sceneScale=wsNormalizationMtx[0][0];vec3 Dithering =
(voxelBiasParameters.x*wsNormal+voxelBiasParameters.y*wsDirection +
DitherXY.x*T+DitherXY.y*B) /
vxResolution;vec3 O=0.5*wsOrigin+0.5+Dithering;Ray ray_vs=make_ray(O,wsDirection,0.0,10.0);AABB3f voxel_aabb;voxel_aabb.m_min=vec3(0);voxel_aabb.m_max=vec3(1);float near,far;if (!ray_box_intersection(voxel_aabb,ray_vs,near,far))
return 0.0;ray_vs.t_min=max(ray_vs.t_min,near);ray_vs.t_max=min(ray_vs.t_max,far);
return anyHitVoxels(ray_vs,voxel_march_diagnostic_info) ? 1.0f : 0.0f;
return anyHitVoxels(ray_vs) ? 1.0f : 0.0f;
}
void main(void) {uint nbDirs=uint(SHADOWdirs);uint frameId=uint(SHADOWframe);float envRot=SHADOWenvRot;vec2 Resolution=vec2(textureSize(depthSampler,0));ivec2 currentPixel=ivec2(vUV*Resolution);uint GlobalIndex=(frameId*uint(Resolution.y)+uint(currentPixel.y)) *
uint(Resolution.x) +
uint(currentPixel.x);vec3 N=texelFetch(worldNormalSampler,currentPixel,0).xyz;if (length(N)<0.01) {glFragColor=vec4(1.0,1.0,0.0,1.0);return;}
float normalizedRotation=envRot/(2.0*PI);float depth=texelFetch(depthSampler,currentPixel,0).x;
depth=depth*2.0-1.0;
vec2 temp=(vec2(currentPixel)+vec2(0.5))*2.0/Resolution-vec2(1.0);vec4 VP=invProjMtx*vec4(temp.x,-temp.y,depth,1.0);VP/=VP.w;N=normalize(N);vec3 noise=texelFetch(blueNoiseSampler,currentPixel & 0xFF,0).xyz;noise.z=fract(noise.z+goldenSequence(frameId*nbDirs));
float heat=0.0f;
float shadowAccum=0.001;float specShadowAccum=0.001;float sampleWeight=0.001;
vec3 totalLight=vec3(0.001);vec3 shadowedLight=vec3(0.0);
for (uint i=0u; i<nbDirs; i++) {uint dirId=nbDirs*GlobalIndex+i;vec4 L;vec2 T;{vec2 r=plasticSequence(frameId*nbDirs+i);r=fract(r+vec2(2.0)*abs(noise.xy-vec2(0.5)));T.x=textureLod(icdfSampler,vec2(r.x,0.0),0.0).x;T.y=textureLod(icdfSampler,vec2(T.x,r.y),0.0).y;L=vec4(uv_to_normal(vec2(T.x-normalizedRotation,T.y)),0);
L.z*=-1.0;
}
vec3 lightDir=uv_to_normal(vec2(1.0-fract(T.x+0.25),T.y));vec3 ibl=textureLod(iblSampler,lightDir,0.0).xyz;float pdf=textureLod(icdfSampler,T,0.0).z;
float cosNL=dot(N,L.xyz);float opacity=0.0;if (cosNL>0.0) {vec4 VP2=VP;VP2.y*=-1.0;vec4 unormWP=invViewMtx*VP2;vec3 WP=(wsNormalizationMtx*unormWP).xyz;vec2 vxNoise=vec2(uint2float(hash(dirId*2u)),uint2float(hash(dirId*2u+1u)));
VoxelMarchDiagnosticInfo voxel_march_diagnostic_info;opacity=max(opacity,shadowOpacity.x*voxelShadow(WP,L.xyz,N,vxNoise,voxel_march_diagnostic_info));heat+=voxel_march_diagnostic_info.heat;
opacity =
max(opacity,shadowOpacity.x*voxelShadow(WP,L.xyz,N,vxNoise));
vec3 VL=(viewMtx*L).xyz;
float nearPlaneZ=-projMtx[3][2]/(projMtx[2][2]-1.0);
float farPlaneZ=-projMtx[3][2]/(projMtx[2][2]+1.0);
float nearPlaneZ=-projMtx[3][2]/(projMtx[2][2]+1.0);
float farPlaneZ=-projMtx[3][2]/(projMtx[2][2]-1.0);
float ssShadow=shadowOpacity.y *
screenSpaceShadow(VP2.xyz,VL,Resolution,nearPlaneZ,farPlaneZ,
abs(2.0*noise.z-1.0));opacity=max(opacity,ssShadow);
vec3 light=pdf<1e-6 ? vec3(0.0) : vec3(cosNL)/vec3(pdf)*ibl;shadowedLight+=light*opacity;totalLight+=light;
float rcos=(1.0-cosNL);shadowAccum+=(1.0-opacity*(1.0-pow(rcos,8.0)));sampleWeight+=1.0;vec3 VR=-(viewMtx*vec4(reflect(-L.xyz,N),0.0)).xyz;specShadowAccum+=max(1.0-(opacity*pow(VR.z,8.0)),0.0);
}
noise.z=fract(noise.z+GOLD);}
vec3 shadow=(totalLight-shadowedLight)/totalLight;float maxShadow=max(max(shadow.x,max(shadow.y,shadow.z)),1.0);glFragColor=vec4(shadow/maxShadow,1.0);
gl_FragColor=vec4(shadowAccum/float(sampleWeight),
specShadowAccum/float(sampleWeight),heat/float(sampleWeight),1.0);
gl_FragColor=vec4(shadowAccum/float(sampleWeight),specShadowAccum/float(sampleWeight),0.0,1.0);
}`;
// Sideeffect
if (!ShaderStore.ShadersStore[name]) {
ShaderStore.ShadersStore[name] = shader;
}
/** @internal */
export const iblShadowVoxelTracingPixelShader = { name, shader };
//# sourceMappingURL=iblShadowVoxelTracing.fragment.js.map