未验证 提交 c57096f5 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #20119 from WestLangley/dev_roughness_mipmapper

RoughnessMipmapper: clean up formatting
...@@ -19,15 +19,19 @@ import { ...@@ -19,15 +19,19 @@ import {
} from "../../../build/three.module.js"; } from "../../../build/three.module.js";
var _mipmapMaterial = _getMipmapMaterial(); var _mipmapMaterial = _getMipmapMaterial();
var _mesh = new Mesh( new PlaneBufferGeometry( 2, 2 ), _mipmapMaterial ); var _mesh = new Mesh( new PlaneBufferGeometry( 2, 2 ), _mipmapMaterial );
var _flatCamera = new OrthographicCamera( 0, 1, 0, 1, 0, 1 ); var _flatCamera = new OrthographicCamera( 0, 1, 0, 1, 0, 1 );
var _tempTarget = null; var _tempTarget = null;
var _renderer = null; var _renderer = null;
function RoughnessMipmapper( renderer ) { function RoughnessMipmapper( renderer ) {
_renderer = renderer; _renderer = renderer;
_renderer.compile( _mesh, _flatCamera ); _renderer.compile( _mesh, _flatCamera );
} }
...@@ -39,62 +43,79 @@ RoughnessMipmapper.prototype = { ...@@ -39,62 +43,79 @@ RoughnessMipmapper.prototype = {
generateMipmaps: function ( material ) { generateMipmaps: function ( material ) {
var { roughnessMap, normalMap } = material; var { roughnessMap, normalMap } = material;
if ( roughnessMap == null || normalMap == null || ! roughnessMap.generateMipmaps ||
material.userData.roughnessUpdated ) return; if ( roughnessMap === null || normalMap === null || ! roughnessMap.generateMipmaps || material.userData.roughnessUpdated ) return;
material.userData.roughnessUpdated = true; material.userData.roughnessUpdated = true;
var width = Math.max( roughnessMap.image.width, normalMap.image.width ); var width = Math.max( roughnessMap.image.width, normalMap.image.width );
var height = Math.max( roughnessMap.image.height, normalMap.image.height ); var height = Math.max( roughnessMap.image.height, normalMap.image.height );
if ( ! MathUtils.isPowerOfTwo( width ) || ! MathUtils.isPowerOfTwo( height ) ) return; if ( ! MathUtils.isPowerOfTwo( width ) || ! MathUtils.isPowerOfTwo( height ) ) return;
var oldTarget = _renderer.getRenderTarget(); var oldTarget = _renderer.getRenderTarget();
var autoClear = _renderer.autoClear; var autoClear = _renderer.autoClear;
_renderer.autoClear = false; _renderer.autoClear = false;
if ( _tempTarget == null || _tempTarget.width !== width || _tempTarget.height !== height ) { if ( _tempTarget === null || _tempTarget.width !== width || _tempTarget.height !== height ) {
if ( _tempTarget != null ) _tempTarget.dispose(); if ( _tempTarget !== null ) _tempTarget.dispose();
_tempTarget = new WebGLRenderTarget( width, height, { depthBuffer: false } ); _tempTarget = new WebGLRenderTarget( width, height, { depthBuffer: false } );
_tempTarget.scissorTest = true; _tempTarget.scissorTest = true;
} }
if ( width !== roughnessMap.image.width || height !== roughnessMap.image.height ) { if ( width !== roughnessMap.image.width || height !== roughnessMap.image.height ) {
var newRoughnessTarget = new WebGLRenderTarget( width, height, { var newRoughnessTarget = new WebGLRenderTarget( width, height, { minFilter: LinearMipMapLinearFilter, depthBuffer: false } );
minFilter: LinearMipMapLinearFilter,
depthBuffer: false
} );
newRoughnessTarget.texture.generateMipmaps = true; newRoughnessTarget.texture.generateMipmaps = true;
// Setting the render target causes the memory to be allocated. // Setting the render target causes the memory to be allocated.
_renderer.setRenderTarget( newRoughnessTarget ); _renderer.setRenderTarget( newRoughnessTarget );
material.roughnessMap = newRoughnessTarget.texture; material.roughnessMap = newRoughnessTarget.texture;
if ( material.metalnessMap == roughnessMap ) material.metalnessMap = material.roughnessMap; if ( material.metalnessMap == roughnessMap ) material.metalnessMap = material.roughnessMap;
if ( material.aoMap == roughnessMap ) material.aoMap = material.roughnessMap; if ( material.aoMap == roughnessMap ) material.aoMap = material.roughnessMap;
} }
_mipmapMaterial.uniforms.roughnessMap.value = roughnessMap; _mipmapMaterial.uniforms.roughnessMap.value = roughnessMap;
_mipmapMaterial.uniforms.normalMap.value = normalMap; _mipmapMaterial.uniforms.normalMap.value = normalMap;
var position = new Vector2( 0, 0 ); var position = new Vector2( 0, 0 );
var texelSize = _mipmapMaterial.uniforms.texelSize.value; var texelSize = _mipmapMaterial.uniforms.texelSize.value;
for ( var mip = 0; width >= 1 && height >= 1;
++ mip, width /= 2, height /= 2 ) { for ( var mip = 0; width >= 1 && height >= 1; ++ mip, width /= 2, height /= 2 ) {
// Rendering to a mip level is not allowed in webGL1. Instead we must set // Rendering to a mip level is not allowed in webGL1. Instead we must set
// up a secondary texture to write the result to, then copy it back to the // up a secondary texture to write the result to, then copy it back to the
// proper mipmap level. // proper mipmap level.
texelSize.set( 1.0 / width, 1.0 / height ); texelSize.set( 1.0 / width, 1.0 / height );
if ( mip == 0 ) texelSize.set( 0.0, 0.0 ); if ( mip == 0 ) texelSize.set( 0.0, 0.0 );
_tempTarget.viewport.set( position.x, position.y, width, height ); _tempTarget.viewport.set( position.x, position.y, width, height );
_tempTarget.scissor.set( position.x, position.y, width, height ); _tempTarget.scissor.set( position.x, position.y, width, height );
_renderer.setRenderTarget( _tempTarget ); _renderer.setRenderTarget( _tempTarget );
_renderer.render( _mesh, _flatCamera ); _renderer.render( _mesh, _flatCamera );
_renderer.copyFramebufferToTexture( position, material.roughnessMap, mip ); _renderer.copyFramebufferToTexture( position, material.roughnessMap, mip );
_mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap; _mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap;
} }
...@@ -102,6 +123,7 @@ RoughnessMipmapper.prototype = { ...@@ -102,6 +123,7 @@ RoughnessMipmapper.prototype = {
if ( roughnessMap !== material.roughnessMap ) roughnessMap.dispose(); if ( roughnessMap !== material.roughnessMap ) roughnessMap.dispose();
_renderer.setRenderTarget( oldTarget ); _renderer.setRenderTarget( oldTarget );
_renderer.autoClear = autoClear; _renderer.autoClear = autoClear;
}, },
...@@ -109,7 +131,9 @@ RoughnessMipmapper.prototype = { ...@@ -109,7 +131,9 @@ RoughnessMipmapper.prototype = {
dispose: function () { dispose: function () {
_mipmapMaterial.dispose(); _mipmapMaterial.dispose();
_mesh.geometry.dispose(); _mesh.geometry.dispose();
if ( _tempTarget != null ) _tempTarget.dispose(); if ( _tempTarget != null ) _tempTarget.dispose();
} }
...@@ -129,69 +153,119 @@ function _getMipmapMaterial() { ...@@ -129,69 +153,119 @@ function _getMipmapMaterial() {
vertexShader: /* glsl */` vertexShader: /* glsl */`
precision mediump float; precision mediump float;
precision mediump int; precision mediump int;
attribute vec3 position; attribute vec3 position;
attribute vec2 uv; attribute vec2 uv;
varying vec2 vUv; varying vec2 vUv;
void main() { void main() {
vUv = uv; vUv = uv;
gl_Position = vec4( position, 1.0 ); gl_Position = vec4( position, 1.0 );
} }
`, `,
fragmentShader: /* glsl */` fragmentShader: /* glsl */`
precision mediump float; precision mediump float;
precision mediump int; precision mediump int;
varying vec2 vUv; varying vec2 vUv;
uniform sampler2D roughnessMap; uniform sampler2D roughnessMap;
uniform sampler2D normalMap; uniform sampler2D normalMap;
uniform vec2 texelSize; uniform vec2 texelSize;
#define ENVMAP_TYPE_CUBE_UV #define ENVMAP_TYPE_CUBE_UV
vec4 envMapTexelToLinear(vec4 a){return a;}
vec4 envMapTexelToLinear( vec4 a ) { return a; }
#include <cube_uv_reflection_fragment> #include <cube_uv_reflection_fragment>
float roughnessToVariance(float roughness) { float roughnessToVariance( float roughness ) {
float variance = 0.0; float variance = 0.0;
if (roughness >= r1) {
variance = (r0 - roughness) * (v1 - v0) / (r0 - r1) + v0; if ( roughness >= r1 ) {
} else if (roughness >= r4) {
variance = (r1 - roughness) * (v4 - v1) / (r1 - r4) + v1; variance = ( r0 - roughness ) * ( v1 - v0 ) / ( r0 - r1 ) + v0;
} else if (roughness >= r5) {
variance = (r4 - roughness) * (v5 - v4) / (r4 - r5) + v4; } else if ( roughness >= r4 ) {
variance = ( r1 - roughness ) * ( v4 - v1 ) / ( r1 - r4 ) + v1;
} else if ( roughness >= r5 ) {
variance = ( r4 - roughness ) * ( v5 - v4 ) / ( r4 - r5 ) + v4;
} else { } else {
float roughness2 = roughness * roughness; float roughness2 = roughness * roughness;
variance = 1.79 * roughness2 * roughness2; variance = 1.79 * roughness2 * roughness2;
} }
return variance; return variance;
} }
float varianceToRoughness(float variance) {
float varianceToRoughness( float variance ) {
float roughness = 0.0; float roughness = 0.0;
if (variance >= v1) {
roughness = (v0 - variance) * (r1 - r0) / (v0 - v1) + r0; if ( variance >= v1 ) {
} else if (variance >= v4) {
roughness = (v1 - variance) * (r4 - r1) / (v1 - v4) + r1; roughness = ( v0 - variance ) * ( r1 - r0 ) / ( v0 - v1 ) + r0;
} else if (variance >= v5) {
roughness = (v4 - variance) * (r5 - r4) / (v4 - v5) + r4; } else if ( variance >= v4 ) {
roughness = ( v1 - variance ) * ( r4 - r1 ) / ( v1 - v4 ) + r1;
} else if ( variance >= v5 ) {
roughness = ( v4 - variance ) * ( r5 - r4 ) / ( v4 - v5 ) + r4;
} else { } else {
roughness = pow(0.559 * variance, 0.25);// 0.559 = 1.0 / 1.79
roughness = pow( 0.559 * variance, 0.25 ); // 0.559 = 1.0 / 1.79
} }
return roughness; return roughness;
} }
void main() { void main() {
gl_FragColor = texture2D(roughnessMap, vUv, -1.0);
if (texelSize.x == 0.0) return; gl_FragColor = texture2D( roughnessMap, vUv, - 1.0 );
if ( texelSize.x == 0.0 ) return;
float roughness = gl_FragColor.g; float roughness = gl_FragColor.g;
float variance = roughnessToVariance(roughness);
float variance = roughnessToVariance( roughness );
vec3 avgNormal; vec3 avgNormal;
for (float x = -1.0; x < 2.0; x += 2.0) {
for (float y = -1.0; y < 2.0; y += 2.0) { for ( float x = - 1.0; x < 2.0; x += 2.0 ) {
vec2 uv = vUv + vec2(x, y) * 0.25 * texelSize;
avgNormal += normalize(texture2D(normalMap, uv, -1.0).xyz - 0.5); for ( float y = - 1.0; y < 2.0; y += 2.0 ) {
vec2 uv = vUv + vec2( x, y ) * 0.25 * texelSize;
avgNormal += normalize( texture2D( normalMap, uv, - 1.0 ).xyz - 0.5 );
} }
} }
variance += 1.0 - 0.25 * length(avgNormal);
gl_FragColor.g = varianceToRoughness(variance); variance += 1.0 - 0.25 * length( avgNormal );
gl_FragColor.g = varianceToRoughness( variance );
} }
`, `,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册