一看就懂的视频教程 (opengl画空心三角形)

你知不知道

你知不知道

我等到花儿也谢了

绘制三角形已经到了第四篇了,然而三角形还是等不到踪影,不少读者已经开始按耐不住内心的躁动了,好消息来了, 本文就将完成绘制三角形的任务

通过阅读本文,你将获得以下收获:

1.如何使用OpenGL es基本图元绘制点、线、三角形

2.如何使用OpenGL es更高级的图元绘制更复杂的图形

上篇回顾

上一篇博文一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(三)重点介绍了 图元和片段着色器以及OpenGL渲染指令 ,憋了这么久,今天开始,让我们一起体验 渲染 的快感~~

opengl教程三角形,一看就懂的教程视频

绘制图形

回顾下前几篇真正执行渲染的代码:

/**        此处开始将数据传入图形渲染管线              **/
    static float triangleVer[] = {
            0.8f, -0.8f, 0.0f,
            -0.8f, -0.8f, 0.0f,
            0.0f, 0.8f, 0.0f,
    };
    
     GLuint apos = static_cast<GLuint>(glGetAttribLocation(program, "aPosition"));
    glEnableVertexAttribArray(apos);
    glVertexAttribPointer(apos, 3, GL_FLOAT, GL_FALSE, 0, triangleVer);
    
     /**        此处结束将数据传入图形渲染管线              **/
     
      /**        此处开始将图像渲染到屏幕              **/

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
   
    eglSwapBuffers(display, winSurface);
    
     /**        此处结束图像渲染              **/

这里是渲染三角形的代码,glDrawArrays方法传入的图元类型是GL_TRIANGLE_STRIP,但是路要一步一步走,我们就先从最基本的 绘制开始吧。

在前几篇给的代码中,使用的都是直接获取着色器变量名的方式: GLuint apos = static_cast<GLuint>(glGetAttribLocation(program, "aPosition"));

还记得在一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(二) 中 GLSL一章节 中曾经提到过 layout 修饰符:

layout是GLSL的几个 修饰符 中的一个,一般用来 指定变量布局 的,可以说是 着色器和客户端程序或者其他阶段着色器的通信接口

何为变量的位置?你可以想象每一个着色器程序是一层楼,每个需要对接外部的变量住在一个个房间中,假如你现在是客户端的C++程序,你想给着色器里面某个变量传参,然后 你又不知道变量名字,如果此时你知道变量所在的房间编号,那你照样还是可以将数据传给变量 ,就像一个蹑手蹑脚的间谍,偷偷打开对应location的房门,偷偷将一份机密文件交给里面的人(location对应变量)。所以 layout加location的作用已经很明显了,你不需要房间里面住着谁(不用知道变量名称),只需要知道房间号(location),也能按成变量数值的传递

(直到今日,我依旧想为我当初的比喻点赞)

opengl教程三角形,一看就懂的教程视频

于是在今天的例子,我们统一使用这个新特性吧~

C++音视频学习资料免费获取方法:关注 音视频开发T哥 ,+ 「链接」 即可免费获取2023年最新C++音视频开发进阶独家免费学习大礼包!

绘制点

点的图元类型为:

GL_POINTS

表示 每个顶点在屏幕上都是单独的点 (想想一个点确实也玩不出其他花了)

于是渲染代码变为:

//三个点坐标
    static float pointsVer[] = {
            0.8f, -0.8f, 0.0f,
            -0.8f, -0.8f, 0.0f,
            0.0f, 0.8f, 0.0f,
    };

//旧的传输数据方式,已经out了
//    GLuint apos = static_cast<GLuint>(glGetAttribLocation(program, "aPosition"));

//通过layout传输数据,传给了着色器中layout为0的变量
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, pointsVer);
    //打开layout为0的变量传输开关
    glEnableVertexAttribArray(0);

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
//从第0个顶点开始,取三个顶点,绘制成三个点到后备缓冲区
    glDrawArrays(GL_POINTS, 0, 3);
    //窗口显示,交换后备缓冲区到前台
    eglSwapBuffers(display, winSurface);

