提交 dd840a90 编写于 作者: S sunag

SpriteNodeMaterial and example

上级 75a8bd44
/**
* @author sunag / http://www.sunag.com.br/
*/
THREE.SpriteNode = function () {
THREE.GLNode.call( this );
this.color = new THREE.ColorNode( 0xEEEEEE );
};
THREE.SpriteNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.SpriteNode.prototype.constructor = THREE.SpriteNode;
THREE.SpriteNode.prototype.build = function ( builder ) {
var material = builder.material;
var output, code;
material.define( 'SPRITE' );
material.requestAttribs.light = false;
material.requestAttribs.transparent = this.alpha != undefined;
if ( builder.isShader( 'vertex' ) ) {
var transform = this.transform ? this.transform.parseAndBuildCode( builder, 'v3', { cache: 'transform' } ) : undefined;
material.mergeUniform( THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ]
] ) );
material.addVertexPars( [
THREE.ShaderChunk[ "fog_pars_vertex" ],
].join( "\n" ) );
output = [
THREE.ShaderChunk[ "begin_vertex" ]
];
if ( transform ) {
output.push(
transform.code,
"transformed = " + transform.result + ";"
);
}
output.push(
THREE.ShaderChunk[ "project_vertex" ],
THREE.ShaderChunk[ "fog_vertex" ],
'mat4 modelViewMtx = modelViewMatrix;',
'mat4 modelMtx = modelMatrix;',
// ignore position from modelMatrix (use vary position)
'modelMtx[3][0] = 0.0;',
'modelMtx[3][1] = 0.0;',
'modelMtx[3][2] = 0.0;',
// http://www.geeks3d.com/20140807/billboarding-vertex-shader-glsl/
// First colunm.
'modelViewMtx[0][0] = 1.0;',
'modelViewMtx[0][1] = 0.0;',
'modelViewMtx[0][2] = 0.0;',
// Second colunm.
'modelViewMtx[1][0] = 0.0;',
'modelViewMtx[1][1] = 1.0;',
'modelViewMtx[1][2] = 0.0;',
// Thrid colunm.
'modelViewMtx[2][0] = 0.0;',
'modelViewMtx[2][1] = 0.0;',
'modelViewMtx[2][2] = 1.0;',
// apply
'gl_Position = projectionMatrix * modelViewMtx * modelMtx * vec4( position, 1.0 );'
);
code = output.join( "\n" );
} else {
material.addFragmentPars( [
THREE.ShaderChunk[ "fog_pars_fragment" ]
].join( "\n" ) );
// parse all nodes to reuse generate codes
this.color.parse( builder, { slot: 'color' } );
if ( this.alpha ) this.alpha.parse( builder );
// build code
var color = this.color.buildCode( builder, 'c', { slot: 'color' } );
var alpha = this.alpha ? this.alpha.buildCode( builder, 'fv1' ) : undefined;
output = [ color.code ];
if ( alpha ) {
output.push(
alpha.code,
"gl_FragColor = vec4( " + color.result + ", " + alpha.result + " );"
);
} else {
output.push( "gl_FragColor = vec4( " + color.result + ", 1.0 );" );
}
output.push( THREE.ShaderChunk[ "fog_fragment" ] );
code = output.join( "\n" );
}
return code;
};
/**
* @author sunag / http://www.sunag.com.br/
*/
THREE.SpriteNodeMaterial = function () {
this.node = new THREE.SpriteNode();
THREE.NodeMaterial.call( this, this.node, this.node );
};
THREE.SpriteNodeMaterial.prototype = Object.create( THREE.NodeMaterial.prototype );
THREE.SpriteNodeMaterial.prototype.constructor = THREE.SpriteNodeMaterial;
THREE.NodeMaterial.addShortcuts( THREE.SpriteNodeMaterial.prototype, 'node',
[ 'color', 'alpha', 'transform' ] );
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js 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">
<style>
body {
color: #fff;
font-family:Monospace;
font-size:13px;
margin: 0px;
text-align:center;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
display:block;
}
a { color: white }
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Node-Based Sprites
</div>
<script src="../build/three.js"></script>
<script src='js/geometries/TeapotBufferGeometry.js'></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<!-- NodeLibrary -->
<script src="js/nodes/GLNode.js"></script>
<script src="js/nodes/RawNode.js"></script>
<script src="js/nodes/TempNode.js"></script>
<script src="js/nodes/InputNode.js"></script>
<script src="js/nodes/ConstNode.js"></script>
<script src="js/nodes/VarNode.js"></script>
<script src="js/nodes/FunctionNode.js"></script>
<script src="js/nodes/FunctionCallNode.js"></script>
<script src="js/nodes/AttributeNode.js"></script>
<script src="js/nodes/NodeBuilder.js"></script>
<script src="js/nodes/NodeLib.js"></script>
<script src="js/nodes/NodeMaterial.js"></script>
<!-- Accessors -->
<script src="js/nodes/accessors/PositionNode.js"></script>
<script src="js/nodes/accessors/NormalNode.js"></script>
<script src="js/nodes/accessors/UVNode.js"></script>
<script src="js/nodes/accessors/ScreenUVNode.js"></script>
<script src="js/nodes/accessors/ColorsNode.js"></script>
<script src="js/nodes/accessors/CameraNode.js"></script>
<script src="js/nodes/accessors/ReflectNode.js"></script>
<script src="js/nodes/accessors/LightNode.js"></script>
<!-- Inputs -->
<script src="js/nodes/inputs/IntNode.js"></script>
<script src="js/nodes/inputs/FloatNode.js"></script>
<script src="js/nodes/inputs/ColorNode.js"></script>
<script src="js/nodes/inputs/Vector2Node.js"></script>
<script src="js/nodes/inputs/Vector3Node.js"></script>
<script src="js/nodes/inputs/Vector4Node.js"></script>
<script src="js/nodes/inputs/TextureNode.js"></script>
<script src="js/nodes/inputs/Matrix4Node.js"></script>
<script src="js/nodes/inputs/CubeTextureNode.js"></script>
<!-- Math -->
<script src="js/nodes/math/Math1Node.js"></script>
<script src="js/nodes/math/Math2Node.js"></script>
<script src="js/nodes/math/Math3Node.js"></script>
<script src="js/nodes/math/OperatorNode.js"></script>
<!-- Utils -->
<script src="js/nodes/utils/SwitchNode.js"></script>
<script src="js/nodes/utils/JoinNode.js"></script>
<script src="js/nodes/utils/TimerNode.js"></script>
<script src="js/nodes/utils/RoughnessToBlinnExponentNode.js"></script>
<script src="js/nodes/utils/VelocityNode.js"></script>
<script src="js/nodes/utils/LuminanceNode.js"></script>
<script src="js/nodes/utils/ColorAdjustmentNode.js"></script>
<script src="js/nodes/utils/NoiseNode.js"></script>
<script src="js/nodes/utils/ResolutionNode.js"></script>
<script src="js/nodes/utils/BumpNode.js"></script>
<script src="js/nodes/utils/BlurNode.js"></script>
<script src="js/nodes/utils/UVTransformNode.js"></script>
<!-- Sprite Material -->
<script src="js/nodes/materials/SpriteNode.js"></script>
<script src="js/nodes/materials/SpriteNodeMaterial.js"></script>
<script>
var container = document.getElementById( 'container' );
var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
var plane, sprite1, sprite2, sprite3;
var controls;
window.addEventListener( 'load', init );
function init() {
//
// Renderer / Controls
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x0000FF, 0.0, 100 );
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 50;
camera.target = new THREE.Vector3();
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.minDistance = 50;
controls.maxDistance = 200;
//
// SpriteNode
//
// use scale to adjuste the real sprite size
plane = new THREE.PlaneBufferGeometry( 1, 1 );
var walkingManTexture = new THREE.TextureLoader().load( "textures/WalkingManSpriteSheet.png" );
walkingManTexture.wrapS = walkingManTexture.wrapT = THREE.RepeatWrapping;
// horizontal sprite-sheet animator
function createHorizontalSpriteSheetNode( hCount, speed ) {
var speed = new THREE.Vector2Node( speed, 0 ); // frame per second
var scale = new THREE.Vector2Node( 1 / hCount, 1 ); // 8 horizontal images in sprite-sheet
var uvTimer = new THREE.OperatorNode(
new THREE.TimerNode(),
speed,
THREE.OperatorNode.MUL
);
var uvIntegerTimer = new THREE.Math1Node(
uvTimer,
THREE.Math1Node.FLOOR
);
var uvFrameOffset = new THREE.OperatorNode(
uvIntegerTimer,
scale,
THREE.OperatorNode.MUL
);
var uvScale = new THREE.OperatorNode(
new THREE.UVNode(),
scale,
THREE.OperatorNode.MUL
);
var uvFrame = new THREE.OperatorNode(
uvScale,
uvFrameOffset,
THREE.OperatorNode.ADD
);
return uvFrame;
}
// sprites
var spriteWidth = 20,
spriteHeight = 20;
scene.add( sprite1 = new THREE.Mesh( plane, new THREE.SpriteNodeMaterial() ) );
sprite1.scale.x = spriteWidth;
sprite1.scale.y = spriteHeight;
sprite1.material.color = new THREE.TextureNode( walkingManTexture );
sprite1.material.color.coord = createHorizontalSpriteSheetNode( 8, 10 );
sprite1.material.build();
scene.add( sprite2 = new THREE.Mesh( plane, new THREE.SpriteNodeMaterial() ) );
sprite2.position.x = 30;
sprite2.scale.x = spriteWidth;
sprite2.scale.y = spriteHeight;
sprite2.material.color = new THREE.TextureNode( walkingManTexture );
sprite2.material.color.coord = createHorizontalSpriteSheetNode( 8, 30 );
sprite2.material.color = new THREE.Math1Node( sprite2.material.color, THREE.Math1Node.INVERT );
sprite2.material.build();
var sineWaveFunction = new THREE.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 THREE.Mesh( plane, new THREE.SpriteNodeMaterial() ) );
sprite3.position.x = - 30;
sprite3.scale.x = spriteWidth;
sprite3.scale.y = spriteHeight;
sprite3.material.fog = true;
sprite3.material.color = new THREE.TextureNode( walkingManTexture );
sprite3.material.color.coord = new THREE.FunctionCallNode( sineWaveFunction, {
"uv": createHorizontalSpriteSheetNode( 8, 0 ),
"phase": new THREE.TimerNode()
} );
sprite3.material.build();
//
// Events
//
window.addEventListener( 'resize', onWindowResize, false );
onWindowResize();
animate();
}
function onWindowResize() {
var width = window.innerWidth, height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function animate() {
var delta = clock.getDelta();
// update material animation and/or gpu calcs (pre-renderer)
sprite1.material.updateFrame( delta );
sprite2.material.updateFrame( delta );
sprite3.material.updateFrame( delta );
// rotate sprite
sprite3.rotation.z -= Math.PI * .005;
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册