【筆記】《WebGL編程指南》學習-第2章WebGL入門(6-改變點的顏色))

這一節的目標是,在上一節用鼠標點擊畫點的基礎上增加改變顏色的功能,點的顏色取決於其位置。

結果:
這裏寫圖片描述


可以用 uniform 變量將顏色值傳給着色器,其步驟與用 attribute 變量傳遞的類似。不同的僅僅是,這次數據傳輸的目標是片元着色器,而非頂點着色器:

  1. 在片元着色器中準備 uniform 變量。
  2. 用這個 uniform 變量向 gl_FragColor 賦值。
  3. 將顏色數據從JS傳給該 uniform 變量。

示例程序 ColoredPoints.js

//頂點着色器程序
var VSHADER_SOURCE =
    'attribute vec4 a_Position;'+
    'void main(){'+
    'gl_Position=a_Position;'+
    'gl_PointSize=10.0;'+
    '}';

//片元着色器程序
var FSHADER_SOURCE=
    'precision mediump float;'+
    'uniform vec4 u_FragColor;'+
    'void main(){'+
    'gl_FragColor = u_FragColor;'+
    '}';

function main() {
    //獲取canvas元素
    var canvas = document.getElementById("webgl");
    if(!canvas){
        console.log("Failed to retrieve the <canvas> element");
        return;
    }

    //獲取WebGL繪圖上下文
    var gl = getWebGLContext(canvas);
    if(!gl){
        console.log("Failed to get the rendering context for WebGL");
        return;
    }

    //初始化着色器
    if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
        console.log("Failed to initialize shaders.");
        return;
    }

    //獲取a_Position變量存儲位置
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

    if(a_Position < 0){
        console.log("Failed to get the storage location of a_Position");
        return;
    }

    //獲取u_FragColor 變量存儲位置
    var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');

    if(!u_FragColor){
        console.log('Failed to get the storage location of u_FragColor');
        return;
    }

    canvas.onmousedown = function(ev){
        click(ev,gl,canvas,a_Position,u_FragColor);
    };

    //指定清空<canvas>顏色
    gl.clearColor(0.0, 0.0, 0.0, 1.0);

    //清空<canvas>
    gl.clear(gl.COLOR_BUFFER_BIT);
}

var g_points = [];
var g_colors = [];
function click(ev, gl, canvas, a_Position,u_FragColor){
    var x= ev.clientX;
    var y = ev.clientY;
    var rect = ev.target.getBoundingClientRect();
    x = ((x - rect.left) - canvas.width / 2) / (canvas.width / 2);
    y = (canvas.height / 2 - (y - rect.top)) / (canvas.height / 2);
    //將座標存儲到g_points數組中
    g_points.push([x, y]);
    if(x >= 0.0 && y >= 0.0){  //第一象限
        g_colors.push([1.0, 0.0, 0.0, 1.0]);  //紅色
    }else if(x < 0.0 && y < 0.0){  //第三象限
        g_colors.push([0.0, 1.0, 0.0, 1.0]);  //綠色
    }else{
        g_colors.push([1.0, 1.0, 1.0, 1.0]);  //白色
    }

    //清除<canvas>
    gl.clear(gl.COLOR_BUFFER_BIT);

    var len = g_points.length;
    for(var i = 0; i < len; i++){
        var xy=g_points[i];
        var rgba = g_colors[i];

        //將點的位置傳遞到a_Position變量中
        gl.vertexAttrib3f(a_Position, xy[0], xy[1], 0.0);
        //將點的顏色傳遞到u_FragColor變量中
        gl.uniform4f(u_FragColor, rgba[0],  rgba[1], rgba[2], rgba[3]);

        //繪製點
        gl.drawArrays(gl.POINTS, 0, 1);
    }
}

uniform 變量

只有頂點着色器才能使用 attribute 變量,使用片元着色器時,你就需要使用 uniform 變量。

在使用 uniform 變量之前,首先需要按照與聲明 attribute 變量相同的格式<存儲限定符><類型><變量名>來聲明 uniform 變量。

這裏寫圖片描述

在例子中, uniform 變量 u_FragColor 被賦值給 gl_FragColor 變量。向 uniform 變量傳數據的方式向 attribute 變量傳數據相似:首先獲取變量的存儲地址,然後再JS程序中按照地址將數據傳遞過去。

//片元着色器程序
var FSHADER_SOURCE=
    'precision mediump float;'+
    'uniform vec4 u_FragColor;'+
    'void main(){'+
    'gl_FragColor = u_FragColor;'+
    '}';

這一行使用精度限定詞來制定變量的範圍和精度,本例中爲中度精度,後面第5章會詳細講。

'precision mediump float;'+

獲取 uniform 變量的存儲地址

    //獲取u_FragColor 變量存儲位置
    var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');

    if(!u_FragColor){
        console.log('Failed to get the storage location of u_FragColor');
        return;
    }

可以使用以下方法來獲取 uniform 變量的存儲地址

這裏寫圖片描述


向 uniform 變量賦值

有了 uniform 變量的存儲地址,就可以使用 gl.uniform4f()向變量中寫入數據。該函數的功能和參數與 gl.vertexAttrib[1234]f()相似。

這裏寫圖片描述


gl.uniform4f()的同族函數

gl.uniform4f()也有一系列同族函數。

這裏寫圖片描述


結果:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章