varying变量
//创建着色器源码
const VERTEX_SHADER_SOURCE = `
//varying变量在使用时需要在顶点着色器和片元着色器中一起声明
varying vec4 vColor;
attribute vec4 aPosition;
void main(){
vColor = aPosition;
gl_Position = aPosition;
}
` //顶点着色器
const FRAGMENT_SHADER_SOURCE = `
//需要声明精度
precision lowp float;
//varying变量的作用是从顶点着色器向片元着色器传递数据
varying vec4 vColor;
void main(){
gl_FragColor = vColor;
}
`//片元着色器
执行过程
webgl渲染流程介绍
图元装配:将独立的顶点坐标装配成几何图形,图形的类别由gl.drawArrays()的第一个参数确定
光栅化:将装配好的图形转换为片元
剔除:对于不透明的物体,背面对于观察者来说是不可见的,在渲染过程中就会将不可见的部分剔除,不参与绘制,节省渲染开销
裁剪:在可视范围外的物体是看不到的,图形生成后有的部分位于可视范围外,这一部分会被裁剪掉,不参与绘制
给图形添加背景图
着色器
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
//接收纹理坐标
attribute vec4 aTex;
//传递纹理坐标(vec2类型)
varying vec2 vTex;
void main(){
gl_Position = aPosition;
vTex = vec2(aTex.x,aTex.y);
}
` //顶点着色器
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
varying vec2 vTex;
//声明一些变量接收 sampler2D(2d纹理) samplerCube(立方体纹理)
uniform sampler2D uSampler;
void main(){
// 纹理坐标(手动指定)
gl_FragColor = texture2D(uSampler, vTex);
}
`//片元着色器
修改点的信息
const aPosition = gl.getAttribLocation(program,'aPosition')
const aTex = gl.getAttribLocation(program,'aTex')
const uSampler = gl.getUniformLocation(program,'uSampler')
//创建一组顶点数据
//Float32Array是类型化数组
const points = new Float32Array([
//手动指定纹理坐标(4个顶点)
-0.5,0.5,0.0,1.0,
-0.5,-0.5,0.0,0.0,
0.5,0.5,1.0,1.0,
0.5,-0.5,1.0,0.0
])
const buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)
const BYTES = points.BYTES_PER_ELEMENT
gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES*4,0);
gl.enableVertexAttribArray(aPosition)
gl.vertexAttribPointer(aTex,1,gl.FLOAT,false,BYTES*4,BYTES*2);
gl.enableVertexAttribArray(aTex)
script中
//创建img对象
const img = new Image()
//添加onload函数,保证使用时图片已经加载
img.onload = function(){
//创建纹理对象,用于存储图像数据 gl.deleteTexture() 删除纹理对象
const texture = gl.createTexture()
//反转图片y轴
//pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
//开启纹理单元
gl.activeTexture(gl.TEXTURE0)
//webGL通过纹理单元管理纹理对象,每个纹理单元管理一张纹理图像
//绑定纹理对象
//bindTexture(type,texture)type有两种:gl.TEXTURE_2D二维纹理,gl.TEXTURE_CUBE_MAP立方体纹理
gl.bindTexture(gl.TEXTURE_2D,texture);
//texParameteri(type,pname,param)
//pname分为四种:gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小,gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充)
//param :对于gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小 有:gl.NEAREST使用最近像素颜色值,gl.LINEAR使用四周的加权平均值
//param :对于gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充) 有:gl.REPEAT平铺重复,gl.MIRRORED_REPEAT镜像对称,gl.CLAMP_TO_EDGE 边缘延伸
//处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
//处理横向纵向平铺
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE)
//配置纹理对象
//texImage2D(type,level,internalformat,format,dataType,image)level为0即可 image图片对象
//internalformat图像的内部格式,如png图片内部格式为rgba,jpg图片内部格式为rgb:gl.RGB,gl.RGBA,gl.ALPHA,gl.LUMINANCE 使用物体表面的红绿蓝,分量的加权平均值来计算,gl.LUMINANCE_ALPHA
//format纹理的内部格式,必须和internalformat相同
//dataType纹理数据的数据类型 gl.UNISIGNED_BYTE无符号整形,每个颜色分类占一字节,gl.UNSIGNED_SHORT_5_6_5 rgb分量分别占据565比特,gl.UNSIGNED_SHORT_4_4_4_4 rgba分量分别占据4 4 4 4比特,gl.UNSIGNED_SHORT_5_5_5_1 rgba分量分别占据5 5 5 1比特
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
// 当前开启的纹理单元的编号
// i 代表int f代表float
gl.uniform1i(uSampler,0)
gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
}
img.src = './assets/img2.png'
其中还遇到了访问本地资源跨域的问题,解决方案是下载了liveserver插件,使用http请求
但是最后的效果还是不尽人意 实际效果图:
原图:
未找到原因,未能解决
多重纹理(将多个图片填充到同一个图形上)
多重纹理需要多个变量接收数据
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
varying vec2 vTex;
//声明一些变量接收 sampler2D(2d纹理) samplerCube(立方体纹理)
uniform sampler2D uSampler;
uniform sampler2D uSampler1;
void main(){
// 纹理坐标(手动指定)
vec4 c1 = texture2D(uSampler, vTex);
vec4 c2 = texture2D(uSampler1, vTex);
gl_FragColor = c1*c2;
}
`//片元着色器
创建promise对象,获取图像函数执行完成后进行操作
function getImage(){
return new Promise(resolve =>{
//创建img对象
const img = new Image()
//添加onload函数,保证使用时图片已经加载
img.onload = function(){
//创建纹理对象,用于存储图像数据 gl.deleteTexture() 删除纹理对象
const texture = gl.createTexture()
//反转图片y轴
//pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
//开启纹理单元
gl.activeTexture(gl.TEXTURE0)
//webGL通过纹理单元管理纹理对象,每个纹理单元管理一张纹理图像
//绑定纹理对象
//bindTexture(type,texture)type有两种:gl.TEXTURE_2D二维纹理,gl.TEXTURE_CUBE_MAP立方体纹理
gl.bindTexture(gl.TEXTURE_2D,texture);
//texParameteri(type,pname,param)
//pname分为四种:gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小,gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充)
//param :对于gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小 有:gl.NEAREST使用最近像素颜色值,gl.LINEAR使用四周的加权平均值
//param :对于gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充) 有:gl.REPEAT平铺重复,gl.MIRRORED_REPEAT镜像对称,gl.CLAMP_TO_EDGE 边缘延伸
//处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
//处理横向纵向平铺
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE)
//配置纹理对象
//texImage2D(type,level,internalformat,format,dataType,image)level为0即可 image图片对象
//internalformat图像的内部格式,如png图片内部格式为rgba,jpg图片内部格式为rgb:gl.RGB,gl.RGBA,gl.ALPHA,gl.LUMINANCE 使用物体表面的红绿蓝,分量的加权平均值来计算,gl.LUMINANCE_ALPHA
//format纹理的内部格式,必须和internalformat相同
//dataType纹理数据的数据类型 gl.UNISIGNED_BYTE无符号整形,每个颜色分类占一字节,gl.UNSIGNED_SHORT_5_6_5 rgb分量分别占据565比特,gl.UNSIGNED_SHORT_4_4_4_4 rgba分量分别占据4 4 4 4比特,gl.UNSIGNED_SHORT_5_5_5_1 rgba分量分别占据5 5 5 1比特
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
// 当前开启的纹理单元的编号
// i 代表int f代表float
gl.uniform1i(uSampler,0)
resolve()
}
img.src = './assets/img1.png'
})
}
function getImage1(){
return new Promise(resolve =>{
//创建img对象
const img = new Image()
//添加onload函数,保证使用时图片已经加载
img.onload = function(){
//创建纹理对象,用于存储图像数据 gl.deleteTexture() 删除纹理对象
const texture = gl.createTexture()
//反转图片y轴
//pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
//开启纹理单元
gl.activeTexture(gl.TEXTURE1)
//webGL通过纹理单元管理纹理对象,每个纹理单元管理一张纹理图像
//绑定纹理对象
//bindTexture(type,texture)type有两种:gl.TEXTURE_2D二维纹理,gl.TEXTURE_CUBE_MAP立方体纹理
gl.bindTexture(gl.TEXTURE_2D,texture);
//texParameteri(type,pname,param)
//pname分为四种:gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小,gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充)
//param :对于gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小 有:gl.NEAREST使用最近像素颜色值,gl.LINEAR使用四周的加权平均值
//param :对于gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充) 有:gl.REPEAT平铺重复,gl.MIRRORED_REPEAT镜像对称,gl.CLAMP_TO_EDGE 边缘延伸
//处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR)
//处理横向纵向平铺
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE)
//配置纹理对象
//texImage2D(type,level,internalformat,format,dataType,image)level为0即可 image图片对象
//internalformat图像的内部格式,如png图片内部格式为rgba,jpg图片内部格式为rgb:gl.RGB,gl.RGBA,gl.ALPHA,gl.LUMINANCE 使用物体表面的红绿蓝,分量的加权平均值来计算,gl.LUMINANCE_ALPHA
//format纹理的内部格式,必须和internalformat相同
//dataType纹理数据的数据类型 gl.UNISIGNED_BYTE无符号整形,每个颜色分类占一字节,gl.UNSIGNED_SHORT_5_6_5 rgb分量分别占据565比特,gl.UNSIGNED_SHORT_4_4_4_4 rgba分量分别占据4 4 4 4比特,gl.UNSIGNED_SHORT_5_5_5_1 rgba分量分别占据5 5 5 1比特
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
// 当前开启的纹理单元的编号
// i 代表int f代表float
gl.uniform1i(uSampler1,1)
resolve()
}
img.src = './assets/img2.png'
})
}
Promise.all([getImage(),getImage1()]).then(()=>{
gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
})
减少重复代码后
function getImage(url,location,index){
return new Promise(resolve =>{
//创建img对象
const img = new Image()
//添加onload函数,保证使用时图片已经加载
img.onload = function(){
//创建纹理对象,用于存储图像数据 gl.deleteTexture() 删除纹理对象
const texture = gl.createTexture()
//反转图片y轴
//pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)
//开启纹理单元
gl.activeTexture(gl[`TEXTURE${index}`])
//webGL通过纹理单元管理纹理对象,每个纹理单元管理一张纹理图像
//绑定纹理对象
//bindTexture(type,texture)type有两种:gl.TEXTURE_2D二维纹理,gl.TEXTURE_CUBE_MAP立方体纹理
gl.bindTexture(gl.TEXTURE_2D,texture);
//texParameteri(type,pname,param)
//pname分为四种:gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小,gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充)
//param :对于gl.TEXTURE_MAG_FILTER放大,gl.TEXTURE_MIN_FILTER缩小 有:gl.NEAREST使用最近像素颜色值,gl.LINEAR使用四周的加权平均值
//param :对于gl.TEXTURE_WRAP_S横向(水平填充),gl.TEXTURE_WRAP_T纵向(垂直填充) 有:gl.REPEAT平铺重复,gl.MIRRORED_REPEAT镜像对称,gl.CLAMP_TO_EDGE 边缘延伸
//处理放大缩小的逻辑
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
//处理横向纵向平铺
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
//配置纹理对象
//texImage2D(type,level,internalformat,format,dataType,image)level为0即可 image图片对象
//internalformat图像的内部格式,如png图片内部格式为rgba,jpg图片内部格式为rgb:gl.RGB,gl.RGBA,gl.ALPHA,gl.LUMINANCE 使用物体表面的红绿蓝,分量的加权平均值来计算,gl.LUMINANCE_ALPHA
//format纹理的内部格式,必须和internalformat相同
//dataType纹理数据的数据类型 gl.UNISIGNED_BYTE无符号整形,每个颜色分类占一字节,gl.UNSIGNED_SHORT_5_6_5 rgb分量分别占据565比特,gl.UNSIGNED_SHORT_4_4_4_4 rgba分量分别占据4 4 4 4比特,gl.UNSIGNED_SHORT_5_5_5_1 rgba分量分别占据5 5 5 1比特
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img)
// 当前开启的纹理单元的编号
// i 代表int f代表float
gl.uniform1i(location,index)
resolve()
}
img.src = url
console.log(img);
})
}
Promise.all([getImage('./assets/img1.png',uSampler,0),getImage('./assets/img2.png',uSampler1,1)]).then(()=>{
gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
})
同上,也不能完整显示图片,未能找到原因