渲染世界的Opengl<1> Opengl基础知识整理

在进行Opengl学习之前,我将会对Opengl语言当中涉及到的诸多基础知识进行整理。一来对自己的思想进行整理,可以说是学习笔记。另外希望可以帮助到和我一样的小白,能够更快的上手入门。和CSDN诸君共勉。

首先关于OPENGL的环境配置,我安装的环境是VS2015+Opengl4.3。下面放出连接:
FreeGlut3.0
Glew1.13
对应的bin和include记得放到VS/VC对应的目录下。同时记得给C盘的Windows,MicrosoftSDKs 里面的最新版本拷贝一份dll过去。我的是v10.0。

1.Opengl程序的主要操作
(1)从Opengl的几何图元中设置数据,用于构建形状。
(2)使用着色器对输入的图源数据进行计算。
(3)将输入图元的数学描述转换为与屏幕位置对应的像素片元。即光栅化。
(4)针对光栅化过程产生的每一个片元,执行片元着色器,从而决定这个片元的最终颜色和位置。

注意:Opengl是客户端-服务端的形式实现的。

2.Opengl程序基本概念

渲染:计算机从模型创建最终图像的过程。
着色器:图形硬件所执行的一类特殊函数。即GPU编译的一种小型程序。分为以下两类:
顶点着色器:处理顶点数据。
片元着色器:处理光栅化之后的片元数据。
像素:显示器上最小的可见单元。(多重定义具体参见计算机图形学教材)
帧缓存:图形硬件设备管理的一块独立内存区域,可以直接映射到最终的显示设备上。

3.Opengl语法基础
函数:gl作为前缀,大写字母开头词组。类似驼峰命名法。
常量:GL_前缀,并且使用下划线来分隔单词。常量通过#define来完成的。
对于Opengl程序,适用版本高于3.1那么就需要指定至少两个着色器:顶点着色器和片元着色器。

4.Opengl渲染管线
定义:一系列数据处理过程,并且将应用程序的数据转换到最终渲染图像。

过程:
顶点着色=》细分着色=》几何着色=》光栅化单元对所有剪切区域内的图元生成片元数据,然后对每个生成的片元都执行一个片元着色器。

详细过程:
(1)向Opengl传送数据
需要将所有的数据都保存到缓存对象。由Opengl服务器端维护的一块内存区域。
(2)将数据传送到Opengl
通过绘制命令请求渲染几何图元。glDrawArrays()。
(3)顶点着色
对于绘制命令的每个顶点,Opengl会调用一个顶点着色器处理顶点相关的数据。
(4)细分着色
顶点着色器处理每个顶点的关联数据之后,如果同时激活了细分着色器,那么它将进一步处理这些数据。使用Patch描述物体形状。
(5)几何着色
允许在光栅化之前对每个几何图元做进一步的处理。
(6)图元装配
构成几何图元的所有信息也会传递到Opengl。将顶点和相关的几何图元进行组装。
(7)剪切
顶点可能会落在视口之外,也就是我们可以进行绘制的窗口之外。保证相关像素不会在视窗之外进行绘制。
(8)光栅化
将剪切后的图元传递到光栅化单元,生成对应的片元。我们可以讲一个片元视为一个“候选的像素”,也就是可以纺织在帧缓存中的像素,但是他也可能被最终剔除。
(9)片元着色
通过编程控制屏幕上显示颜色的阶段,叫做片元着色阶段。
(10)逐片元操作
进行深度测试和模板测试来决定一个片元是否可见。(参照计算机图形学)

在叙述opengl基础函数之前,先贴出一个基础程序,作为之后分析的范例:

#pragma comment(lib,"glew32.lib")
#pragma comment(lib,"freeglut.lib")
#include <GL/glew.h>
#include <iostream>
#include <GL/freeglut.h>
#include "gl/Glew.h"
#include <Windows.h>


enum VAO_IDs {Triangle, NumVAOs};
enum Buffer_IDs {ArrayBuffer, NumBuffers};
enum Attrib_IDs { vPosition=0 };
GLuint VAOs[NumVAOs];
GLuint Buffer[NumBuffers];
const GLuint NumVertices = 6;
// init

