Skip to content

Commit

Permalink
BREAKING feature: preparing for Three.js r167
Browse files Browse the repository at this point in the history
import WebGPU / NodeMaterial stuff from `three/webgpu`
See: mrdoob/three.js#28650

Three.js r167 is not released yet!
I tested the behavior by using `yarn link` on `three` and `@types/three`

importmaps for Three.js in webgpu examples are temporarily replaced to node_modules, please change them back before merging

Some codes inside MToonNodeMaterial emit type errors because of recent @types/three changes
I'm asking Methuselar96 why the change is made
See: three-types/three-ts-types#1023 (comment)
  • Loading branch information
0b5vr committed Jul 23, 2024
1 parent 8d669ae commit 150d637
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/",
"three": "../node_modules/three/build/three.webgpu.js",
"three/webgpu": "../node_modules/three/build/three.webgpu.js",
"three/addons/": "../node_modules/three/examples/jsm/",
"@pixiv/three-vrm-materials-mtoon": "../lib/three-vrm-materials-mtoon.module.js",
"@pixiv/three-vrm-materials-mtoon/nodes": "../lib/nodes/index.module.js"
}
}
</script>

<script type="module">
import * as THREE from 'three';
import * as THREE from 'three/webgpu';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
import { MToonNodeMaterial } from '@pixiv/three-vrm-materials-mtoon/nodes';

// renderer
const renderer = new WebGPURenderer();
const renderer = new THREE.WebGPURenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.164.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.0/examples/jsm/",
"three": "../node_modules/three/build/three.webgpu.js",
"three/webgpu": "../node_modules/three/build/three.webgpu.js",
"three/addons/": "../node_modules/three/examples/jsm/",
"@pixiv/three-vrm-materials-mtoon": "../lib/three-vrm-materials-mtoon.module.js",
"@pixiv/three-vrm-materials-mtoon/nodes": "../lib/nodes/index.module.js"
}
}
</script>

<script type="module">
import * as THREE from 'three';
import * as THREE from 'three/webgpu';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
import { MToonMaterialLoaderPlugin } from '@pixiv/three-vrm-materials-mtoon';
import { MToonNodeMaterial } from '@pixiv/three-vrm-materials-mtoon/nodes';

// renderer
const renderer = new WebGPURenderer();
const renderer = new THREE.WebGPURenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
Expand Down
28 changes: 14 additions & 14 deletions packages/three-vrm-materials-mtoon/src/nodes/MToonAnimatedUVNode.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as Nodes from 'three/addons/nodes/Nodes.js';
import * as THREE from 'three/webgpu';
import {
refUVAnimationMaskTexture,
refUVAnimationRotationPhase,
refUVAnimationScrollXOffset,
refUVAnimationScrollYOffset,
} from './materialReferences';

