《WebGL 编程指南》笔记 —— 第五章 颜色与纹理

本章主要内容:
(1) 将顶点的其他(非坐标)数据 —— 如颜色等 —— 传入顶点着色器
(2)发生在顶点着色器和片元着色器之间的从图形到片元的转化,又称图元光栅化(rasterzation process)
(3)将图形(或称纹理)映射到图形或三维对象的表面上。

  1. 将顶点坐标传入着色器,步骤:
    (1)创建缓冲区对象。
    (2)将缓冲区对象绑定到tartget上。
    (3)将顶点坐标数据写入缓冲区对象。
    (4)将缓冲区对象分配给对应的 attribute 变量。
    (5)开启 attribute 变量。
使用两个缓冲区对象向顶点着色器传输数据
  1. 交错组织(interleaving):将顶点坐标尺寸数据打包到同一缓冲区对象中。

  2. gl.vertexAttribPointer()

gl.vertexAttribPointer()
  1. varying 变量: 从顶点着色器向片元着色器中传入数据。
    varying 变量只能是float(以及相关的vec2,vec3,vec4,mat2,mat3,mat4)。

  2. 在顶点着色器和片元着色器之间,有两个步骤:
    [1] 图形装配过程:将孤立的顶点坐标装配成几何图形。几何图形的类别由gl.drawArray() `函数的第一个参数决定。
    输入数据:gl_Position
    [2] 光栅化过程:将装配好的几何图形转为片元。

顶点着色器和片元着色器之间的图形装配和光栅化

步骤:
(1)根据 gl.drawArrays()的参数n,将执行顶点着色器n次(执行顶点着色器结果:将坐标传入并存储在装配区)
(2)开始装配图形。使用传入的点坐标,根据 gl.drawArrays()的第一个参数信息(如:gl.TRANGLES)来决定如何装配。
(3)光栅化

几何图形装配和光栅化过程
  1. 颜色内插(interpolation)
颜色值的内插
  1. 纹理映射(texture mapping):根据纹理图像,为之前光栅化后的每个片元涂上合适的颜色。
    纹素(texels, texture elements):组成纹理图像的像素。每一个纹素的颜色都是用RGBRGBA格式编码。
纹素
  1. 在WebGL中,要进行纹理映射,需遵循以下四步:
    (1)准备好映射到几何图形上的纹理图像。
    (2)为几何图形配置纹理映射方式。
    (3)加载纹理图像,对其进行一些配置,以在WebGL中使用它。
    (4)在片元着色器中将相应的纹素从纹理中抽取出来,并将纹素的颜色赋给片元。

  2. 纹理坐标
    纹理坐标是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色。
    WebGL系统中的纹理坐标系统是二维的。
    WebGL中使用s和t命名纹理坐标。(st坐标系统)

WebGL的纹理坐标系统
  1. 将纹理图像粘贴到几何图形上
    在WebGL中,我们通过纹理图像的纹理坐标与几何图形顶点坐标间的映射关系,来确定怎样将纹理图像贴上去。
将纹理图像映射到顶点上
  1. 纹理映射过程详解
    步骤:
    (1)顶点着色器中接收定点的纹理坐标,光栅化后传递给片元着色器。
    (2)片元着色器根据片元的纹理坐标,从纹理图像中抽取出纹素颜色,赋给当前片元。
    (3)设置顶点的纹理坐标(initVertexBuffers()
var verticesTexCoords = new Float32Array([
  -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,    
]) 

将顶点坐标和纹理坐标写入缓冲区对象,将其中的顶点坐标分配给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);

获取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);

(4)准备待加载的纹理图像,令浏览器读取它(initTextures())
initTextures() => 配置和加载问题
调用gl.createTexture()创建纹理对象

var texture = gl.createTexture();
gl.createTexture()

同样,也可以使用gl.deleteTeture()来删除一个纹理对象。如果试图删除一个已经被删除的纹理对象,不会报错也不会产生任何影响。

gl.deleteTeture()

调用gl.getUniformLocation()从片元着色器中获取uniform变量u_Sampler(取样器)的存储位置,该变量用来接收纹理图像

var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');

创建image对象

var image = new Image();

注册图像加载事件的响应函数

image.onload = function(){ loadTexture(gl, n, texture, u_Sampler, image); };

浏览器开始加载图像

image.src = '../resources/sky.jpg';

(5)监听纹理图像的加载事件,一旦加载完成,就在WebGL系统中使用纹理(loadTexture())。

loadTexture() => 配置纹理供WebGL使用

对纹理图像进行y轴翻转(WebGL纹理坐标中的t轴的方向和PNG、BMP、JPG等格式图片的坐标系统的Y轴方向是相反的。)

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
图像坐标系统和WebGL纹理坐标系统
gl.pixelStorei()

开启0号纹理单元
WebGL通过纹理单元的机制来同时使用多个纹理。
每个纹理单元有一个单元编号来管理一张纹理图像。
系统支持的纹理单元格数取决于硬件和浏览器的WebGL实现,但是在默认情况下,WebGL至少支持8个纹理单元。
在使用纹理单元之前,还需要调用gl.aactiveTexture()来激活它。

gl.activeTexture(gl.TEXTURE0);
gl.activeTexture()

绑定纹理对象(设置纹理的类型)

gl.bindTexture(gl.TEXTURE_2D, texture);
纹理类型
gl.bindTexture()
将纹理坐标绑定到目标上

配置纹理对象的参数 => 设置纹理图像映射到图形上的具体方式

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri()
param 参数值
四种纹理参数及它们锁产生的效果
纹理参数及它们的默认值

配置纹理图像 => 将纹理图像分配给纹理对象,同时允许你告诉WebGL系统关于该图像的一些特性。

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
gl.texImage2D()
纹素数据的数据格式

format标示纹理数据的格式,必须根据纹理图像的格式来选择这个参数
JPG => gl.RGB
PNG => gl.RGBA
BMP => gl.RGB
gl.LUMUNANCEgl.LUMINANCE_ALPHA 通常用在灰度图像上等等
流明(luminance)标示我们感知到的物体表面的亮度。通常使用物体表面红、蓝颜色分量指的加权平均来计算流明。

纹理数据的数据格式

type参数制定了纹理数据类型。通常使用gl.UNSIGNED_BYTE数据类型。

分配后的WebGL系统:

将图像分配给纹理对象

将0号纹理传递给着色器中的取样器变量

gl.uniform1i(u_Sampler, 0);

uniform sampler2D u_Sampler;
专用于纹理的数据类型

分配给unform变量后的WebGL系统:

将纹理单元分配给uniform变量

绘制矩形

gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);

从顶点着色器向片元着色器传输纹理坐标

var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute vec2 a_TexCoord;\n' +
  'varying vec2 v_TexCoord;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  v_TexCoord = a_TexCoord;\n' +
  '}\n';

在片元着色器中获取纹理像素颜色(texture2D())

 gl_FragColor = texture2D(u_Sampler, v_TexCoord);
texture2D()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容