提交 ac5276b4 编写于 作者: A alteredq

Added normal + ambient occlusion + displacement mapping demo.

A lot of things going on in this commit:

- added tangents computation for geometries
    - mesh must have UV coordinates
    - to be called explicitly once geometry is loaded like this: geometry.computeTangents()
    - tangents are stored in Vertex objects
    - quads are not solved properly (though workaround hack seems to work at least somehow, as far as each vertex appears at least somewhere)

- extended VBOs in WebGLRenderer to include tangent streams (when available)

- added "normal" shader to ShaderUtils (to be used with MeshShaderMaterial)
   - Blinn-Phong with one directional and one point light (7 varyings gone, just one spare)
   - normal maps are in tangent space
   - displacement maps use simple luminance value (could be changed if better precision is needed)

- displacement mapping uses vertex texture fetch
    - this requires GPU with Shader Model 3.0
    - not currently supported in ANGLE
    - for this, added "supportsVertexTextures" method to WebGLRenderer API, so that application can handle this
上级 1da8ee0d
此差异已折叠。
此差异已折叠。
此差异已折叠。
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js - webgl normal map</title>
<meta charset="utf-8">
<style type="text/css">
body {
background:#000;
color:#fff;
padding:0;
margin:0;
font-weight: bold;
overflow:hidden;
}
a { color: #ffffff; }
#info {
position: absolute;
top: 0px; width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
z-index:1000;
}
#oldie {
font-family:monospace;
font-size:13px;
text-align:center;
background:rgb(200,100,0);
color:#fff;
padding:1em;
width:475px;
margin:5em auto 0;
border:solid 2px #fff;
border-radius:10px;
display:none;
}
#vt { display:none }
#vt, #vt a { color:orange; }
.code { }
#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 (<span id="description">normal + ao + displacement</span>) map demo.
ninja head from <a href="http://developer.amd.com/archive/gpu/MeshMapper/pages/default.aspx" target="_blank">AMD GPU MeshMapper</a>
<div id="vt">displacement mapping needs vertex textures (GPU with Shader Model 3.0)<br/>
on Windows use <span class="code">Chrome --use-gl=desktop</span> or Firefox 4<br/>
please star this <a href="http://code.google.com/p/chromium/issues/detail?id=52497">Chrome issue</a> to get ANGLE support
</div>
</div>
<center>
<div id="oldie">
Sorry, your browser doesn't support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a>
and <a href="http://www.whatwg.org/specs/web-workers/current-work/">Web Workers</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/ThreeExtras.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 statsEnabled = true;
var container, stats, loader;
var camera, scene, webglRenderer;
var mesh, zmesh, lightMesh, geometry;
var mesh1, mesh2;
var directionalLight, pointLight, ambientLight;
var mouseX = 0;
var mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var r = 0.0;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
init();
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.projectionMatrix = THREE.Matrix4.makeOrtho( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, -10000, 10000 );
camera.position.z = 6200;
scene = new THREE.Scene();
// LIGHTS
ambientLight = new THREE.AmbientLight( 0x111111 );
scene.addLight( ambientLight );
pointLight = new THREE.PointLight( 0xffff55 );
pointLight.position.z = 10000;
scene.addLight( pointLight );
directionalLight = new THREE.DirectionalLight( 0xaaaa88 );
directionalLight.position.x = 1;
directionalLight.position.y = 1;
directionalLight.position.z = 0.5;
directionalLight.position.normalize();
scene.addLight( directionalLight );
// light representation
var sphere = new Sphere( 100, 16, 8, 1 );
lightMesh = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color:0xffaa00 } ) );
lightMesh.position = pointLight.position;
lightMesh.scale.x = lightMesh.scale.y = lightMesh.scale.z = 0.05;
scene.addObject(lightMesh);
// common material parameters
var ambient = 0x050505, diffuse = 0x555555, specular = 0xaa6600, shininess = 10, scale = 23;
// normal map shader
var fragment_shader = ShaderUtils.lib[ "normal" ].fragment_shader;
var vertex_shader = ShaderUtils.lib[ "normal" ].vertex_shader;
var uniforms = ShaderUtils.lib[ "normal" ].uniforms;
uniforms[ "tNormal" ].texture = ImageUtils.loadTexture( "textures/normal/ninja/normal.jpg" );
uniforms[ "tAO" ].texture = ImageUtils.loadTexture( "textures/normal/ninja/ao.jpg" );
uniforms[ "tDisplacement" ].texture = ImageUtils.loadTexture( "textures/normal/ninja/displacement.jpg" );
uniforms[ "uDisplacementBias" ].value = -0.428408 * scale;
uniforms[ "uDisplacementScale" ].value = 2.436143 * scale;
uniforms[ "uPointLightPos" ].value = pointLight.position;
uniforms[ "uPointLightColor" ].value = pointLight.color;
uniforms[ "uDirLightPos" ].value = directionalLight.position;
uniforms[ "uDirLightColor" ].value = directionalLight.color;
uniforms[ "uAmbientLightColor" ].value = ambientLight.color;
uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
uniforms[ "uSpecularColor" ].value.setHex( specular );
uniforms[ "uAmbientColor" ].value.setHex( ambient );
uniforms[ "uShininess" ].value = shininess;
var material1 = new THREE.MeshShaderMaterial( { fragment_shader: fragment_shader,
vertex_shader: vertex_shader,
uniforms: uniforms
} );
var material2 = new THREE.MeshPhongMaterial( { color: diffuse, specular: specular, ambient: ambient, shininess: shininess } );
loader = new THREE.Loader( true );
document.body.appendChild( loader.statusDomElement );
loader.loadBinary( "obj/ninja/NinjaLo_bin.js", function( geometry ) { createScene( geometry, scale, material1, material2 ) }, "obj/ninja" );
webglRenderer = new THREE.WebGLRenderer( scene );
webglRenderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( webglRenderer.domElement );
var description = "normal + ao" + ( webglRenderer.supportsVertexTextures() ? " + displacement" : " + <strike>displacement</strike>" );
document.getElementById( "description" ).innerHTML = description;
document.getElementById( "vt" ).style.display = webglRenderer.supportsVertexTextures() ? "none" : "block";
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 createScene( geometry, scale, material1, material2 ) {
geometry.computeTangents();
mesh1 = SceneUtils.addMesh( scene, geometry, scale, -scale * 12, 0, 0, 0,0,0, material1 );
mesh2 = SceneUtils.addMesh( scene, geometry, scale, scale * 12, 0, 0, 0,0,0, material2 );
loader.statusDomElement.style.display = "none";
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX ) * 10;
mouseY = ( event.clientY - windowHalfY ) * 10;
}
function loop() {
var ry = mouseX * 0.0003, rx = mouseY * 0.0003;
if( mesh1 ) {
mesh1.rotation.y = ry;
mesh1.rotation.x = rx;
}
if( mesh2 ) {
mesh2.rotation.y = ry;
mesh2.rotation.x = rx;
}
lightMesh.position.x = 2500 * Math.cos( r );
lightMesh.position.z = 2500 * Math.sin( r );
r += 0.01;
webglRenderer.render( scene, camera );
if ( statsEnabled ) stats.update();
}
function log( text ) {
var e = document.getElementById("log");
e.innerHTML = text + "<br/>" + e.innerHTML;
}
function is_browser_compatible() {
// WebGL support
try { var test = new Float32Array(1); } catch(e) { return false; }
// Web workers
return !!window.Worker;
}
</script>
</body>
</html>
<Files *.js>
SetOutputFilter DEFLATE
</Files>
<Files *.bin>
SetOutputFilter DEFLATE
</Files>
// Converted from: ../../examples/obj/ninja/ninjaHead_Low.obj
// vertices: 4485
// faces: 4810
// materials: 0
//
// Generated with OBJ -> Three.js converter
// http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_threejs_slim.py
var model = {
'materials': [ {
"a_dbg_color" : 0xeeeeee,
"a_dbg_index" : 0,
"a_dbg_name" : "default"
}],
'buffers': 'NinjaLo_bin.bin',
'end': (new Date).getTime()
}
postMessage( model );
DisplacementMap Scale: 2.436143
DisplacementMap Bias : -0.428408
......@@ -12,6 +12,8 @@ THREE.Geometry = function () {
this.geometryChunks = {};
this.hasTangents = false;
};
THREE.Geometry.prototype = {
......@@ -167,6 +169,121 @@ THREE.Geometry.prototype = {
},
computeTangents: function() {
// based on http://www.terathon.com/code/tangent.html
// tangents go to vertices
var f, fl, v, vl, face, uv, vA, vB, vC, uvA, uvB, uvC,
x1, x2, y1, y2, z1, z2,
s1, s2, t1, t2, r, t, n,
tan1 = [], tan2 = [],
sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
n = new THREE.Vector3(), w;
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
tan1[ v ] = new THREE.Vector3();
tan2[ v ] = new THREE.Vector3();
}
function handleTriangle( context, a, b, c ) {
vA = context.vertices[ a ].position;
vB = context.vertices[ b ].position;
vC = context.vertices[ c ].position;
uvA = uv[ 0 ];
uvB = uv[ 1 ];
uvC = uv[ 2 ];
x1 = vB.x - vA.x;
x2 = vC.x - vA.x;
y1 = vB.y - vA.y;
y2 = vC.y - vA.y;
z1 = vB.z - vA.z;
z2 = vC.z - vA.z;
s1 = uvB.u - uvA.u;
s2 = uvC.u - uvA.u;
t1 = uvB.v - uvA.v;
t2 = uvC.v - uvA.v;
r = 1.0 / ( s1 * t2 - s2 * t1 );
sdir.set( ( t2 * x1 - t1 * x2 ) * r,
( t2 * y1 - t1 * y2 ) * r,
( t2 * z1 - t1 * z2 ) * r );
tdir.set( ( s1 * x2 - s2 * x1 ) * r,
( s1 * y2 - s2 * y1 ) * r,
( s1 * z2 - s2 * z1 ) * r );
tan1[ a ].addSelf( sdir );
tan1[ b ].addSelf( sdir );
tan1[ c ].addSelf( sdir );
tan2[ a ].addSelf( tdir );
tan2[ b ].addSelf( tdir );
tan2[ c ].addSelf( tdir );
}
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this.faces[ f ];
uv = this.uvs[ f ];
if ( face instanceof THREE.Face3 ) {
handleTriangle( this, face.a, face.b, face.c );
this.vertices[ face.a ].normal.copy( face.vertexNormals[ 0 ] );
this.vertices[ face.b ].normal.copy( face.vertexNormals[ 1 ] );
this.vertices[ face.c ].normal.copy( face.vertexNormals[ 2 ] );
} else if ( face instanceof THREE.Face4 ) {
handleTriangle( this, face.a, face.b, face.c );
// this messes up everything
// quads need to be handled differently
//handleTriangle( this, face.a, face.c, face.d );
this.vertices[ face.a ].normal.copy( face.vertexNormals[ 0 ] );
this.vertices[ face.b ].normal.copy( face.vertexNormals[ 1 ] );
this.vertices[ face.c ].normal.copy( face.vertexNormals[ 2 ] );
this.vertices[ face.d ].normal.copy( face.vertexNormals[ 3 ] );
}
}
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
n.copy( this.vertices[ v ].normal );
t = tan1[ v ];
// Gram-Schmidt orthogonalize
tmp.copy( t );
tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
// Calculate handedness
tmp2.cross( this.vertices[ v ].normal, t );
test = tmp2.dot( tan2[ v ] );
w = (test < 0.0) ? -1.0 : 1.0;
this.vertices[ v ].tangent.set( tmp.x, tmp.y, tmp.z, w );
}
this.hasTangents = true;
},
computeBoundingBox: function () {
if ( this.vertices.length > 0 ) {
......
......@@ -12,6 +12,8 @@ THREE.Vertex = function ( position, normal ) {
this.normalWorld = new THREE.Vector3();
this.normalScreen = new THREE.Vector3();
this.tangent = new THREE.Vector4();
this.__visible = true;
}
......
......@@ -62,6 +62,201 @@ var ShaderUtils = {
"}"
].join("\n")
},
'normal' : {
uniforms: {
"tNormal": { type: "t", value: 2, texture: null },
"tAO": { type: "t", value: 3, texture: null },
"tDisplacement": { type: "t", value: 4, texture: null },
"uDisplacementBias": { type: "f", value: -0.5 },
"uDisplacementScale":{ type: "f", value: 2.5 },
"uPointLightPos": { type: "v3", value: new THREE.Vector3() },
"uPointLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
"uDirLightPos": { type: "v3", value: new THREE.Vector3() },
"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
"uAmbientLightColor":{ type: "c", value: new THREE.Color( 0x050505 ) },
"uDiffuseColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
"uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
"uAmbientColor": { type: "c", value: new THREE.Color( 0x050505 ) },
"uShininess": { type: "f", value: 30 }
},
fragment_shader: [
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"uniform vec3 uPointLightPos;",
"uniform vec3 uPointLightColor;",
"uniform vec3 uAmbientColor;",
"uniform vec3 uDiffuseColor;",
"uniform vec3 uSpecularColor;",
"uniform float uShininess;",
"uniform sampler2D tNormal;",
"uniform sampler2D tAO;",
"varying vec3 vTangent;",
"varying vec3 vBinormal;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vLightWeighting;",
"varying vec3 vPointLightVector;",
"varying vec3 vViewPosition;",
"void main() {",
"vec3 normalTex = normalize( texture2D( tNormal, vUv ).xyz * 2.0 - 1.0 );",
"vec3 aoTex = texture2D( tAO, vUv ).xyz;",
"mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
"vec3 finalNormal = tsb * normalTex;",
"vec3 normal = normalize( finalNormal );",
"vec3 viewPosition = normalize( vViewPosition );",
// point light
"vec4 pointDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );",
"vec4 pointSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );",
"vec3 pointVector = normalize( vPointLightVector );",
"vec3 pointHalfVector = normalize( vPointLightVector + vViewPosition );",
"float pointDotNormalHalf = dot( normal, pointHalfVector );",
"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
"float pointSpecularWeight = 0.0;",
"if ( pointDotNormalHalf >= 0.0 )",
"pointSpecularWeight = pow( pointDotNormalHalf, uShininess );",
"pointDiffuse += vec4( uDiffuseColor, 1.0 ) * pointDiffuseWeight;",
"pointSpecular += vec4( uSpecularColor, 1.0 ) * pointSpecularWeight;",
// directional light
"vec4 dirDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );",
"vec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );",
"vec4 lDirection = viewMatrix * vec4( uDirLightPos, 0.0 );",
"vec3 dirVector = normalize( lDirection.xyz );",
"vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );",
"float dirDotNormalHalf = dot( normal, dirHalfVector );",
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
"float dirSpecularWeight = 0.0;",
"if ( dirDotNormalHalf >= 0.0 )",
"dirSpecularWeight = pow( dirDotNormalHalf, uShininess );",
"dirDiffuse += vec4( uDiffuseColor, 1.0 ) * dirDiffuseWeight;",
"dirSpecular += vec4( uSpecularColor, 1.0 ) * dirSpecularWeight;",
// all lights contribution summation
"vec4 totalLight = vec4( uAmbientColor, 1.0 );",
"totalLight += dirDiffuse + dirSpecular;",
"totalLight += pointDiffuse + pointSpecular;",
"gl_FragColor = vec4( totalLight.xyz * vLightWeighting * aoTex, 1.0 );",
"}"
].join("\n"),
vertex_shader: [
"attribute vec4 tangent;",
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"uniform vec3 uPointLightPos;",
"uniform vec3 uPointLightColor;",
"uniform vec3 uAmbientLightColor;",
"#ifdef VERTEX_TEXTURES",
"uniform sampler2D tDisplacement;",
"uniform float uDisplacementScale;",
"uniform float uDisplacementBias;",
"#endif",
"varying vec3 vTangent;",
"varying vec3 vBinormal;",
"varying vec3 vNormal;",
"varying vec2 vUv;",
"varying vec3 vLightWeighting;",
"varying vec3 vPointLightVector;",
"varying vec3 vViewPosition;",
"void main() {",
"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
"vViewPosition = cameraPosition - mPosition.xyz;",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalize( normalMatrix * normal );",
// tangent and binormal vectors
"vTangent = normalize( normalMatrix * tangent.xyz );",
"vBinormal = cross( vNormal, vTangent ) * tangent.w;",
"vBinormal = normalize( vBinormal );",
"vUv = uv;",
// ambient light
"vLightWeighting = uAmbientLightColor;",
// point light
"vec4 lPosition = viewMatrix * vec4( uPointLightPos, 1.0 );",
"vPointLightVector = normalize( lPosition.xyz - mvPosition.xyz );",
"float pointLightWeighting = max( dot( vNormal, vPointLightVector ), 0.0 );",
"vLightWeighting += uPointLightColor * pointLightWeighting;",
// directional light
"vec4 lDirection = viewMatrix * vec4( uDirLightPos, 0.0 );",
"float directionalLightWeighting = max( dot( vNormal, normalize( lDirection.xyz ) ), 0.0 );",
"vLightWeighting += uDirLightColor * directionalLightWeighting;",
// displacement mapping
"#ifdef VERTEX_TEXTURES",
"vec3 dv = texture2D( tDisplacement, uv ).xyz;",
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
"vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;",
"gl_Position = projectionMatrix * displacedPosition;",
"#else",
"gl_Position = projectionMatrix * mvPosition;",
"#endif",
"}"
].join("\n")
}
}
......
......@@ -159,13 +159,14 @@ THREE.WebGLRenderer = function ( scene ) {
this.createBuffers = function ( object, g ) {
var f, fl, fi, face, vertexNormals, normal, uv, v1, v2, v3, v4, m, ml, i,
var f, fl, fi, face, vertexNormals, normal, uv, v1, v2, v3, v4, t1, t2, t3, t4, m, ml, i,
faceArray = [],
lineArray = [],
vertexArray = [],
normalArray = [],
tangentArray = [],
uvArray = [],
vertexIndex = 0,
......@@ -193,8 +194,21 @@ THREE.WebGLRenderer = function ( scene ) {
vertexArray.push( v2.x, v2.y, v2.z );
vertexArray.push( v3.x, v3.y, v3.z );
if ( object.geometry.hasTangents ) {
t1 = object.geometry.vertices[ face.a ].tangent;
t2 = object.geometry.vertices[ face.b ].tangent;
t3 = object.geometry.vertices[ face.c ].tangent;
tangentArray.push( t1.x, t1.y, t1.z, t1.w );
tangentArray.push( t2.x, t2.y, t2.z, t2.w );
tangentArray.push( t3.x, t3.y, t3.z, t3.w );
}
if ( vertexNormals.length == 3 && needsSmoothNormals ) {
for ( i = 0; i < 3; i ++ ) {
normalArray.push( vertexNormals[ i ].x, vertexNormals[ i ].y, vertexNormals[ i ].z );
......@@ -242,15 +256,29 @@ THREE.WebGLRenderer = function ( scene ) {
vertexArray.push( v2.x, v2.y, v2.z );
vertexArray.push( v3.x, v3.y, v3.z );
vertexArray.push( v4.x, v4.y, v4.z );
if ( object.geometry.hasTangents ) {
t1 = object.geometry.vertices[ face.a ].tangent;
t2 = object.geometry.vertices[ face.b ].tangent;
t3 = object.geometry.vertices[ face.c ].tangent;
t4 = object.geometry.vertices[ face.d ].tangent;
tangentArray.push( t1.x, t1.y, t1.z, t1.w );
tangentArray.push( t2.x, t2.y, t2.z, t2.w );
tangentArray.push( t3.x, t3.y, t3.z, t3.w );
tangentArray.push( t4.x, t4.y, t4.z, t4.w );
}
if ( vertexNormals.length == 4 && needsSmoothNormals ) {
for ( i = 0; i < 4; i ++ ) {
normalArray.push( vertexNormals[ i ].x, vertexNormals[ i ].y, vertexNormals[ i ].z );
}
} else {
for ( i = 0; i < 4; i ++ ) {
......@@ -302,6 +330,14 @@ THREE.WebGLRenderer = function ( scene ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLNormalBuffer );
_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( normalArray ), _gl.STATIC_DRAW );
if ( object.geometry.hasTangents ) {
geometryChunk.__webGLTangentBuffer = _gl.createBuffer();
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLTangentBuffer );
_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( tangentArray ), _gl.STATIC_DRAW );
}
if ( uvArray.length > 0 ) {
geometryChunk.__webGLUVBuffer = _gl.createBuffer();
......@@ -346,7 +382,7 @@ THREE.WebGLRenderer = function ( scene ) {
}
cacheUniformLocations( material.program, identifiers );
cacheAttributeLocations( material.program, [ "position", "normal", "uv" ] );
cacheAttributeLocations( material.program, [ "position", "normal", "uv", "tangent" ] );
}
......@@ -374,7 +410,6 @@ THREE.WebGLRenderer = function ( scene ) {
this.loadCamera( program, camera );
this.loadMatrices( program );
if ( material instanceof THREE.MeshShaderMaterial ) {
mWireframe = material.wireframe;
......@@ -507,6 +542,15 @@ THREE.WebGLRenderer = function ( scene ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLNormalBuffer );
_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
// tangents
if ( attributes.tangent >= 0 ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLTangentBuffer );
_gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
}
// uvs
if ( attributes.uv >= 0 ) {
......@@ -828,6 +872,19 @@ THREE.WebGLRenderer = function ( scene ) {
};
this.supportsVertexTextures = function() {
return maxVertexTextures() > 0;
};
function maxVertexTextures() {
return _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
};
function initGL() {
try {
......@@ -940,7 +997,7 @@ THREE.WebGLRenderer = function ( scene ) {
"} else if ( material == 4 ) { ",
"gl_FragColor = vec4( 0.5*normalize( vNormal ) + vec3(0.5, 0.5, 0.5), mOpacity );",
"gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, mOpacity );",
// Depth
......@@ -1184,6 +1241,8 @@ THREE.WebGLRenderer = function ( scene ) {
].join("\n"),
prefix_vertex = [
maxVertexTextures() > 0 ? "#define VERTEX_TEXTURES" : "",
"uniform mat4 objectMatrix;",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册