提交 e151ff39 编写于 作者: A alteredq

Added Ribbon object.

It provides a lean way how to render TRIANGLE_STRIP primitives: needs just n+2 vertices for n triangles (one Ribbon = one strip). There are no faces, no indices, everything is rendered in one simple drawArray call.

Vertex colors are supported, normals not yet.
上级 313ce3ed
此差异已折叠。
此差异已折叠。
此差异已折叠。
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js - ribbons - webgl</title>
<meta charset="utf-8">
<style type="text/css">
body {
background-color: #000000;
margin: 0px;
overflow: hidden;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
text-align:center;
}
a {
color:#0078ff;
}
#info {
color:#fff;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
z-index:100;
}
</style>
</head>
<body>
<div id="info">
<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - webgl ribbons example
</div>
<script type="text/javascript" src="../build/ThreeExtrasRibbon.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript">
if ( ! THREE.Detector.webgl ) THREE.Detector.addGetWebGLMessage();
var container, stats;
var camera, scene, renderer, ribbon, geometry, geometry2, materials = [], ribbons = [],
parameters, i, i2, h, color, x, y, z, z2, s, n, n2, nribbons, grid;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var postprocessing = {
enabled : true
};
init();
setInterval( loop, 1000 / 60 );
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.Camera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.z = 1200;
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0x000000, 0.0016 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
renderer.setClearColor( scene.fog.color, 1 );
geometry = new THREE.Geometry();
geometry2 = new THREE.Geometry();
n = 1000;
n2 = 2 * n;
for ( i = -n; i < n; i++ ) {
i2 = i + n;
x = i * 1.175;
y = ( i2 % 2 ) * 5;
if ( i2 % 2 ) {
z = 10 * Math.sin( i2 * 0.3 ) * Math.cos( i2 * 0.1 );
}
vector = new THREE.Vector3( x, y, z );
geometry.vertices.push( new THREE.Vertex( vector ) );
vector = new THREE.Vector3( x, y, z );
geometry2.vertices.push( new THREE.Vertex( vector ) );
h = i2%2 ? 1 : 0.15;
if( i2%4 <= 2 ) h -= 0.15;
color = new THREE.Color( 0xffffff );
color.setHSV( 0.1 , 0, h );
geometry.colors.push( color );
geometry2.colors.push( color );
}
var material_base = new THREE.MeshBasicMaterial( { color:0xffffff, vertex_colors:true } );
renderer.initMaterial( material_base, scene.lights, scene.fog );
xgrid = 34;
ygrid = 15;
nribbons = xgrid * ygrid;
c = 0;
for ( i = 0; i < xgrid; i++ )
for ( j = 0; j < ygrid; j++ ) {
materials[c] = new THREE.MeshBasicMaterial( { color:0xffffff, vertex_colors:true } );
materials[c].program = material_base.program;
materials[c].uniforms = Uniforms.clone( THREE.ShaderLib[ 'basic' ].uniforms );
ribbon = new THREE.Ribbon( i % 2 ? geometry : geometry2, materials[c] );
ribbon.rotation.x = 1.57;
ribbon.rotation.y = 1.57;
ribbon.rotation.z = -3.14;
x = 40 * ( i - xgrid/2 );
y = 40 * ( j - ygrid/2 );
z = 0;
ribbon.position.set( x, y, z );
materials[c].color.setHSV( i/xgrid, 0.3 + 0.7*j/ygrid, 1 );
ribbon.doubleSided = true;
ribbon.autoUpdateMatrix = false;
ribbon.updateMatrix();
ribbons.push( ribbon );
scene.addObject( ribbon );
c++;
}
scene.autoUpdateMatrix = false;
initPostprocessing();
renderer.autoClear = false;
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
function onDocumentTouchStart( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
mouseY = event.touches[ 0 ].pageY - windowHalfY;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
mouseY = event.touches[ 0 ].pageY - windowHalfY;
}
}
function initPostprocessing() {
postprocessing.scene = new THREE.Scene();
postprocessing.camera = new THREE.Camera();
postprocessing.camera.projectionMatrix = THREE.Matrix4.makeOrtho( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, -10000, 10000 );
postprocessing.camera.position.z = 100;
var pars = { min_filter: THREE.LinearFilter, mag_filter: THREE.LinearFilter };
postprocessing.rtTexture1 = new THREE.RenderTarget( window.innerWidth, window.innerHeight, pars );
postprocessing.rtTexture2 = new THREE.RenderTarget( 512, 512, pars );
postprocessing.rtTexture3 = new THREE.RenderTarget( 512, 512, pars );
var screen_shader = ShaderUtils.lib["screen"];
var screen_uniforms = Uniforms.clone( screen_shader.uniforms );
screen_uniforms["tDiffuse"].texture = postprocessing.rtTexture1;
screen_uniforms["opacity"].value = 1.0;
postprocessing.materialScreen = new THREE.MeshShaderMaterial( {
uniforms: screen_uniforms,
vertex_shader: screen_shader.vertex_shader,
fragment_shader: screen_shader.fragment_shader,
blending: THREE.AdditiveBlending
} );
var convolution_shader = ShaderUtils.lib["convolution"];
var convolution_uniforms = Uniforms.clone( convolution_shader.uniforms );
postprocessing.blurx = new THREE.Vector2( 0.001953125, 0.0 ),
postprocessing.blury = new THREE.Vector2( 0.0, 0.001953125 );
convolution_uniforms["tDiffuse"].texture = postprocessing.rtTexture1;
convolution_uniforms["uImageIncrement"].value = postprocessing.blurx;
convolution_uniforms["cKernel"].value = ShaderUtils.buildKernel( 4.0 );
postprocessing.materialConvolution = new THREE.MeshShaderMaterial( {
uniforms: convolution_uniforms,
vertex_shader: "#define KERNEL_SIZE 25.0\n" + convolution_shader.vertex_shader,
fragment_shader: "#define KERNEL_SIZE 25\n" + convolution_shader.fragment_shader
} );
postprocessing.quad = new THREE.Mesh( new Plane( window.innerWidth, window.innerHeight ), postprocessing.materialConvolution );
postprocessing.quad.position.z = -500;
postprocessing.scene.addObject( postprocessing.quad );
}
function loop() {
var time = new Date().getTime() * 0.00005;
camera.position.x += ( mouseX - camera.position.x ) * 0.036;
camera.position.y += ( - (mouseY) - camera.position.y ) * 0.036;
for ( i = -n; i < n; i++ ) {
i2 = i + n;
z = 10 * Math.sin( i2 * 0.1 + time*30 );
z2 = 20 * Math.cos( Math.sin( i2 * 0.1 + time * 20 ) );
geometry.vertices[i2].position.z = z;
geometry2.vertices[i2].position.z = z2;
}
geometry.__dirtyVertices = true;
geometry2.__dirtyVertices = true;
for( i = 0; i < nribbons; i++ ) {
h = ( 360 * ( i/nribbons + time ) % 360 ) / 360;
materials[i].color.setHSV( h, 0.5+0.5*(i%20/20), 1 );
}
//renderer.render( scene, camera );
if ( postprocessing.enabled ) {
renderer.clear();
// Render scene into texture
renderer.render( scene, camera, postprocessing.rtTexture1 );
// Render quad with blured scene into texture (convolution pass 1)
postprocessing.quad.materials = [ postprocessing.materialConvolution ];
postprocessing.materialConvolution.uniforms.tDiffuse.texture = postprocessing.rtTexture1;
postprocessing.materialConvolution.uniforms.uImageIncrement.value = postprocessing.blurx;
renderer.render( postprocessing.scene, postprocessing.camera, postprocessing.rtTexture2 );
// Render quad with blured scene into texture (convolution pass 2)
postprocessing.materialConvolution.uniforms.tDiffuse.texture = postprocessing.rtTexture2;
postprocessing.materialConvolution.uniforms.uImageIncrement.value = postprocessing.blury;
renderer.render( postprocessing.scene, postprocessing.camera, postprocessing.rtTexture3 );
// Render original scene with superimposed blur to texture
postprocessing.quad.materials = [ postprocessing.materialScreen ];
postprocessing.materialScreen.uniforms.tDiffuse.texture = postprocessing.rtTexture3;
postprocessing.materialScreen.uniforms.opacity.value = 1.2;
renderer.render( postprocessing.scene, postprocessing.camera, postprocessing.rtTexture1, false );
// Render to screen
postprocessing.materialScreen.uniforms.tDiffuse.texture = postprocessing.rtTexture1;
renderer.render( postprocessing.scene, postprocessing.camera );
} else {
renderer.clear();
renderer.render( scene, camera );
}
stats.update();
}
</script>
</body>
</html>
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
<script type="text/javascript" src="../src/objects/Mesh.js"></script> <script type="text/javascript" src="../src/objects/Mesh.js"></script>
<script type="text/javascript" src="../src/objects/Bone.js"></script> <script type="text/javascript" src="../src/objects/Bone.js"></script>
<script type="text/javascript" src="../src/objects/SkinnedMesh.js"></script> <script type="text/javascript" src="../src/objects/SkinnedMesh.js"></script>
<script type="text/javascript" src="../src/objects/Ribbon.js"></script>
<script type="text/javascript" src="../src/animation/AnimationHandler.js"></script> <script type="text/javascript" src="../src/animation/AnimationHandler.js"></script>
<script type="text/javascript" src="../src/animation/Animation.js"></script> <script type="text/javascript" src="../src/animation/Animation.js"></script>
<script type="text/javascript" src="../src/cameras/Camera.js"></script> <script type="text/javascript" src="../src/cameras/Camera.js"></script>
......
...@@ -132,7 +132,7 @@ THREE.Object3D.prototype.addChild = function( child ) { ...@@ -132,7 +132,7 @@ THREE.Object3D.prototype.addChild = function( child ) {
if( child.parent !== undefined ) if( child.parent !== undefined )
child.parent.removeChild( child ); child.parent.removeChild( child );
child.parent = this; child.parent = this;
this.children.push( child ); this.children.push( child );
} }
......
...@@ -205,6 +205,13 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -205,6 +205,13 @@ THREE.WebGLRenderer = function ( parameters ) {
}; };
function createRibbonBuffers ( geometry ) {
geometry.__webGLVertexBuffer = _gl.createBuffer();
geometry.__webGLColorBuffer = _gl.createBuffer();
};
function createMeshBuffers ( geometryChunk ) { function createMeshBuffers ( geometryChunk ) {
geometryChunk.__webGLVertexBuffer = _gl.createBuffer(); geometryChunk.__webGLVertexBuffer = _gl.createBuffer();
...@@ -235,6 +242,17 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -235,6 +242,17 @@ THREE.WebGLRenderer = function ( parameters ) {
}; };
function initRibbonBuffers ( geometry ) {
var nvertices = geometry.vertices.length;
geometry.__vertexArray = new Float32Array( nvertices * 3 );
geometry.__colorArray = new Float32Array( nvertices * 3 );
geometry.__webGLVertexCount = nvertices;
};
function initParticleBuffers ( geometry ) { function initParticleBuffers ( geometry ) {
var nvertices = geometry.vertices.length; var nvertices = geometry.vertices.length;
...@@ -1039,6 +1057,60 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -1039,6 +1057,60 @@ THREE.WebGLRenderer = function ( parameters ) {
}; };
function setRibbonBuffers ( geometry, hint ) {
var v, c, vertex, offset,
vertices = geometry.vertices,
colors = geometry.colors,
vl = vertices.length,
cl = colors.length,
vertexArray = geometry.__vertexArray,
colorArray = geometry.__colorArray,
dirtyVertices = geometry.__dirtyVertices,
dirtyColors = geometry.__dirtyColors;
if ( dirtyVertices ) {
for ( v = 0; v < vl; v++ ) {
vertex = vertices[ v ].position;
offset = v * 3;
vertexArray[ offset ] = vertex.x;
vertexArray[ offset + 1 ] = vertex.y;
vertexArray[ offset + 2 ] = vertex.z;
}
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webGLVertexBuffer );
_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
}
if ( dirtyColors ) {
for ( c = 0; c < cl; c++ ) {
color = colors[ c ];
offset = c * 3;
colorArray[ offset ] = color.r;
colorArray[ offset + 1 ] = color.g;
colorArray[ offset + 2 ] = color.b;
}
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webGLColorBuffer );
_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
}
};
function setParticleBuffers ( geometry, hint, object, camera ) { function setParticleBuffers ( geometry, hint, object, camera ) {
var v, c, vertex, offset, var v, c, vertex, offset,
...@@ -1377,8 +1449,8 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -1377,8 +1449,8 @@ THREE.WebGLRenderer = function ( parameters ) {
} else if ( material instanceof THREE.MeshDepthMaterial ) { } else if ( material instanceof THREE.MeshDepthMaterial ) {
m_uniforms.mNear.value = camera.near; m_uniforms.mNear.value = camera.zNear;
m_uniforms.mFar.value = camera.far; m_uniforms.mFar.value = camera.zFar;
m_uniforms.opacity.value = material.opacity; m_uniforms.opacity.value = material.opacity;
} else if ( material instanceof THREE.MeshNormalMaterial ) { } else if ( material instanceof THREE.MeshNormalMaterial ) {
...@@ -1560,6 +1632,12 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -1560,6 +1632,12 @@ THREE.WebGLRenderer = function ( parameters ) {
_gl.drawArrays( _gl.POINTS, 0, geometryChunk.__webGLParticleCount ); _gl.drawArrays( _gl.POINTS, 0, geometryChunk.__webGLParticleCount );
// render ribbon
} else if ( object instanceof THREE.Ribbon ) {
_gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryChunk.__webGLVertexCount );
} }
}; };
...@@ -2066,6 +2144,29 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -2066,6 +2144,29 @@ THREE.WebGLRenderer = function ( parameters ) {
geometry.__dirtyTangents = false; geometry.__dirtyTangents = false;
geometry.__dirtyColors = false; geometry.__dirtyColors = false;
} else if ( object instanceof THREE.Ribbon ) {
if( ! geometry.__webGLVertexBuffer ) {
createRibbonBuffers( geometry );
initRibbonBuffers( geometry );
geometry.__dirtyVertices = true;
geometry.__dirtyColors = true;
}
if( geometry.__dirtyVertices || geometry.__dirtyColors ) {
setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
}
add_buffer( objlist, objmap, 0, geometry, object );
geometry.__dirtyVertices = false;
geometry.__dirtyColors = false;
} else if ( object instanceof THREE.Line ) { } else if ( object instanceof THREE.Line ) {
if( ! geometry.__webGLVertexBuffer ) { if( ! geometry.__webGLVertexBuffer ) {
......
...@@ -34,6 +34,7 @@ COMMON_FILES = [ ...@@ -34,6 +34,7 @@ COMMON_FILES = [
'objects/Mesh.js', 'objects/Mesh.js',
'objects/Bone.js', 'objects/Bone.js',
'objects/SkinnedMesh.js', 'objects/SkinnedMesh.js',
'objects/Ribbon.js',
'animation/AnimationHandler.js', 'animation/AnimationHandler.js',
'animation/Animation.js', 'animation/Animation.js',
'cameras/Camera.js', 'cameras/Camera.js',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册