博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Webgl 纹理
阅读量:6375 次
发布时间:2019-06-23

本文共 3332 字,大约阅读时间需要 11 分钟。

纹理单元和对象

纹理单元,也称纹理映射单元或纹理处理单元,是GPU进行采样的组件。纹理对象是包含图片颜色数据的数据结构和纹理相关数学信息。一个纹理单元必须访问一个纹理对象来完成工作。纹理单元是处理器,而纹理对象保存被处理的数据。
GLSL中的sampler类型包括sampler2D和samplerCube。 sampler2D用在标准纹理图像上,而samplerCube用在立方体纹理上。sampler类型的值索引到一个纹理单元上。值用来告诉采样过程中哪个纹理单元被用到。采样值必须是声明在全局的uniform类型中,不能在着色器程序中去分配值。纹理单元的值可以是0,1,2... 在GLSL中的应用
uniform sampler2D u_texture;复制代码
在JS中:
u_texture_location = gl.getUniformLocation(prog, "u_texture");gl.uniform1i(u_texture_location, 2);复制代码
纹理的使用:
图像纹理的使用基本过程就是创建,激活,并与对应的着色器程序关联;
  • 创建纹理对象,关联到对应的内存中
textureObj = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D, textureObj);// 用来加载图片到纹理对象中gl.texImage2D(target, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);复制代码
  • 匹配纹理单元 在告知纹理单元处理纹理对象时需要先激活纹理单位“gl.activeTexture”。参数包括gl.TEXTURE0, gl.TEXTURE1... 初始情况下 TEXTURE0是激活的。
gl.activeTexture(gl.TEXTURE2);gl.bindTexture(gl.TEXTURE_2D, textureObj);复制代码
           
        texture 来源 http://math.hws.edu/graphicsbook/c6/s4.html#webgl.4.4

立方体纹理

Webgl支持立方体纹理。纹理对象可以保存立方体纹理。两个纹理对象可以同时绑定到同一个纹理单元,一个是普通纹理,另一个是立方体纹理。两个纹理对象绑定到不同的目标上gl.TEXTURE2D和gl.TEXTURE_CUBE_MAP。纹理对象texObj绑定的方式:
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texObj);复制代码
纹理对象一旦绑定到一个对象上,就不能再次被绑定到其他地方。立方体纹理包含6个图片,每张图片对应立方体的一个面。绑定到立方体纹理上的纹理对象有6个常数进行指定:
gl.TEXTURE_CUBE_MAP_NEGATIVE_Xgl.TEXTURE_CUBE_MAP_POSITIVE_Xgl.TEXTURE_CUBE_MAP_NEGATIVE_Ygl.TEXTURE_CUBE_MAP_POSITIVE_Ygl.TEXTURE_CUBE_MAP_NEGATIVE_Zgl.TEXTURE_CUBE_MAP_POSITIVE_Z复制代码
这些常数被用在gl.texImage2D和gl.copyTexImage2D的目标上。图片加载到cubemap纹理对象有6个目标,但用来将纹理对象绑定到纹理单元的只有gl.TEXTURE_CUBE_MAP。立方体纹理存储了一组6张图片,必须单独的加载到纹理对象上。例子鱼眼??
function loadCubemapTexture(){  var tex = gl.createTexture();  var imageCt = 0;  load("negx.jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_X);  load("posx.jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_X);  load("negy.jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_Y);  load("posy.jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_Y);  load("negz.jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_Z);  load("posz.jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_Z);    function load(url, target){     var img = new Image();     img.onload = function(){        gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);        gl.texImage2D(target, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);        imageCt++;        if(imageCt === 6){            gl.generateMipmap(gl.TEXTURE_CUBE_MAP);            textureObject = tex;            draw();         }     }     img.src = url;  } }复制代码
立方体纹理中的图像必须相同大小,并且是正方体的,大小也应该是2的幂次。另外对于纹理参数必须应用在所有的6个面上。如:
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);复制代码
对于立方体纹理为了面与面之间没有明显的裂缝,建议将纹理wrap的模式改为CLAMP_TO_EDGE来避免。
在片段着色器上,uniform sapmlerCube
vec4 color = textureCube(u_texture, vector);复制代码

纹理坐标

纹理坐标通常是根据将要渲染的物体坐标进行计算的。纹理坐标也是跟着物体坐标的变换而变化的。最简单生成方式是使用物体坐标的x,y坐标。如果一个点坐标是acoords,那么意味着会采用a_coords_xy作为纹理坐标。这种简单的映射对应朝向正z轴方向的多边形来说是可行的,但对于在xy面的多边形来说并没有好的结果。结果可能如下图:
                             
                       来源:http://math.hws.edu/graphicsbook/c7/s3.html
可以看到的是正面的结果是正常的,而其他几个面的结果就比较奇怪。这个问题的原因在于我们没有对其他面纹理坐标进行投影变换。
对于平的材质,多边形上所有的法向量都是同一方向的,这个计算就可以在顶点着色器上完成;对于平滑的材质而言,每个点上的法向量都不太一样,如果在不同的顶点上投影不同方向的纹理坐标并进行插值,那么结果很可能是一团糟的。因此这种情况就适合在片段着色器中计算。

程序式的纹理

程序式纹理是通过指定一个函数来计算值而不是选取已知的。在Webgl中程序式纹理定义在片段着色器中。采用vec2代表纹理坐标而不是sampler2D。这也可以扩展到3D纹理,使用vec3。相比于二维纹理投影在平面点上,三维纹理是投影在空间中。
vec4 color;float a = floor(v_texCoords.x * scale);float b = floor(v_texCoords.y * scale);if(mod(a+b, 2.0) > 0.5){   color = vec4(1.0, 0.5, .5, 1.0);} else {    color = vec4(0.6, 0.6, 1.0, 1.0);}复制代码

参考:

转载于:https://juejin.im/post/5b49b5a6f265da0f7b2f5954

你可能感兴趣的文章
bash 交互与非交互
查看>>
分布式事务
查看>>
怎么提高自身技术
查看>>
北京游泳馆
查看>>
linux利用rpm包安装jdk,mysql
查看>>
第三方登录原理和流程
查看>>
cacti安装与配置
查看>>
Mac 安卓模拟器打开 ONS
查看>>
完全卸载Oracle 11g教程
查看>>
Oracle调整表空间大小——ORA-03297: 文件包含在请求的 RESIZE 值以外使用的数据
查看>>
二叉树(一)
查看>>
[Windows Azure]Windows Azure Identity
查看>>
Java 技术新手入门
查看>>
【运维囧事】显卡而引起的事故
查看>>
mysql MHA
查看>>
Python系统管理
查看>>
Bootstrap3 概述
查看>>
防范SQL注入漏洞攻击
查看>>
ExtJS应用架构设计(二)
查看>>
点滴积累【other】---VS2008常用快捷键
查看>>