OpenGL

来自CGTWiki
跳转至:导航搜索

从OpenGL 3开始[1],编程模式被分为3种:

  1. 兼容模式:即传统的方式
  2. 核心模式:完全新式纯可编程流水线模式,但兼容废弃特性。(注:API不兼容旧的)
  3. 核心向前兼容模式:完全不兼容废弃特性,其它同核心模式。(主要表现在线宽、线调色板这一类,其它同核心模式)

OPENGL简略发展史[2]

从发展历程上看,

OpenGL 1.0~OpenGL 1.5是经典的固定管线时代;

OpenGL 2.0~OpenGL 2.1是固定管线和可编程管线并存的时代;

OpenGL 3.0~OpenGL 4.x开始是可编程管线崛起的时代。

在出现可编程管线的那个时代,OpenGL因为OpenGL ARB的臃肿而一度落后,取而代之的是Khronos Group管理的精简的OpenGL ES流行;最后ARB决定将OpenGL的接力棒交给Khronos Group,在之后的几年内,OpenGL重新焕发了活力,推陈出新至今。另外在移动设备上免授权费用的OpenGL ES的胜利,在一方面上也促进了桌面版的OpenGL重新回到主流地位,现在先进的OpenGL已经受到各个厂家的重视,Nvidia和AMD等显卡制造商都争相发布相关的OpenGL驱动;在游戏开发方面,因为其良好的可移植性,不同的平台、不同的主流引擎都会有OpenGL的实现。

顶点的几种表达形式

无光照顶点

struct RenderVertex
{
	Vector3 p;//position
	float u,v;//texturemappingcoordinates
	Vector3 n;//normal
};

法线贴图的顶点

//Untransformed,unlit vertex with basis vectors
struct RenderVertexBasis
{
	Vector3 p;//position
	Vector3 n;//normal
	Vector3 tangent;//1st basis vector
	float det;//Determinant of tangent space
	//transform(mirrorflag)
	float u,v;//texture mapping coordinates
};

VAO与VBO的区别与联系[3]

基本流程

//generate
unsigned int vaoID;
glGenVertexArrays(1, &vaoID);

//bind
glBindVertexArray(vaoID);

// ..:: 初始化代码(只运行一次 (除非你的物体频繁改变)) :: ..
// 1. 绑定VAO
glBindVertexArray(vaoID);
// 2. 把顶点数组复制到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

[...]

// ..:: 绘制代码(渲染循环中) :: ..
// 4. 绘制物体
glUseProgram(shaderProgram);
glBindVertexArray(vaoID);
someOpenGLFunctionThatDrawsOurTriangle();


VAO(Vertex Array Object)简单理解其实代表的就是模型的数据,我们可能需要很多个模型,所以需要有个id来区分,所以创建vao的时候会返回一个vaoID。VAO中有一个属性列表,默认有16个属性(0 - 15),我们可以为属性指定数据,其中属性可以是顶点位置,颜色,法线,纹理坐标等等我们需要的数据,其中的每一个属性对应的数据其实就是VBO(vertex buffer object)。

OpenGL有两类函数,第一种是状态设置函数,第二种是状态使用函数。比如对于vao对象,glBindVertexArray(vaoID)函数就是状态设置函数,glVertexAttribPointer就是状态使用函数,用来为属性列表中的某个属性绑定数据,绑定的数据就是vbo,如果我们已经为vao绑定过数据了,下一次使用的时候就不需要重新绑定了,直接使用这个vao就可以了,相当于我们已经有模型的数据了。在bind和unbind(就是调用glBindVertexArray(0))之间的操作都是针对这一个vao对象的。形象的理解两者之间的关系可以看下图:

VAO与VBO的区别与联系

例子[4]

现在,我要用多个ID绑定同一类型的GL_ARRAY_BUFFER。我为vboPos,vboColor生成两个VBO;为vboId生成一个VBO。前两者指定一个顶点的位置和颜色,后者则制定顶点绘制的索引(四边形就是0,1,2,3)。

但是,同一时刻只能指定一种类型的VBO。因此,按照以下步骤分别上传顶点的位置属性和颜色属性:


glGenVertexArrays ( 1, &userData->vaoId );
   glBindVertexArray ( userData->vaoId );

   glBindBuffer ( GL_ARRAY_BUFFER, userData->vboPos );
   glEnableVertexAttribArray ( VERTEX_POS_INDX );
   glVertexAttribPointer ( VERTEX_POS_INDX, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, VERTEX_POS_STRIDE, 0 );

   glBindBuffer ( GL_ARRAY_BUFFER, userData->vboColor );
   glEnableVertexAttribArray ( VERTEX_COLOR_INDX );
   glVertexAttribPointer ( VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE, VERTEX_COLOR_STRIDE, 0 );

glBindVertexArray ( 0 )

GLSL

对应关系

GLSL与Opengl版本的对应

mat4变量

GLSL参考手册的第5.6节说,您可以使用operator [] []样式语法以下列方式访问mat4数组元素:

mat4 m;
m[1] = vec4(2.0); // sets the second column to all 2.0
m[0][0] = 1.0; // sets the upper left element to 1.0
m[2][3] = 2.0; // sets the 4th element of the third column to 2.0
  • OpenGL默认为列主矩阵,这意味着访问的格式为mat [col] [row]。在该示例中,m [2] [3]将第3个COLUMN(索引2)的第4个ROW(索引3)设置为2.0。在示例m [1] = vec4(2.0)中,它一次设置整个列(因为m [1]是指列#2,当仅使用一个索引时,它意味着COLUMN.m [1]第二列向量)。

几何着色器

分层渲染Cubemap

  • gl_Layer — contains the selected layer of a multi-layer framebuffer attachment. //一般和三维纹理相绑定

void glFramebufferTextureLayer(GLenum target​, GLenum attachment​, GLuint texture​, GLint level​, GLint layer​); In the geometry language, gl_Layer is used to select a specific layer (or face and layer of cube map) in a multi-layer framebuffer attachment.

  • gl_ViewportIndex — contains the index of the viewport to be used in viewport transformation and scissoring

In the geometry language, gl_ViewportIndex is used to specify the index of the viewport to which the next primitive emitted from the shader should be drawn. Primitives generated by the geometry shader will undergo viewport transformation and scissor testing using the viewport transformation and scissor rectangle selected by the value of gl_ViewportIndex. The viewport index used will come from one of the vertices in the primitive being shaded. However, which vertex the viewport index comes from is implementation-defined, and so it is recommended to use the same viewport index for all vertices of a primitive. If a geometry shader does not assign a value to gl_ViewportIndex, viewport transform and scissor rectangle zero will be used. If a geometry shader statically assigns a value to gl_ViewportIndex and there is a path through the shader that does not assign a value to gl_ViewportIndex, the value of gl_ViewportIndex is undefined for executions of the shader that take that path.

引用