提交 548c3315 编写于 作者: A alteredq

Added crude lines support to WebGLRenderer.

As expected, performance of one-to-one conversion from CanvasRenderer was horrible, so I had to change a bit how lines are handled.

Line object now has "type" property:

    - default type is "THREE.LineContinuous" which should behave as before: geometry represents one continuous line (v0 ... vn)

    - new option is "THREE.LinePieces" which tells renderer that geometry represents collection of individual line segments (v0,v1) ... (vn-1, vn)

(one Line object corresponds to one VBO)

(same limitations as with meshes - once VBO is baked, no changes are possible except object transforms - scale / rotation / position)
上级 1bf91db7
此差异已折叠。
此差异已折叠。
此差异已折叠。
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js - lines - spheres - webgl</title>
<meta charset="utf-8">
<style type="text/css">
body {
background-color: #000;
margin: 0px;
overflow: hidden;
}
a {
color:#0078ff;
}
#info {
position: absolute;
top: 10px; width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
z-index:100;
}
#oldie {
font-family:monospace;
font-size:13px;
text-align:center;
background:rgb(50,0,0);
color:#fff;
padding:1em;
width:475px;
margin:5em auto 0;
display:none;
}
a {
color: #ff0080;
text-decoration: none;
}
a:hover {
color: #0080ff;
}
</style>
</head>
<body>
<div id="info">
<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - lines WebGL demo
</div>
<center>
<div id="oldie">
Sorry, your browser doesn't support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a>.<br/>
<br/>
Please try in
<a href="http://www.chromium.org/getting-involved/dev-channel">Chrome 9+</a> /
<a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Firefox 4+</a> /
<a href="http://nightly.webkit.org/">Safari OSX 10.6+</a>
</div>
</center>
<script type="text/javascript" src="../build/Three.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript">
if ( !is_browser_compatible() ) {
document.getElementById( "oldie" ).style.display = "block";
}
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight,
r = 450,
mouseX = 0, mouseY = 0,
windowHalfX = window.innerWidth / 2,
windowHalfY = window.innerHeight / 2,
camera, scene, renderer,
stats;
init();
setInterval( loop, 1000 / 60 );
function init() {
var container;
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.Camera( 80, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 3000 );
camera.position.z = 1000;
scene = new THREE.Scene();
var i, line, vector1, vector2, material, p,
parameters = [ [ 0.25, 0xff7700, 1, 2 ], [ 0.5, 0xff9900, 1, 1 ], [ 0.75, 0xffaa00, 0.75, 1 ], [ 1, 0xffaa00, 0.5, 1 ], [ 1.25, 0x000833, 0.8, 1 ],
[ 3.0, 0xaaaaaa, 0.75, 2 ], [ 3.5, 0xffffff, 0.5, 1 ], [ 4.5, 0xffffff, 0.25, 1 ], [ 5.5, 0xffffff, 0.125, 1 ] ],
geometry = new THREE.Geometry();
for ( i = 0; i < 1500; ++i ) {
vector1 = new THREE.Vector3( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
vector1.normalize();
vector1.multiplyScalar( r );
vector2 = vector1.clone();
vector2.multiplyScalar( Math.random() * 0.09 + 1 );
geometry.vertices.push( new THREE.Vertex( vector1 ) );
geometry.vertices.push( new THREE.Vertex( vector2 ) );
}
for( i = 0; i < parameters.length; ++i ) {
p = parameters[ i ];
material = new THREE.LineBasicMaterial( { color: p[ 1 ], opacity: p[ 2 ], linewidth: p[ 3 ] } );
line = new THREE.Line( geometry, material, THREE.LinePieces );
line.scale.x = line.scale.y = line.scale.z = p[ 0 ];
line.originalScale = p[ 0 ];
line.rotation.y = Math.random() * Math.PI;
line.updateMatrix();
scene.addObject( line );
}
renderer = new THREE.WebGLRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container.appendChild(renderer.domElement);
/*
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 loop() {
//camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY + 200 - camera.position.y ) * .05;
camera.updateMatrix();
renderer.render( scene, camera );
var time = new Date().getTime() * 0.0001;
for( var i = 0; i<scene.objects.length; i++ ) {
scene.objects[i].rotation.y = time * ( i < 4 ? i+1 : - (i+1) );
if ( i < 5 ) scene.objects[i].scale.x = scene.objects[i].scale.y = scene.objects[i].scale.z = scene.objects[i].originalScale * (i/5+1) * (1 + 0.5 * Math.sin( 7*time ) );
}
//stats.update();
}
function is_browser_compatible() {
// WebGL support
try { var test = new Float32Array(1); } catch(e) { return false; }
return true;
}
</script>
</body>
</html>
......@@ -2,14 +2,19 @@
* @author mr.doob / http://mrdoob.com/
*/
THREE.Line = function ( geometry, materials ) {
THREE.Line = function ( geometry, materials, type ) {
THREE.Object3D.call( this );
this.geometry = geometry;
this.materials = materials instanceof Array ? materials : [ materials ];
this.type = type !== undefined ? type : THREE.LineContinuous;
};
THREE.LineContinuous = 0;
THREE.LinePieces = 1;
THREE.Line.prototype = new THREE.Object3D();
THREE.Line.prototype.constructor = THREE.Line;
......@@ -116,6 +116,51 @@ THREE.WebGLRenderer = function ( parameters ) {
};
this.createLineBuffers = function( object ) {
var v, vl, vertex,
vertexArray = [], lineArray = [],
vertices = object.geometry.vertices;
for ( v = 0, vl = vertices.length; v < vl; v++ ) {
vertex = vertices[ v ].position;
vertexArray.push( vertex.x, vertex.y, vertex.z );
if ( object.type == THREE.LineContinuous ) {
if ( v < ( vl - 1 ) ) {
lineArray.push( v, v + 1 );
}
} else {
lineArray.push( v );
}
}
if ( !vertexArray.length ) {
return;
}
object.__webGLVertexBuffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webGLVertexBuffer );
_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW );
object.__webGLLineBuffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, object.__webGLLineBuffer );
_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW );
object.__webGLLineCount = lineArray.length;
};
this.createBuffers = function ( object, g ) {
var f, fl, fi, face, vertexNormals, faceNormal, normal, uv, v1, v2, v3, v4, t1, t2, t3, t4, m, ml, i,
......@@ -361,6 +406,30 @@ THREE.WebGLRenderer = function ( parameters ) {
}
};
function refreshUniformsLine( material, fog ) {
material.uniforms.color.value.setRGB( material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity );
material.uniforms.opacity.value = material.opacity;
if ( fog ) {
material.uniforms.fogColor.value.setHex( fog.color.hex );
if ( fog instanceof THREE.Fog ) {
material.uniforms.fogNear.value = fog.near;
material.uniforms.fogFar.value = fog.far;
} else if ( fog instanceof THREE.FogExp2 ) {
material.uniforms.fogDensity.value = fog.density;
}
}
};
function refreshUniformsPhong( material ) {
......@@ -386,7 +455,7 @@ THREE.WebGLRenderer = function ( parameters ) {
this.renderBuffer = function ( camera, lights, fog, material, geometryChunk ) {
var program, u, identifiers, attributes, parameters, vector_lights, maxLightCount;
var program, u, identifiers, attributes, parameters, vector_lights, maxLightCount, linewidth;
if ( !material.program ) {
......@@ -419,6 +488,12 @@ THREE.WebGLRenderer = function ( parameters ) {
refreshUniformsCommon( material, fog );
} else if ( material instanceof THREE.LineBasicMaterial ) {
setMaterialShaders( material, THREE.ShaderLib[ 'basic' ] );
refreshUniformsLine( material, fog );
}
// heuristics to create shader parameters according to lights in the scene
......@@ -469,6 +544,11 @@ THREE.WebGLRenderer = function ( parameters ) {
}
if ( material instanceof THREE.LineBasicMaterial ) {
refreshUniformsLine( material, fog );
}
if ( material instanceof THREE.MeshPhongMaterial ) {
refreshUniformsPhong( material );
......@@ -524,20 +604,23 @@ THREE.WebGLRenderer = function ( parameters ) {
}
// render triangles
// render lines
if ( ! material.wireframe ) {
if ( material.wireframe || material instanceof THREE.LineBasicMaterial ) {
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLFaceBuffer );
_gl.drawElements( _gl.TRIANGLES, geometryChunk.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );
linewidth = material.wireframe_linewidth !== undefined ? material.wireframe_linewidth :
material.linewidth !== undefined ? material.linewidth : 1;
_gl.lineWidth( linewidth );
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLLineBuffer );
_gl.drawElements( _gl.LINES, geometryChunk.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );
// render lines
// render triangles
} else {
_gl.lineWidth( material.wireframe_linewidth );
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLLineBuffer );
_gl.drawElements( _gl.LINES, geometryChunk.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLFaceBuffer );
_gl.drawElements( _gl.TRIANGLES, geometryChunk.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );
}
......@@ -581,6 +664,20 @@ THREE.WebGLRenderer = function ( parameters ) {
}
};
this.renderPassLines = function( camera, lights, fog, object ) {
var m, ml, material;
for ( m = 0, ml = object.materials.length; m < ml; m++ ) {
material = object.materials[ m ];
this.setBlending( material.blending );
this.renderBuffer( camera, lights, fog, material, object );
}
};
this.render = function( scene, camera ) {
......@@ -601,6 +698,23 @@ THREE.WebGLRenderer = function ( parameters ) {
_viewMatrixArray.set( camera.matrix.flatten() );
_projectionMatrixArray.set( camera.projectionMatrix.flatten() );
// lines
for ( o = 0, ol = scene.__webGLLines.length; o < ol; o++ ) {
webGLObject = scene.__webGLLines[ o ];
object = webGLObject.object;
if ( object.visible ) {
this.setupMatrices( object, camera );
this.renderPassLines( camera, lights, fog, object );
}
}
// opaque pass
for ( o = 0, ol = scene.__webGLObjects.length; o < ol; o++ ) {
......@@ -662,21 +776,28 @@ THREE.WebGLRenderer = function ( parameters ) {
scene.__webGLObjectsMap = {};
}
if ( !scene.__webGLLines ) {
scene.__webGLLines = [];
scene.__webGLLinesMap = {};
}
for ( o = 0, ol = scene.objects.length; o < ol; o++ ) {
object = scene.objects[ o ];
if ( scene.__webGLObjectsMap[ object.id ] == undefined ) {
scene.__webGLObjectsMap[ object.id ] = {};
}
if ( object instanceof THREE.Mesh ) {
if ( scene.__webGLObjectsMap[ object.id ] == undefined ) {
objmap = scene.__webGLObjectsMap[ object.id ];
scene.__webGLObjectsMap[ object.id ] = {};
if ( object instanceof THREE.Mesh ) {
}
objmap = scene.__webGLObjectsMap[ object.id ];
// create separate VBOs per geometry chunk
for ( g in object.geometry.geometryChunks ) {
......@@ -704,9 +825,34 @@ THREE.WebGLRenderer = function ( parameters ) {
}
}/* else if ( object instanceof THREE.Line ) {
} else if ( object instanceof THREE.Line ) {
if ( scene.__webGLLinesMap[ object.id ] == undefined ) {
scene.__webGLLinesMap[ object.id ] = {};
}
lmap = scene.__webGLLinesMap[ object.id ];
if( ! object.__webGLVertexBuffer ) {
this.createLineBuffers( object );
}
g = 0;
if ( lmap[ g ] == undefined ) {
globject = { object: object };
scene.__webGLLines.push( globject );
lmap[ g ] = 1;
}
} else if ( object instanceof THREE.Particle ) {
}/* else if ( object instanceof THREE.Particle ) {
}*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册