目录引言激活绑定配置分配传递效果代码着色器设置数据缓存区的设置纹理对象的初始化绘制和动态变化小结一下引言 基于上篇的内容,纹理中最小的单位是纹素,若干纹素组成一个纹理单元,每个纹理单
基于上篇的内容,纹理中最小的单位是纹素,若干纹素组成一个纹理单元,每个纹理单元用一个number值来管理,那么我们来看看它是如何工作的。
在使用纹理单元之前,得需要激活纹理单元
activeTexture()
参数:
这一步,需要告诉WebGL系统纹理对象使用的是何种类型的纹理,在对该对象的操作之前,需要先绑定该对象,这和之前的缓冲区对象的数据写操作类似。
bindTexture(webgl.TEXTURE_2D, texture0)
参数:
该方法开启纹理对象,以及将纹理对象texture0绑定到纹理单元webgl.TEXTURE0上,之后通过操作纹理单元去操作纹理对象。
这儿主要是对纹理对象具体的信息操作了,例如纹理单元类型、尺寸、是否裁剪、纹理的展示方式(放大或缩小)等,下面我们再一一分析。
texParameteri(target, pname, param)
参数:
会发现参数pname、param中的参数常量分类比较多,对应的分类是
和
纹理对象信息配置好后,接着可以将纹理图像分配给纹理对象
webgl.texImage2D(target, level, internalfORMat, format type, image)
参数:
其中的纹理数据类型有:
webgl.UNSIGNED_BYTE: 无符号整型,每个颜色分量占据1字节
webgl.UNSIGNED_SHORT_5_6_5:RGB
webgl.UNSIGNED_SHORT_4_4_4:RGBA
webgl.UNSIGNED_SHORT_5_5_5_1:RGBA
经过上面一系列准备后,我们就可以把最终的纹理单元传递给片元着色器了,这儿就用到了方法 webgl.uniform1i(),上篇这个方法已经说过了,就不再说明了。
主要看看片元着色器中是怎么做的
uniform sampler2D texture;
varying vec2 inUV;
vec4 color1=texture2D(texture, vec2(inUV.x, 1.0 - inUV.y));
gl_FraGColor=color1;
经过对纹理的加载、设置、映射,剩下的就是绘画了。
webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4)
好了,晦涩难懂的概念介绍完了,就把具体的代码贴出来吧!
const VSHADER_SOURCE = `
attribute vec2 a_position;
attribute vec2 outUV;
varying vec2 inUV;
void main(void){
gl_Position=vec4(a_position, 0.0, 1.0);
inUV=outUV;
}
`
const FSHADER_SOURCE = `
precision mediump float;
uniform sampler2D texture;
uniform sampler2D texture1;
varying vec2 inUV;
uniform float anim;
void main(void){
vec4 color1=texture2D(texture, vec2(inUV.x, 1.0 - inUV.y));
vec4 color2=texture2D(texture1, vec2(inUV.x + anim, 1.0 - inUV.y));
gl_FragColor=color1+color2;
}
`
const initBuffer = async () => {
let positions = [
0.8, -0.8,
-0.8, -0.8,
0.8, 0.8,
-0.8, 0.8,
]
let pointPosition = new Float32Array(positions)
let aPsotion = webgl.getAttribLocation(webgl.program, "a_position")
let triangleBuffer = webgl.createBuffer()
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW)
webgl.enableVertexAttribArray(aPsotion)
webgl.vertexAttribPointer(aPsotion, 2, webgl.FLOAT, false, 0, 0)
var texCoords = [
1, 0,
0, 0,
1, 1,
0, 1,
]
const attribOutUV = webgl.getAttribLocation(webgl.program, "outUV")
let texCoordBuffer = webgl.createBuffer()
webgl.bindBuffer(webgl.ARRAY_BUFFER, texCoordBuffer)
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(texCoords), webgl.STATIC_DRAW)
webgl.enableVertexAttribArray(attribOutUV)
webgl.vertexAttribPointer(attribOutUV, 2, webgl.FLOAT, false, 0, 0)
uniformTexture = webgl.getUniformLocation(webgl.program, "texture")
uniformTexture1 = webgl.getUniformLocation(webgl.program, "texture1")
texture0 = await initTexture('/web-gl/landscape.png')
texture1 = await initTexture("/web-gl/fog.png")
}
主要是设置顶点坐标和纹理坐标的数据
const initTexture = (imageSrc: string): Promise<WebGLTexture> => {
return new Promise((resolve, reject) => {
let textureHandle = webgl.createTexture()
const image = new Image()
image.onload = function () {
webgl.bindTexture(webgl.TEXTURE_2D, textureHandle)
webgl.texParameteri(
webgl.TEXTURE_2D,
webgl.TEXTURE_WRAP_S,
webgl.CLAMP_TO_EDGE
)
webgl.texParameteri(
webgl.TEXTURE_2D,
webgl.TEXTURE_WRAP_T,
webgl.CLAMP_TO_EDGE
)
webgl.texParameteri(
webgl.TEXTURE_2D,
webgl.TEXTURE_MIN_FILTER,
webgl.LINEAR
)
webgl.texImage2D(
webgl.TEXTURE_2D,
0,
webgl.RGBA,
webgl.RGBA,
webgl.UNSIGNED_BYTE,
image
)
resolve(textureHandle)
}
image.onerror = reject
image.src = imageSrc
})
}
这儿需要使用异步方法,因为需要在image.onload方法中返回设置信息数据后的纹理对象。 在 webgl 的纹理加载中,由于图片是异步加载的,因此我们需要使用 Promise 来处理加载完毕后的回调函数。
const updateCount = () => {
count = count + 0.001
if (count >= 1.14) {
count = -1.0
}
}
const draw = () => {
webgl.clearColor(0.0, 1.0, 1.0, 1.0)
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT)
webgl.enable(webgl.DEPTH_TEST)
//纹理变动
uniformAnim = webgl.getUniformLocation(webgl.program, "anim");
updateCount()
webgl.uniform1f(uniformAnim, count);
webgl.activeTexture(webgl.TEXTURE0)
webgl.bindTexture(webgl.TEXTURE_2D, texture0)
webgl.uniform1i(uniformTexture, 0)
webgl.activeTexture(webgl.TEXTURE1)
webgl.bindTexture(webgl.TEXTURE_2D, texture1)
webgl.uniform1i(uniformTexture1, 1)
webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4)
requestAnimationFrame(draw)
}
具体的代码就是这些了。
到目前为止,我们已经了解了顶点着色器、片元着色器、顶点缓冲区、矩阵绘制和变换、纹理图像、纹理叠加等,这样我们已经基本上对二维绘图掌握了,一个面我们了解了,之后我们可能就去看看多个面的物体和场景。
那么就让我们一起看看三维世界吧!
以上就是WebGL 多重纹理的详细内容,更多关于WebGL 多重纹理的资料请关注编程网其它相关文章!
--结束END--
本文标题: WebGL 多重纹理的使用介绍
本文链接: https://lsjlt.com/news/210331.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0