使用多幅纹理/纹理叠加

  • 1.demo效果
  • 2.实现要点
    • 2.1 顶点着色器中声明varying变量v_TexCoord
    • 2.2 片元着色器中多纹理处理
    • 2.3 外部纹理图像加载
    • 2.4 纹理叠加处理与绘图
  • 3.demo代码

1.demo效果

如上图,这个demo加载了三幅外部纹理图片,分别是背景草原、骏马、卡通小羊,通过纹理叠加让它们呈现在同一个页面上。

2.实现要点

2.1 顶点着色器中声明varying变量v_TexCoord

在顶点着色器中需要声明attribute变量a_TexCoord和varying变量v_TexCoord,a_TexCoord用来存放纹理坐标;v_TexCoord用来向片元着色器传输纹理坐标,需要在main函数中将a_TexCoord赋值给v_TexCoord用来实现纹理坐标的传输

//顶点着色器
var VSHADER_SOURCE = '' +'attribute vec4 a_Position;\n' + //声明attribute变量a_Position,用来存放顶点位置信息'attribute vec2 a_TexCoord;\n' + //声明attribute变量a_TexCoord,用来存放纹理坐标'varying vec2 v_TexCoord;\n' + //声明varying变量v_TexCoord,用来向片元着色器传值纹理坐标'void main(){\n' +'  gl_Position = a_Position;\n' + //变量a_Position赋值给顶点着色器内置变量gl_Position'  v_TexCoord = a_TexCoord;\n' + //将纹理坐标传给片元着色器,'}\n';

2.2 片元着色器中多纹理处理

在片元着色器中也要声明varying变量v_TexCoord,用来接收顶点着色器传送的纹理坐标;还需要声明三个sampler2D类型的uniform变量,用来存放不同纹理图像的纹理单元编号,然后在main函数中使用 GLSL ES 内置函数texture2D() 来抽取每一个纹理图像的纹素颜色,这个函数需要接受两个参数:纹理单元编号和纹理坐标。之后将每一个纹素颜色相乘赋值给内置变量gl_FragColor

//片元着色器
var FSHADER_SOURCE = '' +'precision mediump float;\n' + // 设置精度'uniform sampler2D u_Sampler;\n' + //声明uniform变量u_Sampler,存放第一个纹理单元编号'uniform sampler2D u_Sampler1;\n' + //声明uniform变量u_Sampler1,存放第二个纹理单元编号'uniform sampler2D u_Sampler2;\n' + //声明uniform变量u_Sampler2,存放第三个纹理单元编号'varying vec2 v_TexCoord;\n' + //声明varying变量v_TexCoord,用来接收顶点着色器传送的纹理坐标'void main(){\n' +' vec4 color = texture2D(u_Sampler,v_TexCoord);\n' + //使用texture2D函数抽取纹理单元0纹素颜色' vec4 color1 = texture2D(u_Sampler1,v_TexCoord);\n' + //使用texture2D函数抽取纹理单元1纹素颜色' vec4 color2 = texture2D(u_Sampler2,v_TexCoord);\n' + //使用texture2D函数抽取纹理单元2纹素颜色//纹素颜色相乘,并赋值给内置变量gl_FragColor' gl_FragColor = color * color1 * color2;\n' +'}\n';

2.3 外部纹理图像加载

//获取片元着色器uniform变量u_Sampler、u_Sampler1、u_Sampler2的存储地址
var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler')
var u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1')
var u_Sampler2 = gl.getUniformLocation(gl.program, 'u_Sampler2')var image = new Image()
var image1 = new Image()
var image2 = new Image()image.src = './resources/grassland.png' //设置纹理资源1路径
image1.src = './resources/horse.png' //设置纹理资源2路径
image2.src = './resources/sheep.png' //设置纹理资源3路径//注册图片1加载事件的响应函数
image.onload = function () {//调用加载纹理函数loadTexTure(gl, n, u_Sampler, image, 0)
}//注册图片2加载事件的响应函数
image1.onload = function () {//调用加载纹理函数loadTexTure(gl, n, u_Sampler1, image1, 1)
}
//注册图片3加载事件的响应函数
image2.onload = function () {//调用加载纹理函数loadTexTure(gl, n, u_Sampler2, image2, 2)
}

