學習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變量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM