学习WebGL:着色器、绘制一个点

WebGL使用着色器信息绘图,着色器使用OpenGL ES(GLSL)编写

着色器分为顶点着色器(Vertex shader)和片元着色器(Fragment shader),顶点着色器描述位置信息,片元着色器描述颜色信息

//顶点着色器
void main(){
    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
    gl_PointSize = 10.0;
}
//片元着色器
void main(){
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

gl_Position、gl_PointSize、gl_FragColor均为GLSL内置变量名

vec4描述了数据类型为4个浮点数,相应的vec1表示1个浮点数,vec2表示2个浮点数,vec3表示3个浮点数

在gl_Position中的4个数值中,前3个应该是三维坐标的x、y、z,目前还不太明白最后一个数值的意义

有了着色器信息后,就可以使用这些信息开始绘制了

<!DOCTYPE html>
<html lang='zh-cmn-Hans'>
<head>
<meta charset='utf-8' />
<title>Canvas - WebGL</title>
</head>

<body>
<h1>HTML5 - Canvas - WebGL</h1>
<canvas id='glcanvas' width='600' height='600'></canvas>
<p>在坐标原点(画布中央)绘制一个红色的点</p>
<script id="vShader" type="x-shader/x-vertex">
    void main(){
        gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
        gl_PointSize = 10.0;
    }
</script>
<script id="fShader" type="x-shader/x-fragment">
    void main(){
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
</script>

<script type="text/javascript">
window.onload = function(){
    init();
}
function init() {
    var canvas, gl,
        vShader, fShader, shaderProgram; canvas
= document.getElementById('glcanvas'); gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); if (!gl) { console.log('WebGL Fails!'); return; } try { vShader = gl.createShader(gl.VERTEX_SHADER); //创建着色器 fShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(vShader, document.getElementById('vShader').textContent); //设置着色器的源码 gl.shaderSource(fShader, document.getElementById('fShader').textContent); gl.compileShader(vShader); //编译着色器 gl.compileShader(fShader); shaderProgram = gl.createProgram(); //创建着色器程序 gl.attachShader(shaderProgram, vShader); //把着色器信息附加到着色器程序 gl.attachShader(shaderProgram, fShader); gl.linkProgram(shaderProgram); //连接着色器程序 gl.useProgram(shaderProgram); // gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.POINTS, 0, 1); } catch (e) { console.log('WebGL Error!') } } </script> </body> </html>

不理解的是shaderSource这个方法,为何WebGL不直接提供设置着色器的API,而要通过这样的方法

上面的例子中着色器信息是在绘制前就设置好了的,如果要在绘制过程中设置,则需使用attribute和uniform等变量

<script id="vShader" type="x-shader/x-vertex">
    attribute vec4 vp;
    attribute float vps;
    void main(){
        gl_Position = vp;
        gl_PointSize = vps;
    }
</script>
<script id="fShader" type="x-shader/x-fragment">
    uniform vec4 fc;
    void main(){
        gl_FragColor = fc;
    }
</script>

然后取得这些变量,并赋值

        vShader = gl.createShader(gl.VERTEX_SHADER); //创建着色器
        fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(vShader, document.getElementById('vShader').textContent); //设置着色器的源码
        gl.shaderSource(fShader, document.getElementById('fShader').textContent);
        gl.compileShader(vShader); //编译着色器
        gl.compileShader(fShader);
        shaderProgram = gl.createProgram(); //创建着色器程序
        gl.attachShader(shaderProgram, vShader); //把着色器信息附加到着色器程序
        gl.attachShader(shaderProgram, fShader);
        gl.linkProgram(shaderProgram); //连接着色器程序
        gl.useProgram(shaderProgram); //

        var vp = gl.getAttribLocation(shaderProgram, 'vp'); //取得变量
        var vps = gl.getAttribLocation(shaderProgram, 'vps');
        var fc = gl.getUniformLocation(shaderProgram, 'fc');
        gl.vertexAttrib4f(vp, 0.5, 0.5, 0.0, 1.0); //变量赋值
        gl.vertexAttrib1f(vps, 10.0);
        gl.uniform4f(fc, 1.0, 0.0, 0.0, 1.0);
        gl.drawArrays(gl.POINTS, 0, 1); //绘制点

attribute变量用于与顶点相关的数据,uniform变量用于与顶点无关的数据。书上是这么写,但理解起来很别扭。我的理解是在3D绘图中,每个点的坐标都会经过坐标变换最后映射到2D画布上,这时点的坐标是经过变换后的坐标,那么这个坐标信息就要使用attribute变量,而不管怎么变换,点的颜色都是不变的,所以颜色信息使用uniform变量。

posted on 2017-03-11 17:39  余之乐  阅读(3452)  评论(0编辑  收藏  举报

导航