opengl es 2.0 obj导入、光照、混合、雾化

opengl es 2.0 obj导入、光照、混合、雾化基本操作

法线
法线是垂直于物体表面的单位长度的向量
在三维空间中垂直于指定平面或垂直于给点曲面上某一点切面的向量,法线向量只表示方向,不表示大小(即与长度无关)
对于立体表面而言,法线是有方向的:一般来说,由立体的内部指向外部的是法线正方向,反过来的是法线负方向

法线贴图
在高模的情况下计算每个像素的法线,将计算所得的像素法线保存在一个贴图中,在低模时,使用该法线贴图来体现物体的效果
在3D建模中,对应于模型表面的存储法线信息的贴图,是凸凹贴图技术的一种应用。使物件显得厚重而真实,我们引入法线贴图
法线贴图最大的优点是我们可以通过使用高分辨率模型的法线贴图大幅度地提高低模的显示效果。

平面法向量
平面上两个不平行,不共线的向量叉乘得到(平面法向量进行归一化)

顶点法向量
以这个点为顶点的全部平面的法向量之和的均值 (即各平面法线的平均值,顶点法向量进行归一化)

OpenGL ES 将确定每个顶点与光源的夹角。它利用这一夹角并根据物体和光源材质的环境色、漫反射色与镜面反射色等属性计算顶点的颜色

obj导入:
Obj 文件的格式:
符号 内容
“#” 注释
“v” 顶点坐标,其后面的3个数值分别表示一个顶点的x,y,z 坐标。
“vt” 顶点纹理坐标,其后面的3个数值分别表示纹理坐标的S,T,W
“vn” 法向量,其后面的3个数值 分别表示一个顶点的法向量在x,y,z的分量
“g” 表示一组,后面的字符串为组的名称。
所谓组是指由顶点组成的一些面的几何形状。
只包含“g”的行表示一组的结束,与“g”开头的行对应
“f” 组中一个面,三个数值依次表示顶点坐标的数据索引
//每组顶点包含3个数值,用 “/” 分割,依次表示顶点坐标的数据索引,顶点纹理坐标的数据索引,顶点法向量的数据索引.

采用面法向量计算法: 平面法线量
也就是说该点所在平面的法向量(叉积计算),即是该点的发现量
采用点法向量计算法: 取顶点发现量
一般曲面采取该方法计算,会得到更加平滑的法向量计算光照, 每个顶点的法向量 = 临近3个面的法向量的平均值

光效
则是由导出模型的顶点法线来设置的。通过灯光和法线的夹角来确定光线的相对明暗,最终由光源和材质(物体的材料)共同决定的。
即从该点到光源的单位向量与表面法线单位向量做点积,得到的结果就是光线在表面上的强度。

光源: Emitted
1):环境光:
环境光是一种低强度的光,由光线经过周围环境表面多次反射后形成的,
利用环境光可以描述一块区域的亮度,通常在场景中,环境光的颜色是一个常量.
2):太阳光:
即定向光源,特点是从无穷远出发射光线,光线是平行的,光线强度不会随着距离衰减.
3):点光源:
在有限空间内某个点上发出的光线,光线强度会随着距离衰减.衰减系数一般是距离的二次多项式倒数.
4):聚光灯:
特点是有主照射方向,强度随着距离衰减,并且光线延着中心向外衰减
环境光:ambient
环境光是一种低强度的光,由光线经过周围环境表面多次反射后形成,最终无法分辨其方向的光
漫反射:diffuse
向各个方向反射的光线强度都相等
镜面反射:specular
会形成强烈的光反射,反射的路线与入射方向和表面法线形成的反射方向保持一致

材质概念
物体的材质属性通过反射不同方向的环境光,漫反射光,镜面光的RGB颜色来表示的。分为四种:
泛射材质
漫反射材质
镜面反射材质
发射材质

两种方法实现光效:
1、opengl es函数调用实现
材质:
物体表面材料(Material)的反光属性(颜色和材质)
使用函数:
public void glMaterialf(int face,int pname,float param)
public void glMaterialfv(int face,int pname,float[] params,int offset)
public void glMaterialfv(int face,int pname,FloatBuffer params)
face : 表示物体的前、后面,有GL_FRONT(正面),GL_BACK(反面),OpenGL ES中只能使用GL_FRONT_AND_BACK,表示修改物体的前面和后面的材质光线属性。
pname:材质属性类型(这些参数用在光照方程)
GL_AMBIENT
表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度
GL_DIFFUSE
表示光线照射到该材质上,经过漫反射后形成的光线强度
GL_SPECULAR
表示光线照射到该材质上,经过镜面反射后形成的光线强度
GL_SHININESS
取值范围是0到128。该值越小,表示材质越粗糙,
GL_EMISSION
该属性由四个值组成,表示一种颜色。OpenGL认为材质本身就微微的向外发射光线,光线比较微弱,不会影响到其它物体的颜色
GL_COLOR_INDEXES
颜色索引
param: 材质属性类型对应的值(float数组或者buffer类型)
offset:偏移量
其中GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR, GL_EMISSION为颜色RGBA值,GL_SHININESS值可以从0到128,值越大,光的散射越小

光照
glLightModleXX 光照模型:
public void glLightModelf(int pname,float param)
public void glLightModelfv(int pname,float[] params,int offset)
public void glLightModelfv(int pname,FloatBuffer params)
pname: 参数类型
GL_LIGHT_MODEL_AMBIENT、GL_LIGHT_MODEL_TWO_SIDE
params:参数的值

