首页 > 3D > OpenGL概述及实例(基于webGL绘制一个立方体)
2019
06-10

OpenGL概述及实例(基于webGL绘制一个立方体)

OpenGL概述

OpenGL是一个三维绘图标准(这个标准规定了API的输入和输出,具体的内部实现一般是由显卡厂商实现)。这个标准也有一个web的版本(WebGL)。

标准化组织:

Khronos Group 成立于 2000 年 1 月,由包括 3Dlabs, ATI, Discreet, Evans & Sutherland, Intel, Nvidia, SGI 和 Sun Microsystems 在内的多家国际知名多媒体行业领导者创立,致力于发展开放标准的应用程序接口 API ,以实现在多种平台和终端设备上的富媒体创作、加速和回放。

clip_image002.jpg

WebGL图形系统

计算机图形系统

clip_image004.jpg

clip_image006.png

 

 渲染管线:渲染流水线

clip_image008.jpg

图元装配

clip_image010.jpg

绘制一个立方体(使用WebGL)

顶点结构

clip_image011.png

立方体8个顶点,如果让 立方体的三条棱线和xyz轴重合,你可以很容易用Javascript的数组写出他的坐标,假设立方体顶点是WebGL坐标系中的相对值±0.5,8各顶点就是(±0.5,±0.5,±0.5),排列组合就可以。对于旋转而言就是旋转矩阵。(线性代数)


旋转变换矩阵

假设一个点的坐标是(x,y,z),经过旋转变换后的坐标为(x,,y,,z,),绕Z轴旋转γ角度z的坐标不变不变,x、y的坐标发生变化,在笛卡尔坐标系下通过简单的数学计算就可以知道结果,x,=xcosγ-ysinγ,y,=xsinγ+ycosγ

clip_image002.png

  这个过程如何用矩阵的乘法描述,如何利用线性代数进行建模,如果你有足够的数学训练,其实很简单, 不做深入线性代数的矩阵变换,仅仅采用矩阵的乘法法则进行验证

image.png

WebGL API文档

https://www.khronos.org/registry/webgl/specs/latest/2.0/

最终案例代码及注释:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<canvas id="webgl" width="500" height="500" style="background-color: #0d72da"></canvas>
<script>
    var canvasElement=document.getElementById('webgl');
    var gl=canvasElement.getContext('webgl');
    //顶点着色器源码
    var vertexShaderSource = '' +
        //attribute声明vec4类型变量apos
        'attribute vec4 apos;'+
        'void main(){' +
        //设置几何体轴旋转角度为30度,并把角度值转化为浮点值
        'float radian = radians(30.0);'+
        //求解旋转角度余弦值
        'float cos = cos(radian);'+
        //求解旋转角度正弦值
        'float sin = sin(radian);'+
        //引用上面的计算数据,创建绕x轴旋转矩阵
        // 1      0       0    0
        // 0   cosα   sinα   0
        // 0  -sinα   cosα   0
        // 0      0        0   1
        'mat4 mx = mat4(1,0,0,0,  0,cos,-sin,0,  0,sin,cos,0,  0,0,0,1);'+
        //引用上面的计算数据,创建绕y轴旋转矩阵
        // cosβ   0   sinβ    0
        //     0   1   0        0
        //-sinβ   0   cosβ    0
        //     0   0   0        1
        'mat4 my = mat4(cos,0,-sin,0,  0,1,0,0,  sin,0,cos,0,  0,0,0,1);'+
        //两个旋转矩阵、顶点齐次坐标连乘
        '   gl_Position = mx*my*apos;' +
        '}';
    //片元着色器源码
    var fragShaderSource = '' +
        'void main(){' +
        '   gl_FragColor = vec4(1.0,0.0,0.0,1.0);' +
        '}';
    //初始化着色器
    var program = initShader(gl,vertexShaderSource,fragShaderSource);
    //获取顶点着色器的位置变量apos
    var aposLocation = gl.getAttribLocation(program,'apos');

    //9个元素构建三个顶点的xyz坐标值
    var data=new Float32Array([
        //z为0.5时,xOy平面上的四个点坐标
         0.5,  0.5,  0.5,
        -0.5,  0.5,  0.5,
        -0.5, -0.5,  0.5,
         0.5, -0.5,  0.5,
        //z为-0.5时,xOy平面上的四个点坐标
         0.5,  0.5, -0.5,
        -0.5,  0.5, -0.5,
        -0.5, -0.5, -0.5,
         0.5, -0.5, -0.5,
        //上面两组坐标分别对应起来组成一一对
        0.5,  0.5,  0.5,
        0.5,  0.5,  -0.5,

        -0.5,  0.5,  0.5,
        -0.5,  0.5,  -0.5,

        -0.5, -0.5,  0.5,
        -0.5, -0.5,  -0.5,

        0.5, -0.5,  0.5,
        0.5, -0.5,  -0.5,
    ]);

    //创建缓冲区对象
    var buffer=gl.createBuffer();
    //绑定缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
    //顶点数组data数据传入缓冲区
    gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
    //缓冲区中的数据按照一定的规律传递给位置变量apos
    gl.vertexAttribPointer(aposLocation,3,gl.FLOAT,false,0,0);
    //允许数据传递
    gl.enableVertexAttribArray(aposLocation);

    //LINE_LOOP模式绘制前四个点
    gl.drawArrays(gl.LINE_LOOP,0,4);
    //LINE_LOOP模式从第五个点开始绘制四个点
    gl.drawArrays(gl.LINE_LOOP,4,4);
    //LINES模式绘制后8个点
    gl.drawArrays(gl.LINES,8,8);

    //声明初始化着色器函数
    function initShader(gl,vertexShaderSource,fragmentShaderSource){
        var vertexShader = gl.createShader(gl.VERTEX_SHADER);
        var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(vertexShader,vertexShaderSource);
        gl.shaderSource(fragmentShader,fragmentShaderSource);
        gl.compileShader(vertexShader);
        gl.compileShader(fragmentShader);
        var program = gl.createProgram();
        gl.attachShader(program,vertexShader);
        gl.attachShader(program,fragmentShader);
        gl.linkProgram(program);
        gl.useProgram(program);
        return program;
    }
</script>
</body>
</html>


效果图:

image.png

作者:admin
admin
TTF的家园-www.ttfde.top 个人博客以便写写东西,欢迎喜欢互联网的朋友一起交流!

本文》有 0 条评论

留下一个回复