• 首页
  • 技术
  • 旅行
  • 车模
  • 关于

JZ's Blog

{技术, 绘画, 旅行, 摄影, 多肉}
  • 首页
  • 技术
  • 旅行
  • 车模
  • 关于
首页  /  技术  /  WebGL基础绘制之三:给物体上色
22 二月 2016

WebGL基础绘制之三:给物体上色

作者:jz1108
技术 WebGL 写评论

在这篇文章中,我们会讲解如何给物体添加颜色,你将了解如下信息:

  • 如何在JavaScript中给shader传递颜色
  • shader的varying
  • shader的浮点数精度问题
  • 光栅化概念

添加颜色

还是先给出完整的代码,在这里。

下面我们看看有哪些地方发生了变化。首先来看shader:

vertex shader:

attribute vec3 aPos;
attribute vec4 aColor;

varying vec4 vColor;
void main(void){
    gl_Position = vec4(aPos, 1);
    vColor = aColor;
}

fragment shader:

precision highp float;

varying vec4 vColor;
void main(void) {
    gl_FragColor = vColor;
}

在vertex shader中,出现了第二个attribute:aColor,类型是vec4,另外还有一个varying(varying的字面意思是:可变的,目前没有找到一个合适的词来翻译,你把它理解成一种变量即可,varying的作用后面会说)类型也是vec4。在main函数中我们看到除了给内置变量gl_Position赋值以外还把aColor赋值给了vColor。

在fragment shader中,首先出现了这一行:

precision highp float;

它的作用是设置fragment shader的浮点数精度,因为现在出现了变量,vertex shader因为有默认的精度所以可以不用显式设置。

接下来的一行同样出现了varying,定义和在vertex shader中一样。在main函数中我们把vColor赋值给gl_FragColor。

从上面的代码我们可以看出varying的作用是将数据从vertex shader传递给fragment shader,它是vertex shader的输出、fragment shader的输入。使用时需要在两个shader中对varying进行定义。

最后再说说shader的命名规范。shader中我们通常用第一个字母来标志数据的类型,即匈牙利命名法。attribute用a开头(如aColor)、varying用v开头(比如vColor)等等。

在JavaScript代码里,setupBuffer函数中增加了给aColor赋值的代码,这和给aPos赋值过程几乎一致:

var color = [
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1
];
var colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(color), gl.STATIC_DRAW);

var aColorPosition = gl.getAttribLocation(glProgram, 'aColor');
gl.vertexAttribPointer(aColorPosition, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aColorPosition);

在color数组中,我们为每一个点添加颜色信息,每个点的颜色是个四元组,即RGBA四项内容,取值范围0-1。后面的代码你已经见过了了,无非是创建缓冲区、获取attribute索引并让它指向颜色数据。

在浏览器中你会看到如下结果:

你可能会有疑问,我只给三角形的三个顶点赋值了,那么之间区域的颜色是怎么确定的?这还是与渲染管线有关。

再看渲染管线

在前面的文章中,我们给出了一个简单的渲染管线图,现在我们在这张图上补充一些新内容:

  • 在shader中增加varying
  • 增加光栅化过程

varying

前面讲到,varying可以用来从vertex shader向fragment shader传递数据,它是前者的输出、后者的输入。

光栅化

光栅化(Rasterization)过程发生在fragment shader执行之前,vertex shader处理的是顶点信息、fragment shader处理的是像素,那么光栅化的作用的就是将顶点信息转换为像素。如果你熟悉Photoshop、Illustrator一类的绘图软件,这个过程就如同将矢量图形转换为位图。在转换过程中,每一个像素的颜色将会通过插值计算的方式计算的得出,这就是为什么我们会在三角形填充区域看到的那些颜色。

光栅化 Rasterization

现在我们在管线图中增加以上内容。

WebGL渲染管线

一些修改

为了验证Rasterization会计算插值颜色,我们可以修改fragment shader代码:

precision highp float;

varying vec4 vColor;

int findMax(float r, float g, float b) {
    if (r > g && r > b) {
        return 0;
    }
    if (g > r && g > b) {
        return 1;
    }
    return 2;
}

