1. 概述

在上一篇教程《WebGL简易教程(一):第一个简单示例》中,通过一个绘制点的例子,对WebGL中的可编程渲染管线有了个基本的认识。在之前绘制点的例子中,点的位置,点的大小,点的颜色,都是固定写在着色器中的,这样的程序是缺乏可扩展性的。

比如我想绘制一张地形(DEM),平时地形数据是保存在地形文件之中的。被程序加载之后,数据信息首先要被读取到内存,然后传递给显存,最后由显卡进行绘制。渲染管线之所以灵活强大,正是由于可以向负责绘制工作的着色器传递数据。

2. 示例:绘制一个点(改进版)

在上一篇绘制点例子之上进行改进,改进后的HelloPoint1.js代码如下:

// 顶点着色器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // attribute variable
'void main() {\n' +
' gl_Position = a_Position;\n' + // Set the vertex coordinates of the point
' gl_PointSize = 10.0;\n' + // Set the point size
'}\n'; // 片元着色器程序
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform vec4 u_FragColor;\n' + // uniform変数
'void main() {\n' +
' gl_FragColor = u_FragColor;\n' + // Set the point color
'}\n'; function main() {
// 获取 <canvas> 元素
var canvas = document.getElementById('webgl'); // 获取WebGL渲染上下文
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
} // 初始化着色器
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
} // 获取attribute变量的存储位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
} // 将顶点位置传输给attribute变量
gl.vertexAttrib3f(a_Position, 0.5, 0.5, 0.0); //获取u_FragColor变量的存储地址
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
if (!u_FragColor) {
console.log('Failed to get the storage location of u_FragColor');
return;
} //将点的颜色传入到u_FragColor变量中
gl.uniform4f(u_FragColor, 0.0, 0.8, 0.0, 1.0); // 指定清空<canvas>的颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0); // 清空<canvas>
gl.clear(gl.COLOR_BUFFER_BIT); // 绘制一个点
gl.drawArrays(gl.POINTS, 0, 1);
}

1) attribute变量

在顶点着色器中,可以看到声明了一个attribute的全局变量a_Position,并且将这其赋值给gl_Position:

// 顶点着色器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // attribute variable
'void main() {\n' +
' gl_Position = a_Position;\n' + // Set the vertex coordinates of the point
' gl_PointSize = 10.0;\n' + // Set the point size
'}\n';

attribute是glsl中三种变量声明之一,代表的是与顶点相关的数据,只能用在顶点着色器中。这个变量存储了从外部传输进顶点着色器的数据。

在shader中定义好attribute变量之后,还需要通过JS与shader进行交互。通过WebGL的渲染上下文变量gl,可以得到获取attribute变量的存储地址的方法getAttribLocation(),其定义如下:

通过这个函数,获取着色器中attribute变量的位置:

  // 获取attribute变量的存储位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}

获取地址之后,就可以向attribute变量传送数据了。通过使用gl. vertexAttrib3f()函数来向着色器传入值。这里将想要绘制点的位置传送给顶点着色器。

  // 将顶点位置传输给attribute变量
gl.vertexAttrib3f(a_Position, 0.5, 0.5, 0.0);

其函数定义如下:

注意这个函数是有一系列的同族函数,都是以基础函数名+参数个数+参数类型来命名的,以应付传输不同的数据。具体可以查阅WebGL的API。

2) uniform变量

同样的,在片元着色器中,声明了一个全局的uniform变量u_FragColor,并将其赋值给gl_FragColor:

// 片元着色器程序
var FSHADER_SOURCE =
'precision mediump float;\n' +
'uniform vec4 u_FragColor;\n' + // uniform変数
'void main() {\n' +
' gl_FragColor = u_FragColor;\n' + // Set the point color
'}\n';

uniform是glsl中另外一种变量声明,表示的是JavaScript程序向顶点着色器和片元着色器传输的一致的(不变的)数据;也就是是说这种变量既可以用在顶点着色器也可以用于片元着色器。

与attribute变量类似,uniform变量也是先获取其地址,然后向其传值。这里将想要绘制的颜色传送给片元着色器:

//获取u_FragColor变量的存储地址
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
if (!u_FragColor) {
console.log('Failed to get the storage location of u_FragColor');
return;
} //将点的颜色传入到u_FragColor变量中
gl.uniform4f(u_FragColor, 0.0, 0.8, 0.0, 1.0);

可以看到uniform变量是通过gl.getUniformLocation()函数获取地址,gl.uniform4f()变量传送数据的。它们的函数定义如下:



3) varying变量

除了attribute变量和uniform变量之外,还有一种varying变量,它表示的是从顶点着色器流向片元着色器可变的变量。这一点会在以后讲到。如下所示为向着色器传输数据的方式:

3. 结果

再次打开HelloPoint1.html,其显示结果如下:

可以看到点的位置发生了变化,同时颜色也从红色变成了绿色。位置信息和颜色信息不再是硬编码在着色器中,而是从外部传入的。

4. 参考

本来部分代码和插图来自《WebGL编程指南》。

代码和数据地址

上一篇

目录

