Linux OpenGL 实践篇-3 绘制三角形
本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用。
顶点数组对象
顶点数组对象负责管理一组顶点属性,顶点属性包括位置、法线、纹理坐标等。
OpenGL缓存
OpenGL缓存实质上是OpenGL服务端的一块内存区域,用于存储数据。OpenGL的所有数据都是存储在缓存对象中的。
在本次实践的思路是创建一个顶点数组对象来管理所绘制的三角性的顶点数据,数据存储在缓存对象中,然后使用绘制API绘制三角形。
首先,创建顶点数组对象,函数原型:void genVertexArrays(GLsizei n, GLuint *arrays);其中n表示数量,结果保存在arrays中。
然后使用glBindVertexArray绑定数组对象,那为什么需要绑定数组对象了?在使用OpenGL的过程中会生成的非常多的对象,每一种对象都会有许多的操作,如使用glVertexAttribPointer设置顶点数组对象的属性,在进行这些操作之前需要明确是对哪个对象进行操作,而绑定机制就是做这件事的。OpenGL绑定对象后,接下来的操作就表示作用于这个对象。示例如下:
glGenVertexArrays(NumVAOs,VAOs);
glBindVertexArray(VAOs[Triangles]);
绑定好对象后我们就需要设置这个顶点数组对象所管理的顶点数据,这个时候就需要缓存了。创建和绑定类似顶点数组对象,但最后需要glBufferData来输入数据,示例如下:
glGenBuffers(NumBuffers,Buffers);
glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
创建缓存
glGenBuffers(GLsizei n, GLuint* buffers);//创建n个缓存对象,保存在buffers数组中
向缓存中输入或输出数据
glBindBuffer(GLenum target, GLuint buffer); //绑定缓存到target指定的缓存结合点
glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); //为绑定到target的缓存对象分配size大小的存储空间,如果data不为NULL,则使用data初始化所为配的存储空间。usage指示缓存中的数据可能具备的一些特定的用途。
glBufferSubData(GLenum target, GLsizeiptr offset, GLsizeiptr size, const GLvoid* data);//使用新数据替换缓存中的部分数据
清除数据
glClearBufferData(GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data); //使用data填充缓存存储空间,format和type指定data的数据格式和类型,填充前需要把data转化为internalformat
glClearSubBufferData(GLenum target, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); //同上,区别是这个方法只填充offset和size指定的区域;
接着我们需要设置顶点属性,使用glVertexAttribPointer.示例如下:
glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));
设置顶点属性
glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
这些都做好了之后,我们就可以使用顶点数组对象来绘制我们的三角形了。
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES,0,NumVertices);
使用顶点数据之前需要先绑定,表示当前绘制使用该对象。
绘制命令
glDrawArrays(GLenum mode, GLint first, GLsizei count);//直接读取顶点数据绘制
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);基于索引绘制(即所有的顶点在一个数组中,使用索引来引用顶点数据)
具体的示例代码如下:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include "ShaderHelper.h" #define BUFFER_OFFSET(n) ((GLvoid*)n)
enum VAO_IDs { Triangles,NumVAOs};
enum Buffers_IDs { ArrayBuffer, NumBuffers }; enum Attrib_IDs { vPosition=0 }; GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers]; const GLuint NumVertices=6; void init();
void display(); int main(int argc,char* argv[])
{
glutInit(&argc,argv);
glutInitContextVersion(3,3);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(0,0);
glutInitWindowSize(300,300);
glutCreateWindow("Frame Buffer"); /* const GLubyte* name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字
const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬>
件平台
const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回当前OpenGL实现的版本号
const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回当前GLU工具库版本
printf("OpenGL实现厂商的名字:%s\n", name);
printf("渲染器标识符:%s\n", biaoshifu);
printf("OOpenGL实现的版本号:%s\n",OpenGLVersion );
printf("OGLU工具库版本:%s\n", gluVersion);*/
glewExperimental=GL_TRUE;
glewInit();
init();
glutDisplayFunc(display); glutMainLoop();
return 0;
} void init()
{
glClearColor(0.0,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glOrtho(-5,5,-5,5,5,15);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0,0,10,0,0,0,0,1,0); glGenVertexArrays(NumVAOs,VAOs);
glBindVertexArray(VAOs[Triangles]); GLfloat vertices[NumVertices][2]={
{-0.90,-0.90},
{0.85, -0.90},
{ -0.90, 0.85 },
{ 0.90, -0.85 },
{ 0.90, 0.90 },
{-0.85, 0.90 },
}; glGenBuffers(NumBuffers,Buffers);
glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); ShaderInfo shaders[] = {
{GL_VERTEX_SHADER,"triangles.vert"},
{GL_FRAGMENT_SHADER,"triangles.frag"},
{GL_NONE,NULL},
}; GLuint program = LoadShaders(shaders);
glUseProgram(program); glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0)); glEnableVertexAttribArray(vPosition);
} void display()
{
glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES,0,NumVertices); glFlush();
}
注意:代码根据红宝书编写,一些辅助性代码(如LoadShader)并未贴出,详情请参照www.opengl-readbook.com。
GLEW说明
GLEW(OpenGL Extension Wrangler) 是OpenGL的另一个辅助库,主要封装了从OpenGL库中获取函数地址的过程,还包含了一些可以跨平台使用的OpenGL编程方法。
最终的效果如下:

Linux OpenGL 实践篇-3 绘制三角形的更多相关文章
- iOS OpenGL ES简单绘制三角形
OpenGL 是用于2D/3D图形编程的一套基于C语言的统一接口. windows,Linux,Unix上均可兼容. OpenGL ES 是在OpenGL嵌入式设备上的版本, android/iOS ...
- Android OpenGL 入门示例----绘制三角形和正方形
Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况.本文记录OpenGL在Android上的入门级示例 ...
- Linux OpenGL 实践篇-4 坐标系统
OpenGL中顶点经过顶点着色器后会变为标准设备坐标系.标准设备坐标系的各坐标的取值范围是[-1,1],超过这个范围的点将会被剔除.而这个变换的过程可描述为顶点在几个坐标系统的变换,这几个坐标系统为: ...
- Linux OpenGL 实践篇-16 文本绘制
文本绘制 本文主要射击Freetype的入门理解和在OpenGL中实现文字的渲染. freetype freetype的官网,本文大部分内容参考https://www.freetype.org/fre ...
- Linux OpenGL 实践篇-14-多实例渲染
多实例渲染 OpenGL的多实例渲染是一种连续执行多条相同的渲染命令的方法,并且每条命令产生的结果都有轻微的差异,通常用于渲染大量的几何物体. 设想一个场景,比如太空,我们需要渲染数以万记的星球,如果 ...
- Linux OpenGL 实践篇-13-geometryshader
几何着色器 几何着色器是位于图元装配和片元着色器之前的一个着色器阶段,是一个可选阶段.它的输入是一个图元的完整的顶点信息,通常来自于顶点着色器,但如果细分计算着色器启用的话,那输入则是细分计算着色器的 ...
- Linux OpenGL 实践篇-5 纹理
纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...
- Linux OpenGL 实践篇-2 创建一个窗口
OpenGL 作为一个图形接口,并没有包含窗口的相关内容,但OpenGL使用必须依赖窗口,即必须在窗口中绘制.这就要求我们必须了解一种窗口系统,但不同的操作系统提供的创建窗口的API都不相同,如果我们 ...
- Linux OpenGL 实践篇-11-shadow
OpenGL 阴影 在三维场景中,为了使场景看起来更加的真实,通常需要为其添加阴影,OpenGL可以使用很多种技术实现阴影,其中有一种非常经典的实现是使用一种叫阴影贴图的实现,在本节中我们将使用阴影贴 ...
随机推荐
- java中有关流操作的类和接口
一.java操作l流有关的类和接口 1.File 文件类 2.RandomAccessFile 随机存储文件类 3.InputStream 字节输入流 4.OutputStream 字节输出流 5.R ...
- kvm之十二:虚拟机迁移
虚拟机迁移该方式要确保虚拟机是关机状态.virsh shutdown snalevirsh dumpxml snale > /etc/libvirt/qemu/snale_qy.xml // ...
- 解决C盘中的文件不能修改问题
在不能修改的文件右击属性>点击安全>编辑>点击用户>完全控制. 步骤如图: 最后点击确定.
- 项目Alpha冲刺Day10
一.会议照片 二.项目进展 1.今日安排 解决前后台联调问题,完善全局的请求和路由跳转处理,添加空文件完善路由信息,优化界面跳转等待.完成个人信息和修改密码.修改前台数据组织和方法调用方式.解决登录和 ...
- MySort实验报告
实验日期:2017.5.2 实验内容:利用sort方法对已给的数据进行重新排序. 实验原图: 对原代码进行添加,补充新的内容: 在for循环中,新输入一个变量j,并新定义新的长度toSort.leng ...
- 关于Android 7.0(API24)相机的问题汇总
在开发Android项目的时候,我们会用到相机,有些时候只是开发一个普通的扫码,仅仅赋予一下 权限 就好了,但是有些时候是需要拍照和从相册中获取照片的.我们在Android 5.0以及5.0之前调用相 ...
- 前端之bootstrap模态框
简介:模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. Modal简介 Modal实现弹出表单 M ...
- mycat入门_介绍与安装
利用闲暇时间接触了下mycat. 一.介绍 1.概述: 国内最活跃的.性能最好的开源数据库中间件,可以理解为数据库和应用层之间的一个代理组件. 2.作用: 读写分离.分表分库.主从切换. 3.原理: ...
- nyoj Dinner
Dinner 时间限制:100 ms | 内存限制:65535 KB 难度:1 描述 Little A is one member of ACM team. He had just won t ...
- PC或者手机弹出窗效果
http://layer.layui.com/ 这个网站提供弹窗,是在jq封装的,弹窗之后,背景页面还可以滑动. 这个里面的js可能也会包含css,这个css不能移动位置,否则会报错,还有谷歌浏览器在 ...