光源的方法:
public void glLightfv(int light, int pname, FloatBuffer params)
public void glLightfv(int light, int pname, float[] params, int offset)
light: 光源的序号,OpenGL至少会支持8个光源,GL_LIGHT0到GL_LIGHT7
pname: 光源属性名称
GL_SPOT_EXPONEN
表示聚光的程度,为零时表示光照范围内向各方向发射的光线强度相同,为正数时表示光照向中央集中,
正对发射方向的位置受到更多光照,其它位置受到较少光照。数值越大,聚光效果就越明显
GL_SPOT_CUTOFF
表示一个角度,它是光源发射光线所覆盖角度的一半,其取值范围在0到90之间,也可以取180这个特殊值。
取值为180时表示光源发射光线覆盖360度,即不使用聚光灯,向全周围发射
GL_CONSTANT_ATTENUATION
表示光线按常量衰减
GL_LINEAR_ATTENUATION
表示光线按距离线性衰减
GL_QUADRATIC_ATTENUATION
表示光线按距离以二次函数衰减
GL_AMBIENT
表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度
GL_DIFFUSE
表示光线照射到该材质上,经过漫反射后形成的光线强度
GL_SPECULAR
表示光线照射到该材质上,经过镜面反射后形成的光线强度
GL_SPOT_DIRECTION
表示一个向量,即光源发射的方向。默认方向是(0.0,0.0,-1.0)
GL_POSITION
表示光源所在的位置,由四个值(X, Y, Z, W)表示,
W为0表示平行光源,表示该光源位于无限远处,类似太阳,
W不为0表示位置性光源,(X/W, Y/W, Z/W)表示了光源的位置,可以设置各种衰减因子
params:光源属性的值(float数组或是buffer类型)
offset:偏移量
glEnable(GL10.GL_LIGHTING); //打开光源总开关

最终顶点的颜色由这些参数(光源,材质光学属性,光照模型)综合决定(光照方程计算出)。

顶点法向量
设置法向量来确定图元的明暗程度,有两个方法可以为平面设置法线:
public void glNormal3f(float nx,float ny,float nz);//为后续所有平面设置同样的方向,直到重新设置新的法线为止
public void glNormalPointer(int type,int stride, Buffer pointer);//为某个顶点设置法线

2、着色器语言实现
顶点的颜色同样由光源、摄像机位置、散射光、镜面光强度、变换矩阵、法线量等参数计算得到

着色器是描述了物件在灯光下的行为,而纹理则指该物件在shader的不同输入下的行为
着色器脚本:完成雾化的纹理,光照效果

vertex_light.sh(顶点着色器)
uniform mat4 uMVPMatrix; //总变换矩阵
uniform mat4 uMMatrix; //变换矩阵
uniform vec3 uLightLocation; //光源位置
uniform vec3 uCamera; //摄像机位置
attribute vec3 aPosition; //顶点位置
attribute vec3 aNormal; //顶点法向量
varying vec4 ambient;
varying vec4 diffuse;
varying vec4 specular;

//定位光光照计算的方法
void pointLight( //定位光光照计算的方法
in vec3 normal, //法向量, 光照效果需要与法线量进行设置
inout vec4 ambient, //环境光最终强度, out表示函数输出参数
inout vec4 diffuse, //散射光最终强度
inout vec4 specular, //镜面光最终强度
in vec3 lightLocation, //光源位置, in表示函数输入参数
in vec4 lightAmbient, //环境光强度
in vec4 lightDiffuse, //散射光强度
in vec4 lightSpecular //镜面光强度
){
ambient=lightAmbient; //直接由程序赋值得出环境光的最终强度,
vec3 normalTarget=aPosition+normal; //计算变换后的法向量
vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
newNormal=normalize(newNormal); //对法向量规格化
vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz); //计算从表面点到摄像机的向量
vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz); //计算从表面点到光源位置的向量vp
vp=normalize(vp);//格式化vp
vec3 halfVector=normalize(vp+eye); //求视线与光线的半向量
float shininess=50.0; //粗糙度,越小越光滑, 粗糙度范围0~128,值越大,光的散射越小
float nDotViewPosition=max(0.0,dot(newNormal,vp)); //求法向量与vp的点积与0的最大值
diffuse=lightDiffuse*nDotViewPosition; //计算散射光的最终强度

float nDotViewHalfVector=dot(newNormal,halfVector); //法线与半向量的点积
float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); //镜面反射光强度因子
specular=lightSpecular*powerFactor; //计算镜面光的最终强度
}
void main()
{
gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置, vec4(aPosition,1)齐次坐标
vec4 ambientTemp, diffuseTemp, specularTemp; //存放环境光、散射光、镜面反射光的临时变量
//调用光照计算函数
pointLight(normalize(aNormal),ambientTemp, diffuseTemp, specularTemp, 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));
ambient=ambientTemp;
diffuse=diffuseTemp;
specular=specularTemp;
}

frag_light.sh(片元着色器)
precision mediump float; //定义float精度
varying vec4 ambient;
varying vec4 diffuse;
varying vec4 specular;
void main()
{
vec4 finalColor = vec4(1.0,1.0,1.0,0.0);//物体颜色

//根据顶点着色器计算得出的环境光、散射光、镜面反射光计算得到片元颜色值   
gl_FragColor = finalColor*ambient+finalColor*specular+finalColor*diffuse; 

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值