下一篇

WebGL简易教程(二):向着色器传输数据的更多相关文章

  1. WebGL简易教程(三):绘制一个三角形(缓冲区对象)

    目录 1. 概述 2. 示例:绘制三角形 1) HelloTriangle.html 2) HelloTriangle.js 3) 缓冲区对象 (1) 创建缓冲区对象(gl.createBuffer( ...

  2. WebGL简易教程(四):颜色

    目录 1. 概述 2. 示例:绘制三角形 1) 数据的组织 2) varying变量 3. 结果 4. 理解 1) 图形装配和光栅化 2) 内插过程 5. 参考 1. 概述 在上一篇教程<Web ...

  3. WebGL简易教程——目录

    目录 1. 绪论 2. 目录 3. 资源 1. 绪论 最近研究WebGL,看了<WebGL编程指南>这本书,结合自己的专业知识写的一系列教程.之前在看OpenGL/WebGL的时候总是感觉 ...

  4. WebGL简易教程(十二):包围球与投影

    目录 1. 概述 2. 实现详解 3. 具体代码 4. 参考 1. 概述 在之前的教程中,都是通过物体的包围盒来设置模型视图投影矩阵(MVP矩阵),来确定物体合适的位置的.但是在很多情况下,使用包围盒 ...

  5. WebGL简易教程(十三):帧缓存对象(离屏渲染)

    目录 1. 概述 2. 示例 2.1. 着色器部分 2.2. 初始化/准备工作 2.2.1. 着色器切换 2.2.2. 帧缓冲区 2.3. 绘制函数 2.3.1. 初始化顶点数组 2.3.2. 传递非 ...

  6. WebGL简易教程(十四):阴影

    目录 1. 概述 2. 示例 2.1. 着色器部分 2.1.1. 帧缓存着色器 2.1.2. 颜色缓存着色器 2.2. 绘制部分 2.2.1. 整体结构 2.2.2. 具体改动 3. 结果 4. 参考 ...

  7. WebGL简易教程(六):第一个三维示例(使用模型视图投影变换)

    目录 1. 概述 2. 示例:绘制多个三角形 2.1. Triangle_MVPMatrix.html 2.2. Triangle_MVPMatrix.js 2.2.1. 数据加入Z值 2.2.2. ...

  8. WebGL简易教程(七):绘制一个矩形体

    目录 1. 概述 2. 示例 2.1. 顶点索引绘制 2.2. MVP矩阵设置 2.2.1. 模型矩阵 2.2.2. 投影矩阵 2.2.3. 视图矩阵 2.2.4. MVP矩阵 3. 结果 4. 参考 ...

  9. WebGL简易教程(九):综合实例:地形的绘制

    目录 1. 概述 2. 实例 2.1. TerrainViewer.html 2.2. TerrainViewer.js 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(八 ...

随机推荐

  1. Python之matplotlib库学习:实现数据可视化

    1. 安装和文档 pip install matplotlib 官方文档 为了方便显示图像,还使用了ipython qtconsole方便显示.具体怎么弄网上搜一下就很多教程了. pyplot模块是提 ...

  2. Codeforces Gym101341K:Competitions(DP)

    http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...

  3. centos7安装hadoop完全分布式集群

    groupadd test             //新建test工作组 useradd -g test phpq        //新建phpq用户并增加到test工作组 userdel 选项 用 ...

  4. asp.net core 系列之Configuration

    在ASP.NET Core中的App configuration 是通过configuration providers基于key-value对建立的.Configuration providers读取 ...

  5. SQLite的使用案例

    示例图 : activity_main.xml : <TextView android:id="@+id/t1" android:layout_width="wra ...

  6. 星际旅行(欧拉路,欧拉回路)(20190718 NOIP模拟测试5)

    瞎搞了一个ans+=du*(du-1)/2 wa20分,好桑心(话外音:居然还有二十分,出题人太周到了) 还是判欧拉路 题解没太仔细想,感觉还是kx的思路明白 具体就是:因为每条边要走两遍,可以把一条 ...

  7. 【并查集】连接格点-C++

    连接格点 描述 有一个M行N列的点阵,相邻两点可以相连.一条纵向的连线花费一个单位,一条横向的连线花费两个单位.某些点之间已经有连线了,试问至少还需要花费多少个单位才能使所有的点全部连通. 输入 第一 ...

  8. HAproxy+Keepalived实现高可用

    HAproxy+Keepalived实现高可用 说明: HA1:HAproxy+Keepalived(master) HA2:HAproxy+Keepalived(backup) 1.HA1上keep ...

  9. 「PowerBI相关」一款极其优秀的DAX建模工具Tabular Editor

    做Excel插件开发的时间久了,大部分人的印象是笔者是做软件开发,谈不上软件,也是插件开发级别. 但笔者更希望大家记住的身份是做BI开发,特别是企业级的BI. 故也借着Excel催化剂这个平台,输送一 ...

  10. 下拉选择框,PopupWindow的使用

    实现下拉选择框 直接上代码 Activity.java package com.example.shaofei.customerviewdemo1; import android.os.Bundle; ...