webgl学习日志(1)——创建几何图形

webgl入门也挺麻烦的,需要了解JavaScript脚本编辑语言,需要会Html,需要懂点Opengl,还要有懂些计算机图形学的知识。做得精还需要会编写shader。

当然,这些都可以慢慢学,而且webgl看似难入门,其实把它各个部分割裂开,也挺简单的。当然,JavaScript和Html知识是必备的技能。

编辑器还是选择强大的visual studio。然后创建TypeScript的Html项目。这里创建这个项目就可以直接在chrome上查看结果,很方便,不用搞什么服务器什么的。

好,来看第一个部分,创建几何图形。

首先在index.html里写入主体代码。这里写了两个着色器,顶点着色器和片面着色器,当然也可以放在其他地方。然后,确定画布大小。

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="app.js"></script>
    <script id="shader-vs">
        attribute vec3 v3Position;
        void main(void)
        {
            gl_Position = vec4(v3Position, 1.0);
        }
    </script>

    <script id="shader-fs">
        precision mediump float;
        void main(void)
        {
            gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
        }
    </script>

    <script type="text/javascript" src="Common/gl-matrix.js"></script>
    <script type="text/javascript" src="Common/initShaders.js"></script>
    <script type="text/javascript" src="Common/webgl_utils.js"></script>
    <script type="text/javascript" src="Test/test001.js"></script>
    <script>
        function Init()
        {
            var canvas = document.getElementById('gl-canvas');
            webgl = canvas.getContext("webgl");

            webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);
            InitGeometry(webgl);
        }
    </script>      
</head>
<body onload='Init()'>
   <canvas id="gl-canvas" width="512" height="512"></canvas>
</body>
</html>

接下来创建着色器,并应用着色器到程序中,这部分可以不用细究,后面再学。这部分是initshader.js.

function initShaderToWebgl(webgl, v3PositionIndex)
{
    vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
    fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);

    webgl.shaderSource(vertexShaderObject, getShaderSource("shader-vs"));
    webgl.shaderSource(fragmentShaderObject, getShaderSource("shader-fs"));

    webgl.compileShader(vertexShaderObject);
    webgl.compileShader(fragmentShaderObject);

    if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
        alert("error:vertexShaderObject");
        return;
    }
    if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
        alert("error:fragmentShaderObject");
        return;
    }

    programObject = webgl.createProgram();

    webgl.attachShader(programObject, vertexShaderObject);
    webgl.attachShader(programObject, fragmentShaderObject);

    webgl.bindAttribLocation(programObject, v3PositionIndex, "v3Position");

    webgl.linkProgram(programObject);
    if (!webgl.getProgramParameter(programObject, webgl.LINK_STATUS)) {
        alert("error:programObject");
        return;
    }

    webgl.useProgram(programObject);
}
//
// Initialize a shader program, so WebGL knows how to draw our data
//
function initShaderProgram(gl, vsSource, fsSource) {
    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
    const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

    // Create the shader program

    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    // If creating the shader program failed, alert

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
        return null;
    }

    return shaderProgram;
}

//
// creates a shader of the given type, uploads the source and
// compiles it.
//
function loadShader(gl, type, source) {
    const shader = gl.createShader(type);

    // Send the source to the shader object

    gl.shaderSource(shader, source);

    // Compile the shader program

    gl.compileShader(shader);

    // See if it compiled successfully

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {

        alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }

    return shader;
}

function getShaderSource(scriptID) {
    var shaderScript = document.getElementById(scriptID);
    if (shaderScript == null) return "";

    var sourceCode = "";
    var child = shaderScript.firstChild;
    while (child) {
        if (child.nodeType == child.TEXT_NODE) sourceCode += child.textContent;
        child = child.nextSibling;
    }

    return sourceCode;
}

最后就是他的几何部分,卸载test001.js中。

var webgl = null;
var vertexShaderObject = null;
var fragmentShaderObject = null;
var programObject = null;
var triangleBuffer = null;
var v3PositionIndex = 0;

function InitGeometry(webgl) {   

   

    var jsArrayData =
        [
            0.0, 1.0, 0.0,//上顶点
            -1.0, -1.0, 0.0,//左顶点
            1.0, -1.0, 0.0
        ];//右顶点   
    
    render(webgl, v3PositionIndex, jsArrayData);

    //开启着色器中的顶点属性
    webgl.enableVertexAttribArray(v3PositionIndex);
    //描述顶点数组中的数据形式
    webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
    //画三角形
    webgl.drawArrays(webgl.TRIANGLES, 0, 3);

}

function render(webgl, v3PositionIndex, jsArrayData)
{
    //初始化定义shader
    initShaderToWebgl(webgl, v3PositionIndex);
    initBuffer(webgl, jsArrayData);
    webgl.clearColor(0.0, 0.0, 0.0, 1.0);
    webgl.clear(webgl.COLOR_BUFFER_BIT);
}

//创建缓冲区并绑定顶点数据
function initBuffer(webgl, jsArrayData)
{
    triangleBuffer = webgl.createBuffer();
    webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
    webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);    
}

webgl_utils.js用来写各种小工具。gl-matrix.js用来存放矩阵计算的方法。暂时用不上。

最后结果:


现在来画几条线,这个就简单了,直接在上面的InitGeometry()方法里修改,比如我要画四条直线,那就是8个点。只需要在jsArrayData里添加点即可,另外,需要把drawArray里的3改为8,另外用上webgl.LINES的模式。更多样式请参考:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawArrays

各个实例请参考:http://www.cocoachina.com/ios/20170710/19798.html

function InitGeometry(webgl) {   

   

    var jsArrayData =
        [
          -0.5, -0.5, 0.0,
    -0.5, 0.5, 0.0,

    -0.5, 0.5, 0.0,
    0.5, 0.5, 0.0,

    0.5, 0.5, 0.0,
    0.5, -0.5, 0.0,

    0.5, -0.5, 0.0,
    -0.5, -0.5, 0.0,
        ];//右顶点   
    
    render(webgl, v3PositionIndex, jsArrayData);

    //开启着色器中的顶点属性
    webgl.enableVertexAttribArray(v3PositionIndex);
    //描述顶点数组中的数据形式
    webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
    //画直线
    webgl.drawArrays(webgl.LINES, 0, 8);

}

讲得比较简单,最好结合书和视频教程来看。但是把各个部分分隔开,还是很好理解的。


猜你喜欢

转载自blog.csdn.net/niuge8905/article/details/79515395