未验证 提交 bbe6f1ee 编写于 作者: T Takahiro 提交者: GitHub

Improve MeshPhysicalMaterial transmission support (#21884)

* Imptove MeshPhysicalMaterial transmission support

* Add webgl_loader_gltf_transmission example

* Update webgl_materials_physical_transmission screenshot

* Dispose transmissionRenderTarget in WebGLRenderer.dispose()

* Remove _transmissionSamplerMap from MeshPhysicalMaterial

* Fix transmissionMap

* Remove unnecessary sRGB-Linear conversion from transmission shader

* Improve transmission shaders

* Add more parameters to webgl_materials_physical_transmission example

* Update screenshot
上级 ec96437a
......@@ -86,6 +86,7 @@
"webgl_loader_gltf",
"webgl_loader_gltf_compressed",
"webgl_loader_gltf_extensions",
"webgl_loader_gltf_transmission",
"webgl_loader_gltf_variants",
"webgl_loader_ifc",
"webgl_loader_imagebitmap",
......
# Transmission Test
## Screenshot
![screenshot](screenshot/screenshot_large.png)
## Description
This model demonstrates the usage of the `KHR_materials_transmission`. The grid of spheres demonstrate different combinations of uniform transmission and textured transmission and how they should render in conjunction with opacity (`baseColor.a`) and surface roughness/metalicity.
## License Information
[![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png)](http://creativecommons.org/publicdomain/zero/1.0/)
To the extent possible under law, Adobe has waived all copyright and related or neighboring rights to this asset.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - glTF loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - GLTFLoader + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission" target="_blank" rel="noopener">KHR_materials_transmission</a> extension<br />
<a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/TransmissionTest" target="_blank" rel="noopener">Transmission Test</a> by
<a href="https://www.adobe.com/" target="_blank" rel="noopener">Adobe, Inc</a><br />
<a href="https://hdrihaven.com/hdri/?h=quarry_01" target="_blank" rel="noopener">Quarry</a> by <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
</div>
<script type="module">
import * as THREE from '../build/three.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
import { RGBELoader } from './jsm/loaders/RGBELoader.js';
import { RoughnessMipmapper } from './jsm/utils/RoughnessMipmapper.js';
let camera, scene, renderer;
init();
render();
function init() {
const container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
camera.position.set( 0, 0, 2.0 );
scene = new THREE.Scene();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setPath( 'textures/equirectangular/' )
.load( 'quarry_01_1k.hdr', function ( texture ) {
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
render();
// model
const loader = new GLTFLoader().setPath( 'models/gltf/TransmissionTest/glTF/' );
loader.load( 'TransmissionTest.gltf', function ( gltf ) {
scene.add( gltf.scene );
render();
} );
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 1;
controls.maxDistance = 10;
controls.target.set( 0, 0.0, - 0.2 );
controls.update();
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
//
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
......@@ -23,7 +23,10 @@
const params = {
color: 0xffffff,
transmission: 0.90,
transmission: 1,
opacity: 1,
metalness: 0,
roughness: 0,
envMapIntensity: 1,
lightIntensity: 1,
exposure: 1
......@@ -88,15 +91,14 @@
const material = new THREE.MeshPhysicalMaterial( {
color: params.color,
metalness: 0,
roughness: 0,
metalness: params.metalness,
roughness: params.roughness,
alphaMap: texture,
alphaTest: 0.5,
envMap: hdrCubeRenderTarget.texture,
envMapIntensity: params.envMapIntensity,
depthWrite: false,
transmission: params.transmission, // use material.transmission for glass materials
opacity: 1, // set material.opacity to 1 when material.transmission is non-zero
opacity: params.opacity,
transparent: true
} );
......@@ -165,7 +167,7 @@
} );
gui.add( params, 'transmission', 0, 1 )
gui.add( params, 'transmission', 0, 1, 0.01 )
.onChange( function () {
material1.transmission = material2.transmission = params.transmission;
......@@ -173,7 +175,31 @@
} );
gui.add( params, 'envMapIntensity', 0, 1 )
gui.add( params, 'opacity', 0, 1, 0.01 )
.onChange( function () {
material1.opacity = material2.opacity = params.opacity;
material1b.opacity = material2b.opacity = params.opacity;
} );
gui.add( params, 'metalness', 0, 1, 0.01 )
.onChange( function () {
material1.metalness = material2.metalness = params.metalness;
material1b.metalness = material2b.metalness = params.metalness;
} );
gui.add( params, 'roughness', 0, 1, 0.01 )
.onChange( function () {
material1.roughness = material2.roughness = params.roughness;
material1b.roughness = material2b.roughness = params.roughness;
} );
gui.add( params, 'envMapIntensity', 0, 1, 0.01 )
.name( 'envMap intensity' )
.onChange( function () {
......@@ -182,7 +208,7 @@
} );
gui.add( params, 'lightIntensity', 0, 1 )
gui.add( params, 'lightIntensity', 0, 1, 0.01 )
.name( 'light intensity' )
.onChange( function () {
......@@ -190,7 +216,7 @@
} );
gui.add( params, 'exposure', 0, 1 )
gui.add( params, 'exposure', 0, 1, 0.01 )
.onChange( function () {
renderer.toneMappingExposure = params.exposure;
......
......@@ -80,6 +80,10 @@ class MaterialLoader extends Loader {
if ( json.shininess !== undefined ) material.shininess = json.shininess;
if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
if ( json.transmission !== undefined ) material.transmission = json.transmission;
if ( json.thickness !== undefined ) material.thickness = json.thickness;
if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance;
if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor );
if ( json.fog !== undefined ) material.fog = json.fog;
if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
if ( json.blending !== undefined ) material.blending = json.blending;
......@@ -278,8 +282,8 @@ class MaterialLoader extends Loader {
if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
if ( json.transmission !== undefined ) material.transmission = json.transmission;
if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap );
return material;
......
......@@ -262,6 +262,13 @@ class Material extends EventDispatcher {
}
if ( this.transmission !== undefined ) data.transmission = this.transmission;
if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
if ( this.thickness !== undefined ) data.thickness = this.thickness;
if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
if ( this.attenuationDistance !== undefined ) data.attenuationDistance = this.attenuationDistance;
if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
if ( this.size !== undefined ) data.size = this.size;
if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
......
......@@ -18,7 +18,12 @@ import * as MathUtils from '../math/MathUtils.js';
* sheen: <Color>,
*
* transmission: <float>,
* transmissionMap: new THREE.Texture( <Image> )
* transmissionMap: new THREE.Texture( <Image> ),
*
* thickness: <float>,
* thicknessMap: new THREE.Texture( <Image> ),
* attenuationDistance: <float>,
* attenuationColor: <Color>
* }
*/
......@@ -64,6 +69,11 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
this.transmission = 0.0;
this.transmissionMap = null;
this.thickness = 0.01;
this.thicknessMap = null;
this.attenuationDistance = 0.0;
this.attenuationColor = new Color( 1, 1, 1 );
this.setValues( parameters );
}
......@@ -101,6 +111,11 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
this.transmission = source.transmission;
this.transmissionMap = source.transmissionMap;
this.thickness = source.thickness;
this.thicknessMap = source.thicknessMap;
this.attenuationDistance = source.attenuationDistance;
this.attenuationColor.copy( source.attenuationColor );
return this;
}
......
......@@ -4,7 +4,10 @@ import {
FloatType,
UnsignedByteType,
LinearEncoding,
NoToneMapping
NoToneMapping,
LinearMipmapLinearFilter,
NearestFilter,
ClampToEdgeWrapping
} from '../constants.js';
import { Frustum } from '../math/Frustum.js';
import { Matrix4 } from '../math/Matrix4.js';
......@@ -30,6 +33,7 @@ import { WebGLPrograms } from './webgl/WebGLPrograms.js';
import { WebGLProperties } from './webgl/WebGLProperties.js';
import { WebGLRenderLists } from './webgl/WebGLRenderLists.js';
import { WebGLRenderStates } from './webgl/WebGLRenderStates.js';
import { WebGLRenderTarget } from './WebGLRenderTarget.js';
import { WebGLShadowMap } from './webgl/WebGLShadowMap.js';
import { WebGLState } from './webgl/WebGLState.js';
import { WebGLTextures } from './webgl/WebGLTextures.js';
......@@ -160,6 +164,11 @@ function WebGLRenderer( parameters ) {
let _clippingEnabled = false;
let _localClippingEnabled = false;
// transmission
let _transmissionRenderTarget = null;
const _transmissionSamplerSize = new Vector2( 1024, 1024 ); // Should be configurable?
// camera matrices cache
const _projScreenMatrix = new Matrix4();
......@@ -596,6 +605,13 @@ function WebGLRenderer( parameters ) {
xr.removeEventListener( 'sessionstart', onXRSessionStart );
xr.removeEventListener( 'sessionend', onXRSessionEnd );
if ( _transmissionRenderTarget ) {
_transmissionRenderTarget.dispose();
_transmissionRenderTarget = null;
}
animation.stop();
};
......@@ -1058,9 +1074,11 @@ function WebGLRenderer( parameters ) {
// render scene
const opaqueObjects = currentRenderList.opaque;
const transmissiveObjects = currentRenderList.transmissive;
const transparentObjects = currentRenderList.transparent;
if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
if ( transmissiveObjects.length > 0 ) renderTransmissiveObjects( opaqueObjects, transmissiveObjects, scene, camera );
if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
//
......@@ -1246,6 +1264,31 @@ function WebGLRenderer( parameters ) {
}
function renderTransmissiveObjects( opaqueObjects, transmissiveObjects, scene, camera ) {
if ( _transmissionRenderTarget === null ) {
_transmissionRenderTarget = new WebGLRenderTarget( _transmissionSamplerSize.x, _transmissionSamplerSize.y, {
generateMipmaps: true,
minFilter: LinearMipmapLinearFilter,
magFilter: NearestFilter,
wrapS: ClampToEdgeWrapping,
wrapT: ClampToEdgeWrapping
} );
}
const currentRenderTarget = _this.getRenderTarget();
_this.setRenderTarget( _transmissionRenderTarget );
_this.clear();
renderObjects( opaqueObjects, scene, camera );
textures.updateRenderTargetMipmap( _transmissionRenderTarget );
_this.setRenderTarget( currentRenderTarget );
renderObjects( transmissiveObjects, scene, camera );
}
function renderObjects( renderList, scene, camera ) {
const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
......@@ -1699,7 +1742,7 @@ function WebGLRenderer( parameters ) {
}
materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height );
materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
......
......@@ -86,8 +86,8 @@ import specularmap_fragment from './ShaderChunk/specularmap_fragment.glsl.js';
import specularmap_pars_fragment from './ShaderChunk/specularmap_pars_fragment.glsl.js';
import tonemapping_fragment from './ShaderChunk/tonemapping_fragment.glsl.js';
import tonemapping_pars_fragment from './ShaderChunk/tonemapping_pars_fragment.glsl.js';
import transmissionmap_fragment from './ShaderChunk/transmissionmap_fragment.glsl.js';
import transmissionmap_pars_fragment from './ShaderChunk/transmissionmap_pars_fragment.glsl.js';
import transmission_fragment from './ShaderChunk/transmission_fragment.glsl.js';
import transmission_pars_fragment from './ShaderChunk/transmission_pars_fragment.glsl.js';
import uv_pars_fragment from './ShaderChunk/uv_pars_fragment.glsl.js';
import uv_pars_vertex from './ShaderChunk/uv_pars_vertex.glsl.js';
import uv_vertex from './ShaderChunk/uv_vertex.glsl.js';
......@@ -218,8 +218,8 @@ export const ShaderChunk = {
specularmap_pars_fragment: specularmap_pars_fragment,
tonemapping_fragment: tonemapping_fragment,
tonemapping_pars_fragment: tonemapping_pars_fragment,
transmissionmap_fragment: transmissionmap_fragment,
transmissionmap_pars_fragment: transmissionmap_pars_fragment,
transmission_fragment: transmission_fragment,
transmission_pars_fragment: transmission_pars_fragment,
uv_pars_fragment: uv_pars_fragment,
uv_pars_vertex: uv_pars_vertex,
uv_vertex: uv_vertex,
......
export default /* glsl */`
#ifdef USE_TRANSMISSION
#ifdef USE_TRANSMISSIONMAP
totalTransmission *= texture2D( transmissionMap, vUv ).r;
#endif
#ifdef USE_THICKNESSNMAP
thicknessFactor *= texture2D( thicknessMap, vUv ).g;
#endif
vec3 pos = vWorldPosition.xyz / vWorldPosition.w;
vec3 v = normalize( cameraPosition - pos );
vec3 viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );
vec3 n = normalize( vNormal );
float ior = ( 1.0 + 0.4 * reflectivity ) / ( 1.0 - 0.4 * reflectivity );
// From https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping
vec3 f0 = vec3( pow( ior - 1.0, 2.0 ) / pow( ior + 1.0, 2.0 ) );
vec3 f90 = vec3( 1.0 );
vec3 f_transmission = totalTransmission * getIBLVolumeRefraction(
n, v, viewDir, roughnessFactor, diffuseColor.rgb, f0, f90,
pos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,
attenuationColor, attenuationDistance);
diffuseColor.rgb = mix( diffuseColor.rgb, f_transmission, totalTransmission );
#endif
`;
export default /* glsl */`
#ifdef USE_TRANSMISSION
// Transmission code is based on glTF-Sampler-Viewer
// https://github.com/KhronosGroup/glTF-Sample-Viewer
#ifdef USE_TRANSMISSIONMAP
uniform sampler2D transmissionMap;
#endif
#ifdef USE_THICKNESSMAP
uniform sampler2D thicknessMap;
#endif
uniform vec2 transmissionSamplerSize;
uniform sampler2D transmissionSamplerMap;
uniform mat4 modelMatrix;
uniform mat4 projectionMatrix;
varying vec4 vWorldPosition;
vec3 getVolumeTransmissionRay(vec3 n, vec3 v, float thickness, float ior, mat4 modelMatrix) {
// Direction of refracted light.
vec3 refractionVector = refract(-v, normalize(n), 1.0 / ior);
// Compute rotation-independant scaling of the model matrix.
vec3 modelScale;
modelScale.x = length(vec3(modelMatrix[0].xyz));
modelScale.y = length(vec3(modelMatrix[1].xyz));
modelScale.z = length(vec3(modelMatrix[2].xyz));
// The thickness is specified in local space.
return normalize(refractionVector) * thickness * modelScale;
}
float applyIorToRoughness(float roughness, float ior) {
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
// an IOR of 1.5 results in the default amount of microfacet refraction.
return roughness * clamp(ior * 2.0 - 2.0, 0.0, 1.0);
}
vec3 getTransmissionSample(vec2 fragCoord, float roughness, float ior) {
float framebufferLod = log2(transmissionSamplerSize.x) * applyIorToRoughness(roughness, ior);
return textureLod(transmissionSamplerMap, fragCoord.xy, framebufferLod).rgb;
}
vec3 applyVolumeAttenuation(vec3 radiance, float transmissionDistance, vec3 attenuationColor, float attenuationDistance) {
if (attenuationDistance == 0.0) {
// Attenuation distance is +∞ (which we indicate by zero), i.e. the transmitted color is not attenuated at all.
return radiance;
} else {
// Compute light attenuation using Beer's law.
vec3 attenuationCoefficient = -log(attenuationColor) / attenuationDistance;
vec3 transmittance = exp(-attenuationCoefficient * transmissionDistance); // Beer's law
return transmittance * radiance;
}
}
vec3 getIBLVolumeRefraction(vec3 n, vec3 v, vec3 viewDir, float perceptualRoughness, vec3 baseColor, vec3 f0, vec3 f90,
vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness, vec3 attenuationColor, float attenuationDistance) {
vec3 transmissionRay = getVolumeTransmissionRay(n, v, thickness, ior, modelMatrix);
vec3 refractedRayExit = position + transmissionRay;
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
vec4 ndcPos = projMatrix * viewMatrix * vec4(refractedRayExit, 1.0);
vec2 refractionCoords = ndcPos.xy / ndcPos.w;
refractionCoords += 1.0;
refractionCoords /= 2.0;
// Sample framebuffer to get pixel the refracted ray hits.
vec3 transmittedLight = getTransmissionSample(refractionCoords, perceptualRoughness, ior);
vec3 attenuatedColor = applyVolumeAttenuation(transmittedLight, length(transmissionRay), attenuationColor, attenuationDistance);
float NdotV = saturate(dot(n, viewDir));
vec2 brdf = integrateSpecularBRDF(NdotV, perceptualRoughness);
vec3 specularColor = f0 * brdf.x + f90 * brdf.y;
return (1.0 - specularColor) * attenuatedColor * baseColor;
}
#endif
`;
export default /* glsl */`
#ifdef USE_TRANSMISSIONMAP
totalTransmission *= texture2D( transmissionMap, vUv ).r;
#endif
`;
export default /* glsl */`
#ifdef USE_TRANSMISSIONMAP
uniform sampler2D transmissionMap;
#endif
`;
export default /* glsl */`
#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )
vec4 worldPosition = vec4( transformed, 1.0 );
......
......@@ -299,6 +299,12 @@ ShaderLib.physical = {
sheen: { value: new Color( 0x000000 ) },
transmission: { value: 0 },
transmissionMap: { value: null },
transmissionSamplerSize: { value: new Vector2() },
transmissionSamplerMap: { value: null },
thickness: { value: 0 },
thicknessMap: { value: null },
attenuationDistance: { value: 0 },
attenuationColor: { value: new Color( 0x000000 ) }
}
] ),
......
......@@ -4,7 +4,6 @@ export default /* glsl */`
#ifdef PHYSICAL
#define REFLECTIVITY
#define CLEARCOAT
#define TRANSMISSION
#endif
uniform vec3 diffuse;
......@@ -13,8 +12,11 @@ uniform float roughness;
uniform float metalness;
uniform float opacity;
#ifdef TRANSMISSION
#ifdef USE_TRANSMISSION
uniform float transmission;
uniform float thickness;
uniform vec3 attenuationColor;
uniform float attenuationDistance;
#endif
#ifdef REFLECTIVITY
......@@ -56,8 +58,8 @@ varying vec3 vViewPosition;
#include <aomap_pars_fragment>
#include <lightmap_pars_fragment>
#include <emissivemap_pars_fragment>
#include <transmissionmap_pars_fragment>
#include <bsdfs>
#include <transmission_pars_fragment>
#include <cube_uv_reflection_fragment>
#include <envmap_common_pars_fragment>
#include <envmap_physical_pars_fragment>
......@@ -81,8 +83,9 @@ void main() {
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
vec3 totalEmissiveRadiance = emissive;
#ifdef TRANSMISSION
#ifdef USE_TRANSMISSION
float totalTransmission = transmission;
float thicknessFactor = thickness;
#endif
#include <logdepthbuf_fragment>
......@@ -97,7 +100,7 @@ void main() {
#include <clearcoat_normal_fragment_begin>
#include <clearcoat_normal_fragment_maps>
#include <emissivemap_fragment>
#include <transmissionmap_fragment>
#include <transmission_fragment>
// accumulation
#include <lights_physical_fragment>
......@@ -110,11 +113,6 @@ void main() {
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
// this is a stub for the transmission model
#ifdef TRANSMISSION
diffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness );
#endif
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
#include <tonemapping_fragment>
......
......@@ -16,6 +16,12 @@ varying vec3 vViewPosition;
#endif
#ifdef USE_TRANSMISSION
varying vec4 vWorldPosition;
#endif
#include <common>
#include <uv_pars_vertex>
#include <uv2_pars_vertex>
......@@ -67,5 +73,10 @@ void main() {
#include <shadowmap_vertex>
#include <fog_vertex>
#ifdef USE_TRANSMISSION
vWorldPosition = worldPosition;
#endif
}
`;
......@@ -19,7 +19,7 @@ function WebGLMaterials( properties ) {
}
function refreshMaterialUniforms( uniforms, material, pixelRatio, height ) {
function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
if ( material.isMeshBasicMaterial ) {
......@@ -46,7 +46,7 @@ function WebGLMaterials( properties ) {
if ( material.isMeshPhysicalMaterial ) {
refreshUniformsPhysical( uniforms, material );
refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
} else {
......@@ -553,7 +553,7 @@ function WebGLMaterials( properties ) {
}
function refreshUniformsPhysical( uniforms, material ) {
function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
refreshUniformsStandard( uniforms, material );
......@@ -561,6 +561,7 @@ function WebGLMaterials( properties ) {
uniforms.clearcoat.value = material.clearcoat;
uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
if ( material.sheen ) uniforms.sheen.value.copy( material.sheen );
if ( material.clearcoatMap ) {
......@@ -596,6 +597,24 @@ function WebGLMaterials( properties ) {
}
if ( material.transmission > 0.0 ) {
uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
}
uniforms.thickness.value = material.thickness;
if ( material.thicknessMap ) {
uniforms.thicknessMap.value = material.thicknessMap;
}
uniforms.attenuationDistance.value = material.attenuationDistance;
uniforms.attenuationColor.value.copy( material.attenuationColor );
}
function refreshUniformsMatcap( uniforms, material ) {
......
......@@ -468,7 +468,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.transmission ? '#define USE_TRANSMISSION' : '',
parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
parameters.vertexTangents ? '#define USE_TANGENT' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',
......@@ -609,7 +611,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.sheen ? '#define USE_SHEEN' : '',
parameters.transmission ? '#define USE_TRANSMISSION' : '',
parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
parameters.vertexTangents ? '#define USE_TANGENT' : '',
parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
......
......@@ -45,7 +45,7 @@ function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingSta
'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
'alphaTest', 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering',
'sheen', 'transmissionMap'
'sheen', 'transmission', 'transmissionMap', 'thicknessMap'
];
function getMaxBones( object ) {
......@@ -202,15 +202,17 @@ function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingSta
sheen: !! material.sheen,
transmission: !! material.transmission,
transmissionMap: !! material.transmissionMap,
thicknessMap: !! material.thicknessMap,
combine: material.combine,
vertexTangents: ( material.normalMap && material.vertexTangents ),
vertexColors: material.vertexColors,
vertexAlphas: material.vertexColors === true && object.geometry && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4,
vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmissionMap,
uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmission || !! material.transmissionMap || !! material.thicknessMap,
uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmission || !! material.transmissionMap || !! material.thicknessMap ) && !! material.displacementMap,
fog: !! fog,
useFog: material.fog,
......
......@@ -57,6 +57,7 @@ function WebGLRenderList( properties ) {
let renderItemsIndex = 0;
const opaque = [];
const transmissive = [];
const transparent = [];
const defaultProgram = { id: - 1 };
......@@ -66,6 +67,7 @@ function WebGLRenderList( properties ) {
renderItemsIndex = 0;
opaque.length = 0;
transmissive.length = 0;
transparent.length = 0;
}
......@@ -115,7 +117,15 @@ function WebGLRenderList( properties ) {
const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
( material.transparent === true ? transparent : opaque ).push( renderItem );
if ( material.transmission !== undefined && material.transmission > 0.0 ) {
transmissive.push( renderItem );
} else {
( material.transparent === true ? transparent : opaque ).push( renderItem );
}
}
......@@ -123,13 +133,22 @@ function WebGLRenderList( properties ) {
const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
( material.transparent === true ? transparent : opaque ).unshift( renderItem );
if ( material.transmission !== undefined && material.transmission > 0.0 ) {
transmissive.unshift( renderItem );
} else {
( material.transparent === true ? transparent : opaque ).unshift( renderItem );
}
}
function sort( customOpaqueSort, customTransparentSort ) {
if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
}
......@@ -158,6 +177,7 @@ function WebGLRenderList( properties ) {
return {
opaque: opaque,
transmissive: transmissive,
transparent: transparent,
init: init,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册