提交 b84bca3b 编写于 作者: M Mr.doob

WebGLRenderer optimisation: flattening camera matrices just once per render,...

WebGLRenderer optimisation: flattening camera matrices just once per render, it was doing it once per object before.
WebGLRenderer2: Trying to re-create WebGLRenderer from scratch... Creating a program per material instead of just one for everything. Seems to be 3x faster by now...
上级 94d01d8c
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -174,7 +174,7 @@
uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
uniforms[ "uSpecularColor" ].value.setHex( specular );
uniforms[ "uAmbientColor" ].value.setHex( ambient );
uniforms[ "uAmbientLightColor" ].value.setHex( ambient );
uniforms[ "uShininess" ].value = shininess;
......
......@@ -67,6 +67,7 @@
<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLRenderer2.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace3.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
......
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js - webgl</title>
<meta charset="utf-8">
<style type="text/css">
body {
background:#fff;
padding:0;
margin:0;
font-weight: bold;
overflow:hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
z-index:1000;
}
a {
color: #ffffff;
}
#log { position:absolute; top:50px; text-align:left; display:block; z-index:100 }
</style>
</head>
<body>
<pre id="log"></pre>
<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - webgl cube Fresnel shader demo.</div>
<!--
<script type="text/javascript" src="../build/Three.js"></script>
-->
<script type="text/javascript" src="../src/Three.js"></script>
<script type="text/javascript" src="../src/core/Color.js"></script>
<script type="text/javascript" src="../src/core/Vector2.js"></script>
<script type="text/javascript" src="../src/core/Vector3.js"></script>
<script type="text/javascript" src="../src/core/Vector4.js"></script>
<script type="text/javascript" src="../src/core/Ray.js"></script>
<script type="text/javascript" src="../src/core/Rectangle.js"></script>
<script type="text/javascript" src="../src/core/Matrix3.js"></script>
<script type="text/javascript" src="../src/core/Matrix4.js"></script>
<script type="text/javascript" src="../src/core/Vertex.js"></script>
<script type="text/javascript" src="../src/core/Face3.js"></script>
<script type="text/javascript" src="../src/core/Face4.js"></script>
<script type="text/javascript" src="../src/core/UV.js"></script>
<script type="text/javascript" src="../src/core/Geometry.js"></script>
<script type="text/javascript" src="../src/cameras/Camera.js"></script>
<script type="text/javascript" src="../src/lights/Light.js"></script>
<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
<script type="text/javascript" src="../src/lights/PointLight.js"></script>
<script type="text/javascript" src="../src/objects/Object3D.js"></script>
<script type="text/javascript" src="../src/objects/Particle.js"></script>
<script type="text/javascript" src="../src/objects/Line.js"></script>
<script type="text/javascript" src="../src/objects/Mesh.js"></script>
<script type="text/javascript" src="../src/materials/Material.js"></script>
<script type="text/javascript" src="../src/materials/LineBasicMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshBasicMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshLambertMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshDepthMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshNormalMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshCubeMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshShaderMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleBasicMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleDOMMaterial.js"></script>
<script type="text/javascript" src="../src/materials/Texture.js"></script>
<script type="text/javascript" src="../src/materials/mappings/CubeReflectionMapping.js"></script>
<script type="text/javascript" src="../src/materials/mappings/CubeRefractionMapping.js"></script>
<script type="text/javascript" src="../src/materials/mappings/LatitudeReflectionMapping.js"></script>
<script type="text/javascript" src="../src/materials/mappings/LatitudeRefractionMapping.js"></script>
<script type="text/javascript" src="../src/materials/mappings/SphericalReflectionMapping.js"></script>
<script type="text/javascript" src="../src/materials/mappings/SphericalRefractionMapping.js"></script>
<script type="text/javascript" src="../src/materials/mappings/UVMapping.js"></script>
<script type="text/javascript" src="../src/scenes/Scene.js"></script>
<script type="text/javascript" src="../src/renderers/Projector.js"></script>
<script type="text/javascript" src="../src/renderers/DOMRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLRenderer2.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace3.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
<script type="text/javascript" src="../src/extras/ShaderUtils.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript">
var statsEnabled = true;
var container, stats;
var camera, scene, webglRenderer;
var mesh, zmesh, lightMesh, geometry;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
init();
// loop();
setInterval( loop, 1000 / 60 );
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.Camera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.z = 3200;
scene = new THREE.Scene();
var geometry = new Sphere( 100, 32, 16 );
var uniforms = ShaderUtils.lib[ 'basic' ].uniforms;
var vertex_shader = ShaderUtils.lib[ 'basic' ].vertex_shader;
var fragment_shader = ShaderUtils.lib[ 'basic' ].fragment_shader;
/*
var material = new THREE.MeshShaderMaterial( {
uniforms: uniforms,
vertex_shader: vertex_shader,
fragment_shader: fragment_shader
} );
*/
var material = new THREE.MeshBasicMaterial( { color: 0x0000ff, opacity: 0.5 } );
for ( var i = 0; i < 1000; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = Math.random() * 10000 - 5000;
mesh.position.y = Math.random() * 10000 - 5000;
mesh.position.z = Math.random() * 10000 - 5000;
mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 4 + 1;
scene.addObject( mesh );
}
webglRenderer = new THREE.WebGLRenderer2();
webglRenderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( webglRenderer.domElement );
if ( statsEnabled ) {
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
}
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX ) * 10;
mouseY = ( event.clientY - windowHalfY ) * 10;
}
function loop() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
webglRenderer.render( scene, camera );
if ( statsEnabled ) stats.update();
}
function log( text ) {
var e = document.getElementById("log");
e.innerHTML = text + "<br/>" + e.innerHTML;
}
</script>
</body>
</html>
......@@ -260,7 +260,7 @@ var ShaderUtils = {
].join("\n")
},
/*
'hatching' : {
uniforms: {
......@@ -347,8 +347,8 @@ var ShaderUtils = {
].join("\n")
},
'new': {
*/
'basic': {
uniforms: {},
......@@ -366,7 +366,7 @@ var ShaderUtils = {
"void main() {",
"gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);",
"gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);",
"}"
......
......@@ -24,7 +24,7 @@ THREE.MeshShaderMaterial = function ( parameters ) {
this.opacity = 1;
this.shading = THREE.SmoothShading;
this.blending = THREE.NormalBlending;
this.wireframe = false;
this.wireframe_linewidth = 1;
this.wireframe_linecap = 'round';
......
......@@ -24,7 +24,7 @@ THREE.Projector = function() {
var o, ol, v, vl, f, fl, n, nl, objects, object,
objectMatrix, objectRotationMatrix, objectMaterial, objectOverdraw,
vertices, vertex, vertexPositionScreen,
geometry, vertices, vertex, vertexPositionScreen,
faces, face, faceVertexNormals, normal, v1, v2, v3, v4;
_renderList = [];
......@@ -48,9 +48,11 @@ THREE.Projector = function() {
if ( object instanceof THREE.Mesh ) {
geometry = object.geometry;
// vertices
vertices = object.geometry.vertices;
vertices = geometry.vertices;
for ( v = 0, vl = vertices.length; v < vl; v++ ) {
......@@ -74,7 +76,7 @@ THREE.Projector = function() {
// faces
faces = object.geometry.faces;
faces = geometry.faces;
for ( f = 0, fl = faces.length; f < fl; f ++ ) {
......
......@@ -412,7 +412,7 @@ THREE.WebGLRenderer = function ( scene ) {
if ( material instanceof THREE.MeshShaderMaterial ) {
mWireframe = material.wireframe;
mWireframe = material.wireframe; _modelViewMatrixArray.set( _modelViewMatrix.flatten() );
mLineWidth = material.wireframe_linewidth;
mBlending = material.blending;
......@@ -646,6 +646,9 @@ THREE.WebGLRenderer = function ( scene ) {
camera.autoUpdateMatrix && camera.updateMatrix();
_viewMatrixArray.set( camera.matrix.flatten() );
_projectionMatrixArray.set( camera.projectionMatrix.flatten() );
// opaque pass
for ( o = 0, ol = scene.__webGLObjects.length; o < ol; o++ ) {
......@@ -782,10 +785,7 @@ THREE.WebGLRenderer = function ( scene ) {
object.autoUpdateMatrix && object.updateMatrix();
_modelViewMatrix.multiply( camera.matrix, object.matrix );
_viewMatrixArray.set( camera.matrix.flatten() );
_modelViewMatrixArray.set( _modelViewMatrix.flatten() );
_projectionMatrixArray.set( camera.projectionMatrix.flatten() );
_normalMatrix = THREE.Matrix4.makeInvert3x3( _modelViewMatrix ).transpose();
_normalMatrixArray.set( _normalMatrix.m );
......
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.WebGLRenderer2 = function ( scene ) {
var _canvas = document.createElement( 'canvas' ),
_gl, _currentProgram,
_modelViewMatrix = new THREE.Matrix4(),
_viewMatrixArray = new Float32Array( 16 ),
_modelViewMatrixArray = new Float32Array( 16 ),
_projectionMatrixArray = new Float32Array( 16 ),
_normalMatrixArray = new Float32Array( 9 ),
_objectMatrixArray = new Float32Array( 16 );
try {
_gl = _canvas.getContext( 'experimental-webgl', { antialias: true } );
} catch(e) { }
if ( !_gl ) {
alert("WebGL not supported");
throw "cannot create webgl context";
}
_gl.clearColor( 0, 0, 0, 1 );
_gl.clearDepth( 1 );
_gl.enable( _gl.DEPTH_TEST );
_gl.depthFunc( _gl.LEQUAL );
_gl.frontFace( _gl.CCW );
_gl.cullFace( _gl.BACK );
_gl.enable( _gl.CULL_FACE );
_gl.enable( _gl.BLEND );
_gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
_gl.clearColor( 0, 0, 0, 0 );
this.domElement = _canvas;
this.autoClear = true;
this.setSize = function ( width, height ) {
_canvas.width = width;
_canvas.height = height;
_gl.viewport( 0, 0, _canvas.width, _canvas.height );
};
this.clear = function () {
_gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT );
};
this.render = function( scene, camera ) {
var o, ol;
this.autoClear && this.clear();
camera.autoUpdateMatrix && camera.updateMatrix();
_viewMatrixArray.set( camera.matrix.flatten() );
_projectionMatrixArray.set( camera.projectionMatrix.flatten() );
for ( o = 0, ol = scene.objects.length; o < ol; o++ ) {
object = scene.objects[ o ];
if ( object.visible ) {
renderObject( object );
}
}
function renderObject( object ) {
var geometry, material, m, nl,
program, attributes;
object.autoUpdateMatrix && object.updateMatrix();
_objectMatrixArray.set( object.matrix.flatten() );
_modelViewMatrix.multiply( camera.matrix, object.matrix );
_modelViewMatrixArray.set( _modelViewMatrix.flatten() );
if ( object instanceof THREE.Mesh ) {
geometry = object.geometry;
if ( geometry.__webglBuffers == undefined ) {
if ( buildBuffers( geometry ) == false ) return;
}
for ( m = 0, ml = object.material.length; m < ml; m ++ ) {
material = object.material[ m ];
if ( material.__webglProgram == undefined ) {
if ( createProgram( material ) == false ) continue;
}
program = material.__webglProgram;
attributes = program.attributes;
if( program != _currentProgram ) {
_gl.useProgram( program );
_currentProgram = program;
}
if ( material instanceof THREE.MeshBasicMaterial ) {
_gl.uniform4f( program.uniforms.mColor, material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity, material.opacity );
}
_gl.uniform3f( program.uniforms.cameraPosition, camera.position.x, camera.position.y, camera.position.z );
_gl.uniformMatrix4fv( program.uniforms.viewMatrix, false, _viewMatrixArray );
_gl.uniformMatrix4fv( program.uniforms.projectionMatrix, false, _projectionMatrixArray );
_gl.uniformMatrix4fv( program.uniforms.objectMatrix, false, _objectMatrixArray );
_gl.uniformMatrix4fv( program.uniforms.modelViewMatrix, false, _modelViewMatrixArray );
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglBuffers.vertexBuffer );
_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
if ( ! material.wireframe ) {
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometry.__webglBuffers.faceBuffer );
_gl.drawElements( _gl.TRIANGLES, geometry.__webglBuffers.faceCount, _gl.UNSIGNED_SHORT, 0 );
} else {
_gl.lineWidth( material.wireframe_linewidth );
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometry.__webglBuffers.lineBuffer );
_gl.drawElements( _gl.LINES, geometry.__webglBuffers.lineCount, _gl.UNSIGNED_SHORT, 0 );
}
}
}
}
function buildBuffers( geometry ) {
var f, fl, face, v1, v2, v3, verticesIndex = 0,
verticesArray = [], facesArray = [], linesArray = [],
buffers = {};
for ( f = 0, fl = geometry.faces.length; f < fl; f++ ) {
face = geometry.faces[ f ];
if ( face instanceof THREE.Face3 ) {
v1 = geometry.vertices[ face.a ].position;
v2 = geometry.vertices[ face.b ].position;
v3 = geometry.vertices[ face.c ].position;
verticesArray.push( v1.x, v1.y, v1.z );
verticesArray.push( v2.x, v2.y, v2.z );
verticesArray.push( v3.x, v3.y, v3.z );
facesArray.push( verticesIndex, verticesIndex + 1, verticesIndex + 2 );
// TODO: don't add lines that already exist (faces sharing edge)
linesArray.push( verticesIndex, verticesIndex + 1 );
linesArray.push( verticesIndex, verticesIndex + 2 );
linesArray.push( verticesIndex + 1, verticesIndex + 2 );
verticesIndex += 3;
} else if ( face instanceof THREE.Face4 ) {
v1 = geometry.vertices[ face.a ].position;
v2 = geometry.vertices[ face.b ].position;
v3 = geometry.vertices[ face.c ].position;
v4 = geometry.vertices[ face.d ].position;
verticesArray.push( v1.x, v1.y, v1.z );
verticesArray.push( v2.x, v2.y, v2.z );
verticesArray.push( v3.x, v3.y, v3.z );
verticesArray.push( v4.x, v4.y, v4.z );
facesArray.push( verticesIndex, verticesIndex + 1, verticesIndex + 2 );
facesArray.push( verticesIndex, verticesIndex + 2, verticesIndex + 3 );
// TODO: don't add lines that already exist (faces sharing edge)
linesArray.push( verticesIndex, verticesIndex + 1 );
linesArray.push( verticesIndex, verticesIndex + 2 );
linesArray.push( verticesIndex, verticesIndex + 3 );
linesArray.push( verticesIndex + 1, verticesIndex + 2 );
linesArray.push( verticesIndex + 2, verticesIndex + 3 );
verticesIndex += 4;
}
}
if ( !verticesArray.length ) return false;
buffers.vertexBuffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.vertexBuffer );
_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( verticesArray ), _gl.STATIC_DRAW );
buffers.faceBuffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, buffers.faceBuffer );
_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( facesArray ), _gl.STATIC_DRAW );
buffers.lineBuffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, buffers.lineBuffer );
_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( linesArray ), _gl.STATIC_DRAW );
buffers.faceCount = facesArray.length;
buffers.lineCount = linesArray.length;
geometry.__webglBuffers = buffers;
return true;
}
function createProgram( material ) {
var vs = '', fs = '',
identifiers = [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition' ];
if ( material instanceof THREE.MeshBasicMaterial ) {
vs += 'void main() {\n';
vs += 'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n';
vs += '}'
fs += 'uniform vec4 mColor;\n';
fs += 'void main() {\n';
fs += 'gl_FragColor = mColor;\n';
fs += '}';
identifiers.push( 'mColor' );
} else if ( material instanceof THREE.MeshShaderMaterial ) {
vs = material.vertex_shader;
fs = material.fragment_shader;
for( uniform in material.uniforms ) {
identifiers.push( uniform );
}
} else {
return false;
}
material.__webglProgram = compileProgram( vs, fs );
cacheUniformLocations( material.__webglProgram, identifiers );
cacheAttributeLocations( material.__webglProgram, [ "position", "normal", "uv", "tangent" ] );
return true;
}
function compileProgram( vertex_shader, fragment_shader ) {
var program = _gl.createProgram(), shader
prefix_vertex = [
//maxVertexTextures() > 0 ? "#define VERTEX_TEXTURES" : "",
"uniform mat4 objectMatrix;",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
//"uniform mat4 viewMatrix;",
"uniform mat3 normalMatrix;",
"uniform vec3 cameraPosition;",
"attribute vec3 position;",
//"attribute vec3 normal;",
//"attribute vec2 uv;",
""
].join("\n"),
prefix_fragment = [
"#ifdef GL_ES",
"precision highp float;",
"#endif",
//"uniform mat4 viewMatrix;",
""
].join("\n");
// Vertex shader
shader = _gl.createShader( _gl.VERTEX_SHADER );
_gl.shaderSource( shader, prefix_vertex + vertex_shader );
_gl.compileShader( shader );
_gl.attachShader( program, shader );
if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
alert( _gl.getShaderInfoLog( shader ) );
return null;
}
// Fragment Shader
shader = _gl.createShader( _gl.FRAGMENT_SHADER );
_gl.shaderSource( shader, prefix_fragment + fragment_shader );
_gl.compileShader( shader );
_gl.attachShader( program, shader );
if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
alert( _gl.getShaderInfoLog( shader ) );
return null;
}
_gl.linkProgram( program );
if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
alert( "Could not initialise shaders\n VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
}
program.uniforms = {};
program.attributes = {};
return program;
}
function cacheUniformLocations( program, identifiers ) {
var i, l, id;
for( i = 0, l = identifiers.length; i < l; i++ ) {
id = identifiers[ i ];
program.uniforms[ id ] = _gl.getUniformLocation( program, id );
}
}
function cacheAttributeLocations( program, identifiers ) {
var i, l, id;
for( i = 0, l = identifiers.length; i < l; i++ ) {
id = identifiers[ i ];
program.attributes[ id ] = _gl.getAttribLocation( program, id );
if ( program.attributes[ id ] >= 0 ) {
_gl.enableVertexAttribArray( program.attributes[ id ] );
}
}
}
};
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册