首先看一下光照颜色在顶点着色器中的效果:
1、颜色计算放在顶点着色器中
const VSHADER=` uniform vec3 u_LightColor; uniform vec3 u_LightDirction; uniform vec3 u_AmbientLight; uniform vec3 u_Color; varying vec4 v_Color; void main(){ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); //计算变换后的法向量并归一化 vec3 newnormal=normalize(vec3(normalMatrix*normal)); //计算光线方向和法向量的点积 float nDotL=max(dot(u_LightDirction,newnormal),0.0); //计算漫反射光的颜色 vec3 diffuse=u_LightColor*u_Color.rgb*nDotL; //计算环境光产生的反射光的颜色 vec3 ambient=u_AmbientLight*u_Color.rgb; //将以上两者相加作为最终的颜色 v_Color=vec4(diffuse+ambient,1.0); } ` const FSHADER=` precision mediump float; varying vec4 v_Color; void main(){ gl_FragColor=v_Color; } `2、颜色计算放在片元着色器中
const VSHADER=` varying vec3 v_Normal; void main(){ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); //计算变换后的法向量并归一化 v_Normal=normalize(vec3(normalMatrix*normal)); } ` const FSHADER=` precision mediump float; uniform vec3 u_LightColor; uniform vec3 u_LightDirction; uniform vec3 u_AmbientLight; varying vec3 v_Normal; uniform vec3 u_Color; void main(){ //计算光线方向和法向量的点积 float nDotL=max(dot(u_LightDirction,v_Normal),0.0); //计算漫反射光的颜色 vec3 diffuse=u_LightColor*u_Color.rgb*nDotL; //计算环境光产生的反射光的颜色 vec3 ambient=u_AmbientLight*u_Color.rgb; //将以上两者相加作为最终的颜色 gl_FragColor=vec4(diffuse+ambient,1.0); } `从二者的结果来看,把计算放在片元着色器中,效果会更好,颜色界限处会更平滑。
在three.js中使用的代码
let geometry = new THREE.SphereBufferGeometry( 2, 64, 64 ); geometry.computeVertexNormals () let geometryMat = new THREE.ShaderMaterial( { uniforms:{ u_Color:{value:new THREE.Color(0xff0000)}, u_LightColor:{value:this.dirLight.color}, u_LightDirction:{value:this.dirLight.position}, u_AmbientLight:{value:this.ambientLight.color} }, vertexShader:VSHADER, fragmentShader:FSHADER, vertexColors: true } ); let cube = new THREE.Mesh( geometry, geometryMat ); cube.castShadow=true cube.position.set(0,0,2) this.scene.add( cube );源码地址:
https://gitee.com/niuge8905/webglsample
