@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
100 lines • 9.24 kB
JavaScript
import { TgdVec3, TgdVec4 } from "./../math/index.js";
import { TgdMaterial } from "./material.js";
import { TgdLight } from "./../light/index.js";
import { TgdTexture2D } from "./../texture/index.js";
const DEFAULT_COLOR = new TgdVec4(0.8, 0.6, 0.1, 1);
export class TgdMaterialToon extends TgdMaterial {
constructor(options = {}) {
const color = options.color instanceof TgdTexture2D ? options.color : new TgdVec4(options.color ?? DEFAULT_COLOR);
const hasTexture = !(color instanceof TgdVec4);
const vertexShaderCode = ["varNormal = mat3(uniTransfoMatrix) * NORMAL;"];
const uniforms = {
uniShades: "float",
uniShadesInverse: "float",
uniLight: "vec3",
uniLightDir: "vec3",
uniAmbient: "vec3",
uniSpecularSharpness: "float",
uniSpecularSize: "float",
uniSpecularIntensity: "float",
uniModelViewMatrix: "mat4",
};
const varyings = {
varNormal: "vec3",
};
if (hasTexture) {
vertexShaderCode.push("varUV = TEXCOORD_0;");
varyings.varUV = "vec2";
uniforms.texDiffuse = "sampler2D";
}
super({
uniforms,
varyings,
fragmentShaderCode: [
"vec3 normal = normalize(varNormal);",
`float light = .2 + .4 * (1.0 - dot(normal, uniLightDir));`,
`light *= uniShades;`,
`light -= fract(light);`,
`light /= uniShadesInverse;`,
hasTexture ? `vec4 color = texture(texDiffuse, varUV);` : `vec4 color = vec4(${color.join(", ")});`,
`vec3 normal2 = mat3(uniModelViewMatrix) * normal;`,
`float spec = max(0.0, reflect(uniLightDir, normal2).z);`,
`float a = 1.0 - uniSpecularSize;`,
`float b = a + (1.0 - a) * (1.0 * uniSpecularSharpness);`,
`spec = smoothstep(a, b, spec) * uniSpecularIntensity;`,
`color = vec4(`,
` color.rgb * (`,
` uniAmbient + uniLight * light`,
` ) + vec3(spec),`,
` 1.0`,
`);`,
`return color;`,
],
setUniforms: ({ program }) => {
program.uniform1f("uniShades", this.shades);
program.uniform1f("uniShadesInverse", 1 / this.shades);
program.uniform3fv("uniLightDir", this.light.direction);
this.lightColor.from(this.light.color).scale(this.light.color.w);
program.uniform3fv("uniLight", this.lightColor);
this.ambientColor.from(this.ambient.color).scale(this.ambient.color.w);
program.uniform3fv("uniAmbient", this.ambientColor);
program.uniform1f("uniSpecularSharpness", this.specularSharpness);
program.uniform1f("uniSpecularSize", this.specularSize);
program.uniform1f("uniSpecularIntensity", this.specularIntensity);
const { texture } = this;
if (texture)
texture.activate(0, program, "texDiffuse");
},
});
this.light = new TgdLight({
direction: new TgdVec3(0.2, -0.3, -0.6).normalize(),
});
this.ambient = new TgdLight({ color: new TgdVec4(0.2, 0.1, 0, 0) });
this.specularSharpness = 0.9;
this.specularSize = 0.1;
this.specularIntensity = 0.5;
this.shades = 3;
this.lightColor = new TgdVec3();
this.ambientColor = new TgdVec3();
this.shades = options.shades ?? this.shades;
if (options.light) {
this.light = options.light;
}
this.ambient =
options.ambient ??
new TgdLight({
color: new TgdVec4(1, 1, 1, 1),
});
if (typeof options.specularSharpness === "number") {
this.specularSharpness = options.specularSharpness;
}
if (typeof options.specularSize === "number") {
this.specularSize = options.specularSize;
}
if (typeof options.specularIntensity === "number") {
this.specularIntensity = options.specularIntensity;
}
this.texture = hasTexture ? color : null;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tYXRlcmlhbC90b29uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQzVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDeEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNyQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBYTNDLE1BQU0sYUFBYSxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFBO0FBSW5ELE1BQU0sT0FBTyxlQUFnQixTQUFRLFdBQVc7SUFjNUMsWUFBWSxVQUFrQyxFQUFFO1FBQzVDLE1BQU0sS0FBSyxHQUNQLE9BQU8sQ0FBQyxLQUFLLFlBQVksWUFBWSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLGFBQWEsQ0FBQyxDQUFBO1FBQ3ZHLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxLQUFLLFlBQVksT0FBTyxDQUFDLENBQUE7UUFDOUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLDhDQUE4QyxDQUFDLENBQUE7UUFDekUsTUFBTSxRQUFRLEdBQXlDO1lBQ25ELFNBQVMsRUFBRSxPQUFPO1lBQ2xCLGdCQUFnQixFQUFFLE9BQU87WUFDekIsUUFBUSxFQUFFLE1BQU07WUFDaEIsV0FBVyxFQUFFLE1BQU07WUFDbkIsVUFBVSxFQUFFLE1BQU07WUFDbEIsb0JBQW9CLEVBQUUsT0FBTztZQUM3QixlQUFlLEVBQUUsT0FBTztZQUN4QixvQkFBb0IsRUFBRSxPQUFPO1lBQzdCLGtCQUFrQixFQUFFLE1BQU07U0FDN0IsQ0FBQTtRQUNELE1BQU0s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