Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TSL: parallaxUV #27739

Merged
merged 10 commits into from
Feb 13, 2024
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
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@
"webgpu_morphtargets",
"webgpu_morphtargets_face",
"webgpu_occlusion",
"webgpu_parallax_uv",
"webgpu_particles",
"webgpu_portal",
"webgpu_reflection",
Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/Nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export { default as ReflectorNode, reflector } from './utils/ReflectorNode.js';
export * from './shadernode/ShaderNode.js';

// accessors
export { TBNViewMatrix } from './accessors/AccessorsUtils.js';
export { TBNViewMatrix, parallaxDirection, parallaxUV } from './accessors/AccessorsUtils.js';
export { default as UniformsNode, uniforms } from './accessors/UniformsNode.js';
export { default as BitangentNode, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, transformedBitangentView, transformedBitangentWorld } from './accessors/BitangentNode.js';
export { default as BufferAttributeNode, bufferAttribute, dynamicBufferAttribute, instancedBufferAttribute, instancedDynamicBufferAttribute } from './accessors/BufferAttributeNode.js';
Expand Down
4 changes: 4 additions & 0 deletions examples/jsm/nodes/accessors/AccessorsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ import { bitangentView } from './BitangentNode.js';
import { normalView } from './NormalNode.js';
import { tangentView } from './TangentNode.js';
import { mat3 } from '../shadernode/ShaderNode.js';
import { positionViewDirection } from './PositionNode.js';

export const TBNViewMatrix = mat3( tangentView, bitangentView, normalView );

export const parallaxDirection = positionViewDirection.mul( TBNViewMatrix )/*.normalize()*/;
export const parallaxUV = ( uv, scale ) => uv.sub( parallaxDirection.mul( scale ) );
6 changes: 6 additions & 0 deletions examples/jsm/nodes/accessors/TangentNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class TangentNode extends Node {

outputNode = attribute( 'tangent', 'vec4' );

if ( builder.geometry.hasAttribute( 'tangent' ) === false ) {

builder.geometry.computeTangents();

}

} else if ( scope === TangentNode.LOCAL ) {

outputNode = varying( tangentGeometry.xyz );
Expand Down
3 changes: 2 additions & 1 deletion examples/jsm/nodes/display/BlendModeNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import TempNode from '../core/TempNode.js';
import { EPSILON } from '../math/MathNode.js';
import { /*mix, step,*/ EPSILON } from '../math/MathNode.js';
import { addNodeClass } from '../core/Node.js';
import { addNodeElement, tslFn, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';

Expand Down Expand Up @@ -51,6 +51,7 @@ export const ScreenNode = tslFn( ( { base, blend } ) => {
export const OverlayNode = tslFn( ( { base, blend } ) => {

const fn = ( c ) => base[ c ].lessThan( 0.5 ).cond( base[ c ].mul( blend[ c ], 2.0 ), base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus() );
//const fn = ( c ) => mix( base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus(), base[ c ].mul( blend[ c ], 2.0 ), step( base[ c ], 0.5 ) );

return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );

Expand Down
Binary file added examples/screenshots/webgpu_parallax_uv.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
153 changes: 153 additions & 0 deletions examples/webgpu_parallax_uv.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgpu - parallax uv</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> webgpu - parallax uv<br />
Textures by <a href="https://ambientcg.com/view?id=Ice002" target="_blank" rel="noopener">ambientCG</a><br />

</div>

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

<script type="module">

import * as THREE from 'three';
import { MeshStandardNodeMaterial, texture, parallaxUV, uv } from 'three/nodes';

import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

let camera, scene, renderer;

let controls;

init();

function init() {

// scene

scene = new THREE.Scene();

// camera

camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, .1, 50 );
camera.position.set( 10, 14, 10 );

// environment

const environmentTexture = new THREE.CubeTextureLoader()
.setPath( './textures/cube/Park2/' )
.load( [ 'posx.jpg', 'negx.jpg', 'posy.jpg', 'negy.jpg', 'posz.jpg', 'negz.jpg' ] );


scene.environment = environmentTexture;
scene.background = environmentTexture;

// textures

const loader = new THREE.TextureLoader();

const topTexture = loader.load( 'textures/ambientcg/Ice002_1K-JPG_Color.jpg' );
topTexture.colorSpace = THREE.SRGBColorSpace;

const roughnessTexture = loader.load( 'textures/ambientcg/Ice002_1K-JPG_Roughness.jpg' );
roughnessTexture.colorSpace = THREE.SRGBColorSpace;

const normalTexture = loader.load( 'textures/ambientcg/Ice002_1K-JPG_NormalGL.jpg' );
normalTexture.colorSpace = THREE.NoColorSpace;

const displaceTexture = loader.load( 'textures/ambientcg/Ice002_1K-JPG_Displacement.jpg' );
displaceTexture.colorSpace = THREE.SRGBColorSpace;
Comment on lines +70 to +77
Copy link
Collaborator

Choose a reason for hiding this comment

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

roughness and displacement should be NoColorSpace.

And likewise, the normal texture, but its color profile is sRGB. Regardless, I'd leave it as NoColorSpace.

/ping @donmccurdy for second opinion.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed, we should use NoColorSpace for all textures containing non-color data, including all three here. The color profiles tend to be unreliable, and I'm not sure there's any way to tag an image clearly identifying it as non-color data. If the material looks incorrect when non-color textures are annotated with NoColorSpace, then we would need fix the textures.

Copy link
Collaborator

Choose a reason for hiding this comment

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


//

const bottomTexture = loader.load( 'textures/ambientcg/Ice003_1K-JPG_Color.jpg' );
bottomTexture.colorSpace = THREE.SRGBColorSpace;
bottomTexture.wrapS = THREE.RepeatWrapping;
bottomTexture.wrapT = THREE.RepeatWrapping;

// paralax effect

const parallaxScale = .3;
const offsetUV = texture( displaceTexture ).mul( parallaxScale );

const parallaxUVOffset = parallaxUV( uv(), offsetUV );
const parallaxResult = texture( bottomTexture, parallaxUVOffset );

const iceNode = texture( topTexture ).overlay( parallaxResult );

// material

const material = new MeshStandardNodeMaterial();
material.colorNode = iceNode.mul( 5 ); // increase the color intensity to 5 ( contrast )
material.roughnessNode = texture( roughnessTexture );
material.normalMap = normalTexture;
material.metalness = 0;

const geometry = new THREE.BoxGeometry( 10, 10, 10 );

const ground = new THREE.Mesh( geometry, material );
ground.rotateX( - Math.PI / 2 );
scene.add( ground );

// renderer

renderer = new WebGPURenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.toneMappingExposure = 6;
document.body.appendChild( renderer.domElement );

// controls

controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 0, 0 );
controls.maxDistance = 40;
controls.minDistance = 10;
controls.autoRotate = true;
controls.autoRotateSpeed = - 1;
controls.update();

window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );

}

function animate() {

controls.update();

renderer.render( scene, camera );

}

</script>
</body>
</html>