混合技术
一、混合基本技术
混合技术就是将两个片元调和,主要通过各种测试将准备进入帧缓冲(源片元)与帧缓冲中原有片元(目标片元)按照设定的比例加权计算出最终片元的颜色值 。
两种常用 组合 :
源因子为SRC_ALPHA,目标因子为ONE_MINUS_SRC _ALPHA,若源片元是透明的,则根据透明度透过后面的内容,若源片元不透明,则仅能看到源片元。
源因子为SRC_COLOR,目标因子为ONE_MINUS_SRC_COLOR,此组合可以实现滤光镜效果,也就是平时透过有色眼镜或玻璃窗观察事物的感觉。
关键代码
//启用混合模式并绘制滤光镜
frunction drawFrame(){....//此处省略绘制场景中物体的代码gl.enable(gl.BLEND) //开启混合gl.blendFunc(gl.SRC_COLOR,gl.ONE_MINUS_SRC_COLOR) //设置混合因子.....gl.disable(gl.BLEND)}
二、雾的原理与优势
有很多数学原型可以实现雾效果,以下介绍两个模型
线性模型:
f=max(min((end-dist)/(end-start),1.0),0.0)
f为雾化因子,取值范围为0.0-1.0,值 为0表示雾浓,值 为1表示雾淡
dist 为当前要绘制的片元离摄像机的距离
end表示一个特定的距离值,片元距摄像机的距离超过end时,雾化因子为0
start表示一个特定的距离值 , 片元距摄像机的距离小于start时,雾化因子为1
非线性模型:
f=1.0-smoothstep(sttart,end,dist)
一般情况下采用此公式进行计算可以取得比线性公式更好的效果。
三 、雾的简单实现
关键代码
顶点着色器
#version 300 es //声明使用WebGL2.0着色器uniform mat4 uMVPMatrix; //总变换矩阵uniform mat4 uMMatrix; //变换矩阵uniform vec3 uLightLocation; //光源位置uniform vec3 uCamera; //摄像机位置in vec3 aPosition; //顶点位置in vec3 aNormal; //顶点法向量out vec4 finalLight; //传递给片元着色器的最终光照强度out float vFogFactor; //传递给片元着色器的雾化因子...//此处省略了计算光照的pointLight方法,读者可自行查看随书源代码float computeFogFactor(){ //计算雾化因子的方法float tmpFactor; //定义雾化因子float fogDistance = length(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);//顶点到摄像机的距离const float end = 450.0; //雾结束位置const float start = 350.0; //雾开始位置tmpFactor = max(min((end- fogDistance)/(end-start),1.0),0.0);//用雾公式计算雾化因子return tmpFactor; //返回雾化因子}void main(){gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制的顶点位置finalLight = pointLight(normalize(aNormal), uLightLocation,vec4(0.4,0.4,0.4,1.0), vec4(0.7,0.7,0.7,1.0), vec4(0.3,0.3,0.3,1.0));//计算光照强度vFogFactor = computeFogFactor(); //计算雾化因子}
片元着色器
#version 300 es //声明使用WebGL2.0着色器precision mediump float; //给出默认的浮点精度in vec4 finalLight; //接收顶点着色器传过来的最终光照强度in float vFogFactor; //从顶点着色器传递过来的雾化因子out vec4 fragColor; //输出片元颜色void main(){vec4 objectColor=vec4(0.95,0.95,0.95,1.0); //物体颜色vec4 fogColor = vec4(0.97,0.76,0.03,1.0); //雾的颜色if(vFogFactor ! = 0.0){ //如果雾化因子为0,不必计算光照objectColor = objectColor*finalLight; //计算光照之后的物体颜色//物体颜色和雾颜色进行插值计算最终颜色fragColor = objectColor*vFogFactor + fogColor*(1.0-vFogFactor);}else{//如果雾化因子为0,不必计算光照,不必加权,直接使用雾颜色作为片元颜色fragColor=fogColor;}}
实现非线性计算模型只需修改computeFogFactor
float computeFogFactor(){float tmpFactor; //定义雾化因子float fogDistance = length(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);//顶点到摄像机的距离const float end = 490.0; //雾结束位置const float start = 350.0; //雾开始位置tmpFactor = 1.0-smoothstep(start, end, fogDistance); //计算雾化因子return tmpFactor; //返回雾化因子}