二十四课代码(WebGL课程代码专用)

380 阅读1分钟

二十四课代码:

index.html:


<!doctype html>
<html>

<head>
    <style>
        canvas {
            border: 1px solid #000000;
        }
    </style>
    <script type="text/javascript" src="models_tri.js"></script>

</head>

<body>
    <p>
        <b>scale value:</b>
        <input id="scalex" type="range" min="-2" max="2" value="1" step="0.1" oninput="updatefunc()" />
        <b id="scalevaluex">0</b>
        <input id="scaley" type="range" min="-2" max="2" value="1" step="0.1" oninput="updatefunc()" />
        <b id="scalevaluey">0</b>
    </p>
    <p>
        <b>offset value:</b>
        <input id="offsetx" type="range" min="-1" max="1" value="0" step="0.1" oninput="updatefunc()" />
        <b id="offsetvaluex">0</b>
        <input id="offsety" type="range" min="-1" max="1" value="0" step="0.1" oninput="updatefunc()" />
        <b id="offsetvaluey">0</b>
    </p>

    <p>
        <b>rotate value:</b>
        <input id="rotate" type="range" min="0" max="6.28" value="0" step="0.01" oninput="updatefunc()" />
        <b id="rotatevalue">0</b>
    </p>

    <p>
        <b>N边形:</b>
        <input id="N" type="range" min="3" max="100" value="3" step="1" oninput="updatefunc()" />
        <b id="Nvalue">0</b>
    </p>


    <canvas id="tri" width="600" height="600" style="width:300px; height:300px">
    </canvas>
    <script id="vertex_shader" type="myshader">
        // Vertex Shader
        precision mediump int;
        precision mediump float;
        
        uniform mat3 u_all;

        attribute vec2 a_PointVertex;

        attribute vec3 a_PointColor;

        varying vec3 color;

        void main() {
          vec3 coord = u_all * vec3(a_PointVertex, 1.0);
          gl_Position = vec4(coord.x, coord.y, 0.0, 1.0);
          color = a_PointColor;
        }
    </script>
    <script id="fragment_shader" type="myshader">
        // Fragment shader
        precision mediump int;
        precision mediump float;

        varying vec3 color;

        void main() {
        
          gl_FragColor = vec4(color, 1.0);
        }
        
    </script>
    <script type="text/javascript">
        var pointCanvas = document.getElementById('tri'); // 我们的纸
        var gl = pointCanvas.getContext('webgl', { preserveDrawingBuffer: true }); // 我们的笔
        var data;
        var dataArr;
        var pointCount;
        var buffer_point = null;
        var buffer_color = null;
        //
        var vertex_shader_code = document.getElementById('vertex_shader').textContent;

        var vertex_shader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertex_shader, vertex_shader_code);
        gl.compileShader(vertex_shader);
        //
        var fragment_shader_code = document.getElementById('fragment_shader').textContent;
        var fragment_shader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragment_shader, fragment_shader_code);
        gl.compileShader(fragment_shader);
        //
        var program = gl.createProgram();
        gl.attachShader(program, vertex_shader);
        gl.attachShader(program, fragment_shader);
        gl.linkProgram(program);
        gl.useProgram(program);
        //
        var a_PointVertex = gl.getAttribLocation(program, 'a_PointVertex');
        var a_PointColor = gl.getAttribLocation(program, 'a_PointColor');
        //

    </script>
    <script>
        var u_all_loc = gl.getUniformLocation(program, "u_all");

        var scaleDomX = document.getElementById("scalex");
        var scaleValueDomX = document.getElementById("scalevaluex");
        var scaleDomY = document.getElementById("scaley");
        var scaleValueDomY = document.getElementById("scalevaluey");
        var offsetDomX = document.getElementById("offsetx");
        var offsetValueDomX = document.getElementById("offsetvaluex");
        var offsetDomY = document.getElementById("offsety");
        var offsetValueDomY = document.getElementById("offsetvaluey");

        var rotateDom = document.getElementById("rotate");
        var rotateValueDom = document.getElementById("rotatevalue");

        var NDom = document.getElementById("N");
        var NValueDom = document.getElementById("Nvalue");

        function genMat3ForGL(a, b, alpha, A, B) {
            let mat3 = [
                a * Math.cos(alpha), a * Math.sin(alpha), 0,
                -b * Math.sin(alpha), b * Math.cos(alpha), 0,
                A, B, 1,
            ];
            return new Float32Array(mat3);
        }

        function updatefunc() {

            if (buffer_point) {
                gl.deleteBuffer(buffer_point);
            }
            if (buffer_color) {
                gl.deleteBuffer(buffer_color);
            }

            data = GetPolyN([0, 0], 0.5, NDom.value);
            dataArr = new Float32Array(data);
            pointCount = data.length / 2;

            buffer_point = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, buffer_point);
            gl.bufferData(gl.ARRAY_BUFFER, dataArr, gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_PointVertex, 2, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(a_PointVertex);

            data = GetRandomColor(pointCount);
            dataArr = new Float32Array(data);

            buffer_color = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, buffer_color);
            gl.bufferData(gl.ARRAY_BUFFER, dataArr, gl.STATIC_DRAW);

            gl.vertexAttribPointer(a_PointColor, 3, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(a_PointColor);


            gl.uniformMatrix3fv(u_all_loc, false, genMat3ForGL(scaleDomX.value,
                scaleDomY.value, rotateDom.value, offsetDomX.value, offsetDomY.value
            ));

            scaleValueDomX.innerText = scaleDomX.value;
            offsetValueDomX.innerText = offsetDomX.value;
            scaleValueDomY.innerText = scaleDomY.value;
            offsetValueDomY.innerText = offsetDomY.value;
            rotateValueDom.innerText = rotateDom.value;
            NValueDom.innerText = NDom.value;

            gl.enable(gl.CULL_FACE);
            gl.enable(gl.DEPTH_TEST);

            gl.clearColor(0, 0, 0, 0);
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            gl.drawArrays(gl.TRIANGLES, 0, pointCount);
        }
        updatefunc();
    </script>
    </script>
</body>

</html>

models_tri.js

function GetTri(A, B, C) {
    return [A[0], A[1], B[0], B[1], C[0], C[1]];
}

function GetPolyN(center, R, N) {
    // 1. 先在圆周上,均匀获取 N 个点
    let idx = 0;
    let x = 0;
    let y = 0;
    let rad = 0;
    let pointArr = [];
    for (; idx != N; idx++) {
        rad = ((2 * Math.PI) / N) * idx;
        x = R * Math.cos(rad) + center[0]; // 考虑 R 和 中心
        y = R * Math.sin(rad) + center[1]; // 考虑 R 和 中心
        pointArr.push([x, y]);
    }
    // 2. 将这N个点,每两个一组,与中心,正好是三个点,组成N个三角形
    let res = []; // 平坦化数组
    for (idx = 0; idx != N; idx++) {
        res.push(...GetTri(pointArr[idx], pointArr[(idx + 1) % N], center)); // 注意这里是逆时针排布的
    }
    return res;
}
// 获取随机颜色 RGB
function GetRandomColor(pointCount) {
    let res = [];
    let idx = 0;
    for (; idx != pointCount; idx++) {
        res.push(Math.random());//R
        res.push(Math.random());//G
        res.push(Math.random());//B
    }
    return res;
}

将上面两个文件放在一个目录里,用任意http服务器监听此目录即可