这里顶点属性数组传入的是6个浮点数,然后通过glVertexAttribPointer方法告知OpenGL 如何解析 这个顶点属性数组(如有不清楚,请看一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(二)中的叙述),在这里,就是 将三个顶点属性依次传给顶点着色器中layout为0的变量 ,那么顶点着色器现在是什么样子的呢:

        #version 300 es
        layout (location = 0) 
        in vec4 aPosition;//输入的顶点坐标,会在程序指定layout将数据输入到该字段

        void main() {
           //直接把传入的坐标值作为传入渲染管线。gl_Position是OpenGL内置的表示坐标的变量
            gl_Position = aPosition;   
            //点的尺寸
            gl_PointSize = 50.0;
        }"

注意这里需要指定点的尺寸,点在这里以正方形呈现,所以指定的就是正方形的边长

片段着色器和上一篇一摸一样,只是给当前片段赋颜色值:

       #version 300 es
       precision mediump float;
       out vec4 FragColor;

        void main() {
           //给当前片段赋颜色值
           FragColor = vec4(1.0,0.5,0.5,1.0);
        }

于是乎 顶点着色器执行3次 ,得到 三个顶点的最终坐标 传到图形渲染管线中,执行完图元装配,光栅化之后,每个片段都执行一次片段着色器 ,于是乎再执行完渲染程序,三个小红点便跃然纸上:

opengl教程三角形,一看就懂的教程视频

那么绘制4个点呢?只要传入的顶点属性数组为4*3个, 并通过glVertexAttribPointer方法告知OpenGL有4个顶点属性即可 。以此类推~

绘制线段

说起绘制线段,OpenGL就开始展现他*器武**库之丰富了。

绘制线段的图元类型有3种,分别为:

GL_LINES                         
GL_LINE_LOOP                      
GL_LINE_STRIP   

三者的区别在上一篇文章图元装配一章已经有所提及:

opengl教程三角形,一看就懂的教程视频

如果现在传入顶点着色器的顶点数组的元素分别为:v0,v1,v2,v3,v4,v5,v6,v7,那么 对应的图元效果图 如下所示:

opengl教程三角形,一看就懂的教程视频

相信在做列位看官都能理解它们的区别了,接下来就实践分别瞥一瞥它们各自的风采。

这次传4个点,依次每种图元看看效果:

//四个点坐标
    static float lineVer[] = {
            0.8f, -0.8f, 0.0f,
            -0.8f, -0.8f, 0.0f,
            0.0f, 0.8f, 0.0f,
            0.4f, 0.8f, 0.0f,
    };

不过画线之前,别忘了要 指定线段的宽度,不然宽度就是0 ,即一条抽象到看不见的线段。

//设置线段宽度
glLineWidth(20);

GL_LINES

glDrawArrays(GL_LINES, 0, 4);

从第0个顶点开始,读取4个顶点,每两个组成一对连成线

opengl教程三角形,一看就懂的教程视频

是屏幕下方两条红色横线,下面一条的顶点分别为 0.8f, -0.8f, 0.0f -0.8f, -0.8f, 0.0f ,上面的线段顶点分别为 0.0f, 0.8f, 0.0f 0.4f, 0.8f, 0.0f

GL_LINE_STRIP :

glDrawArrays(GL_LINE_STRIP, 0, 4);

opengl教程三角形,一看就懂的教程视频

这种是 从第一个顶点开始一路连到到最后一个顶点

GL_LINE_LOOP

glDrawArrays(GL_LINE_LOOP, 0, 4);

opengl教程三角形,一看就懂的教程视频

还是这种给力, 一路连成闭环

绘制三角形

画完线段,接下来就是开始令人兴奋的三角形了。而三角形,就更能体现OpenGL就开始展现他*器武**库之丰富,简直是东风快递、民兵、白杨皆有之。

opengl教程三角形,一看就懂的教程视频

顶点属性数组改为传入3个顶点属性(当然你要传4个也行,在后面读取的时候指定读取几个就可以了):

static float triangleVer[] = {
        0.8f, -0.8f, 0.0f,
        -0.8f, -0.8f, 0.0f,
        0.0f, 0.8f, 0.0f,
};

三角形的图元类型也是三种,我们也来一一领略一番:

opengl教程三角形,一看就懂的教程视频

三角形的就比较复杂了:

这是官网的解释:

opengl教程三角形,一看就懂的教程视频

第一种 GL_TRIANGLES 是每三个顶点就分别连成一个三角形,也就是说把顶点数组 每三个为一组分,互相之间没有瓜葛

第二种 GL_TRIANGLE_STRIP 就比较牛逼了, 从第0个顶点开始,每3个顶点连在一起形成三角形 , v0,v1,v2为一个三角形,v1,v2,v3为一个三角形,v2,v3,v4为一个三角形依此类推。