2.4 纹理叠加处理与绘图

var g_texUnit = false,g_texUnit1 = false,g_texUnit2 = false//加载纹理函数
function loadTexTure(gl, n, u_Sampler, image, texUnit) {var texture = gl.createTexture() //创建纹理对象gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) //对纹理图像镜像y轴反转 if (texUnit === 0) {gl.activeTexture(gl.TEXTURE0) //激活纹理单元0 g_texUnit = true} else if (texUnit === 1) {gl.activeTexture(gl.TEXTURE1) //激活纹理单元1 g_texUnit1 = true} else if (texUnit === 2) {gl.activeTexture(gl.TEXTURE2) //激活纹理单元2 g_texUnit2 = true}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) //纹理图像分配给纹理对象gl.uniform1i(u_Sampler, texUnit) //纹理单元编号传给片元着色器中uniform变量//清空canvasgl.clear(gl.COLOR_BUFFER_BIT);//纹理图像全部处理完绘制图像if (g_texUnit && g_texUnit1 && g_texUnit2) {gl.drawArrays(gl.TRIANGLE_STRIP, 0, n)gl.deleteTexture(texture)}
}

3.demo代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title></title>
</head><body><!--通过canvas标签创建一个800px*800px大小的画布--><canvas id="webgl" width="800" height="800"></canvas><script>//顶点着色器var VSHADER_SOURCE = '' +'attribute vec4 a_Position;\n' + //声明attribute变量a_Position,用来存放顶点位置信息'attribute vec2 a_TexCoord;\n' + //声明attribute变量a_TexCoord,用来存放纹理坐标'varying vec2 v_TexCoord;\n' + //声明varying变量v_TexCoord,用来向片元着色器传值纹理坐标'void main(){\n' +'  gl_Position = a_Position;\n' + //变量a_Position赋值给顶点着色器内置变量gl_Position'  v_TexCoord = a_TexCoord;\n' + //将纹理坐标传给片元着色器,'}\n';//片元着色器var FSHADER_SOURCE = '' +'precision mediump float;\n' + // 设置精度'uniform sampler2D u_Sampler;\n' + //声明uniform变量u_Sampler,存放第一个纹理单元编号'uniform sampler2D u_Sampler1;\n' + //声明uniform变量u_Sampler1,存放第二个纹理单元编号'uniform sampler2D u_Sampler2;\n' + //声明uniform变量u_Sampler2,存放第三个纹理单元编号'varying vec2 v_TexCoord;\n' + //声明varying变量v_TexCoord,用来接收顶点着色器传送的纹理坐标'void main(){\n' +' vec4 color = texture2D(u_Sampler,v_TexCoord);\n' + //使用texture2D函数抽取纹理单元0纹素颜色' vec4 color1 = texture2D(u_Sampler1,v_TexCoord);\n' + //使用texture2D函数抽取纹理单元1纹素颜色' vec4 color2 = texture2D(u_Sampler2,v_TexCoord);\n' + //使用texture2D函数抽取纹理单元2纹素颜色//纹素颜色相乘,并赋值给内置变量gl_FragColor' gl_FragColor = color * color1 * color2;\n' +'}\n';//初始化着色器函数function initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE) {//创建顶点着色器对象var vertexShader = gl.createShader(gl.VERTEX_SHADER);//创建片元着色器对象var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);//引入顶点、片元着色器源代码gl.shaderSource(vertexShader, VSHADER_SOURCE);gl.shaderSource(fragmentShader, FSHADER_SOURCE);//编译顶点、片元着色器gl.compileShader(vertexShader);gl.compileShader(fragmentShader);//创建程序对象programvar program = gl.createProgram();//附着顶点着色器和片元着色器到programgl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);//链接programgl.linkProgram(program);//使用programgl.useProgram(program);gl.program = program//返回程序program对象return program;}function init() {//通过getElementById()方法获取canvas画布var canvas = document.getElementById('webgl');//通过方法getContext()获取WebGL上下文var gl = canvas.getContext('webgl');//初始化着色器initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE);// 设置canvas的背景色gl.clearColor(0.0, 0.0, 0.0, 1.0);//清空canvasgl.clear(gl.COLOR_BUFFER_BIT);//初始化顶点坐标和颜色var n = initVertexBuffers(gl)//初始化纹理initTextures(gl, n)}//初始化顶点坐标和纹理坐标function initVertexBuffers(gl) {var verticesTexCoords = new Float32Array([//顶点坐标   纹理坐标//------\\ //----\\-0.9, 0.9, 0.0, 1.0, //顶点1-0.9, -0.9, 0.0, 0.0, //顶点20.9, 0.9, 1.0, 1.0, //顶点30.9, -0.9, 1.0, 0.0, //顶点4])//创建缓冲区对象var vertexTexCoordBuffer = gl.createBuffer();if (!vertexTexCoordBuffer) {console.log('创建缓冲区对象失败!')return -1}//将顶点坐标和纹理坐标写入缓冲区对象gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer)gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW)//获取类型化数组中每个元素的大小var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT//获取顶点着色器attribute变量a_Position的存储地址, 分配缓存并开启var a_Position = gl.getAttribLocation(gl.program, 'a_Position');gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0)gl.enableVertexAttribArray(a_Position)//获取顶点着色器attribute变量a_TexCoord(纹理坐标)的存储地址, 分配缓存并开启var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2)gl.enableVertexAttribArray(a_TexCoord)return verticesTexCoords.length / 4}//初始化纹理function initTextures(gl, n) {//获取片元着色器uniform变量u_Sampler、u_Sampler1、u_Sampler2的存储地址var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler')var u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1')var u_Sampler2 = gl.getUniformLocation(gl.program, 'u_Sampler2')var image = new Image()var image1 = new Image()var image2 = new Image()image.src = './resources/grassland.png' //设置纹理资源1路径image1.src = './resources/horse.png' //设置纹理资源2路径image2.src = './resources/sheep.png' //设置纹理资源3路径//注册图片1加载事件的响应函数image.onload = function () {//调用加载纹理函数loadTexTure(gl, n, u_Sampler, image, 0)}//注册图片2加载事件的响应函数image1.onload = function () {//调用加载纹理函数loadTexTure(gl, n, u_Sampler1, image1, 1)}//注册图片3加载事件的响应函数image2.onload = function () {//调用加载纹理函数loadTexTure(gl, n, u_Sampler2, image2, 2)}return true}var g_texUnit = false,g_texUnit1 = false,g_texUnit2 = false//加载纹理函数function loadTexTure(gl, n, u_Sampler, image, texUnit) {var texture = gl.createTexture() //创建纹理对象gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) //对纹理图像镜像y轴反转 if (texUnit === 0) {gl.activeTexture(gl.TEXTURE0) //激活纹理单元0 g_texUnit = true} else if (texUnit === 1) {gl.activeTexture(gl.TEXTURE1) //激活纹理单元1 g_texUnit1 = true} else if (texUnit === 2) {gl.activeTexture(gl.TEXTURE2) //激活纹理单元2 g_texUnit2 = true}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) //纹理图像分配给纹理对象gl.uniform1i(u_Sampler, texUnit) //纹理单元编号传给片元着色器中uniform变量//清空canvasgl.clear(gl.COLOR_BUFFER_BIT);//纹理图像全部处理完绘制图像if (g_texUnit && g_texUnit1 && g_texUnit2) {gl.drawArrays(gl.TRIANGLE_STRIP, 0, n)gl.deleteTexture(texture)}}init()</script>
</body></html>