void main(void) {
    float red = vColor.r;
    float green = vColor.g;
    float blue = vColor.b;
    int max = findMax(red, green, blue);
    vec4 finalColor = vColor;
    if (max == 0) {
        finalColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    else if (max == 1) {
        finalColor = vec4(0.0, 1.0, 0.0, 1.0);
    }
    else if (max == 2) {
        finalColor = vec4(0.0, 0.0, 1.0, 1.0);
    }
    gl_FragColor = finalColor;
}

vColor是插值好的颜色,我们这里不希望进行插值计算,在不同颜色相交界的地方采用硬处理。做法是读取每个像素的颜色值,看r、g、b三个分量哪个最大,然后将这个像素的颜色赋值为最大的那个颜色,比如r分量最大,则该点最终修改为纯红色,即1, 0, 0, 1。修改之后会得到如下效果:

果然,插值出来的颜色被我们改掉了,同时也验证了在fragment shader执行之前vColor已经是插值好的颜色。完整的代码请看这里。

 Previous Article WebGL基础绘制之二:绘制三角形
Next Article   再游新加坡——到达

相关文章

  • iOS 13 Safari 的一些变化

    2019年11月13日
  • WebGL 文章汇总

    2019年9月12日
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能

    2019年3月24日

留言

取消回复

近期文章

  • 记录一次解决 no buffer is bound to enabled attribute 报错的过程
  • TypeScript 中的装饰器
  • iOS 13 Safari 的一些变化
  • WebGL 文章汇总
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能

近期评论

  • lew发表在《WebGL绘制详解之五:Stencil Buffer》
  • jz1108发表在《WebGL基础绘制之一:绘制一个点》
  • jz1108发表在《WebGL 文章汇总》
  • xtx发表在《WebGL 文章汇总》
  • thy发表在《WebGL基础绘制之一:绘制一个点》

文章归档

  • 2021年三月
  • 2019年十一月
  • 2019年九月
  • 2019年三月
  • 2018年十二月
  • 2018年十一月
  • 2018年十月
  • 2017年十一月
  • 2017年十月
  • 2017年九月
  • 2017年五月
  • 2017年四月
  • 2017年三月
  • 2017年二月
  • 2017年一月
  • 2016年十一月
  • 2016年十月
  • 2016年四月
  • 2016年三月
  • 2016年二月
  • 2016年一月
  • 2015年十二月
  • 2015年十一月
  • 2015年十月
  • 2015年九月
  • 2015年八月
  • 2015年七月
  • 2015年六月
  • 2015年三月
  • 2014年十二月
  • 2014年十一月
  • 2014年十月
  • 2014年八月
  • 2014年七月
  • 2014年六月
  • 2014年五月
  • 2014年四月
  • 2014年三月
  • 2014年二月
  • 2014年一月
  • 2013年十二月
  • 2013年十一月
  • 2013年十月
  • 2013年九月
  • 2013年八月
  • 2013年七月
  • 2013年六月
  • 2013年五月
  • 2013年四月
  • 2013年三月
  • 2013年二月
  • 2013年一月
  • 2012年十二月
  • 2012年十月
  • 2012年九月
  • 2012年七月
  • 2012年六月
  • 2012年五月
  • 2012年一月
  • 2011年十一月
  • 2011年十月
  • 2011年九月
  • 2011年八月
  • 2011年七月
  • 2011年六月
  • 2011年五月
  • 2011年四月
  • 2011年二月
  • 2011年一月
  • 2010年十二月
  • 2010年十月
  • 2010年九月
  • 2010年六月
  • 2010年五月
  • 2010年四月
  • 2010年三月
  • 2010年二月
  • 2010年一月
  • 2009年十二月
  • 2009年十一月
  • 2009年九月
  • 2009年八月
  • 2009年六月
  • 2009年三月
  • 2009年二月
  • 2009年一月

分类目录

  • 地图API
  • 多肉
  • 开发
  • 技术
  • 摄影
  • 旅行
  • 未分类
  • 汽车
  • 绘画
  • 美食
  • 车模
  • 随笔

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org
© Copyright 2015. Theme by BloomPixel.