{"version":3,"file":"RoughnessMipmapper.cjs","sources":["../../src/utils/RoughnessMipmapper.js"],"sourcesContent":["/**\n * This class generates custom mipmaps for a roughness map by encoding the lost variation in the\n * normal map mip levels as increased roughness in the corresponding roughness mip levels. This\n * helps with rendering accuracy for MeshStandardMaterial, and also helps with anti-aliasing when\n * using PMREM. If the normal map is larger than the roughness map, the roughness map will be\n * enlarged to match the dimensions of the normal map.\n */\n\nimport {\n MathUtils,\n Mesh,\n NoBlending,\n OrthographicCamera,\n PlaneGeometry,\n RawShaderMaterial,\n Vector2,\n WebGLRenderTarget,\n} from 'three'\n\nvar _mipmapMaterial = /* @__PURE__ */ _getMipmapMaterial()\n\nvar _mesh = /* @__PURE__ */ new Mesh(/* @__PURE__ */ new PlaneGeometry(2, 2), _mipmapMaterial)\n\nvar _flatCamera = /* @__PURE__ */ new OrthographicCamera(0, 1, 0, 1, 0, 1)\n\nvar _tempTarget = null\n\nclass RoughnessMipmapper {\n constructor(renderer) {\n this._renderer = renderer\n\n this._renderer.compile(_mesh, _flatCamera)\n }\n\n generateMipmaps = function (material) {\n if ('roughnessMap' in material === false) return\n\n var { roughnessMap, normalMap } = material\n\n if (\n roughnessMap === null ||\n normalMap === null ||\n !roughnessMap.generateMipmaps ||\n material.userData.roughnessUpdated\n ) {\n return\n }\n\n material.userData.roughnessUpdated = true\n\n var width = Math.max(roughnessMap.image.width, normalMap.image.width)\n\n var height = Math.max(roughnessMap.image.height, normalMap.image.height)\n\n if (!MathUtils.isPowerOfTwo(width) || !MathUtils.isPowerOfTwo(height)) return\n\n var oldTarget = this._renderer.getRenderTarget()\n\n var autoClear = this._renderer.autoClear\n\n this._renderer.autoClear = false\n\n if (_tempTarget === null || _tempTarget.width !== width || _tempTarget.height !== height) {\n if (_tempTarget !== null) _tempTarget.dispose()\n\n _tempTarget = new WebGLRenderTarget(width, height, {\n depthBuffer: false,\n })\n\n _tempTarget.scissorTest = true\n }\n\n if (width !== roughnessMap.image.width || height !== roughnessMap.image.height) {\n var params = {\n wrapS: roughnessMap.wrapS,\n wrapT: roughnessMap.wrapT,\n magFilter: roughnessMap.magFilter,\n minFilter: roughnessMap.minFilter,\n depthBuffer: false,\n }\n\n var newRoughnessTarget = new WebGLRenderTarget(width, height, params)\n\n newRoughnessTarget.texture.generateMipmaps = true\n\n // Setting the render target causes the memory to be allocated.\n\n this._renderer.setRenderTarget(newRoughnessTarget)\n\n material.roughnessMap = newRoughnessTarget.texture\n\n if (material.metalnessMap == roughnessMap) material.metalnessMap = material.roughnessMap\n\n if (material.aoMap == roughnessMap) material.aoMap = material.roughnessMap\n }\n\n _mipmapMaterial.uniforms.roughnessMap.value = roughnessMap\n\n _mipmapMaterial.uniforms.normalMap.value = normalMap\n\n var position = new Vector2(0, 0)\n\n var texelSize = _mipmapMaterial.uniforms.texelSize.value\n\n for (let mip = 0; width >= 1 && height >= 1; ++mip, width /= 2, height /= 2) {\n // Rendering to a mip level is not allowed in webGL1. Instead we must set\n // up a secondary texture to write the result to, then copy it back to the\n // proper mipmap level.\n\n texelSize.set(1.0 / width, 1.0 / height)\n\n if (mip == 0) texelSize.set(0.0, 0.0)\n\n _tempTarget.viewport.set(position.x, position.y, width, height)\n\n _tempTarget.scissor.set(position.x, position.y, width, height)\n\n this._renderer.setRenderTarget(_tempTarget)\n\n this._renderer.render(_mesh, _flatCamera)\n\n this._renderer.copyFramebufferToTexture(position, material.roughnessMap, mip)\n\n _mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap\n }\n\n if (roughnessMap !== material.roughnessMap) roughnessMap.dispose()\n\n this._renderer.setRenderTarget(oldTarget)\n\n this._renderer.autoClear = autoClear\n }\n\n dispose = function () {\n _mipmapMaterial.dispose()\n\n _mesh.geometry.dispose()\n\n if (_tempTarget != null) _tempTarget.dispose()\n }\n}\n\nfunction _getMipmapMaterial() {\n var shaderMaterial = new RawShaderMaterial({\n uniforms: {\n roughnessMap: { value: null },\n normalMap: { value: null },\n texelSize: { value: new Vector2(1, 1) },\n },\n\n vertexShader: /* glsl */ `\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tattribute vec3 position;\n\t\t\tattribute vec2 uv;\n\n\t\t\tvarying vec2 vUv;\n\n\t\t\tvoid main() {\n\n\t\t\t\tvUv = uv;\n\n\t\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t\t}\n\t\t`,\n\n fragmentShader: /* glsl */ `\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec2 vUv;\n\n\t\t\tuniform sampler2D roughnessMap;\n\t\t\tuniform sampler2D normalMap;\n\t\t\tuniform vec2 texelSize;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\n\t\t\tvec4 envMapTexelToLinear( vec4 a ) { return a; }\n\n\t\t\t#include \n\n\t\t\tfloat roughnessToVariance( float roughness ) {\n\n\t\t\t\tfloat variance = 0.0;\n\n\t\t\t\tif ( roughness >= r1 ) {\n\n\t\t\t\t\tvariance = ( r0 - roughness ) * ( v1 - v0 ) / ( r0 - r1 ) + v0;\n\n\t\t\t\t} else if ( roughness >= r4 ) {\n\n\t\t\t\t\tvariance = ( r1 - roughness ) * ( v4 - v1 ) / ( r1 - r4 ) + v1;\n\n\t\t\t\t} else if ( roughness >= r5 ) {\n\n\t\t\t\t\tvariance = ( r4 - roughness ) * ( v5 - v4 ) / ( r4 - r5 ) + v4;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tfloat roughness2 = roughness * roughness;\n\n\t\t\t\t\tvariance = 1.79 * roughness2 * roughness2;\n\n\t\t\t\t}\n\n\t\t\t\treturn variance;\n\n\t\t\t}\n\n\t\t\tfloat varianceToRoughness( float variance ) {\n\n\t\t\t\tfloat roughness = 0.0;\n\n\t\t\t\tif ( variance >= v1 ) {\n\n\t\t\t\t\troughness = ( v0 - variance ) * ( r1 - r0 ) / ( v0 - v1 ) + r0;\n\n\t\t\t\t} else if ( variance >= v4 ) {\n\n\t\t\t\t\troughness = ( v1 - variance ) * ( r4 - r1 ) / ( v1 - v4 ) + r1;\n\n\t\t\t\t} else if ( variance >= v5 ) {\n\n\t\t\t\t\troughness = ( v4 - variance ) * ( r5 - r4 ) / ( v4 - v5 ) + r4;\n\n\t\t\t\t} else {\n\n\t\t\t\t\troughness = pow( 0.559 * variance, 0.25 ); // 0.559 = 1.0 / 1.79\n\n\t\t\t\t}\n\n\t\t\t\treturn roughness;\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = texture2D( roughnessMap, vUv, - 1.0 );\n\n\t\t\t\tif ( texelSize.x == 0.0 ) return;\n\n\t\t\t\tfloat roughness = gl_FragColor.g;\n\n\t\t\t\tfloat variance = roughnessToVariance( roughness );\n\n\t\t\t\tvec3 avgNormal;\n\n\t\t\t\tfor ( float x = - 1.0; x < 2.0; x += 2.0 ) {\n\n\t\t\t\t\tfor ( float y = - 1.0; y < 2.0; y += 2.0 ) {\n\n\t\t\t\t\t\tvec2 uv = vUv + vec2( x, y ) * 0.25 * texelSize;\n\n\t\t\t\t\t\tavgNormal += normalize( texture2D( normalMap, uv, - 1.0 ).xyz - 0.5 );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tvariance += 1.0 - 0.25 * length( avgNormal );\n\n\t\t\t\tgl_FragColor.g = varianceToRoughness( variance );\n\n\t\t\t}\n\t\t`,\n\n blending: NoBlending,\n depthTest: false,\n depthWrite: false,\n })\n\n shaderMaterial.type = 'RoughnessMipmapper'\n\n return shaderMaterial\n}\n\nexport { RoughnessMipmapper }\n"],"names":["Mesh","PlaneGeometry","OrthographicCamera","MathUtils","WebGLRenderTarget","Vector2","RawShaderMaterial","NoBlending"],"mappings":"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"}