如果顶点个数为n,则可以生成n-2个三角形

第三种 GL_TRIANGLE_FAN 是谁是 第一个顶点谁就拥有优先的绘图权 (排在第一位的果真是大佬), 第一个顶点会和后面每2个顶点为一组绘制三角形 。v0,v1,v2为一个三角形,v0,v2,v3为一个三角形,v0,v3,v4为一个三角形依此类推。最后形成一个 扇形形状

用代码一一感受它们的风采吧:

首先用最简单的三个点绘制:

static float triangleVer[] = {
        0.8f, -0.8f, 0.0f,
        -0.8f, -0.8f, 0.0f,
        0.0f, 0.8f, 0.0f,
};
//对于三个点来说,GL_TRIANGLES,GL_TRIANGLE_STRIP和GL_TRIANGLE_FAN绘制结果都一样
glDrawArrays(GL_TRIANGLES, 0, 3);

opengl教程三角形,一看就懂的教程视频

开始玩点好玩的了

将传入的顶点属性数组改为 6个元素

static float triangleVer[] = {
        0.8f, 0.8f, 0.0f,
        0.0f, 0.8f, 0.0f,
        0.4f, 0.4f, 0.0f,
        -0.8f, 0.5f, 0.0f,
        -0.4f, 0.8f, 0.0f,
        -0.8f, 0.8f, 0.0f,
};

绘制顶点数目也改为6 :

glDrawArrays(GL_TRIANGLES, 0, 6);

opengl教程三角形,一看就懂的教程视频

尝试下 GL_TRIANGLE_STRIP

opengl教程三角形,一看就懂的教程视频

惊奇发现已经面目全非了,几乎看不到三角形的痕迹了。

再看下 GL_TRIANGLE_FAN

opengl教程三角形,一看就懂的教程视频

更加没有三角形痕迹了,v5还被抛弃了什么鬼。

为什么呢?按照前面对GL_TRIANGLE_FAN的讲解,v0,v4,v5会连成一个三角形,不过仔细看坐标就会发现, 它们三个点是在一条直线上的,连不了三角形,索性直接抛弃了v5

opengl教程三角形,一看就懂的教程视频

其实OpenGL之前是有 四边形的图元类型的,但是在OpenGL3.1之后就被移除了 ,那这次就不讲了,那么问题来了,四边形要怎么绘制呢?

C++音视频学习资料免费获取方法:关注 音视频开发T哥 ,+正在跳转即可免费获取2023年最新C++音视频开发进阶独家免费学习大礼包!

其实答案已经在上面了, 通过GL_TRIANGLE_STRIP或者GL_TRIANGLE_FAN ,只要给 四个任何三个点不共线的点 ,就可以绘制出来。

三角形是最基本的图形,三角形三个点必然是共面的,所以在OpenGL的世界里,任何图形都可以通过三角形来构建。

举个例子,画个正方形瞧瞧?

opengl教程三角形,一看就懂的教程视频

static float triangleVer[] = {
        0.8f, 0.8f, 0.0f,
        0.8f, -0.8f, 0.0f,
        -0.8f, 0.8f, 0.0f,
        -0.8f, -0.8f, 0.0f,
};

使用GL_TRIANGLE_STRIP绘制:

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

show you the rectangle:

opengl教程三角形,一看就懂的教程视频

嗯?说好的正方形怎么变成长方形了。 坐标上确实是正方形,但是因为坐标是按照比例系数传的并且手机屏幕是长方形的 ,所以无奈被拉长。不过也是有办法解决的,后面讲矩阵的博文就告诉你们答案。

总结

本文主要详细介绍了OpenGL es各种 基本图元的绘制 ,通过本文的学习,各种基本图图元的绘制相信不在话下了,而且通过一些图元类型还可以玩出一些花了。现在距离一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(一)中 绘制三角形的终极任务只差那种看起来酷毙的绚烂的渐变色彩了 ,别急,还是那句话,* 欲知后事如何*,*且听下回分解* 哈哈。下一篇文章一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(五)

代码地址

opengl-es-study-demo (不断更新中)

参考

OpenGL官网Primitives Learn OpenGL

作者:半岛铁盒里的猫 链接:https://juejin.cn/post/7144335420644392991 来源:*土稀**掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在开发的路上你不是一个人,欢迎加入C++音视频开发交流群「链接」 大家庭讨论交流!