01、WebGL初尝试

1、opengl、webgl、threejs、opengl es2.0之间的关系?
WebGL标准来自OpenGL ES 2.0,OpenGL ES 2.0的标准来自纯可编程管线技术,把原来很多API给裁剪掉了。
OpenGL ES 2.0:OpenGL是针对PC端的桌面的,OpenGL ES是针对嵌入式移动设备,在OpenGL的基础上裁剪了一些固定管线技术与使用起来很慢的API,采用了可编程管线的技术。
2、查询WebGl相关API的网址?
https://www.khronos.org/webgl/

image.png

3、使用齐次坐标的好处?
其一是区分向量和点,向量加0,点加1;
其二是易于进行仿射变化(平移、缩放、旋转)
4、尝试编写第一个WebGL程序?了解在显卡上是如何完成绘制一个三角形
4.1 顶点着色器与片元着色器
(1)在顶点着色器上定义一个attribute类型的三维变量v3Position,用来存储需要绘制的顶点的三维坐标,在main函数中加1.0参数为表示成齐次坐标的形式,赋值给内置变量gl_Position.
(2)在片元着色器里,定义一个四维变量表示rgba的值,赋值给内置变量gl_FragColor,这里填充的颜色是对三角形内的元素进行填充的颜色。片元即像素,对像素进行着色。

    <!-- 
        这里的代码是在显卡上执行的,现在都还只是一些字符串,需要在后面进行编译、连接
        定义一个attribute类型的三维变量(顶点的xyz坐标)
        在main函数中,转成4维的赋值给内置变量gl_Position 
    -->
    <script id="shader-vs" type="x-shader/x-vertex">
        attribute vec3 v3Position; 
        void main(void) { 
            gl_Position = vec4(v3Position, 1.0); 
        }
    </script>
    <!-- 2、片元着色器:给绘制结果填充颜色 -->
    <script id="shader-fs" type="x-shader/x-fragment">
        void main(void) { 
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); 
        }
    </script>

4.2 程序具体执行流程描述
(1)定义一个canvas画布,id是mycanvas。资源加载完之后,会调用Init()函数进行初始化操作。

<body onload="Init()">
    <canvas id="mycanvas" style="border:1px solid red;" width="600" height="450"></canvas>
</body>

(2)Init函数的内部
具体解释可以看代码的内部注释。
大致的流程是:
1)先获取界面上的mycanvas对象,调用getContext函数创建webgl上下文对象,设置坐标原点位置与窗口大小。
2)在前面有写到的顶点着色器与片元着色器的代码,其实相当于是一些字符串,需要在Init函数的内部做创建对象等一系列操作。
3)创建。创建顶点着。色器对象与片元着色器对象,创建调用的函数是createShader(),传入参数是需要创建的Shader类型。
4)填充。新创建的着色器对象需要指定它的源代码(用上面定义的着色器字符串填充),调用的方法是shaderSource(),参数包括新创建的着色器对象与定义一个获取着色器字符串的函数。
5)编译。对这两个填充完毕的对象进行编译,编译的结果是生成在显卡上执行的汇编代码。调用的函数是compileShader(),参数是需要编译的对象。
6)编译出错处理。
7)创建程序.exe对象。调用createProgram()函数生成一个program程序对象。
8)生成exe可执行代码。将program对象与着色器的汇编对象代码关联,形成exe可执行代码。调用attachShader()函数,传入的参数是program对象与shader对象进行关联。
9)链接。调用linkProgram()进行链接,形成真正意义上的程序。
10)使用。使用可执行程序,useProgram()。

11)传入真正的三角形数据,进行绘制。
12)声明三角形的顶点坐标位置数组,以屏幕中心为原点
13)显卡中创建一个缓冲区对象,并绑定为数组缓存类型,把jsArrayData中的数据传到显存中。调用函数createBuffer()创建缓冲区,bindBuffer()函数绑定缓冲区类型,bufferData()函数传入真实数据。
14)调用clearColor()设置缓冲区的背景颜色与透明度,clear()函数真正将颜色缓冲区设置成上面设置的颜色。
15)通过bindAttribLocation()函数,给shader-vs里的attribute类型的v3Position变量赋值,后面可以通过给v3PositionIndex赋值从而给v3Position赋值。
16)启用v3PositionIndex变量。调用enableVertexAttribArray()函数,将已经与shader的变量绑定的变量启动。
17)调用drawArrays()将三角形画出来,参数是从第几个元素开始,绘制几个。

 function Init() {
            var canvas = document.getElementById('mycanvas');
            //创建opengl上下文,返回一个opengl对象
            webgl = canvas.getContext("webgl");
            //
            webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight);

            //2.1 创建顶点着色器、片元着色器对象
            vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
            fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
            //2.2 给这两个对象填充东西
            webgl.shaderSource(vertexShaderObject, getShaderSource("shader-vs"));
            webgl.shaderSource(fragmentShaderObject, getShaderSource("shader-fs"));
            //2.3 编译这两个对象,编译的结果是生成显卡可执行的汇编代码
            webgl.compileShader(vertexShaderObject);
            webgl.compileShader(fragmentShaderObject);
            //2.4 编译有错
            if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
                alert("error,vectorshader");
                console.log(webgl.getShaderInfoLog(vertexShaderObject));
                return;
            }
            if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
                alert("error,FRAGshader");
                console.log(webgl.getShaderInfoLog(fragmentShaderObject));
                return;
            }
            //2.5 创建一个程序.exe
            programObject = webgl.createProgram();
            //2.6 program与shader链接起来形成可执行代码
            webgl.attachShader(programObject, vertexShaderObject);
            webgl.attachShader(programObject, fragmentShaderObject);
            //2.7 webgl绑定顶点数据,给shader-vs里的attribute类型的v3Position变量赋值
            //    通过给v3PositionIndex赋值从而给v3Position赋值
            webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position');
            //2.8 链接  成为真正意义上的程序
            webgl.linkProgram(programObject);
            //2.9 使用可执行程序
            webgl.useProgram(programObject);

            //3.1 声明三角形的顶点坐标位置数组,以屏幕中心为原点
            var jsArrayData = [
                    0.0,
                    1.0,
                    0.0, -1.0, -1.0,
                    0.0,
                    1.0, -1.0,
                    0.0
                ]
                //3.2 在显卡中创建一个缓冲区对象,并绑定为数组缓存类型,把jsArrayData中的数据传到显存中
            triangleBuffer = webgl.createBuffer();
            webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
            webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);


            //相当于画刷颜色用float,其他颜色用123/255表示
            webgl.clearColor(0.0, 0.0, 0.0, 1.0);
            //将画布设置成上述颜色,帧缓冲区就是相当于一张二维图片
            //此处是颜色缓冲区
            webgl.clear(webgl.COLOR_BUFFER_BIT);

            //4.1 使用triangleBuffer缓冲区
            webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
            //4.2 启用v3PositionIndex变量
            webgl.enableVertexAttribArray(v3PositionIndex);
            //4.3 给该变量赋具体的值,返回指针指向jsArrayData数组。
            //    给什么变量,赋值维数,赋值类型,是否规格化,变量之间的间隔字节数,从缓冲区第几个元素开始取值
            webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0);
            //4.4 从第几个元素开始,绘制几个
            webgl.drawArrays(webgl.TRIANGLES, 0, 3);
        }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容