Linux OpenGL 实践篇-3 framebuffer

GLEW说明

  GLEW(OpenGL Extension Wrangler) 是OpenGL的另一个辅助库,主要封装了从OpenGL库中获取函数地址的过程,还包含了一些可以跨平台使用的OpenGL编程方法。

本次实践是使用数据缓存绘制两个三角形,重点是缓存的创建和数据输入。数据输入后,根据数据使用方式可分为非基于索引绘制和基于索引绘制,使用的方法分别为glDrawArray和glDrayElements。

首先,明确OpenGL缓存使用步骤:

  1. glGenBuffer
  2. glBindBuffer
  3. glBufferData
  4. glVertexAttribPointer
  5. glBindVertexArray
  6. glDrawArrays

简单来说就是:先创建缓存,然后输入缓存数据,然后绘制。以下是相关API的一个说明:

创建缓存

glGenBuffer(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(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);

绘制

glDrawArrays(GLenum mode, GLint first, GLsizei count);//直接读取顶点数据绘制

glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);基于索引绘制(即所有的顶点在一个数组中,使用索引来引用顶点数据)

以下是根据上述API编写的绘制两个三角形的例子。

#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。

最终的效果如下:

原文地址:https://www.cnblogs.com/xin-lover/p/8470247.html

时间: 2024-10-02 03:25:21

Linux OpenGL 实践篇-3 framebuffer的相关文章

Linux OpenGL 实践篇-1

本次实践所使用环境为CentOS 7. 参考:http://www.xuebuyuan.com/1472808.html OpenGL开发环境搭建: 1.opengl库安装 opengl库使用mesa库,安装命令: yum intall mesa* mesa库是一个开源的三维计算机图形库,以开源的形式实现了opengl应用程序接口.具体介绍:https://www.mesa3d.org/intro.html. 2.glut安装 下载freeglut,下载地址为: https://github.c

Linux OpenGL 实践篇-2 创建一个窗口

OpenGL 作为一个图形接口,并没有包含窗口的相关内容,但OpenGL使用必须依赖窗口,即必须在窗口中绘制.这就要求我们必须了解一种窗口系统,但不同的操作系统提供的创建窗口的API都不相同,如果我们在学习OpenGL时要去学习一整套的窗口系统,这将带来很多的不便,所以出现了GLUT.GLUT全称OpenGL Utility Toolkit,是一套和窗口系统无关的软件包,为我们提供了窗口创建,用户输入输出处理等功能.优点是:简小,精悍.注意GLUT并不是一个功能特别全面的窗口系统工具包,所以构建

Linux OpenGL 实践篇-6 光照

经典光照模型 经典光照模型通过单独计算光源成分得到综合光照效果,然后添加到物体表面特定点,这些成分包括:环境光.漫反射光.镜面光. 环境光:是指不是来特定方向的光,在经典光照模型中基本是个常量. 漫反射光:是散射在各个方向上均匀的表面特定光源.物体表面通过光照照亮,即使这个表面没有将光源直接反射到你的眼睛中.漫反射与眼睛的方向没有关系,但与光源的方向有关,当表面直接面向光源的时候会表现的亮一些,而倾斜的时候则暗一些,因为在现实中倾斜的表面接受的光要少一些.在经典光照模型中,我们使用表面的法向量来

Linux OpenGL 实践篇-9 模型

之前一直渲染箱子,显得有点单调.这一次我们绘制一个用艺术家事先用建模工具创建的模型. 本次实践参考:https://learnopengl-cn.github.io/03%20Model%20Loading/01%20Assimp/ 在之前我们的OpenGL实践中,绘制图形的过程是先定义顶点的位置.法线.纹理坐标(UV)等信息,按一定的规则组织后传给着色器处理,最终绘制到屏幕上.现在使用艺术家构建的模型,绘制的过程并没有变,只不过顶点和使用的贴图信息从原来我们自己定义变为从已构建好的模型中提取,

Linux OpenGL 实践篇-12-ProceduralTexturing

程序式纹理 简单的来说程序式纹理就是用数学公式描述物体表面的纹路 .而实现这个过程的着色器我们称之为程序纹理着色器,通常在这类着色器中我们能使用的输入信息也就是顶点坐标和纹理坐标. 程序式纹理的优点 1.程序式纹理的内存占用比预存纹理要低的多:因为程序式纹理主要是算法的实现,数据都是通过计算产生的: 2.程序生成的纹理没有固定的面积和分辨率,可以随意的应用到不同大小的物体,而不用担心精度不够的问题: 3.程序式纹理可以写入一些算法的关键参数,可以方便的供程序修改从而创建出有趣的效果,而预存的纹理

Linux OpenGL 实践篇-14-多实例渲染

多实例渲染 OpenGL的多实例渲染是一种连续执行多条相同的渲染命令的方法,并且每条命令产生的结果都有轻微的差异,通常用于渲染大量的几何物体. 设想一个场景,比如太空,我们需要渲染数以万记的星球,如果我们使用常规的做法,渲染的过程应该是是:绘制第一个星球glBindVertexArray--glDrawArrays或glDrawElements,然后使用同样的流程绘制其它的星球.但这种方式非常容易达到计算机的性能瓶颈,就算是渲染的物体是最简单的面片,因为在绘制的整个过程中,绘制物体的时间其实非常

Linux驱动框架之framebuffer驱动框架

1.什么是framebuffer? (1)framebuffer帧缓冲(一屏幕数据)(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备.帧缓冲(framebuffer) 是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作.这种操作是抽象的,统一的.用 户不必关心物理显存的位置.换页机制等等具体细节.这些都是由Framebuffer设备驱动来完成的. (2)从驱动来看,f

Linux内核修炼之framebuffer分析

Linux源码包中/document/fb/framebuffer.txt有如下介绍: The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and allows application software to access the graphics hardware through a wel

linux驱动开发之framebuffer驱动介绍

framebuffer是linux里面的显示设备.在驱动底下如何操作lcd实现图形的显示. 1.什么是framebuffer? (1)首先想一下在裸机中我们是怎么操作LCD的. Soc内部有lcd的控制器,Soc外面有lcd的驱动器,lcd的驱动器连接着lcd的屏幕,Soc的内部还有CPU,外部还有DDR内存.这些设备都参与到了lcd的显示中. 在裸机中我们是怎么搞的呢,lcd的驱动器和lcd的控制器之间通过排线进行链接,连接的接口就是lcd所特有的一个接口.lcd控制器里面是很多和lcd相关的