Przeglądaj źródła

ShaderChunk: Implemented mipped bicubic transmission texture filtering. (#25483)

mrdoob 2 lat temu
rodzic
commit
9a0ea14aec

+ 92 - 0
src/renderers/shaders/ShaderChunk/common.glsl.js

@@ -114,5 +114,97 @@ vec2 equirectUv( in vec3 dir ) {
 
 	return vec2( u, v );
 
+}
+
+// Mipped Bicubic Texture Filtering by N8
+// https://www.shadertoy.com/view/Dl2SDW
+
+float w0( float a ) {
+
+	return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );
+
+}
+
+float w1( float a ) {
+
+	return ( 1.0 / 6.0 ) * ( a *  a * ( 3.0 * a - 6.0 ) + 4.0 );
+
+}
+
+float w2( float a ){
+
+    return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );
+
+}
+
+float w3( float a ) {
+
+	return ( 1.0 / 6.0 ) * ( a * a * a );
+
+}
+
+// g0 and g1 are the two amplitude functions
+float g0( float a ) {
+
+	return w0( a ) + w1( a );
+
+}
+
+float g1( float a ) {
+
+	return w2( a ) + w3( a );
+
+}
+
+// h0 and h1 are the two offset functions
+float h0( float a ) {
+
+	return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );
+
+}
+
+float h1( float a ) {
+
+    return 1.0 + w3( a ) / ( w2( a ) + w3( a ) );
+
+}
+
+vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, vec2 fullSize, float lod ) {
+
+	uv = uv * texelSize.zw + 0.5;
+
+	vec2 iuv = floor( uv );
+    vec2 fuv = fract( uv );
+
+    float g0x = g0( fuv.x );
+    float g1x = g1( fuv.x );
+    float h0x = h0( fuv.x );
+    float h1x = h1( fuv.x );
+    float h0y = h0( fuv.y );
+    float h1y = h1( fuv.y );
+
+    vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;
+    vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;
+    vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;
+    vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;
+    
+    vec2 lodFudge = pow( 1.95, lod ) / fullSize;
+
+	return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +
+		   g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );
+
+}
+
+vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {
+
+	vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );
+	vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );
+	vec2 fLodSizeInv = 1.0 / fLodSize;
+	vec2 cLodSizeInv = 1.0 / cLodSize;
+	vec2 fullSize = vec2( textureSize( sampler, 0 ) );
+	vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), fullSize, floor( lod ) );
+	vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), fullSize, ceil( lod ) );
+	return mix( fSample, cSample, fract( lod ) );
+
 }
 `;

+ 2 - 11
src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js

@@ -55,17 +55,8 @@ export default /* glsl */`
 
 	vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {
 
-		float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
-
-		#ifdef texture2DLodEXT
-
-			return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );
-
-		#else
-
-			return texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );
-
-		#endif
+		float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
+		return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );
 
 	}