[WebGL入门]十一,着色器编译器和连接器
注意:文章翻译http://wgld.org/,原作者杉本雅広(doxas)。文章中假设有我的额外说明。我会加上[lufy:]。另外。鄙人webgl研究还不够深入。一些专业词语,假设翻译有误。欢迎大家指正。
重复重复的东西
这已经是第11篇了,由于仅仅说了一些主要的东西。到如今为止连个多边形也没绘制出来。哎呀呀呀......
不管怎么说吧。基础是非常重要的。那就在这些基础上。来绘制一个多边形吧。须要准备的知识都已经介绍过了。剩下的就是依照步骤開始绘制多边形。首先,来确认一下绘制的步骤。
・从HTML中获取canvas对象
・从canvas中获取WebGL的context
・编译着色器
・准备模型数据
・顶点缓存(VBO)的生成和通知
・坐标变换矩阵的生成和通知
・发出画图命令
・更新canvas并渲染
上面所列举的步骤中,到如今为止全然没有介绍的是最后两个,关于画图命令的部分和canvas更新部分。稍后。我会说一说它们主要的概念。
尽管这些步骤看起来挺复杂的。可是这就是使用WebGL进行渲染的基本步骤。
这次的文章。就从上到下来依次看一下前三个步骤,先说到编译着色器。
*当中有几个步骤顺序能够有变化,如今先依照这个顺序来看一下。
HTML和canvas的处理
关于HTML和canvas的处理。在之前的文章中(七。context的初始化)也已经讲过了。基本上也不会有什么变化。在这里再说一下。
>HTML代码
<html>
<head>
<title>WebGL TEST</title>
<script src="script.js" type="text/javascript"></script>
<script src="minMatrix.js" type="text/javascript"></script> <script id="vs" type="x-shader/x-vertex">
attribute vec3 position;
uniform mat4 mvpMatrix; void main(void){
gl_Position = mvpMatrix * vec4(position, 1.0);
}
</script> <script id="fs" type="x-shader/x-fragment">
void main(void){
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
HTML代码就是上面这样。head标签中引用了两个javascript文件,一个是WebGL的处理文件script.js,还有一个是本站点自己写的矩阵计算的库minMatrix.js。
顶点着色器的处理
接着,该出现顶点着色器和片段着色器的代码了。首先,先从type是x-shader/x-vertex的顶点着色器開始。以下是顶点着色器部分的代码。
>顶点着色器的代码
attribute vec3 position;
uniform mat4 mvpMatrix; void main(void){
gl_Position = mvpMatrix * vec4(position, 1.0);
}
这里用到了一个attribute变量和一个uniform变量。
变量position的类型是vec3,是一个3维向量。里面是顶点的位置。向量的三个元素各自是X,Y。Z坐标。
还有一个uniform声明的变量mvpMatrix。类型是mat4,所以是一个4x4的方阵。是模型,视图,投影的各个变换矩阵结合后的坐标变换矩阵。
这次的顶点着色器,仅仅是利用坐标变换矩阵来变换顶点的坐标位置。使用乘法运算。
这时候,为了让position和矩阵相乘,使用vec4函数,先将其变成一个4维的向量,然后相乘。最后将计算结果代入到gl_Position,顶点着色器的处理结束。
片段着色器的处理
接着说片段着色器。
这次。绘制的模型是一个简单的三角形,先不进行着色,仅仅是使用白色来填充。
所以,片段着色器中的处理,就仅仅是将白色信息传给gl_FragColor中。
以下是片段着色器的代码。
>片段着色器的代码
void main(void){
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
关于颜色,基本上使用vec3或者vec4的情况比較多。
由于一般就是使用RGB或者RGBA,须要3~4个元素。这一次使用的vec4是全部的參数都是1.0的向量,颜色是白色[红,绿。蓝。不透明度的各元素都是最大=白色]。
编译代码,生成着色器
接着来看顶点着色器和片段着色器的编译。
编译也不须要什么特别的编译器。仅仅须要调用WebGL内部的函数就能够进行编译了。准备一个函数,从着色器的编译,到实际着色器的生成这一连串的流程,都在这一个函数中来完毕。以下是这个函数的代码。
*以下的函数中的gl,是提前从WebGL的context中获取的。
>生成和编译着色器的函数
function create_shader(id){
// 用来保存着色器的变量
var shader;
// 依据id从HTML中获取指定的script标签
var scriptElement = document.getElementById(id);
// 假设指定的script标签不存在,则返回
if(!scriptElement){return;}
// 推断script标签的type属性
switch(scriptElement.type){
// 顶点着色器的时候
case 'x-shader/x-vertex':
shader = gl.createShader(gl.VERTEX_SHADER);
break;
// 片段着色器的时候
case 'x-shader/x-fragment':
shader = gl.createShader(gl.FRAGMENT_SHADER);
break;
default :
return;
}
// 将标签中的代码分配给生成的着色器
gl.shaderSource(shader, scriptElement.text);
// 编译着色器
gl.compileShader(shader);
// 推断一下着色器是否编译成功
if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
// 编译成功,则返回着色器
return shader;
}else{
// 编译失败,弹出错误消息
alert(gl.getShaderInfoLog(shader));
}
}
使用这个函数的时候。须要传入script标签的id作为參数,函数中依据这个id来获取指定的标签。
生成着色器的时候。使用WebGL中的函数createShader。这个函数在生成着色器的时候,依据顶点着色器和片段着色器的不同来传入不同的參数。參数指定为gl.VERTEX_SHADER的时候会生成顶点着色器,參数指定为gl.FRAGMENT_SHADER的时候会生成片段着色器。
首先。将代码分配给生成的着色器的时候。使用的是shaderSource函数。參数有两个,第一个參数是着色器对象,第二个參数是着色器的代码。这时候。仅仅是把着色器的代码分配给了着色器,还没有进行编译。编译的时候,使用的是compileShader函数,将着色器对象作为參数传给这个函数。就能够将着色器进行编译。
着色器是否编译成功。通过着色器中的參数能够推断。获取这个參数的时候。使用getShaderParameter函数,并使用WebGL中存在的常量COMPILE_STATUS作为參数。假设这时候的返回值是false。则表示由于什么原因导致编译失败了。要想查看原因的话,将着色器传入getShaderInfoLog函数中,就能够确认log了。
这个自己定义函数。不管是顶点着色器还是片段着色器。都能够进行编译。
实际上,顶点着色器和片段着色器的处理不同的地方就是createShader函数。其它地方是全然一样的。
程序对象的生成和连接
着色器生成之后,接着来生成程序对象。这里突然出现的程序对象,究竟是个什么对象呢?
曾经的文章中(八,着色器的说明和基础)也略微接触了一些,使用varying修饰符定义的变量。能够从顶点着色器向片段着色器中传递数据。
事实上,实现从一个着色器向还有一个着色器传递数据的,不是别的,就是程序对象。程序对象是管理顶点着色器和片段着色器,或者WebGL程序和各个着色器之间进行数据的互相通信的重要的对象。
那么,生成程序对象。并把着色器传给程序对象。然后连接着色器,将这些处理函数化。
>程序对象的生成和着色器连接的函数
function create_program(vs, fs){
// 程序对象的生成
var program = gl.createProgram();
// 向程序对象里分配着色器
gl.attachShader(program, vs);
gl.attachShader(program, fs);
// 将着色器连接
gl.linkProgram(program);
// 推断着色器的连接是否成功
if(gl.getProgramParameter(program, gl.LINK_STATUS)){
// 成功的话,将程序对象设置为有效
gl.useProgram(program);
// 返回程序对象
return program;
}else{
// 假设失败,弹出错误信息
alert(gl.getProgramInfoLog(program));
}
}
这个函数接收顶点着色器和片段着色器两个參数。然后,首先生成程序对象。分配着色器。
生成着色器的时候。使用WebGL中的函数createProgram。将着色器分配给程序对象的时候使用函数attachShader。attachShader函数的第一个參数是程序对象,第二个參数是着色器。
着色器分配结束后。依据程序对象,要连接两个着色器,这时候使用linkProgram函数,參数就是程序对象。
和生成着色器一样。要推断着色器的连接是否成功,这时候使用getProgramParameter函数,并传入常量LINK_STATUS。
假设没有问题的话,为了将程序对象设置为有效,使用useProgram函数。注意。假设不运行这个函数的话,在WebGL中是无法识别这个程序对象的。假设连接失败,则弹出错误信息,使用getProgramInfoLog函数来得到log。
总结
来简单总结一下本次的内容。
HTML代码中引入必要的javascript文件,以及描写叙述着色器的代码。
准备了着色器的编译函数和连接着色器的程序对象相关的函数。每一个函数中都有是否进行了正确处理的推断。
下次。准备好顶点数据,也就是说准备好模型数据,然后变换为VBO。依照前面说的步骤,一步步全都理解的话。就应该没问题了,加油吧。
[WebGL入门]十一,着色器编译器和连接器的更多相关文章
- WebGL编程指南案例解析之多数据存储于一个缓冲区以及着色器通信
//顶点着色器往片元着色器传值 //多个参数值存于一个缓冲对象中 var vShader = ` attribute vec4 a_Position; attribute float a_PointS ...
- WebGL简易教程(二):向着色器传输数据
目录 1. 概述 2. 示例:绘制一个点(改进版) 1) attribute变量 2) uniform变量 3) varying变量 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL ...
- WebGL入门教程(五)-webgl纹理
前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 WebGL入门教程(四)-webgl颜色 这里就需要用到 ...
- WebGL入门教程(四)-webgl颜色
前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 颜色效果图: 操作步骤: 1.创建HTML5 canva ...
- WebGL入门教程(二)-webgl绘制三角形
前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用web ...
- [WebGL入门]五,矩阵的基础知识
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:],另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...
- Unity 渲染教程(二):着色器基础
转载:https://www.jianshu.com/p/7db167704056 这是关于渲染基础的系列教程的第二部分.这个渲染基础的系列教程的第一部分是有关矩阵的内容.在这篇文章中我们将编写我们的 ...
- unity中使用的着色器语言
在unity中,着色器编程使用了一列列的HLSL语言变种(也叫作Cg,但是大部分实际上两者都是一样的). 目前,为了在不同平台下保持最好的跨平台性, 取样贴图时,最好使用DX9风格 的HLSL. 着色 ...
- WebGL之通过外部传入a_PontSize值改变点着色器vshader内置变量gl_PointSize的值
最近分配到一个看起来非常简单的优化需求.通过地图上设置工具来改变地图上显示的点的大小和透明度.无非过程就是从控件面板获取到用户设置的值保存到数据库中.然后地图上画点的时候取出设置的值渲染出点即可.前端 ...
随机推荐
- [array] leetCode-16. 3Sum Closest -Medium
16. 3Sum Closest -Medium descrition Given an array S of n integers, find three integers in S such th ...
- php实现数值的整数次方
php实现数值的整数次方 一.总结 没有考虑到指数为负数的情况 二.php实现数值的整数次方 题目描述: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exp ...
- php json字符串转为数组或对象
从网上查到的方法是 用get_object_vars 把类类型转换成数组 然后在用foreach 遍历即可 $array = get_object_vars($test); $json= '[{&q ...
- mysql mha高可用架构的安装
MMM无法全然地保证数据的一致性,所以MMM适用于对数据的一致性要求不是非常高.可是又想最大程度的保证业务可用性的场景对于那些对数据一致性要求非常高的业务,非常不建议採用MMM的这样的高可用性架构.那 ...
- java判断字符串是否为数字
我们在做安卓开发中,一定会遇到判断某字符串是否是数字的问题,本文使用正则表达式可以很方便的判断出来,希望本文对安卓开发者有所帮助. 1 public boolean isNumeric(Strin ...
- SetProcessWorkingSetSize() 方法使内存降低了很多(把内存放到交换区,其实会降低性能)——打开后长时间不使用软件,会有很长时间的加载过程,原来是这个!
在项目中对程序性能优化时,发现用SetProcessWorkingSetSize() 方法使内存降低了很多,于是查阅了相关的资料如下: 我的程序为什么能够将占用的内存移至虚拟内存呢? 其实,你也可以, ...
- 微信管理系统基于Flask+Vue+Celery+SQLAlchemy+Redis等实现
https://zhuanlan.zhihu.com/p/28102858 现在绝大多数同学都在使用微信,不过微信有很多限制,比如: 微信聊天记录只保存在本地,换个手机那些内容就找不到了 微信扫码加群 ...
- JSON 表达式
JSON语法规则: 数据在名称/值对中: 数据由逗号分隔: 大括号保存对象: 中括号保存数组 1.访问对象值: var myObj,x; myObj = {" ...
- [Postgres] Filter Data in a Postgres Table with Query Statements
We have all this data, but how do we answer questions about it? In this lesson we’ll learn how to fi ...
- Android 带清除功能的输入框控件EditTextWithDel
记录下一个非常有用的小控件EditTextWithDel.就是在Android系统的输入框右边增加一个小图标.点击小图标能够清除输入框里面的内容,由于Android原生EditText不具备此功能,所 ...