[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。按照前面说的步骤,一步步全都理解的话,就应该没问题了,加油吧。

转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

[WebGL入门]十一,着色器的编译和连接,布布扣,bubuko.com

时间: 2024-10-19 08:19:57

[WebGL入门]十一,着色器的编译和连接的相关文章

[WebGL入门]十一,着色器编译器和连接器

注意:文章翻译http://wgld.org/,原作者杉本雅広(doxas).文章中假设有我的额外说明.我会加上[lufy:].另外.鄙人webgl研究还不够深入.一些专业词语,假设翻译有误.欢迎大家指正. 重复重复的东西 这已经是第11篇了,由于仅仅说了一些主要的东西.到如今为止连个多边形也没绘制出来.哎呀呀呀......不管怎么说吧.基础是非常重要的.那就在这些基础上.来绘制一个多边形吧.须要准备的知识都已经介绍过了.剩下的就是依照步骤開始绘制多边形.首先,来确认一下绘制的步骤.?从HTML

[WebGL入门]十四,绘制多边形

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 这是本次的demo的运行结果 绘制流程 这次终于该绘制多边形了,之前的文章(十一,着色器的编译和连接)中介绍了HTML,顶点着色器和片段着色器,这次看一下javascript从开始到最终的全部处理.如果前两篇文章介绍的内容完全理解的话,这次的内容也应该不难了.或许会有不容易理解的地方,不要着急

OpenGL学习笔记5:着色器

初识着色器语言 变量和数据类型 可用的数据类型只有4种:有符号整数,无符号整数,浮点数,布尔值. OpenGL着色语言中没有指针和字符串或字符.返回值可以为void. 向量类型 所有4种基本数据类型都可以存储在二维.三维或者四维向量中: OpenGL着色语言向量数据类型 类型 描述 vec2,vec3,vec4 2分量.3分量和4分量浮点向量 ivec2,ivec3,ivec4 2分量.3分量和4分量整数向量 uvec2,uvec3,uvec4 2分量.3分量和4分量无符号整数向量 bvec2,

[WebGL入门]八,着色器的说明和基础

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 认识GLSL WebGL是无法利用固定渲染管线的,这个在之前的文章(四,渲染准备)里已经简单的说明过了.所以,代替它的是可编辑渲染管线中的一种着色语言,叫做GLSL(OpenGL Shading Language). 是用来在OpenGL中着色编程的语言,GLSL使用C语言为基础,并且有自己独

DirectX11--HLSL编译着色器的三种方法

前言 本文不考虑Effects11(FX11),而是原始的HLSL语言. 该文章从教程02单独抽离出来作为单独的教程. 目前编译与加载着色器的方法如下: 使用Visual Studio中的HLSL编译器,随项目编译期间一同编译,并生成.cso(Compiled Shader Object)对象文件,在运行期间加载该文件以读取字节码. 使用Visual Studio中的HLSL编译器,随项目编译期间一同编译,并生成.inc或.h的头文件,着色器字节码在编译期间就可以确定. 在程序运行期间编译着色器

OpenGL入门4:着色器 GLSL

本文是个人学习记录,非原创,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和多为中文翻译者提供的优质教程 近况 在家呆久了真的是咸 前几天检查出下巴骨头出问题了,没什么治疗手段,有点难受,但也想开了 前言 经过之前一段时间的学习(渲染管线简介)我们已经知道了着色器(Shader)是运行在GPU上的小程序,这些小程序为图形渲染管线的某个特定部分而运行,着色器只是一种把输入转化为输出的程序,着色器也是一种非常独立的程序,因为它

WebGL简易教程(二):向着色器传输数据

目录 1. 概述 2. 示例:绘制一个点(改进版) 1) attribute变量 2) uniform变量 3) varying变量 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(一):第一个简单示例>中,通过一个绘制点的例子,对WebGL中的可编程渲染管线有了个基本的认识.在之前绘制点的例子中,点的位置,点的大小,点的颜色,都是固定写在着色器中的,这样的程序是缺乏可扩展性的. 比如我想绘制一张地形(DEM),平时地形数据是保存在地形文件之中的.被程序加载之后,数据信息

[WebGL入门]十五,为多边形涂抹颜色(顶点颜色的指定)

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 增加顶点属性的个数 上次,终于绘制了一个三角形,但是只绘制了一个纯白色的多边形.这次,给多边形的顶点中添加颜色属性,基本上做的事情和上一篇文章一样,只是稍微增加点步骤而已.首先,就像以前多次重复的那样,顶点可以包含很多种情报(参考:顶点缓存和基础),而且每一个情报叫做

[WebGL入门]十八,利用索引缓存来绘图

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 对应复杂的模型 上次,通过操作模型坐标变换矩阵,实现了多个模型的移动,旋转和放大缩小.但是,渲染的依然是简单的三角形,是个构造及其简单的模型.但是实际中,用WebGL来绘制一个简单的三角形的机会是很少见的.至少是个四角多边形吧,通常会是更复杂的模型.伴随着模型的复杂化