返回
ThreeJS renderBufferDirect 源码解析
前端
2024-01-24 02:06:33
ThreeJS renderBufferDirect 源码解析
ThreeJS renderBufferDirect 源码位于 ThreeJS 库的 /src/renderers/webgl/WebGLRenderer.js 文件中。该函数用于直接渲染一个缓冲区。
renderBufferDirect: function ( camera, scene, geometry, material, object ) {
var uniforms, program;
// Set shader uniforms
program = setProgram( camera, scene, material, object );
// If the program is not set, don't render anything
if ( program === null ) {
return;
}
// TODO: Move this to WebGLRenderer
var updateBuffers = false;
var wireframeBit = material.wireframe ? 1 : 0;
var fogMaterial = material.fog ? 1 : 0;
var geometryProgram = geometry.program;
var materialProgram = material.program;
var index = geometryProgram.id;
var dataStart = geometryProgram.seq;
var indexCount = geometryProgram.indexed ? geometry.index.count : geometry.attributes.position.count;
//
if ( geometryProgram.needBuffers || geometryProgram.program !== materialProgram ) {
geometryProgram.needBuffers = false;
updateBuffers = true;
}
if ( materialProgram !== geometryProgram.program ) {
setProgram( camera, scene, material, object );
}
//
if ( object.morphTargetInfluences !== undefined ) {
var activeInfluences = [];
var morphTargetInfluences = object.morphTargetInfluences;
for ( var i = 0, il = morphTargetInfluences.length; i < il; i ++ ) {
activeInfluences.push( [ morphTargetInfluences[ i ], i ] );
}
activeInfluences.sort( updateMorphs );
if ( activeInfluences.length > 8 ) {
activeInfluences.length = 8;
}
for ( var i = 0, il = activeInfluences.length; i < il; i ++ ) {
morphTargetInfluences[ activeInfluences[ i ][ 1 ] ] = activeInfluences[ i ][ 0 ];
}
}
//
if ( updateBuffers ) {
setupVertexAttributes( geometry, material, program );
if ( geometry.type === BufferGeometry ) {
bindBuffer( gl.ARRAY_BUFFER, geometry.attributes.position.buffer );
} else if ( geometry.type === InstancedBufferGeometry ) {
bindBuffer( gl.ARRAY_BUFFER, geometry.attributes.position.data.buffer );
bindBuffer( gl.ARRAY_BUFFER, geometry.attributes.instanceMatrix.data.buffer );
}
}
//
if ( object.disableLocalTransform ) {
setUniformsLightsDirty( program, true );
} else {
setUniformsMatricesDirty( program, object, camera );
}
// Set the uniforms to use
uniforms = material.uniforms;
if ( uniforms.opacity !== undefined ) {
gl.uniform1f( uniforms.opacity, material.opacity );
}
if ( uniforms.diffuse !== undefined ) {
gl.uniform3fv( uniforms.diffuse, material.color.toArray() );
}
if ( uniforms.emissive !== undefined ) {
gl.uniform3fv( uniforms.emissive, material.emissive.toArray() );
}
if ( uniforms.specular !== undefined ) {
gl.uniform3fv( uniforms.specular, material.specular.toArray() );
}
if ( uniforms.shininess !== undefined ) {
gl.uniform1f( uniforms.shininess, material.shininess );
}
//
if ( uniforms.map !== undefined ) {
gl.uniform1i( uniforms.map, 0 );
setTexture2D( program, uniforms.map, texture, 0 );
}
if ( uniforms.alphaMap !== undefined ) {
gl.uniform1i( uniforms.alphaMap, 1 );
setTexture2D( program, uniforms.alphaMap, texture, 1 );
}
if ( uniforms.lightMap !== undefined ) {
gl.uniform1i( uniforms.lightMap, 2 );
setTexture2D( program, uniforms.lightMap, texture, 2 );
}
if ( uniforms.shadowMap !== undefined ) {
var shadowMap = material.shadowMap;
gl.uniform1i( uniforms.shadowMap, 3 );
gl.uniformMatrix4fv( uniforms.shadowMapSize, false, shadowMap.size );
gl.uniformMatrix4fv( uniforms.shadowMapMatrix, false, shadowMap.matrix );
}
//
if ( uniforms.bumpMap !== undefined ) {
gl.uniform1i( uniforms.bumpMap, 4 );
setTexture2D( program, uniforms.bumpMap, texture, 4 );
}
if ( uniforms.normalMap !== undefined ) {
gl.uniform1i( uniforms.normalMap, 5 );
setTexture2D( program, uniforms.normalMap, texture, 5 );
}
if ( uniforms.specularMap !== undefined ) {
gl.uniform1i( uniforms.specularMap, 6 );
setTexture2D( program, uniforms.specularMap, texture, 6 );
}
//
if ( uniforms.envMap !== undefined ) {
gl.uniform1i( uniforms.envMap, 7 );
if ( material.envMap.mapping === THREE.CubeReflectionMapping ) {
gl.uniform1i( uniforms.envMapMode, 3 );
setTextureCube( program, uniforms.envMap, material.envMap, 7 );
} else if ( material.envMap.mapping === THREE.CubeRefractionMapping ) {
gl.uniform1i( uniforms.envMapMode, 2 );
setTextureCube( program, uniforms.envMap, material.envMap, 7 );
} else if ( material.envMap.mapping === THREE.SphericalReflectionMapping ) {
gl.uniform1i( uniforms.envMapMode, 1 );
setTextureCube( program, uniforms.envMap, material.envMap, 7 );
} else if ( material.envMap.mapping === THREE.EquirectangularReflectionMapping ) {
gl.uniform1i( uniforms.envMapMode, 0 );
setTexture2D( program, uniforms.envMap, texture, 7 );
}
}
//
if ( uniforms.reflectivity !== undefined ) {
gl.uniform1f( uniforms.reflectivity, material.reflectivity );
}
if ( uniforms.refractionRatio !== undefined ) {
gl.uniform1f( uniforms.refractionRatio, material.refractionRatio );
}
if ( uniforms.wireframe !== undefined ) {
gl.uniform1i( uniforms.wireframe, wireframeBit );
}
if ( uniforms.fog !== undefined ) {
gl.uniform1i( uniforms.fog, fogMaterial );
}
//
if ( program.isInstancedMesh !== true ) {
gl.drawArrays( material.wireframe ? gl.LINES : gl.TRIANGLES, dataStart, indexCount );
} else {
var instanceStart = geometry.indexStart;
var instanceCount = geometry.indexCount;
if ( geometry.type === InstancedBufferGeometry ) {
instanceCount = Math.min( indexCount, geometry.attributes.instanceMatrix.count );
}
gl.drawArraysInstanced( material.wireframe ? gl.LINES : gl.TRIANGLES, 0, instanceCount, instanceStart, instanceCount );
}
}
ThreeJS renderBufferDirect 源码分析
-
设置着色器统一变量
首先,通过调用
setProgram()
函数设置着色器统一变量。这个函数将设置用于当前渲染的着色器程序,并将统一变量传递给着色器程序。 -
设置几何体属性
如果几何体需要更新缓冲区,则调用
setupVertexAttributes()
函数设置几何体属性。这个函数将绑定几何体的顶点属性缓冲区到相应的着色器属性。 -
设置灯光属性
如果对象的局部变换被禁用,则调用 `setUniforms