Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added examples/models/gltf/DragonAttenuation.glb
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
323 changes: 323 additions & 0 deletions examples/webgl_materials_physical_transmission.2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>threejs webgl - materials - transmission 2</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">

<style>
body {
background-color: #ffffff;
}

#table {
margin-top: 100px;
border-collapse: collapse;
width: 100%;
}
#table td {
margin: 0;
padding: 0;
font-size: 16px;
text-align: center;
vertical-align: center;
}
#table tr {
height: 250px;
}

#block-ff0000 { background-color: #ff0000; color: white; }
#block-00ff00 { background-color: #00ff00; color: black; }
#block-0000ff { background-color: #0000ff; color: white; }
#block-000000 { background-color: #000000; color: black; }
</style>

</head>
<body>

<table id="table">
<tbody>
<tr>
<td id="block-ff0000">ff0000</td>
<td id="block-00ff00">00ff00</td>
<td id="block-0000ff">0000ff</td>
<td id="block-000000">000000</td>
</tr>
</tbody>
</table>

<div id="container"></div>
<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">threejs</a> - Transmission 2</div>

<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>

<script type="module">

import * as THREE from 'three';

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const params = {
color: 0xffffff,
transmission: 1,
opacity: 1,
metalness: 0,
roughness: 0,
ior: 1.5,
thickness: 0.01,
attenuationColor: 0xffffff,
attenuationDistance: 1,
specularIntensity: 1,
specularColor: 0xffffff,
envMapIntensity: 1,
lightIntensity: 1,
exposure: 1
};

let camera, scene, renderer;

let mesh, material;

const hdrEquirect = new RGBELoader()
.setPath( 'textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function () {

hdrEquirect.mapping = THREE.EquirectangularReflectionMapping;

new GLTFLoader()
.setPath( 'models/gltf/' )
.load( 'DragonAttenuation.glb', function ( gltf ) {

gltf.scene.traverse( function ( child ) {

if ( child.isMesh && child.material.isMeshPhysicalMaterial ) {

mesh = child;
material = mesh.material;

let color = new THREE.Color();

params.color = color.copy( mesh.material.color ).getHex();
params.roughness = mesh.material.roughness;
params.metalness = mesh.material.metalness;

params.ior = mesh.material.ior;
params.specularIntensity = mesh.material.specularIntensity;
params.emissiveIntensity = mesh.material.emissiveIntensity;

params.transmission = mesh.material.transmission;
params.thickness = mesh.material.thickness;
params.attenuationColor = color.copy( mesh.material.attenuationColor ).getHex();
params.attenuationDistance = mesh.material.attenuationDistance;

}

} );

init();

scene.add( gltf.scene );

scene.environment = hdrEquirect;
//scene.background = hdrEquirect;

render();

} );

} );

function init() {

renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );

// transparent background
renderer.setClearColor( 0x000000, 0 );

renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
document.body.appendChild( renderer.domElement );

renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = params.exposure;

// accommodate CSS table
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = 0;

scene = new THREE.Scene();

const light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 0, 1, 1 );
//scene.add( light );

camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( -10, 2, 0 );

const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 5;
controls.maxDistance = 20;

window.addEventListener( 'resize', onWindowResize );

//

const gui = new GUI();

gui.addColor( params, 'color' )
.onChange( function () {

material.color.set( params.color );
render();

} );

gui.add( params, 'transmission', 0, 1, 0.01 )
.onChange( function () {

material.transmission = params.transmission;
render();

} );

gui.add( params, 'opacity', 0, 1, 0.01 )
.onChange( function () {

material.opacity = params.opacity;
const transparent = params.opacity < 1;
if(transparent !== material.transparent) {
material.transparent = transparent;
material.needsUpdate = true;
}
render();

} );

gui.add( params, 'metalness', 0, 1, 0.01 )
.onChange( function () {

material.metalness = params.metalness;
render();

} );

gui.add( params, 'roughness', 0, 1, 0.01 )
.onChange( function () {

material.roughness = params.roughness;
render();

} );