export class MToonAnimatedUVNode extends Nodes.TempNode {
export class MToonAnimatedUVNode extends THREE.TempNode {
public readonly hasMaskTexture: boolean;

public constructor(hasMaskTexture: boolean) {
Expand All @@ -15,30 +15,30 @@ export class MToonAnimatedUVNode extends Nodes.TempNode {
this.hasMaskTexture = hasMaskTexture;
}

public setup(): Nodes.ShaderNodeObject<Nodes.VarNode> {
let uvAnimationMask: Nodes.NodeRepresentation = 1.0;
public setup(): THREE.ShaderNodeObject<THREE.VarNode> {
let uvAnimationMask: THREE.NodeRepresentation = 1.0;

if (this.hasMaskTexture) {
uvAnimationMask = Nodes.vec4(refUVAnimationMaskTexture).context({ getUV: () => Nodes.uv() }).r;
uvAnimationMask = THREE.vec4(refUVAnimationMaskTexture).context({ getUV: () => THREE.uv() }).r;
}

let uv: Nodes.ShaderNodeObject<Nodes.Swizzable> = Nodes.uv();
let uv: THREE.ShaderNodeObject<THREE.Swizzable> = THREE.uv();

// rotate
const phase = refUVAnimationRotationPhase.mul(uvAnimationMask);

// WORKAROUND: Nodes.rotateUV causes an issue with the mask texture
// WORKAROUND: THREE.rotateUV causes an issue with the mask texture
// We are going to spin using a 100% organic handmade rotation matrix
// uv = Nodes.rotateUV(uv, phase, Nodes.vec2(0.5, 0.5));
// uv = THREE.rotateUV(uv, phase, THREE.vec2(0.5, 0.5));

const c = Nodes.cos(phase);
const s = Nodes.sin(phase);
uv = uv.sub(Nodes.vec2(0.5, 0.5));
uv = uv.mul(Nodes.mat2(c, s, s.negate(), c));
uv = uv.add(Nodes.vec2(0.5, 0.5));
const c = THREE.cos(phase);
const s = THREE.sin(phase);
uv = uv.sub(THREE.vec2(0.5, 0.5));
uv = uv.mul(THREE.mat2(c, s, s.negate(), c));
uv = uv.add(THREE.vec2(0.5, 0.5));

// scroll
const scroll = Nodes.vec2(refUVAnimationScrollXOffset, refUVAnimationScrollYOffset).mul(uvAnimationMask);
const scroll = THREE.vec2(refUVAnimationScrollXOffset, refUVAnimationScrollYOffset).mul(uvAnimationMask);
uv = uv.add(scroll);

return uv.temp('AnimatedUV');
Expand Down
64 changes: 32 additions & 32 deletions packages/three-vrm-materials-mtoon/src/nodes/MToonLightingModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Nodes from 'three/addons/nodes/Nodes.js';
import * as THREE from 'three/webgpu';
import {
matcap,
parametricRim,
Expand All @@ -11,15 +11,15 @@ import {

// TODO: 0% confidence about function types.

const linearstep = Nodes.tslFn(
const linearstep = THREE.tslFn(
({
a,
b,
t,
}: {
a: Nodes.ShaderNodeObject<Nodes.Node>;
b: Nodes.ShaderNodeObject<Nodes.Node>;
t: Nodes.ShaderNodeObject<Nodes.Node>;
a: THREE.ShaderNodeObject<THREE.Node>;
b: THREE.ShaderNodeObject<THREE.Node>;
t: THREE.ShaderNodeObject<THREE.Node>;
}) => {
const top = t.sub(a);
const bottom = b.sub(a);
Expand All @@ -30,12 +30,12 @@ const linearstep = Nodes.tslFn(
/**
* Convert NdotL into toon shading factor using shadingShift and shadingToony
*/
const getShading = Nodes.tslFn(({ dotNL }: { dotNL: Nodes.ShaderNodeObject<Nodes.Node> }) => {
const getShading = THREE.tslFn(({ dotNL }: { dotNL: THREE.ShaderNodeObject<THREE.Node> }) => {
const shadow = 1.0; // TODO

const feather = Nodes.float(1.0).sub(shadingToony);
const feather = THREE.float(1.0).sub(shadingToony);

let shading: Nodes.ShaderNodeObject<Nodes.Node> = dotNL.add(shadingShift);
let shading: THREE.ShaderNodeObject<THREE.Node> = dotNL.add(shadingShift);
shading = linearstep({
a: feather.negate(),
b: feather,
Expand All @@ -48,28 +48,28 @@ const getShading = Nodes.tslFn(({ dotNL }: { dotNL: Nodes.ShaderNodeObject<Nodes
/**
* Mix diffuseColor and shadeColor using shading factor and light color
*/
const getDiffuse = Nodes.tslFn(
const getDiffuse = THREE.tslFn(
({
shading,
lightColor,
}: {
shading: Nodes.ShaderNodeObject<Nodes.Node>;
lightColor: Nodes.ShaderNodeObject<Nodes.Node>;
shading: THREE.ShaderNodeObject<THREE.Node>;
lightColor: THREE.ShaderNodeObject<THREE.Node>;
}) => {
const diffuseColor = Nodes.mix(shadeColor, Nodes.diffuseColor, shading);
const col = lightColor.mul(Nodes.BRDF_Lambert({ diffuseColor }));
const diffuseColor = THREE.mix(shadeColor, THREE.diffuseColor, shading);
const col = lightColor.mul(THREE.BRDF_Lambert({ diffuseColor }));

return col;
},
);

export class MToonLightingModel extends Nodes.LightingModel {
export class MToonLightingModel extends THREE.LightingModel {
constructor() {
super();
}

direct({ lightDirection, lightColor, reflectedLight }: Nodes.LightingModelDirectInput) {
const dotNL = Nodes.transformedNormalView.dot(lightDirection).clamp(-1.0, 1.0);
direct({ lightDirection, lightColor, reflectedLight }: THREE.LightingModelDirectInput) {
const dotNL = THREE.transformedNormalView.dot(lightDirection).clamp(-1.0, 1.0);

// toon diffuse
const shading = getShading({
Expand All @@ -79,47 +79,47 @@ export class MToonLightingModel extends Nodes.LightingModel {
// Unable to use `addAssign` in the current @types/three, we use `assign` and `add` instead
// TODO: Fix the `addAssign` issue from the `@types/three` side

(reflectedLight.directDiffuse as Nodes.ShaderNodeObject<Nodes.Node>).assign(
(reflectedLight.directDiffuse as Nodes.ShaderNodeObject<Nodes.Node>).add(
(reflectedLight.directDiffuse as THREE.ShaderNodeObject<THREE.Node>).assign(
(reflectedLight.directDiffuse as THREE.ShaderNodeObject<THREE.Node>).add(
getDiffuse({
shading,
lightColor: lightColor as Nodes.ShaderNodeObject<Nodes.Node>,
lightColor: lightColor as THREE.ShaderNodeObject<THREE.Node>,
}),
),
);

// rim
(reflectedLight.directSpecular as Nodes.ShaderNodeObject<Nodes.Node>).assign(
(reflectedLight.directSpecular as Nodes.ShaderNodeObject<Nodes.Node>).add(
(reflectedLight.directSpecular as THREE.ShaderNodeObject<THREE.Node>).assign(
(reflectedLight.directSpecular as THREE.ShaderNodeObject<THREE.Node>).add(
parametricRim
.add(matcap)
.mul(rimMultiply)
.mul(Nodes.mix(Nodes.vec3(0.0), Nodes.BRDF_Lambert({ diffuseColor: lightColor }), rimLightingMix)),
.mul(THREE.mix(THREE.vec3(0.0), THREE.BRDF_Lambert({ diffuseColor: lightColor }), rimLightingMix)),
),
);
}

indirectDiffuse({ irradiance, reflectedLight }: Nodes.LightingModelIndirectInput) {
indirectDiffuse({ irradiance, reflectedLight }: THREE.LightingModelIndirectInput) {
// indirect irradiance
(reflectedLight.indirectDiffuse as Nodes.ShaderNodeObject<Nodes.Node>).assign(
(reflectedLight.indirectDiffuse as Nodes.ShaderNodeObject<Nodes.Node>).add(
(irradiance as Nodes.ShaderNodeObject<Nodes.Node>).mul(
Nodes.BRDF_Lambert({
diffuseColor: Nodes.diffuseColor,
(reflectedLight.indirectDiffuse as THREE.ShaderNodeObject<THREE.Node>).assign(
(reflectedLight.indirectDiffuse as THREE.ShaderNodeObject<THREE.Node>).add(
(irradiance as THREE.ShaderNodeObject<THREE.Node>).mul(
THREE.BRDF_Lambert({
diffuseColor: THREE.diffuseColor,
}),
),
),
);
}

indirectSpecular({ reflectedLight }: Nodes.LightingModelIndirectInput) {
indirectSpecular({ reflectedLight }: THREE.LightingModelIndirectInput) {
// rim
(reflectedLight.indirectSpecular as Nodes.ShaderNodeObject<Nodes.Node>).assign(
(reflectedLight.indirectSpecular as Nodes.ShaderNodeObject<Nodes.Node>).add(
(reflectedLight.indirectSpecular as THREE.ShaderNodeObject<THREE.Node>).assign(
(reflectedLight.indirectSpecular as THREE.ShaderNodeObject<THREE.Node>).add(
parametricRim
.add(matcap)
.mul(rimMultiply)
.mul(Nodes.mix(Nodes.vec3(1.0), Nodes.vec3(0.0), rimLightingMix)),
.mul(THREE.mix(THREE.vec3(1.0), THREE.vec3(0.0), rimLightingMix)),
),
);
}
Expand Down
Loading

0 comments on commit 150d637

Please sign in to comment.