代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html lang="en">
<head>
<title>Verge3D webgl - sprites nodes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="https://www.soft8soft.com/verge3d" target="_blank" rel="noopener">Verge3D</a> - Node-Based Sprites
</div>
<script type="module">
import * as v3d from '../build/v3d.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { NodeMaterialLoader, NodeMaterialLoaderUtils } from './jsm/loaders/NodeMaterialLoader.js';
import {
NodeFrame,
SpriteNodeMaterial,
MathNode,
OperatorNode,
TextureNode,
Vector2Node,
TimerNode,
FunctionNode,
FunctionCallNode,
PositionNode,
UVNode
} from './jsm/nodes/Nodes.js';
const container = document.getElementById('container');
let renderer, scene, camera;
const clock = new v3d.Clock(), fov = 50;
const frame = new NodeFrame();
let sprite1, sprite2, sprite3;
let walkingManTexture, walkingManTextureURL;
const library = {};
let controls;
window.addEventListener('load', init);
function init() {
//
// Renderer / Controls
//
renderer = new v3d.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
scene = new v3d.Scene();
scene.fog = new v3d.Fog(0x0000FF, 70, 150);
camera = new v3d.PerspectiveCamera(fov, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 100;
controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 50;
controls.maxDistance = 200;
//
// SpriteNode
//
// https://openclipart.org/detail/239883/walking-man-sprite-sheet
walkingManTextureURL = "textures/WalkingManSpriteSheet.png";
walkingManTexture = new v3d.TextureLoader().load(walkingManTextureURL);
walkingManTexture.wrapS = walkingManTexture.wrapT = v3d.RepeatWrapping;
library[walkingManTextureURL] = walkingManTexture;
// horizontal sprite-sheet animator
function createHorizontalSpriteSheetNode(hCount, speed) {
const speedNode = new Vector2Node(speed, 0); // frame per second
const scale = new Vector2Node(1 / hCount, 1); // 8 horizontal images in sprite-sheet
const uvTimer = new OperatorNode(
new TimerNode(),
speedNode,
OperatorNode.MUL
);
const uvIntegerTimer = new MathNode(
uvTimer,
MathNode.FLOOR
);
const uvFrameOffset = new OperatorNode(
uvIntegerTimer,
scale,
OperatorNode.MUL
);
const uvScale = new OperatorNode(
new UVNode(),
scale,
OperatorNode.MUL
);
const uvFrame = new OperatorNode(
uvScale,
uvFrameOffset,
OperatorNode.ADD
);
return uvFrame;
}
// sprites
const spriteWidth = 20, spriteHeight = 20;
scene.add(sprite1 = new v3d.Sprite(new SpriteNodeMaterial()));
sprite1.scale.x = spriteWidth;
sprite1.scale.y = spriteHeight;
sprite1.material.color = new TextureNode(walkingManTexture);
sprite1.material.color.uv = createHorizontalSpriteSheetNode(8, 10);
scene.add(sprite2 = new v3d.Sprite(new SpriteNodeMaterial()));
sprite2.position.x = 30;
sprite2.scale.x = spriteWidth;
sprite2.scale.y = spriteHeight;
sprite2.material.color = new TextureNode(walkingManTexture);
sprite2.material.color.uv = createHorizontalSpriteSheetNode(8, 30);
sprite2.material.color = new MathNode(sprite2.material.color, MathNode.INVERT);
sprite2.material.spherical = false; // look at camera horizontally only, very used in vegetation
// horizontal zigzag sprite
sprite2.material.position = new OperatorNode(
new OperatorNode(
new MathNode(new TimerNode(3), MathNode.SIN), // 3 is speed (time scale)
new Vector2Node(.3, 0), // horizontal scale (position)
OperatorNode.MUL
),
new PositionNode(),
OperatorNode.ADD
);
const sineWaveFunction = new FunctionNode([
// https://stackoverflow.com/questions/36174431/how-to-make-a-wave-warp-effect-in-shader
"vec2 sineWave(vec2 uv, vec2 phase) {",
// wave distortion
" float x = sin(25.0*uv.y + 30.0*uv.x + 6.28*phase.x) * 0.01;",
" float y = sin(25.0*uv.y + 30.0*uv.x + 6.28*phase.y) * 0.03;",
" return vec2(uv.x+x, uv.y+y);",
"}"
].join("\n"));
scene.add(sprite3 = new v3d.Sprite(new SpriteNodeMaterial()));
sprite3.position.x = - 30;
sprite3.scale.x = spriteWidth;
sprite3.scale.y = spriteHeight;
sprite3.material.color = new TextureNode(walkingManTexture);
sprite3.material.color.uv = new FunctionCallNode(sineWaveFunction, {
"uv": createHorizontalSpriteSheetNode(8, 10),
"phase": new TimerNode()
});
sprite3.material.fog = true;
//
// Test serialization
//
spriteToJSON(sprite1);
spriteToJSON(sprite2);
spriteToJSON(sprite3);
//
// Events
//
window.addEventListener('resize', onWindowResize, false);
onWindowResize();
animate();
}
function spriteToJSON(sprite) {
// serialize
const json = sprite.material.toJSON();
// replace uuid to url (facilitates the load of textures using url otherside uuid)
NodeMaterialLoaderUtils.replaceUUID(json, walkingManTexture, walkingManTextureURL);
// deserialize
const material = new NodeMaterialLoader(null, library).parse(json);
// replace material
sprite.material.dispose();
sprite.material = material;
}
function onWindowResize() {
const width = window.innerWidth, height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
function animate() {
const delta = clock.getDelta();
// update material animation and/or gpu calcs (pre-renderer)
frame.update(delta)
.updateNode(sprite1.material)
.updateNode(sprite2.material)
.updateNode(sprite3.material);
// rotate sprite
sprite3.rotation.z -= Math.PI * .005;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。