gui.add( params, 'ior', 1, 2, 0.01 )
.onChange( function () {

material.ior = params.ior;
render();

} );

gui.add( params, 'thickness', 0, 5, 0.01 )
.onChange( function () {

material.thickness = params.thickness;
render();

} );

gui.addColor( params, 'attenuationColor' )
.name( 'attenuation color' )
.onChange( function () {

material.attenuationColor.set( params.attenuationColor );
render();

} );

gui.add( params, 'attenuationDistance', 0, 1, 0.01 )
.onChange( function () {

material.attenuationDistance = params.attenuationDistance;
render();

} );

gui.add( params, 'specularIntensity', 0, 1, 0.01 )
.onChange( function () {

material.specularIntensity = params.specularIntensity;
render();

} );

gui.addColor( params, 'specularColor' )
.onChange( function () {

material.specularColor.set( params.specularColor );
render();

} );

gui.add( params, 'envMapIntensity', 0, 1, 0.01 )
.name( 'envMap intensity' )
.onChange( function () {

material.envMapIntensity = params.envMapIntensity;
render();

} );

gui.add( params, 'exposure', 0, 1, 0.01 )
.onChange( function () {

renderer.toneMappingExposure = params.exposure;
render();

} );

gui.open();

}

function onWindowResize() {

const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize( width, height );

render();

}

//

function render() {

renderer.render( scene, camera );

}

</script>
</body>
</html>
11 changes: 11 additions & 0 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
UnsignedShort4444Type,
UnsignedShort5551Type
} from '../constants.js';
import { Color } from '../math/Color.js';
import { Frustum } from '../math/Frustum.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Vector3 } from '../math/Vector3.js';
Expand Down Expand Up @@ -174,6 +175,9 @@ class WebGLRenderer {
const _currentScissor = new Vector4();
let _currentScissorTest = null;

const _currentClearColor = new Color( 0x000000 );
let _currentClearAlpha = 0;

//

let _width = canvas.width;
Expand Down Expand Up @@ -1359,6 +1363,11 @@ class WebGLRenderer {

const currentRenderTarget = _this.getRenderTarget();
_this.setRenderTarget( _transmissionRenderTarget );

_this.getClearColor( _currentClearColor );
_currentClearAlpha = _this.getClearAlpha();
if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 );

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change from my PR. Are you aware that the render target will have premultiplied values?

So the two values of interest in this PR are 0xffffff * 0.5 = 0x7f7f7f and alpha = 0.5.

In my PR, the values are 0x7f7f7f * 0.8 = 0x666666 and alpha = 0.8.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, we talked offline. I think we're at consensus now. Correct me if I'm wrong.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a subjective decision, and can be changed later.

_this.clear();

// Turn off the features which can affect the frag color for opaque objects pass.
Expand Down Expand Up @@ -1409,6 +1418,8 @@ class WebGLRenderer {

_this.setRenderTarget( currentRenderTarget );

_this.setClearColor( _currentClearColor, _currentClearAlpha );

_this.toneMapping = currentToneMapping;

}
Expand Down
3 changes: 1 addition & 2 deletions src/renderers/shaders/ShaderChunk/output_fragment.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ export default /* glsl */`
diffuseColor.a = 1.0;
#endif

// https://github.com/mrdoob/three.js/pull/22425
#ifdef USE_TRANSMISSION
diffuseColor.a *= material.transmissionAlpha + 0.1;
diffuseColor.a *= material.transmissionAlpha;
#endif

gl_FragColor = vec4( outgoingLight, diffuseColor.a );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export default /* glsl */`
vec3 v = normalize( cameraPosition - pos );
vec3 n = inverseTransformDirection( normal, viewMatrix );

vec4 transmission = getIBLVolumeRefraction(
vec4 transmitted = getIBLVolumeRefraction(
n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,
pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,
material.attenuationColor, material.attenuationDistance );

material.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );
material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );

totalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );
totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );

#endif
`;
Loading