上一篇的补充,通过绘制三角形来完成矩形的绘制。此外,完成章节后练习。

绘制矩形

一个矩形由两个三角形组成,因此绘制矩形需要绘制两个三角形,一共6个顶点,其中2个顶点重复画了两次。

为了减小开销,仅储存矩形的4个顶点来完成绘制,需要使用Element Buffer Object按照绘制顺序存储顶点索引。

举例说明:矩形四个顶点(a, b, c, d),EBO中存储的索引为(0, 1, 2, 0, 2, 3),表示矩形由三角形abc和acd组成。

创建和配置EBO的方法与VBO类似:

初始化顶点和索引数组

float vertices[] = {0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f};
unsigned int indices[] = {0, 1, 2,
1, 2, 3};

创建EBO

unsigned int EBO;
glGenBuffers(1, &EBO);

配置EBO

同样可以通过绑定VAO来保存EBO的配置。



但要注意,和VBO不同的是,在解绑VAO之前,不可以解绑EBO。

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

渲染循环

在使用EBO时,调用glDrawElements函数代替glDrawArrays函数。

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

练习

1. Try to draw 2 triangles next to each other using glDrawArrays by adding more vertices.

float vertices[] = {0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.0f, 1.0f, 0.0f};
while(!glfwWindowShouldClose(window)){

    processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}

2. Create the same 2 triangles using two different VAOs and VBOs for their data.

float vertices1[] = {0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f}; float vertices2[] = {0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.0f, 1.0f, 0.0f};
unsigned int VBO[2];
unsigned int VAO[2];
glGenVertexArrays(2, VAO);
glGenBuffers(2, VBO); glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while(!glfwWindowShouldClose(window)){

    processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(VAO[1]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}

*3.Create two shader programs where the second program uses a different fragment shader that outputs the color yellow; draw both triangles again where one outputs the color yellow. *

int fragmentShader[2];
const char *fragmentShaderSource1 = "#version 330 core\n"
"out vec4 fragColor;"
"void main()"
"{fragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);}";
const char *fragmentShaderSource2 = "#version 330 core\n"
"out vec4 fragColor;"
"void main()"
"{fragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);}";
fragmentShader[0] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader[0], 1, &fragmentShaderSource1, NULL);
glCompileShader(fragmentShader[0]); fragmentShader[1] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader[1], 1, &fragmentShaderSource2, NULL);
glCompileShader(fragmentShader[1]); shaderProgram[0] = glCreateProgram();
glAttachShader(shaderProgram[0], vertexShader);
glAttachShader(shaderProgram[0], fragmentShader[0]);
glLinkProgram(shaderProgram[0]);
shaderProgram[1] = glCreateProgram();
glAttachShader(shaderProgram[1], vertexShader);
glAttachShader(shaderProgram[1], fragmentShader[1]);
glLinkProgram(shaderProgram[1]); glDeleteShader(vertexShader);
glDeleteShader(fragmentShader[0]);
glDeleteShader(fragmentShader[1]);
while(!glfwWindowShouldClose(window)){

    processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram[0]);
glBindVertexArray(VAO[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(shaderProgram[1]);
glBindVertexArray(VAO[1]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}

OpenGL学习(2)——绘制三角形(补)的更多相关文章

  1. Android OpenGL 入门示例----绘制三角形和正方形

    Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况.本文记录OpenGL在Android上的入门级示例 ...

  2. Linux OpenGL 实践篇-3 绘制三角形

    本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用. 顶点数组对象 顶点数组对象负责管理一组顶点属性,顶点属性包括位置.法线.纹理坐标等. OpenGL缓存 OpenGL缓存实质上 ...

  3. iOS OpenGL ES简单绘制三角形

    OpenGL 是用于2D/3D图形编程的一套基于C语言的统一接口. windows,Linux,Unix上均可兼容. OpenGL ES 是在OpenGL嵌入式设备上的版本, android/iOS ...

  4. OpenGL学习(2)——绘制三角形

    在创建窗口的基础上,添加代码实现三角形的绘制. 声明和定义变量 在屏幕上绘制一个三角形需要的变量有: 三角形的三个顶点坐标: Vertex Buffer Object 将顶点数据存储在GPU的内存中: ...

  5. OpenGL学习进程(11)第八课:颜色绘制的详解

        本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...

  6. OpenGL学习进程(10)第七课:四边形绘制与动画基础

        本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图 ...

  7. OpenGL学习进程(4)第二课:绘制图形

    本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...

  8. 1.opengl绘制三角形

    顶点数组对象:Vertex Array Object,VAO,用于存储顶点状态配置信息,每当界面刷新时,则通过VAO进行绘制. 顶点缓冲对象:Vertex Buffer Object,VBO,通过VB ...

  9. Android OpenGL ES(十)绘制三角形Triangle .

    三角形为OpenGL ES支持的面,同样创建一个DrawTriangle Activity,定义6个顶点使用三种不同模式来绘制三角形: float vertexArray[] = { -0.8f, - ...

随机推荐

  1. USB 相关笔记

    1分析已有代码项目 Android从USB声卡录制高质量音频-----使用libusb读取USB声卡数据 github 项目:usbaudio-android-demo usb声卡取数据项目也是参考的 ...

  2. 【待补充】[Linux] nc

    [nc 是做什么的] [nc怎么用] 查看帮助 nc -help # 查看帮助 nc -help # 监听端口 -l, --listen Bind and listen for incoming co ...

  3. Custom Voice 操作步骤

    首先,准备数据 1.Unicode格式的Transcript 2wav格式语音数据,并打包 好,现在POSTMAN进行api测试. 先拿着订阅密钥(Subscription Key)获取令牌(Toke ...

  4. DevExpress05、TileControl、AlertControl

    TileControl控件 该控件是根据Windows 8的用户界面设计的,可以轻松地把各个控制块集成到窗体上. 1.   IndertBetweenGroups属性 控制两个Group之间的间距: ...

  5. 单一事件中心管理组件通信( vuex )

    有时候两个组件也需要通信(非父子关系).在简单的场景下,可以使用一个空的 Vue 实例作为中央事件总线: 补充$emit ,$on的讲解 代码: <!DOCTYPE html> <h ...

  6. 死磕nginx系列--使用nginx做负载均衡

    使用nginx做负载均衡的两大模块: upstream 定义负载节点池. location 模块 进行URL匹配. proxy模块 发送请求给upstream定义的节点池. upstream模块解读 ...

  7. Java 回调函数例子

    首先定义一个类Caller,按照上面的定义就是程序员A写的程序a,这个类里面保存一个接口引用. public class Caller { private MyCallInterface callIn ...

  8. MyBatis实战之解析与运行

    本次所谈的原理仅仅只涉及基本的框架和核心代码,并不会全部都说到,比如关于MyBatis是如何解析XML文件和其他配置文件从而的到内容,还有就是JDBC如何使用,关于JDBC如何使用,可以参考我的这篇博 ...

  9. WorldWind源码剖析系列:图层管理器按钮类LayerManagerButton和菜单条类MenuBar

    WorldWindow用户定制控件类中所包含的的可视化子控件主要有:图层管理器按钮类LayerManagerButton和菜单条类MenuBar.BmngLoader类中所包含的的可视化子控件主要有: ...

  10. ICC2 常用命令

    1. 关于 data preparation : report_ref_libs : report reference library report_lib  lib_aa : report the ...