WebGL入门(十五)-使用多幅纹理/纹理叠加相关推荐

  1. [WebGL入门]十二,模型数据和顶点属性

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外.鄙人webgl研究还不够深入,一些专业词语.假设翻译有误.欢迎大家指 ...

  2. 3D游戏编程入门(十五)索引缓存

    如我公告所言,7号我将断网进行复习,我很愿意把编程学习看做在学武功,高手都会选择一段时间内进行闭关修炼的,这样更方便自己修身养性,抛开一些网络上的繁杂事宜,很容易全身心的投入自己的事情中,待得出关后功 ...

  3. WebGL入门(十九)-三维视图通过调整正射投影矩阵/盒状可视空间实现三角形的显示与消失

    三维视图正射投影矩阵 1.demo效果 2.相关知识点 2.1 正射投影 2.2 Matrix4.setOrtho()函数 3. demo代码 1.demo效果 如上,通过上下键调整正投影矩阵参数fa ...

  4. WebGL入门(十六)-三维视图模型原理,视点、视线、观察点、上方向

    三维视图模型原理 1.demo效果 2.相关知识点 2.1 视点.视线.观察点.上方向 2.2 创建视图矩阵 3. demo代码 1.demo效果 如上图,这个demo中三个不同颜色的三角形展示在三维 ...

  5. CarSim仿真快速入门(十五)—CarSim传感器仿真之ADAS Sensor Objects (1)

    BikeSim,CarSim和TruckSim数学模型包括多达200个可选对象,其位置和运动可以独立于仿真车辆进行控制.这些对象可以表示其他车辆,固定对象(树木,建筑物),行人,动物,道路标记和其他感 ...

  6. IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

    [来源申明]本文引用了微信公众号"鲜枣课堂"的<上网慢?经常掉线?这篇文章告诉你该怎么办!>文章内容.为了更好的内容呈现,即时通讯网在引用和收录时内容有改动,转载时请注 ...

  7. 第十五届智能车入门浅谈

    @TOC第十五届智能车入门浅谈 写博客原因 这次第十五届全国智能车大赛已经结束了,对于我而言,确实是我大学中一个不可多得的经历,我希望我的这段经历可以保存下来通过博客的形式,同时可以对于其他人有帮助, ...

  8. 深度学习入门(五十二)计算机视觉——风格迁移

    深度学习入门(五十二)计算机视觉--风格迁移 前言 计算机视觉--风格迁移 课件 样式迁移 易于CNN的样式迁移 教材 1 方法 2 阅读内容和风格图像 3 预处理和后处理 4 抽取图像特征 5 定义 ...

  9. OpenGL入门学习(十五)

    OpenGL入门学习[十五] 这次讲的所有内容都装在一个立方体中,呵呵. 呵呵,绘制一个立方体,简单呀,我们学了第一课第二课,早就会了. 先别着急,立方体是很简单,但是这里只是拿立方体做一个例子,来说 ...

