add shadows, close #99

This commit is contained in:
Haowei Wen 2022-01-08 04:58:38 +08:00
parent b16194be6a
commit 5fbf497002
4 changed files with 33 additions and 6 deletions

View File

@ -89,5 +89,17 @@ To enable it, you need to replace `SkinViewer` with `FXAASkinViewer`.
Note that FXAA is incompatible with transparent backgrounds.
So when FXAA is enabled, the default background color will be white instead of transparent.
## Lighting
By default, there are two lights on the scene. One is an ambient light, and the other is a point light from the camera.
To change the light intensity:
```js
skinViewer.cameraLight.intensity = 0.9;
skinViewer.globalLight.intensity = 0.1;
```
Setting `globalLight.intensity` to `1.0` and `cameraLight.intensity` to `0.0`
will completely disable shadows.
# Build
`npm run build`

View File

@ -122,6 +122,12 @@
</div>
</div>
<div class="light">
<h1>Light</h1>
<label class="control">Global: <input id="global_light" type="number" value="0.40" step="0.01" min="0.00" max="2.00" size="2"></label>
<label class="control">Camera: <input id="camera_light" type="number" value="0.60" step="0.01" min="0.00" max="2.00" size="2"></label>
</div>
<div class="control-section">
<h1>Animation</h1>
<label class="control">Global Speed: <input id="global_animation_speed" type="number" value="1" step="0.1" size="3"></label>
@ -369,6 +375,8 @@
document.getElementById("canvas_height").addEventListener("change", e => skinViewer.height = e.target.value);
document.getElementById("fov").addEventListener("change", e => skinViewer.fov = e.target.value);
document.getElementById("zoom").addEventListener("change", e => skinViewer.zoom = e.target.value);
document.getElementById("global_light").addEventListener("change", e => skinViewer.globalLight.intensity = e.target.value);
document.getElementById("camera_light").addEventListener("change", e => skinViewer.cameraLight.intensity = e.target.value);
document.getElementById("global_animation_speed").addEventListener("change", e => skinViewer.animations.speed = e.target.value);
document.getElementById("animation_pause_resume").addEventListener("click", () => skinViewer.animations.paused = !skinViewer.animations.paused);
document.getElementById("rotate_animation").addEventListener("change", e => {
@ -469,6 +477,8 @@
skinViewer.height = document.getElementById("canvas_height").value;
skinViewer.fov = document.getElementById("fov").value;
skinViewer.zoom = document.getElementById("zoom").value;
skinViewer.globalLight.intensity = document.getElementById("global_light").value;
skinViewer.cameraLight.intensity = document.getElementById("camera_light").value;
skinViewer.animations.speed = document.getElementById("global_animation_speed").value;
if (document.getElementById("rotate_animation").checked) {
rotateAnimation = skinViewer.animations.add(skinview3d.RotatingAnimation);

View File

@ -1,5 +1,5 @@
import { ModelType } from "skinview-utils";
import { BoxGeometry, BufferAttribute, DoubleSide, FrontSide, Group, Mesh, MeshBasicMaterial, Object3D, Texture, Vector2 } from "three";
import { BoxGeometry, BufferAttribute, DoubleSide, FrontSide, Group, Mesh, MeshStandardMaterial, Object3D, Texture, Vector2 } from "three";
function setUVs(box: BoxGeometry, u: number, v: number, width: number, height: number, depth: number, textureWidth: number, textureHeight: number): void {
const toFaceVertices = (x1: number, y1: number, x2: number, y2: number) => [
@ -66,11 +66,11 @@ export class SkinObject extends Group {
constructor(texture: Texture) {
super();
const layer1Material = new MeshBasicMaterial({
const layer1Material = new MeshStandardMaterial({
map: texture,
side: FrontSide
});
const layer2Material = new MeshBasicMaterial({
const layer2Material = new MeshStandardMaterial({
map: texture,
side: DoubleSide,
transparent: true,
@ -258,7 +258,7 @@ export class CapeObject extends Group {
constructor(texture: Texture) {
super();
const capeMaterial = new MeshBasicMaterial({
const capeMaterial = new MeshStandardMaterial({
map: texture,
side: DoubleSide,
transparent: true,
@ -284,7 +284,7 @@ export class ElytraObject extends Group {
constructor(texture: Texture) {
super();
const elytraMaterial = new MeshBasicMaterial({
const elytraMaterial = new MeshStandardMaterial({
map: texture,
side: DoubleSide,
transparent: true,

View File

@ -1,5 +1,5 @@
import { inferModelType, isTextureSource, loadCapeToCanvas, loadImage, loadSkinToCanvas, ModelType, RemoteImage, TextureSource } from "skinview-utils";
import { Color, ColorRepresentation, EquirectangularReflectionMapping, Group, NearestFilter, PerspectiveCamera, Scene, Texture, Vector2, WebGLRenderer } from "three";
import { Color, ColorRepresentation, PointLight, EquirectangularReflectionMapping, Group, NearestFilter, PerspectiveCamera, Scene, Texture, Vector2, WebGLRenderer, AmbientLight } from "three";
import { RootAnimation } from "./animation.js";
import { BackEquipment, PlayerObject } from "./model.js";
@ -80,6 +80,8 @@ export class SkinViewer {
readonly playerObject: PlayerObject;
readonly playerWrapper: Group;
readonly animations: RootAnimation = new RootAnimation();
readonly globalLight: AmbientLight = new AmbientLight(0xffffff, 0.4);
readonly cameraLight: PointLight = new PointLight(0xffffff, 0.6);
readonly skinCanvas: HTMLCanvasElement;
readonly capeCanvas: HTMLCanvasElement;
@ -112,6 +114,9 @@ export class SkinViewer {
this.scene = new Scene();
this.camera = new PerspectiveCamera();
this.camera.add(this.cameraLight);
this.scene.add(this.camera);
this.scene.add(this.globalLight);
this.renderer = new WebGLRenderer({
canvas: this.canvas,