Skip to content

Commit

Permalink
feat(test): Add test(debug) environment
Browse files Browse the repository at this point in the history
fix #5
  • Loading branch information
il-masaru-yamagishi committed May 13, 2019
1 parent 5689276 commit ab102f5
Show file tree
Hide file tree
Showing 16 changed files with 1,363 additions and 68 deletions.
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ Issues about babylon.js-specific or MToon original-specific will be ignored.
## Pull requests

TBA

## Releases

This repository uses [semantic-release](https://semantic-release.gitbook.io/semantic-release/).

When some `feat:` or `fix:`-prefixed commits pushed to master, CircleCI automatically releases new version to GitHub Releases and npm.
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# babylon-mtoon-material

[![npm version](https://badge.fury.io/js/babylon-mtoon-material.svg)](https://badge.fury.io/js/babylon-mtoon-material) [![Greenkeeper badge](https://badges.greenkeeper.io/virtual-cast/babylon-mtoon-material.svg)](https://greenkeeper.io/) [![CircleCI](https://circleci.com/gh/virtual-cast/babylon-mtoon-material.svg?style=svg)](https://circleci.com/gh/virtual-cast/babylon-mtoon-material)
[![npm version](https://badge.fury.io/js/babylon-mtoon-material.svg)](https://badge.fury.io/js/babylon-mtoon-material) [![Greenkeeper badge](https://badges.greenkeeper.io/virtual-cast/babylon-mtoon-material.svg)](https://greenkeeper.io/) [![CircleCI](https://circleci.com/gh/virtual-cast/babylon-mtoon-material.svg?style=svg)](https://circleci.com/gh/virtual-cast/babylon-mtoon-material) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

![](mtoon.png)

Unity MToon Shader WebGL porting to babylon.js.

Expand All @@ -19,17 +21,41 @@ This is **Work In Progress**. Some settings will be ignored or generates inconsi
- Fog
- Bones in shader
- MorphTargets in shader
- Vertex Alpha
- Shadow
- EffectFallback
- Instances
- ClipPlane
- AmbientColor
- Alpha CutOff
- Textures & Color values
- Diffuse
- Emissive
- Bump
- Shade(shaded diffuse)
- Receive Shadow(received shadow rate texture alpha)
- Shading Grade
- MatCap
- Outline Width
- Todo: Rim

These are not covered.

- Specular
- Vertex Color
- TODO: Serialize Support

## Usage

This material will be automatically assined to VRM/VCI model within [babylon-vrm-loader](https://github.com/virtual-cast/babylon-vrm-loader).

You can explicitly assign MToonMaterial to some meshes.

```ts
const sphere = BABYLON.Mesh.CreateSphere('Sphere', 16, 1, scene);
const material = new MToonMaterial('MtoonMaterial', scene);
sphere.material = material;
```

## Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md).
Expand All @@ -42,7 +68,11 @@ $ yarn build

### Debugging MToonMaterial

TBD
```s
$ yarn debug
```

You can see inspector on http://localhost:8080/

## Related Links

Expand Down
4 changes: 2 additions & 2 deletions dist/index.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/mtoon-material.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ export declare class MToonMaterial extends PushMaterial {
matCapTexture: Nullable<BaseTexture>;
/**
* アウトラインの幅の調整テクスチャ
* @todo 現在は適用されていない
*/
outlineWidthTexture: Nullable<BaseTexture>;
/**
Expand Down Expand Up @@ -178,6 +177,7 @@ export declare class MToonMaterial extends PushMaterial {
/**
* シーンの AmbientColor と掛け合わせた後の色
* @see bindForSubMesh
* @hidden
*/
protected globalAmbientColor: Color3;
/**
Expand Down Expand Up @@ -312,14 +312,14 @@ export declare class MToonMaterial extends PushMaterial {
/**
* @inheritdoc
*/
clone(_: string): Nullable<MToonMaterial>;
clone(name: string): Nullable<MToonMaterial>;
/**
* @inheritdoc
*/
serialize(): any;
/**
* @inheritdoc
*/
static Parse(_: any, __: Scene, ___: string): MToonMaterial;
static Parse(parsedMaterial: any, scene: Scene, rootUrl: string): MToonMaterial;
}
export {};
4 changes: 4 additions & 0 deletions dist/test/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import '@babylonjs/core/Helpers/sceneHelpers';
import '@babylonjs/core/Meshes/Builders/sphereBuilder';
import '@babylonjs/core/Meshes/Builders/torusKnotBuilder';
import '@babylonjs/inspector';
7 changes: 7 additions & 0 deletions dist/test/inspectable-custom-properties.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { MToonMaterial } from '../index';
/**
* MToonMaterial に Inspector 上で調整可能なパラメータを設定する
* @param material
* @link https://doc.babylonjs.com/how_to/debug_layer#extensibility
*/
export declare function addInspectableCustomProperties(material: MToonMaterial): void;
Binary file added mtoon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@babylonjs/core": "^4.0.3"
},
"devDependencies": {
"@babylonjs/inspector": "^4.0.3",
"@semantic-release/commit-analyzer": "^6.1.0",
"@semantic-release/git": "^7.0.8",
"@semantic-release/github": "^5.2.10",
Expand All @@ -45,11 +46,13 @@
"tslint": "^5.16.0",
"typescript": "^3.4.5",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.2"
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.3.1"
},
"scripts": {
"build": "webpack",
"lint": "tslint -p .",
"debug": "webpack-dev-server --config webpack.test.config.js",
"release": "semantic-release"
},
"config": {
Expand Down
17 changes: 4 additions & 13 deletions src/mtoon-material.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ export class MToonMaterial extends PushMaterial {
public matCapTexture: Nullable<BaseTexture> = null;
/**
* アウトラインの幅の調整テクスチャ
* @todo 現在は適用されていない
*/
@expandToProperty('_markAllSubMeshesAsTexturesDirty')
public outlineWidthTexture: Nullable<BaseTexture> = null;
Expand Down Expand Up @@ -235,6 +234,7 @@ export class MToonMaterial extends PushMaterial {
/**
* シーンの AmbientColor と掛け合わせた後の色
* @see bindForSubMesh
* @hidden
*/
protected globalAmbientColor = new Color3(0.0, 0.0, 0.0);
/**
Expand Down Expand Up @@ -420,7 +420,7 @@ export class MToonMaterial extends PushMaterial {
super(name, scene);

// 裏面描画モードになることがあるのでここで右手座標系に強制する
this.sideOrientation = Material.ClockWiseSideOrientation;
// this.sideOrientation = Material.ClockWiseSideOrientation;

// シェーダストアに登録する
if (!Effect.IncludesShadersStore.mtoonUboDeclaration) {
Expand Down Expand Up @@ -766,15 +766,6 @@ export class MToonMaterial extends PushMaterial {

MaterialHelper.BindEyePosition(effect, scene);
effect.setVector3('vEyeUp', scene.activeCamera!.upVector);

// アウトライン設定
if (this.outlineWidthMode !== OutlineWidthMode.None) {
// TODO: 暫定的に OutlineRenderer を利用する
// mesh.renderOutline = true;
// mesh.outlineColor = this.outlineColor.clone();
// アウトラインサイズが肥大化する時があるので調整する
// mesh.outlineWidth = this.outlineWidth >= 0.1 ? 0.00001 : this.outlineWidth / 100;
}
}

if (mustRebind || !this.isFrozen) {
Expand Down Expand Up @@ -1045,7 +1036,7 @@ export class MToonMaterial extends PushMaterial {
/**
* @inheritdoc
*/
public clone(_: string): Nullable<MToonMaterial> {
public clone(name: string): Nullable<MToonMaterial> {
throw new Error(`MToonMaterial cannot be cloned.`);
}

Expand All @@ -1059,7 +1050,7 @@ export class MToonMaterial extends PushMaterial {
/**
* @inheritdoc
*/
public static Parse(_: any, __: Scene, ___: string): MToonMaterial {
public static Parse(parsedMaterial: any, scene: Scene, rootUrl: string): MToonMaterial {
throw new Error(`MToonMaterial cannot be parsed`);
}
//#endregion
Expand Down
2 changes: 1 addition & 1 deletion src/shaders/mtoon.frag
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ vec4 computeMToonDiffuseLighting(vec3 worldView, vec3 worldNormal, vec2 uvOffset
// lighting intensity
float _lightIntensity = dot(lightDirection, worldNormal);
_lightIntensity = _lightIntensity * 0.5 + 0.5; // from [-1, +1] to [0, 1]
_lightIntensity = _lightIntensity * (_receiveShadow * shadow); // receive shadow
_lightIntensity = _lightIntensity * (1.0 - _receiveShadow * (1.0 - (shadow * 0.5 + 0.5))); // receive shadow
_lightIntensity = _lightIntensity * _shadingGrade; // darker
_lightIntensity = _lightIntensity * 2.0 - 1.0; // from [0, 1] to [-1, +1]
_lightIntensity = smoothstep(shadeShift, shadeShift + (1.0 - shadeToony), _lightIntensity); // shade & tooned
Expand Down
140 changes: 140 additions & 0 deletions src/test/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera';
import { Engine } from '@babylonjs/core/Engines/engine';
import { DirectionalLight } from '@babylonjs/core/Lights/directionalLight';
import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight';
import { PointLight } from '@babylonjs/core/Lights/pointLight';
import { ShadowGenerator } from '@babylonjs/core/Lights/Shadows/shadowGenerator';
import { Texture } from '@babylonjs/core/Materials/Textures/texture';
import { Color3, Vector3 } from '@babylonjs/core/Maths/math';
import { Mesh } from '@babylonjs/core/Meshes/mesh';
import { Scene } from '@babylonjs/core/scene';
import { MToonMaterial } from '../mtoon-material';
import { addInspectableCustomProperties } from './inspectable-custom-properties';

import '@babylonjs/core/Helpers/sceneHelpers';
import '@babylonjs/core/Meshes/Builders/sphereBuilder';
import '@babylonjs/core/Meshes/Builders/torusKnotBuilder';
import '@babylonjs/inspector';

async function main() {
const debugProperties = getDebugProperties();
const canvas = document.getElementById('main-canvas') as HTMLCanvasElement;
const engine = new Engine(
canvas,
true,
{
alpha: false,
disableWebGL2Support: debugProperties.webgl1,
},
);

const scene = new Scene(engine);
const camera = new ArcRotateCamera('MainCamera1', 0, 0, 3, new Vector3(0, 1.2, 0), scene, true);
camera.lowerRadiusLimit = 0.1;
camera.upperRadiusLimit = 20;
camera.wheelDeltaPercentage = 0.01;
camera.attachControl(canvas);

scene.createDefaultEnvironment({
createGround: true,
createSkybox: false,
enableGroundMirror: false,
enableGroundShadow: false,
});

// Lights
const directionalLight = new DirectionalLight('DirectionalLight1', new Vector3(1, -0.5, 0.0), scene);
directionalLight.position = new Vector3(-50, 25, 0);
directionalLight.setEnabled(true);
const hemisphericLight = new HemisphericLight('HemisphericLight1', new Vector3(-0.2, -0.8, -1), scene);
hemisphericLight.setEnabled(false);
const pointLight = new PointLight('PointLight1', new Vector3(0, 0, 1), scene);
pointLight.setEnabled(false);

// Meshes
const standardMaterialSphere = Mesh.CreateSphere('StandardMaterialSphere1', 16, 1, scene);
standardMaterialSphere.position = new Vector3(1.2, 1.2, 0);
standardMaterialSphere.receiveShadows = true;

const shadowCaster = Mesh.CreateTorusKnot('ShadowCaster', 1, 0.2, 32, 32, 2, 3, scene);
shadowCaster.position = new Vector3(-10.0, 5.0, 0.0);
shadowCaster.setEnabled(debugProperties.shadow);
if (debugProperties.shadow) {
const shadowGenerator = new ShadowGenerator(1024, directionalLight);
shadowGenerator.addShadowCaster(shadowCaster);
}

const mtoonMaterials: MToonMaterial[] = [];
{
const mat = new MToonMaterial('MtoonMaterialDefault', scene);
mat.outlineWidthMode = 1;
mtoonMaterials.push(mat);
}
{
const mat = new MToonMaterial('MtoonMaterialNormal', scene);
mat.outlineWidthMode = 1;
// Textures from https://www.babylonjs-playground.com/#20OAV9#33
const diffuse = new Texture('http://i.imgur.com/Wk1cGEq.png', scene);
diffuse.uScale = 4;
diffuse.vScale = 4;
mat.diffuseTexture = diffuse;
mat.shadeTexture = mat.diffuseTexture.clone();
mat.shadeColor = new Color3(0.871, 0.196, 0.416);
const bump = new Texture('http://i.imgur.com/wGyk6os.png', scene);
bump.uScale = 4;
bump.vScale = 4;
mat.bumpTexture = bump;
mtoonMaterials.push(mat);
}
{
const mat = new MToonMaterial('MtoonMaterialTransparent', scene);
mat.outlineWidthMode = 1;
// Textures from https://www.babylonjs-playground.com/#YDO1F#18
mat.diffuseTexture = new Texture('https://upload.wikimedia.org/wikipedia/commons/8/87/Alaskan_Malamute%2BBlank.png', scene);
mat.shadeTexture = mat.diffuseTexture.clone();
mat.alphaBlend = true;
mtoonMaterials.push(mat);
}

mtoonMaterials.forEach((mat, index) => {
// MToonMaterial は glTF(右手座標) を考慮しているため、 CullMode をデフォルトから反転させる
mat.cullMode = 1;
mat.outlineCullMode = 2;
addInspectableCustomProperties(mat);
const sphere = Mesh.CreateSphere(`${mat.name}_Sphere`, 16, 1, scene);
sphere.position = new Vector3(-1.2 * index, 1.2, 0);
sphere.receiveShadows = true;
sphere.material = mat;
});

await scene.debugLayer.show({
globalRoot: document.getElementById('wrapper') as HTMLMainElement,
handleResize: true,
});

engine.runRenderLoop(() => {
scene.render();
shadowCaster.rotate(Vector3.Up(), 0.01);
});
window.addEventListener('resize', () => {
engine.resize();
});
}

interface DebugProperties {
webgl1: boolean;
shadow: boolean;
}

function getDebugProperties(): DebugProperties {
const href = window.location.href;

return {
webgl1: href.includes('webgl1'),
shadow: href.includes('shadow'),
};
}

main().catch((reason) => {
console.error(reason);
});
Loading

0 comments on commit ab102f5

Please sign in to comment.