void init(void)
{
    glGenVertexArrays(NumVAOs, VAOs);
    //返回n个未使用的对象名字到达数组arrays当中。
    //用作顶点数组对象。返回的名字可以用来分配更多
    //的缓存对象,并且他们已经使用未初始化的顶点数组集合的默认
    //状态进行数值的初始化。
    glBindVertexArray(VAOs[Triangle]);
    //如果输入变量非零,而且是上一个函数返回的,那么它将创建了一个
    //新的顶点数组对象并且与其名称关联起来。
    GLfloat vertices[NumVertices][2]=
    {
        {-0.90, -0.90},
        {0.85,-0.90},
        {-0.90,0.85},  //The First Triangle
        {0.90, -0.85},
        {0.90,0.90},
        {-0.85,0.90}
    };

    glGenBuffers(NumBuffers,Buffer);
    glBindBuffer(GL_ARRAY_BUFFER,Buffer[ArrayBuffer]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),
        vertices,GL_STATIC_DRAW);

    ShaderInfo shader[] = {
        {GL_VERTEX_SHADER,"triangles.vert"},
        {GL_FRAGMENT_SHADER, "triangles.frag" },
        {GL_NONE, NULL}


    }

    GLuint program = LoadShader(shader);
    glUseProgram(program);
    glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);
}



//几乎所有的程序都要和下面函数完成
//相同的任务
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    //调用Clear清楚窗口内存
    glBindVertexArray(VAOs[Triangle]);
    //调用OpenGL命令来渲染对象
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    //将最终图像输出到屏幕上
    glFlush();
}

//main

int main(int argc,char** argv)
{
    glutInit(&argc, argv);
    //初始化Glut库
    glutInitDisplayMode(GLUT_RGBA);
    //设置初始化窗口式样 
    glutInitWindowSize(512,512);
    //设置窗口的大小
    glutInitContextVersion(4,3);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    //设置Opengl环境,使用的是Opengl的核心模式。
    glutCreateWindow(argv[0]);
    //如果当前满足DisplayMode的显示要求,那么
    //就生成窗口。
    if (glewInit())
    {
        std::cerr << "Unable to initialize GLEW exiting ";
        exit(EXIT_FAILURE);
    }
    init();
    //初始化
    glutDisplayFunc(display);
    //自动调用当中注册的函数。
    glutMainLoop();
}

5.Opnegl基础函数

void glDeleteVertexArrays(GLsizei n,GLuint *array);
//删除n个在arrays中定义的顶点数组对象。这样所有名称可以再次用作顶点数组如果绑定的顶点数组已经被删除,那么当前数组对象重新设置为0。而默认的顶点数组会变成当前对象。在Array当中未使用的名称都会被释放。

GLboolean gllsVertexArray(GLuint array);
//如果array是一个已经用glGenVertexArray()创建而且没有被删除的顶点数组对象的名称,那么返回GL_TRUE。否则返回GL_FALSE。
作为一个检查函数存在。

voidglGenBuffer(GLsizei n,GLuint *buffers);
//返回n个当前未使用的缓存对象名称,并且保存到buffer数组当中。返回到buffers中的名称不一定是连续的整形数据。这里返回的名称只用于分配其他缓存对象,他们在绑定之后只会记录一个可用状态。

void glBindBuffer(GLenum target,GLuint buffer);
//指定当前激活的对象。target必须为一下类型:
GL_ARRAY_BUFFER
GL_ELEMENT_ARRAY_BUFFER
GL_PIXEL_PACK_BUFFER
GL_PIXEL_UNPACK_BUFFER
GL_COPY_READ_BUFFER
GL_COPY_WRITE_BUFFER
GL_TRANSFORM_FEEDBACK_BUFFER
GL_UNIFORM_BUFFER
//buffer设置的是绑定的缓存对象名称。
//本函数的三项工作:如果第一次绑定buffer,而且是一个非零的无符号整型,那么将创建一个与该名称对应的新缓存对象。如果已经绑定到一个已经创建的缓存对象,那么它将成为当前被激活的缓存对象。如果绑定的buffer值为零,那么OPENGL将不会对当前任何target应用任何缓存对象。

void glDeleteBuffers(GLsizei n,const    GLuint* buffer);
//删除n个保存在buffers数组当中的缓存对象。被释放的缓存对象可以重用。

GLboolean gllsBuffer(GLunit buffer);
//如果buffer是一个已经分配没有释放的缓存对象的名称那么就返回GL_TRUE。否则返回GL_FALSE。

void glBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage);
//在OpenGL服务器端内存中分配了size个存储单元,用于存储数据或者索引。如果当前绑定的对象已经存在了关联的数据,那么会首先删除这些数据。
//各个形参的值:
//target:
GL_ARRAY_BUFFER:顶点属性值。
GL_ELEMENT_ARRAY_BUFFER:索引数据。
GL_PIXEL_PACK_BUFFER:从Opengl当中获取的像素数据。
GL_PIXEL_UNPACK_BUFFER:opengl的像素数据。
GL_COPY_READ_BUFFER:缓存之间的复制数据。
GL_COPY_WRITE_BUFFER:缓存之间的复制数据。
GL_TRANSFORM_FEEDBACK_BUFFER:feedback着色器获得的结果。
GL_UNIFORM_BUFFER:一致变量。
//data:要么是一个客户端内存指针,一遍初始化缓存对象,要么是NULL。传入的指针合法,那么将会有size大小的数据从客户端拷贝到服务端。
//usage:用于设置分配数据之后的读取和写入方式,可以使用的方式包括:
GL_STREAM_DRAW
GL_STREAM_READ
GL_STREAM_COPY
GL_STATIC_DRAW
GL_STATIC_READ
GL_STATIC_COPY
GL_DYNAMIC_DRAW
GL_DYNAMIC_READ
GL_DYNAMIC_COPY
//所需的size大小超过了服务端能够分配的额度,那么glBufferData()将会产生一个GL_OUT_OF_MEMORY。usage设置的不是一个可用的模式值,那么将会产生GL_INVALID_VALUE错误。


void glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized, GLsizei stride, const GLvoid*pointer);
//设置index(着色器的属性位置)位。pointer表示缓存对象中,从起始对象开始计算的数组数据的偏移值。使用基本系统单位byte。size表示每个顶点需要更新的分量的数目。normalized设置顶点数据在存储前是否需要归一化。stride是数组中每两个元素之间的大小偏移值。如果stride为0,那么数据应该紧密的封装在一起。

void glEnableVertexAttribArray(GLuint index);
void glDisableVertexAttribArray(GLuint index);
//设置是否启用与index索引相关联的顶点数组。index必须是一个介于0到GL_MAX_VERTEX_ATTRIBS-1之间的值。


对于着色器代码的基础了解:

顶点着色器:

//传递着色器案例
//只负责将输入数据拷贝到输出数据当中
#version 430 core
//指定使用opengl的版本(核心模式)
layout(location = 0) in vec4 vPosition;
//vect4:四维浮点数向量
//in指定了数据进入着色器的流向。
//layout(location = 0):布局限定符。目的是为变量提供元数据。
void main()
{
    //他所实现的就是将输入的顶点位置
    //复制到 顶点着色器的指定输出位置
    //gl_Position中。
    gl_Position = vPosition;
}

片元着色器:


#version 430 core
//指定使用opengl的版本(核心模式)
out vec4 fColor;
//使用了out限定符。在这里着色器
//将会把fColor对应的数值输出,而这就是片元所对应的颜色值。
void main()
{
    //每个片元都会设置一个四维的向量。
    fColor = vec4(0.0,0.0,1.0,1.0);
}

使用OPENGL进行渲染所需要的函数:

void glClear(GLbitfield mask);
//清除指定的缓存数据并且重新设置为当前的清除值。mask可以通过逻辑或操作来指定多个数值的参数。mask值的表:
GL_COLOR_BUFFER_BIT:颜色缓存,opengl默认的清除颜色为黑色。
GL_DEPTH_BUFFER_BIT:深度缓存
GL_STENCIL_BUFFER_BIT:模板缓存

glClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha);
//设置当前使用的清楚颜色值,用于RGBA模式下对颜色缓存的清除工作。
注意:效率更高的方法是在init()函数中设置清除函数。程序运行时不发生变化的数值都应该在init()当中设置。

void glDrawArrays(GLenum moder,GLint first,GLsizei count);
//使用当前绑定的顶点数组元素来建立一系列的几何图元,起始位置为first,而结束为止为first+count-1。mode设置图元的类型:
GL_POINTS
GL_LINES
GL_LINE_STRIP
GL_LINE_LOOP
GL_TRIANGELS
GL_TRIANGE_STRIP
GL_TRIANGLE-fan
GL_PATCHES

void glFlush(void);
//强制之前的OpenGL命令立即执行,这样就可以保证他们在一定时间内全部完成。

void glEnable(GLenum capability);
void glDisable(GLenum capability);
//其会开启一个模式。而disable会关闭它。

GLboolean gllsEnabled(GLenum capability);
//根据是否启用当前模式返回GL_TRUE,GL_FALSE.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值