WebGL.2 --编译shader与program

什么是 Shader

Shader是一种面向GPU的编程语言, 全称是 (OpenGL Shading Language) 由于GPU结构的特殊性,各个厂家对 Shader的支持也不是尽善尽美.就像浏览器厂商有时也不是严格 按照W3C规范来搞,但是大体上的规则还是遵守的. 由于shader语言十分复杂,本文只做简要概述,在后面的章节会有详细的解释. 下面就是一个webgl shader 例子:

vertex shader

attribute vec4 a_Position;
uniform vec4 u_Color;
void main(){
    gl_Position = a_Position;
    gl_PointSize = 10.0;
}

fragment shader

precision highp float;
uniform vec4 u_Color;
void main(){
    gl_FragColor = u_Color;
}

shader 分为两种:

vertex shader (顶点着色器). 控制点的位置和大小.

fragment shader (片元着色器).控制点的颜色.

可以看到在shader中有一些内置的变量如gl_Position gl_PointSize gl_FragColor 他们都是有特殊含义的,这些我们后面再讲.

关于canvas标签

相对于webgl来说context2d api 则大家应该很熟悉了,它比较简单直观,还记得这样的代码吗?

var canvas =document.getElementById('canvas');
var ctx=canvas.getContext("2d");

...
...
ctx.lineTo()

context2d api 是在canvas上绘图的最简单的 API. 我们通过调用 canvas.getContext("2d") 获得了一个 context2d 对象ctx,之后的绘图工作 只需要调用ctx下的相应绘图函数就行.

webgl 下图像也是显示在canvas中的,获取webgl对象的方式与获取context2d对象类似:

var canvas =document.getElementById('canvas');
var gl=canvas.getContext("webgl");

通过调用 canvas.getContext("webgl") 我们会获得一个 webgl绘图上下文对象 gl,之后的绘图工作都会与这个对象相关.

如何在Javascript中关联 Shader

正如上一章讲的,js需要通过 webgl API 将数据发送到 shader上.但目前为止,就像上面的例子,shader还只是一些'字符串'而已.还并不是可用的程序, 所以要使用shader首先要编译它.

var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader,vertexStr); //vertexStr 就是上例的shader字符串
gl.compileShader(vertexShader);

var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader,fragStr);//vertexStr 就是上例的shader字符串
gl.compileShader(fragShader);

这样我们获得了两个shangder对象 一个 vertex shader对象vertexShader,一个fragment shader对象 fragShader.

但是 vertexShaderfragShader 我们仍然不能直接使用, 我们还需要把它们链接起来.因为一个完整的shader是由一个顶点着色器 + 一个片元着色器 组成的. 我们还需要把他们链接起来.

var program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragShader);
gl.linkProgram(program);
gl.useProgram(program);

这样生成的 program对象既是一个可用对象. 最后一句 gl.useProgram(program) 指定当前正在使用的program对象.

这里有点像用gcc 编译 c代码,首先我们编译源码文件,获得 .o文件.

g++ -o a.cpp
g++ -o b.cpp

.o文件我们不能直接用,我们还需要把他们链接起来

g++ a.o b.o -o test.exe

这样通过链接器链接后的 test.exe 我们就可以使用了.

留言:

称呼:*

邮件:

网站:

内容: