浅谈Three.js源码-render之SpritePlugin.js
来源:互联网 发布:钢结构节点分析软件 编辑:程序博客网 时间:2024/06/05 06:05
import { Texture } from '../../../textures/Texture';import { Vector3 } from '../../../math/Vector3';import { Quaternion } from '../../../math/Quaternion';/**当场景中需要添加不被遮挡的热点信息时,就需要使用到精灵类了。 * @author mikael emtinger / http://gomo.se/ * @author alteredq / http://alteredqualia.com/ */function SpritePlugin( renderer, sprites ) {//threejs中精灵的管理类 var gl = renderer.context;//WebGL上下文 var state = renderer.state;//当前WebGL的状态管理对象 var vertexBuffer, elementBuffer;//精灵对象需要的顶点缓冲对象和索引缓冲区 var program, attributes, uniforms;//shader的程序编号、attribute和uniform值 var texture;//精灵所需要的纹理 // decompose matrixWorld var spritePosition = new Vector3();//精灵的位置 var spriteRotation = new Quaternion();//精灵旋转的四元数 var spriteScale = new Vector3();//精灵的缩放倍数 function init() {//初始化精灵的方法 var vertices = new Float32Array( [//构建精灵所需要的顶点坐标信息 - 0.5, - 0.5, 0, 0, 0.5, - 0.5, 1, 0, 0.5, 0.5, 1, 1, - 0.5, 0.5, 0, 1 ] ); var faces = new Uint16Array( [//索引信息 0, 1, 2, 0, 2, 3 ] ); vertexBuffer = gl.createBuffer();//创建顶点缓冲区 elementBuffer = gl.createBuffer();//创建索引缓冲区 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );//绑定顶点缓冲区 gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );//初始化顶点缓冲区 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );//绑定索引缓冲区 gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );//初始化索引缓冲区 program = createProgram();//创建着色器程序 attributes = { position: gl.getAttribLocation ( program, 'position' ), //顶点坐标 uv: gl.getAttribLocation ( program, 'uv' ) //纹理坐标 }; uniforms = { uvOffset: gl.getUniformLocation( program, 'uvOffset' ), //纹理的偏移量 uvScale: gl.getUniformLocation( program, 'uvScale' ), //纹理的缩放值 rotation: gl.getUniformLocation( program, 'rotation' ), //旋转四元数 scale: gl.getUniformLocation( program, 'scale' ), color: gl.getUniformLocation( program, 'color' ), map: gl.getUniformLocation( program, 'map' ), //精灵上的贴图 opacity: gl.getUniformLocation( program, 'opacity' ), //精灵的透明度 modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ), //模-视矩阵 projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ), //投影矩阵 fogType: gl.getUniformLocation( program, 'fogType' ), //雾的类型 fogDensity: gl.getUniformLocation( program, 'fogDensity' ), //雾的密度 fogNear: gl.getUniformLocation( program, 'fogNear' ), //雾的近平面 fogFar: gl.getUniformLocation( program, 'fogFar' ), //雾的远平面 fogColor: gl.getUniformLocation( program, 'fogColor' ), //雾的颜色 alphaTest: gl.getUniformLocation( program, 'alphaTest' ) //透明度检测 }; var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );//创建canvas对象 canvas.width = 8; //设置canvas的长和宽 canvas.height = 8; var context = canvas.getContext( '2d' ); //获取canvas的上下文 context.fillStyle = 'white'; //设置白色背景 context.fillRect( 0, 0, 8, 8 ); //使用白色进行填充 texture = new Texture( canvas ); //将canvas作为纹理 texture.needsUpdate = true; //更新纹理对象 } this.render = function ( scene, camera ) { //精灵的绘制方法 if ( sprites.length === 0 ) return; // setup gl if ( program === undefined ) { //如果没有指定着色器程序编号 init(); //对着色器程序进行初始化 } gl.useProgram( program ); //指定使用的着色器程序 state.initAttributes(); //重置webGL的状态 state.enableAttribute( attributes.position ); //开启顶点坐标数组 state.enableAttribute( attributes.uv ); //开启纹理坐标数组 state.disableUnusedAttributes(); //禁用所有没使用到的属性 state.disable( gl.CULL_FACE ); //关闭背面剪裁 state.enable( gl.BLEND ); //开启混合 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); //绑定顶点坐标缓冲 gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 ); //指定定点坐标缓冲区数据的位置和格式 gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); //指定纹理坐标缓冲区数据的位置和格式 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); //绑定索引缓冲区 gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );//将投影矩阵传入渲染管线 state.activeTexture( gl.TEXTURE0 ); //激活对应纹理????????? gl.uniform1i( uniforms.map, 0 ); //将纹理图传入渲染管线中 var oldFogType = 0; var sceneFogType = 0; var fog = scene.fog; if ( fog ) {//两种雾的实现方法 gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b ); if ( fog.isFog ) { gl.uniform1f( uniforms.fogNear, fog.near ); gl.uniform1f( uniforms.fogFar, fog.far ); gl.uniform1i( uniforms.fogType, 1 ); oldFogType = 1; sceneFogType = 1; } else if ( fog.isFogExp2 ) { gl.uniform1f( uniforms.fogDensity, fog.density ); gl.uniform1i( uniforms.fogType, 2 ); oldFogType = 2; sceneFogType = 2; } } else { gl.uniform1i( uniforms.fogType, 0 ); oldFogType = 0; sceneFogType = 0; } // update positions and sort for ( var i = 0, l = sprites.length; i < l; i ++ ) { var sprite = sprites[ i ]; sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );//更新精灵图的模-视矩阵 sprite.z = - sprite.modelViewMatrix.elements[ 14 ];//获取精灵在摄像机视图下的Z值 (其实也就是深度值) } sprites.sort( painterSortStable );//根据精灵的深度值进行排序,确定渲染顺序(肯定是需要先绘制远处的精灵,再绘制近处的,否则遮挡顺序就不对咯) // render all sprites var scale = []; for ( var i = 0, l = sprites.length; i < l; i ++ ) { var sprite = sprites[ i ];//获取精灵对象 var material = sprite.material;//获取精灵的材质 if ( material.visible === false ) continue;//如果该精灵不可见 直接跳出 sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );//??????????????????????搜索一下再写 gl.uniform1f( uniforms.alphaTest, material.alphaTest ); gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );//根据各种属性 生成精灵的世界坐标矩阵 /* 传入各种着色器中用到的变量 * */ scale[ 0 ] = spriteScale.x; scale[ 1 ] = spriteScale.y; var fogType = 0; if ( scene.fog && material.fog ) { fogType = sceneFogType; } if ( oldFogType !== fogType ) { gl.uniform1i( uniforms.fogType, fogType ); oldFogType = fogType; } if ( material.map !== null ) { gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y ); gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y ); } else { gl.uniform2f( uniforms.uvOffset, 0, 0 ); gl.uniform2f( uniforms.uvScale, 1, 1 ); } gl.uniform1f( uniforms.opacity, material.opacity ); gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b ); gl.uniform1f( uniforms.rotation, material.rotation ); gl.uniform2fv( uniforms.scale, scale ); state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); state.buffers.depth.setTest( material.depthTest );//开启深度测试 state.buffers.depth.setMask( material.depthWrite );//开启深度写入 if ( material.map ) { renderer.setTexture2D( material.map, 0 ); } else { renderer.setTexture2D( texture, 0 ); } gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );//进行绘制 sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); } // restore gl state.enable( gl.CULL_FACE ); renderer.resetGLState(); }; function createProgram() {//创建绘制精灵所用的着色器 var program = gl.createProgram(); var vertexShader = gl.createShader( gl.VERTEX_SHADER ); var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); //*顶点着色器内容*/ gl.shaderSource( vertexShader, [ 'precision ' + renderer.getPrecision() + ' float;', '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform float rotation;', 'uniform vec2 scale;', 'uniform vec2 uvOffset;', 'uniform vec2 uvScale;', 'attribute vec2 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'void main() {', 'vUV = uvOffset + uv * uvScale;', 'vec2 alignedPosition = position * scale;', 'vec2 rotatedPosition;', 'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', 'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', 'vec4 finalPosition;', 'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', 'finalPosition.xy += rotatedPosition;', 'finalPosition = projectionMatrix * finalPosition;', 'gl_Position = finalPosition;', '}' ].join( '\n' ) ); /*片元着色器内容*/ gl.shaderSource( fragmentShader, [ 'precision ' + renderer.getPrecision() + ' float;', '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform vec3 color;', 'uniform sampler2D map;', 'uniform float opacity;', 'uniform int fogType;', 'uniform vec3 fogColor;', 'uniform float fogDensity;', 'uniform float fogNear;', 'uniform float fogFar;', 'uniform float alphaTest;', 'varying vec2 vUV;', 'void main() {', 'vec4 texture = texture2D( map, vUV );', 'if ( texture.a < alphaTest ) discard;',//如果当前片元中的透明度小于alphaTest直接舍弃, 'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', 'if ( fogType > 0 ) {',/*下面是两种雾的着色器实现*/ 'float depth = gl_FragCoord.z / gl_FragCoord.w;', 'float fogFactor = 0.0;', 'if ( fogType == 1 ) {', 'fogFactor = smoothstep( fogNear, fogFar, depth );', '} else {', 'const float LOG2 = 1.442695;', 'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );', 'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', '}', 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );', '}', '}' ].join( '\n' ) ); gl.compileShader( vertexShader ); gl.compileShader( fragmentShader ); gl.attachShader( program, vertexShader ); gl.attachShader( program, fragmentShader ); gl.linkProgram( program ); return program; } function painterSortStable( a, b ) { if ( a.renderOrder !== b.renderOrder ) { return a.renderOrder - b.renderOrder; } else if ( a.z !== b.z ) { return b.z - a.z; } else { return b.id - a.id; } }}export { SpritePlugin };
阅读全文
0 0
- 浅谈Three.js源码-render之SpritePlugin.js
- 浅谈Three.js源码-render之WebGLAttributes.js
- 浅谈Three.js源码-render之WebGLBackground.js
- 浅谈Three.js源码-render之WebGLExtensions.js
- 浅谈Three.js源码-render之WebGLLights.js
- 浅谈Three.js源码-render之WebGLShader.js
- 浅谈Three.js源码-render之WebGLState.js(重要)
- 浅谈Three.js源码-render之WebGLCapabilities.js
- 浅谈Three.js源码-render之WebGLGeometries.js
- 浅谈three.js
- vue.js之render
- THREE.JS 源码注释
- three.js源码注释
- Webgl之three.js
- 前端之js-three
- 10、vue.js 之render
- Three.js源码阅读笔记
- js render
- ubuntu16.04 出现域名解析暂时失败 解决方法
- Harmonic Number(调和级数+欧拉常数)
- 低复杂度Bayer图像色彩重建算法
- Java泛型
- 2017最新上海市居住证申领流程
- 浅谈Three.js源码-render之SpritePlugin.js
- LCD 多层菜单
- JAVA常用集合类详解
- 第三次面试
- CF414E,splay维护括号序列,码农题
- vs 2013的一些设置
- 利用Cordova对H5页面进行APP开发打包
- 进程/线程池/进程ID/进程间的通讯pipe/Queue/Manager/进程同步
- 深机笔记