diff options
Diffstat (limited to 'Master/texmf-dist/asymptote/shaders/fragment.glsl')
-rwxr-xr-x | Master/texmf-dist/asymptote/shaders/fragment.glsl | 209 |
1 files changed, 135 insertions, 74 deletions
diff --git a/Master/texmf-dist/asymptote/shaders/fragment.glsl b/Master/texmf-dist/asymptote/shaders/fragment.glsl index 057acbc744f..5f60a56efd3 100755 --- a/Master/texmf-dist/asymptote/shaders/fragment.glsl +++ b/Master/texmf-dist/asymptote/shaders/fragment.glsl @@ -10,25 +10,13 @@ struct Light vec3 color; }; -uniform int nlights; +uniform uint nlights; uniform Light lights[max(Nlights,1)]; uniform MaterialBuffer { Material Materials[Nmaterials]; }; -#ifdef NORMAL -#ifndef ORTHOGRAPHIC -in vec3 ViewPosition; -#endif -in vec3 Normal; -vec3 normal; -#endif - -#ifdef COLOR -in vec4 Color; -#endif - flat in int materialIndex; out vec4 outColor; @@ -38,41 +26,107 @@ vec3 Specular; // Specular tint for nonmetals float Metallic; // Metallic/Nonmetals parameter float Fresnel0; // Fresnel at zero for nonmetals float Roughness2; // roughness squared, for smoothing +float Roughness; + +#ifdef HAVE_SSBO + +layout(binding=0, std430) buffer sumBuffer { + uint sum[]; +}; + +layout(binding=1, std430) buffer offsetBuffer { + uint offset[]; +}; + +layout(binding=2, std430) buffer countBuffer { + uint count[]; +}; -#ifdef ENABLE_TEXTURE -uniform sampler2D environmentMap; -const float PI=acos(-1.0); -const float twopi=2*PI; -const float halfpi=PI/2; +layout(binding=3, std430) buffer fragmentBuffer { + vec4 fragment[]; +}; -const int numSamples=7; +layout(binding=4, std430) buffer depthBuffer { + float depth[]; +}; + +layout(binding=5, std430) buffer opaqueBuffer { + vec4 opaqueColor[]; +}; + +layout(binding=6, std430) buffer opaqueDepthBuffer { + float opaqueDepth[]; +}; + +uniform uint width; +uniform uint M; +uniform uint r; +#endif + +#ifdef NORMAL + +#ifndef ORTHOGRAPHIC +in vec3 ViewPosition; +#endif +in vec3 Normal; +vec3 normal; + +#ifdef USE_IBL +uniform sampler2D reflBRDFSampler; +uniform sampler2D diffuseSampler; +uniform sampler3D reflImgSampler; + +const float pi=acos(-1.0); +const float piInv=1.0/pi; +const float twopi=2.0*pi; +const float twopiInv=1.0/twopi; // (x,y,z) -> (r,theta,phi); -// theta -> [0,\pi]: colatitude -// phi -> [0, 2\pi]: longitude +// theta -> [0,pi]: colatitude +// phi -> [-pi,pi]: longitude vec3 cart2sphere(vec3 cart) { - float x=cart.z; - float y=cart.x; + float x=cart.x; + float y=cart.z; float z=cart.y; float r=length(cart); + float theta=r > 0.0 ? acos(z/r) : 0.0; float phi=atan(y,x); - float theta=acos(z/r); - return vec3(r,phi,theta); + return vec3(r,theta,phi); } vec2 normalizedAngle(vec3 cartVec) { vec3 sphericalVec=cart2sphere(cartVec); - sphericalVec.y=sphericalVec.y/(2*PI)-0.25; - sphericalVec.z=sphericalVec.z/PI; - return sphericalVec.yz; + sphericalVec.y=sphericalVec.y*piInv; + sphericalVec.z=0.75-sphericalVec.z*twopiInv; + + return sphericalVec.zy; } -#endif -#ifdef NORMAL +vec3 IBLColor(vec3 viewDir) +{ + // + // based on the split sum formula approximation + // L(v)=\int_\Omega L(l)f(l,v) \cos \theta_l + // which, by the split sum approiximation (assuming independence+GGX distrubition), + // roughly equals (within a margin of error) + // [\int_\Omega L(l)] * [\int_\Omega f(l,v) \cos \theta_l]. + // the first term is the reflectance irradiance integral + + vec3 IBLDiffuse=Diffuse*texture(diffuseSampler,normalizedAngle(normal)).rgb; + vec3 reflectVec=normalize(reflect(-viewDir,normal)); + vec2 reflCoord=normalizedAngle(reflectVec); + vec3 IBLRefl=texture(reflImgSampler,vec3(reflCoord,Roughness)).rgb; + vec2 IBLbrdf=texture(reflBRDFSampler,vec2(dot(normal,viewDir),Roughness)).rg; + float specularMultiplier=Fresnel0*IBLbrdf.x+IBLbrdf.y; + vec3 dielectric=IBLDiffuse+specularMultiplier*IBLRefl; + vec3 metal=Diffuse*IBLRefl; + return mix(dielectric,metal,Metallic); +} +#else // h is the halfway vector between normal and light direction // GGX Trowbridge-Reitz Approximation float NDF_TRG(vec3 h) @@ -122,18 +176,24 @@ vec3 BRDF(vec3 viewDirection, vec3 lightDirection) vec3 dielectric=mix(lambertian,rawReflectance*Specular,F); vec3 metal=rawReflectance*Diffuse; - + return mix(dielectric,metal,Metallic); } #endif +#endif + +#ifdef COLOR +in vec4 Color; +#endif + void main() { vec4 diffuse; vec4 emissive; Material m; -#ifdef TRANSPARENT +#ifdef GENERAL m=Materials[abs(materialIndex)-1]; emissive=m.emissive; if(materialIndex >= 0) @@ -150,18 +210,18 @@ void main() #ifdef COLOR diffuse=Color; #if Nlights == 0 - emissive += Color; + emissive += Color; #endif -#else - diffuse=m.diffuse; +#else + diffuse=m.diffuse; #endif #endif - + #if defined(NORMAL) && Nlights > 0 Specular=m.specular.rgb; vec4 parameters=m.parameters; - Roughness2=1.0-parameters[0]; - Roughness2=Roughness2*Roughness2; + Roughness=1.0-parameters[0]; + Roughness2=Roughness*Roughness; Metallic=parameters[1]; Fresnel0=parameters[2]; Diffuse=diffuse.rgb; @@ -178,50 +238,51 @@ void main() #else vec3 viewDir=-normalize(ViewPosition); #endif + vec3 color; +#ifdef USE_IBL + color=IBLColor(viewDir); +#else // For a finite point light, the rendering equation simplifies. - vec3 color=emissive.rgb; - for(int i=0; i < nlights; ++i) { + color=emissive.rgb; + for(uint i=0u; i < nlights; ++i) { Light Li=lights[i]; vec3 L=Li.direction; float cosTheta=max(dot(normal,L),0.0); // $\omega_i \cdot n$ term vec3 radiance=cosTheta*Li.color; color += BRDF(viewDir,L)*radiance; } - -#if defined(ENABLE_TEXTURE) && !defined(COLOR) - // Experimental environment radiance using Riemann sums; - // can also do importance sampling. - vec3 envRadiance=vec3(0.0,0.0,0.0); - - vec3 normalPerp=vec3(-normal.y,normal.x,0.0); - if(length(normalPerp) == 0.0) - normalPerp=vec3(1.0,0.0,0.0); - - // we now have a normal basis; - normalPerp=normalize(normalPerp); - vec3 normalPerp2=normalize(cross(normal,normalPerp)); - - const float step=1.0/numSamples; - const float phistep=twopi*step; - const float thetastep=halfpi*step; - for (int iphi=0; iphi < numSamples; ++iphi) { - float phi=iphi*phistep; - for (int itheta=0; itheta < numSamples; ++itheta) { - float theta=itheta*thetastep; - - vec3 azimuth=cos(phi)*normalPerp+sin(phi)*normalPerp2; - vec3 L=sin(theta)*azimuth+cos(theta)*normal; - - vec3 rawRadiance=texture(environmentMap,normalizedAngle(L)).rgb; - vec3 surfRefl=BRDF(Z,L); - envRadiance += surfRefl*rawRadiance*sin(2.0*theta); - } - } - envRadiance *= halfpi*step*step; - color += envRadiance.rgb; #endif outColor=vec4(color,diffuse.a); -#else +#else outColor=emissive; -#endif +#endif + +#ifndef WIDTH +#ifdef HAVE_SSBO + uint headIndex=uint(gl_FragCoord.y)*width+uint(gl_FragCoord.x); +#if defined(TRANSPARENT) || (!defined(HAVE_INTERLOCK) && !defined(OPAQUE)) + uint listIndex= +#ifdef GPUINDEXING + sum[headIndex < r*(M+1u) ? headIndex/(M+1u) : (headIndex-r)/M]+ +#endif + offset[headIndex]+atomicAdd(count[headIndex],1u); + fragment[listIndex]=outColor; + depth[listIndex]=gl_FragCoord.z; +#ifndef WIREFRAME + discard; +#endif +#else +#ifndef OPAQUE +#ifdef HAVE_INTERLOCK +beginInvocationInterlockARB(); +if(opaqueDepth[headIndex] == 0.0 || gl_FragCoord.z < opaqueDepth[headIndex]) { + opaqueDepth[headIndex]=gl_FragCoord.z; + opaqueColor[headIndex]=outColor; +} +endInvocationInterlockARB(); +#endif +#endif +#endif +#endif +#endif } |