Skip to content

Commit

Permalink
Merge pull request #1429 from pixiv/materialtype
Browse files Browse the repository at this point in the history
feat: Change the MToonNodeMaterial API
  • Loading branch information
0b5vr committed Jul 1, 2024
2 parents 7c54574 + 83fcdf9 commit 25d12d4
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 103 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,31 @@ loader.load(
### Use with WebGPURenderer

Starting from v3, we provide [WebGPURenderer](https://github.com/mrdoob/three.js/blob/master/examples/jsm/renderers/webgpu/WebGPURenderer.js) compatibility.
To use three-vrm with WebGPURenderer, specify the WebGPU-compatible `MToonNodeMaterialLoaderPlugin` for the `mtoonMaterialPlugin` option of `VRMLoaderPlugin`.
To use three-vrm with WebGPURenderer, specify the WebGPU-compatible `MToonNodeMaterial` for the `materialType` option of `MToonMaterialLoaderPlugin`.

`MToonNodeMaterial` only supports Three.js r161 or later.
The NodeMaterial system of Three.js is still under development, so we may break compatibility with older versions of Three.js more frequently than other parts of three-vrm.

```js
import { VRMLoaderPlugin } from '@pixiv/three-vrm';
import { MToonNodeMaterialLoaderPlugin } from '@pixiv/three-vrm/nodes';
import { MToonNodeMaterial } from '@pixiv/three-vrm/nodes';

// ...

// Register a VRMLoaderPlugin
loader.register((parser) => {

// create a WebGPU compatible MToon loader plugin
const mtoonMaterialPlugin = new MToonNodeMaterialLoaderPlugin(parser);
// create a WebGPU compatible MToonMaterialLoaderPlugin
const mtoonMaterialPlugin = new MToonMaterialLoaderPlugin(parser, {

// set the material type to MToonNodeMaterial
materialType: MToonNodeMaterial,

});

return new VRMLoaderPlugin(parser, {

// Specify the MToon loader plugin to use in the VRMLoaderPlugin instance
// Specify the MToonMaterialLoaderPlugin to use in the VRMLoaderPlugin instance
mtoonMaterialPlugin,

});
Expand Down
18 changes: 8 additions & 10 deletions packages/three-vrm-materials-mtoon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,25 @@ MToon (toon material) module for @pixiv/three-vrm
## WebGPU Support

Starting from v3, we provide [WebGPURenderer](https://github.com/mrdoob/three.js/blob/master/examples/jsm/renderers/webgpu/WebGPURenderer.js) compatibility.
To use three-vrm with WebGPURenderer, specify the WebGPU-compatible `MToonNodeMaterialLoaderPlugin` for the `mtoonMaterialPlugin` option of `VRMLoaderPlugin`.
To use MToon with WebGPURenderer, specify the WebGPU-compatible `MToonNodeMaterial` for the `materialType` option of `MToonMaterialLoaderPlugin`.

`MToonNodeMaterial` only supports Three.js r161 or later.
The NodeMaterial system of Three.js is still under development, so we may break compatibility with older versions of Three.js more frequently than other parts of three-vrm.

```js
import { VRMLoaderPlugin } from '@pixiv/three-vrm';
import { MToonNodeMaterialLoaderPlugin } from '@pixiv/three-vrm/nodes';
import { MToonMaterialLoaderPlugin } from '@pixiv/three-vrm-materials-mtoon';
import { MToonNodeMaterial } from '@pixiv/three-vrm-materials-mtoon/nodes';

// ...

// Register a VRMLoaderPlugin
// Register a MToonMaterialLoaderPlugin with MToonNodeMaterial
loader.register((parser) => {

// create a WebGPU compatible MToon loader plugin
const mtoonMaterialPlugin = new MToonNodeMaterialLoaderPlugin(parser);
// create a WebGPU compatible MToonMaterialLoaderPlugin
return new MToonMaterialLoaderPlugin(parser, {

return new VRMLoaderPlugin(parser, {

// Specify the MToon loader plugin to use in the VRMLoaderPlugin instance
mtoonMaterialPlugin,
// set the material type to MToonNodeMaterial
materialType: MToonNodeMaterial,

});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
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 { MToonNodeMaterialLoaderPlugin } from '@pixiv/three-vrm-materials-mtoon/nodes';
import { MToonMaterialLoaderPlugin } from '@pixiv/three-vrm-materials-mtoon';
import { MToonNodeMaterial } from '@pixiv/three-vrm-materials-mtoon/nodes';

// renderer
const renderer = new WebGPURenderer();
Expand Down Expand Up @@ -68,8 +69,14 @@

loader.register( ( parser ) => {

const plugin = new MToonNodeMaterialLoaderPlugin( parser );
return plugin;

// create a WebGPU compatible MToonMaterialLoaderPlugin
return new MToonMaterialLoaderPlugin( parser, {

// set the material type to MToonNodeMaterial
materialType: MToonNodeMaterial,

} );

} );

Expand Down
77 changes: 60 additions & 17 deletions packages/three-vrm-materials-mtoon/src/MToonMaterialLoaderPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import * as THREE from 'three';
import * as V1MToonSchema from '@pixiv/types-vrmc-materials-mtoon-1.0';
import type { GLTF, GLTFLoader, GLTFLoaderPlugin, GLTFParser } from 'three/examples/jsm/loaders/GLTFLoader.js';
import type { MToonMaterialParameters } from './MToonMaterialParameters';
import { MToonMaterialOutlineWidthMode } from './MToonMaterialOutlineWidthMode';
import type { MToonMaterialOutlineWidthMode } from './MToonMaterialOutlineWidthMode';
import { GLTFMToonMaterialParamsAssignHelper } from './GLTFMToonMaterialParamsAssignHelper';
import { MToonMaterialLoaderPluginOptions } from './MToonMaterialLoaderPluginOptions';
import type { MToonMaterialLoaderPluginOptions } from './MToonMaterialLoaderPluginOptions';
import type { MToonMaterialDebugMode } from './MToonMaterialDebugMode';
import { GLTF as GLTFSchema } from '@gltf-transform/core';
import { MToonMaterial } from './MToonMaterial';
import type { MToonNodeMaterialLoaderPlugin } from './nodes/MToonNodeMaterialLoaderPlugin';
import type { MToonNodeMaterial } from './nodes/MToonNodeMaterial';

/**
* Possible spec versions it recognizes.
Expand All @@ -18,24 +18,56 @@ const POSSIBLE_SPEC_VERSIONS = new Set(['1.0', '1.0-beta']);
/**
* A loader plugin of {@link GLTFLoader} for the extension `VRMC_materials_mtoon`.
*
* This plugin is for uses with WebGLRenderer.
* To use MToon in WebGPURenderer, use {@link MToonNodeMaterialLoaderPlugin} instead.
* This plugin is for uses with WebGLRenderer by default.
* To use MToon in WebGPURenderer, set {@link materialType} to {@link MToonNodeMaterial}.
*
* @example to use with WebGPURenderer
* ```js
* import { MToonMaterialLoaderPlugin } from '@pixiv/three-vrm-materials-mtoon';
* import { MToonNodeMaterial } from '@pixiv/three-vrm-materials-mtoon/nodes';
*
* // ...
*
* // Register a MToonMaterialLoaderPlugin with MToonNodeMaterial
* loader.register((parser) => {
*
* // create a WebGPU compatible MToonMaterialLoaderPlugin
* return new MToonMaterialLoaderPlugin(parser, {
*
* // set the material type to MToonNodeMaterial
* materialType: MToonNodeMaterial,
*
* });
*
* });
* ```
*/
export class MToonMaterialLoaderPlugin implements GLTFLoaderPlugin {
public static EXTENSION_NAME = 'VRMC_materials_mtoon';

/**
* The type of the material that this plugin will generate.
*
* If you are using this plugin with WebGPU, set this to {@link MToonNodeMaterial}.
*
* @default MToonMaterial
*/
public materialType: typeof THREE.Material;

/**
* This value will be added to `renderOrder` of every meshes who have MaterialsMToon.
* The final renderOrder will be sum of this `renderOrderOffset` and `renderQueueOffsetNumber` for each materials.
* `0` by default.
*
* @default 0
*/
public renderOrderOffset: number;

/**
* There is a line of the shader called "comment out if you want to PBR absolutely" in VRM0.0 MToon.
* When this is true, the material enables the line to make it compatible with the legacy rendering of VRM.
* Usually not recommended to turn this on.
* `false` by default.
*
* @default false
*/
public v0CompatShade: boolean;

Expand All @@ -44,6 +76,8 @@ export class MToonMaterialLoaderPlugin implements GLTFLoaderPlugin {
* You can visualize several components for diagnosis using debug mode.
*
* See: {@link MToonMaterialDebugMode}
*
* @default 'none'
*/
public debugMode: MToonMaterialDebugMode;

Expand All @@ -62,6 +96,7 @@ export class MToonMaterialLoaderPlugin implements GLTFLoaderPlugin {
public constructor(parser: GLTFParser, options: MToonMaterialLoaderPluginOptions = {}) {
this.parser = parser;

this.materialType = options.materialType ?? MToonMaterial;
this.renderOrderOffset = options.renderOrderOffset ?? 0;
this.v0CompatShade = options.v0CompatShade ?? false;
this.debugMode = options.debugMode ?? 'none';
Expand All @@ -80,7 +115,7 @@ export class MToonMaterialLoaderPlugin implements GLTFLoaderPlugin {
public getMaterialType(materialIndex: number): typeof THREE.Material | null {
const v1Extension = this._getMToonExtension(materialIndex);
if (v1Extension) {
return MToonMaterial;
return this.materialType;
}

return null;
Expand Down Expand Up @@ -248,6 +283,22 @@ export class MToonMaterialLoaderPlugin implements GLTFLoaderPlugin {
}
}

/**
* Check whether the material should generate outline or not.
* @param surfaceMaterial The material to check
* @returns True if the material should generate outline
*/
private _shouldGenerateOutline(surfaceMaterial: THREE.Material): boolean {
// we might receive MToonNodeMaterial as well as MToonMaterial
// so we're gonna duck type to check if it's compatible with MToon type outlines
return (
typeof (surfaceMaterial as any).outlineWidthMode === 'string' &&
(surfaceMaterial as any).outlineWidthMode !== 'none' &&
typeof (surfaceMaterial as any).outlineWidthFactor === 'number' &&
(surfaceMaterial as any).outlineWidthFactor > 0.0
);
}

/**
* Generate outline for the given mesh, if it needs.
*
Expand All @@ -265,15 +316,7 @@ export class MToonMaterialLoaderPlugin implements GLTFLoaderPlugin {
return;
}

// check whether we really have to prepare outline or not
// we might receive MToonNodeMaterial as well as MToonMaterial
// so we're gonna duck type to check if it's compatible with MToon type outlines
if (
typeof (surfaceMaterial as any).outlineWidthMode !== 'string' ||
(surfaceMaterial as any).outlineWidthMode === 'none' ||
typeof (surfaceMaterial as any).outlineWidthFactor !== 'number' ||
(surfaceMaterial as any).outlineWidthFactor <= 0.0
) {
if (!this._shouldGenerateOutline(surfaceMaterial)) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import type * as THREE from 'three';
import type { MToonMaterialDebugMode } from './MToonMaterialDebugMode';
import type { MToonNodeMaterial } from './nodes/MToonNodeMaterial';

export interface MToonMaterialLoaderPluginOptions {
/**
* The type of the material that the loader plugin will generate.
*
* If you are using this plugin with WebGPU, set this to {@link MToonNodeMaterial}.
*
* @default MToonMaterial
*/
materialType?: typeof THREE.Material;

/**
* This value will be added to `renderOrder` of every meshes who have MToonMaterial.
* The final `renderOrder` will be sum of this `renderOrderOffset` and `renderQueueOffsetNumber` for each materials.
* `0` by default.
*
* @default 0
*/
renderOrderOffset?: number;

/**
* There is a line of the shader called "comment out if you want to PBR absolutely" in VRM0.0 MToon.
* When this is true, the material enables the line to make it compatible with the legacy rendering of VRM.
* Usually not recommended to turn this on.
* `false` by default.
*
* @default false
*/
v0CompatShade?: boolean;

Expand All @@ -21,6 +34,8 @@ export interface MToonMaterialLoaderPluginOptions {
* You can visualize several components for diagnosis using debug mode.
*
* See: {@link MToonMaterialDebugMode}
*
* @default 'none'
*/
debugMode?: MToonMaterialDebugMode;
}
14 changes: 14 additions & 0 deletions packages/three-vrm-materials-mtoon/src/nodes/MToonNodeMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ export class MToonNodeMaterial extends Nodes.NodeMaterial {
return cacheKey;
}

/**
* Readonly boolean that indicates this is a {@link MToonNodeMaterial}.
*/
public get isMToonNodeMaterial(): true {
return true;
}

public constructor(parameters: MToonNodeMaterialParameters = {}) {
super();

Expand All @@ -124,6 +131,13 @@ export class MToonNodeMaterial extends Nodes.NodeMaterial {
}
delete parameters.transparentWithZWrite;

// `MToonMaterialLoaderPlugin` assigns these parameters to the material
// However, `MToonNodeMaterial` does not support these parameters
// so we delete them here to suppress warnings
delete (parameters as any).giEqualizationFactor;
delete (parameters as any).v0CompatShade;
delete (parameters as any).debugMode;

this.emissiveNode = null;

this.lights = true;
Expand Down

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion packages/three-vrm-materials-mtoon/src/nodes/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { MToonAnimatedUVNode } from './MToonAnimatedUVNode';
export { MToonLightingModel } from './MToonLightingModel';
export { MToonNodeMaterial } from './MToonNodeMaterial';
export { MToonNodeMaterialLoaderPlugin } from './MToonNodeMaterialLoaderPlugin';
export type { MToonNodeMaterialParameters } from './MToonNodeMaterialParameters';
Loading

0 comments on commit 25d12d4

Please sign in to comment.