最新文章

  1. py-redis中的批量删除key方法
  2. LeetCode 77. Combinations--回溯法,-Python,Java解法
  3. 【NLP】simhash判断文档相似度
  4. 「更高更快更稳」,看阿里巴巴如何修炼容器服务「内外功」
  5. oracle 批量修改表结构,关于Oracle批量修改表结构相关内容的整理
  6. linux文件描述符设置
  7. Spark rdd 介绍,和案例介绍
  8. 那些年,冒死拍过的老师逗逼搞笑照片 !
  9. css+沿正方形旋转,CSS3+SVG+JS 正方形沿着正方本中轴移动翻转的动画
  10. axure选中后横线切换_Axure8.0|动态面板内容简单切换技巧
  11. nlp-tutorial代码注释笔记
  12. 一家世界500强企业为什么还要做不赚钱的生意?
  13. Download and Install R and RStudio for win10
  14. _itemmod_refresh
  15. GoldenGate Director安装
  16. 数据服务化——打通企业数据应用的最后一公里
  17. s3c2440芯片累加汇编语言,S3C2440—3.用点亮LED来熟悉裸机开发的详细流程
  18. sql server 2008新建视图时出现对象名无效
  19. 软件测试岗位具体是做什么的?
  20. HDU Today-SPEA

热门文章

  1. python字典由什么组成_python字典
  2. 杜教板子(BM) 线性递推式(板子)
  3. 经济学中的定量分析python_论定量分析在经济学研究中的应用
  4. 【Oracle】看懂执行计划之基于规则的优化器(RBO)
  5. 说硅谷是个村儿的, 你们考虑过生活费的感受吗?
  6. Fibonacci数列 C语言
  7. 欢迎进入神奇的大数据时代,
  8. 使用哈工大LTP测试分词并且增加自定义字典
  9. 氧化硅湿蚀刻中枝晶状缺陷的去除方法
  10. linux驱动程序 ---- 触摸屏