前言:
这几天又把纹理的知识看了看,突然发现edge浏览器能实现纹理图片的加载(把我激动坏了,还以为必须要配置个本地服务器来解决跨域呢),后来看了其他人的opengl的笔记,了解到了材质这个功能,发现从纹理到材质的变化比较容易理解,于是我就决定把材质和纹理这两个功能放在一起写。
先上效果:

这个是贴上纹理并且把纹理所返回的rgb作为材质来影响三种光的效果。
两种坐标系统的对应关系:

首先是顶点着色器:
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main(void){
v_TexCoord = a_TexCoord;
}
片元着色器:
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main(void){
...
float spec=0.0;
if(nDotL >0.0){
spec=pow(dot(normal,halfvector),u_shininess);//镜面光强
}
vec3 specular = u_shininessColor * (spec * vec3(texture2D(u_Sampler, v_TexCoord)));
vec3 diffuse = u_LightColor * nDotL * vec3(texture2D(u_Sampler, v_TexCoord));
vec3 ambient = u_AmbientLight * vec3(texture2D(u_Sampler, v_TexCoord));
gl_FragColor = vec4(diffuse + ambient + specular,1.0);
}
顶点着色器用来接受来自缓冲区的纹理坐标,通过varying传递,片元着色器接收内插后的纹理坐标。texture2D()获取纹理像素颜色
u_Sampler即为纹理图像
缓冲区设置纹理坐标(注意要与顶点坐标相对应):
//纹理坐标
var texCoords = new Float32Array([
1.0,1.0,0.0,1.0,0.0,0.0,1.0,0.0,
0.0,1.0,0.0,0.0,1.0,0.0,1.0,1.0,
1.0,0.0,1.0,1.0,0.0,1.0,0.0,0.0,
1.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,
0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0,
0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0,
]);
配置和加载纹理:
function initTextures(gl){
let texture = gl.createTexture();//创建纹理对象
let u_Sampler = gl.getUniformLocation(gl.program,'u_Sampler');//拿到u_Sampler的存储位置
let image = new Image();//new一个对象来放图片
image.onload = function(){
loadTexture(gl,texture,u_Sampler,image)
} // 该步为异步加载图像
image.src = './texture/砖墙.jpg';
return true;
}
为WEBGL配置纹理:
function loadTexture(gl,texture,u_Sampler,image){
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 反转Y轴,因为图片坐标系Y轴向下
// 激活纹理
gl.activeTexture(gl.TEXTURE0);
// 绑定纹理
gl.bindTexture(gl.TEXTURE_2D, texture);
// 设置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// 将纹理图像分配给纹理对象
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
//把0号纹理单元传递给片元着色器
gl.uniform1i(u_Sampler, 0);
}
关于纹理参数的设置内容这里不涉及
接下来是关于材质的内容了。现在回看一下片元着色器中三种光的设置,以纹理做为材质
vec3 specular = u_shininessColor * (spec * vec3(texture2D(u_Sampler, v_TexCoord)));
vec3 diffuse = u_LightColor * nDotL * vec3(texture2D(u_Sampler, v_TexCoord));
vec3 ambient = u_AmbientLight * vec3(texture2D(u_Sampler, v_TexCoord));
单材质:
vec3 specular = u_shininessColor * (spec * material.specular);
vec3 diffuse = u_LightColor * nDotL * material.diffuse;
vec3 ambient = u_AmbientLight * material.ambient;
对比一下你就明白了。这里的材质可以理解为就是用光照来设置物体的颜色。实际是对不同物体表面材质来设置三种光的效果。
翡翠材质效果:
