OpenGL概述
1 什么是OpenGL
名词解释
模型(场景对象):利用基本几何图元创建的,也可以称为物体
渲染:根据模型创建最终图像的过程
着色器:专为GPU编译的一个小型程序,
光栅化:将构建的模型转为像素,
位平面:和像素有关的信息被组织成位平面
帧缓冲区:位平面可以组织成帧缓冲区,在显存上分配。
主要过程
1 利用几何图元创建形状
2 不同的着色器对图元数据执行计算操作,判断颜色、位置、其他渲染属性
3 将图元的输入描述转为像素片元(fragment),即光栅化(rasterization)
4 执行片元着色器。决定片元的最终颜色和位置
第一个OpenGL程序
//////////////////////////////////////////////////////////////////////////////
//
// media/shaders/triangles/triangles.vert
//
//////////////////////////////////////////////////////////////////////////////
#version 450 core //GLSL(OpenGL shader language)版本, core模式
layout (location = 0) in vec4 vPosition;
// layout (location = 0):布局限定符,目的是为变量提供元数据,设置属性,此处位置属性为0
// in:指定了数据进入着色器的流向,也可以是out
// vec4:变量类型,表示四维浮点向量类型,
// vPosition:变量名称
void main
{
gl_Position = vPosition;
}
//////////////////////////////////////////////////////////////////////////////
//
// media/shaders/triangles/triangles.frag
//
//////////////////////////////////////////////////////////////////////////////
#version 450 core
layout (location = 0) out vec4 fColor;
void main()
{
fColor = vec4(0.5, 0.4, 0.8, 1.0);
}
//////////////////////////////////////////////////////////////////////////////
//
// Triangles.cpp
//
//////////////////////////////////////////////////////////////////////////////
#include "vgl.h"
#include "LoadShaders.h"
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
//----------------------------------------------------------------------------
//
// init
//
void
init( void )
{
//分配顶点数组对象,得到NumVAOs个顶点数组对象的名称,存放在AVOs中
glGenVertexArrays( NumVAOs, VAOs );
//激活顶点数组对象,绑定到OpenGL环境中,所有后继的操作都会作用于这个被绑定的对象,如状态
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.90f }, { 0.85f, -0.90f }, { -0.90f, 0.85f }, // Triangle 1
{ 0.90f, -0.85f }, { 0.90f, 0.90f }, { -0.85f, 0.90f } // Triangle 2
};
//创建缓存对象,得到NumBuffers个缓存对象名称,存放在Buffers中
glCreateBuffers( NumBuffers, Buffers );
//激活缓存对象,绑定到OpenGL环境中,其中需要指定绑定目标,如GL_ARRAY_BUFFER
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
//分配顶点数据存储空间大小为sizeof(vertices),将应用程序(客户端)顶点数据vertices传输到OpenGL服务端
//glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
glNamedBufferStorage(Buffers[ArrayBuffer], sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
//设置着色器vPosition位置对应的数据值。
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
//启用与vPosition位置相关联的顶点数据
glEnableVertexAttribArray( vPosition );
}
//----------------------------------------------------------------------------
//
// display
//
void
display( void )
{
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
//----------------------------------------------------------------------------
//
// main
//
#ifdef _WIN32
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
#else
int
main( int argc, char** argv )
#endif
{
glfwInit(); //初始化glfw库,处理向程序输入的命令行参数
//窗口的大小和类型,还创建一个与window关联的OpenGL设备环境
GLFWwindow* window = glfwCreateWindow(800, 600, "Triangles", NULL, NULL);
glfwMakeContextCurrent(window);
gl3wInit();//初始化gl3w库
init();
while (!glfwWindowShouldClose(window))
{
display();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window); //清理窗口
glfwTerminate(); //关闭glfw库
}
OpenGL数据类型
| 后缀 | 数据类型 | C类型 | OpenGl类型 |
|---|---|---|---|
| b | 8位整数 | signed char | GLbyte |
| s | 16位整数 | short | GLshort |
| i | 32位整数 | int或long | GLint, GLsizei |
| f | 32位浮点数 | float | GLfloat, GLclampf |
| d | 64位浮点数 | double | GLdouble, GLclampd |
| ub | 8位无符号整数 | unsigned char | GLubyte, GLboolean |
| us | 16位无符号整数 | insigned short | GLushort |
| ui | 32位无符号整数 | unsigned int 或 unsigned long | GLuint, GLenum, GLbitfield |
| v | 向量类型 |
OpenGL渲染管线

着色器基础
OpenGL的可编程管线
- 顶点着色阶段:
- 细分着色阶段:
- 几何着色阶段:
- 片元着色阶段:
- 计算着色阶段:
OpenGL着色语言
存储限制符

- uniform
uniform修饰一个在应用程序中设置好的变量,可以在各着色器阶段之间共享,并且着色器无法写入,无法改变它的值。
如果需要设置它的值,就要调用专用的接口:
GLSL编译器在链接着色器程序时,会创建一个uniform变量列表。如果要想修改某个变量,就要用glGetUniformLocation()函数获取该变量在uniform变量列表中的索引。

当得到索引值后,就可以用glUniform*()和glUniformMatrix*()函数设置对应的unifrom变量的值。


如:
GLint timeLoc;
GLfloat timeValue;
timeLoc = glGetUniformLocation(program, "time");
glUniform1f(timeLoc, timeValue);
- buffer
buffer可以指定一块在应用程序和着色器之间共享的缓存空间。该缓存空间对着色器也是可读可写的。 - shared
shared只能用于计算着色器中,它可以建立本地工作组内共享的内存。
着色器的预处理


- #progma
#progma optimize(on) //开启优化
#progma optimize(off) //关闭优化
#progma debug(on) //开启调试
#progma debug(off) //关闭调试
#progma STDGL invariant(all) //开启所有输出变量值的不变性检查
- #extension
#extension extension-name <directive>
#extension all <directive>
<directive的可选项>

数据块接口
1 uniform块
uniform变量的集合, 声明如下:
uniform b {
vec4 v1;
bool v2;
}; //匿名uniform块
uniform b {
vec4 v1;
bool v2;
} name; //有名uniform块

//设置一个uniform块
layout (shared, row_major) uniform b {
vec4 v1;
bool v2;
}; //匿名uniform块
//设置后面所有的uniform块
layout(packed, column_major) uniform;
layout (shared, row_major) uniform b {
layout(offset=32) vec4 v1;
layout(aligne=1024) bool v2;
} name; //有名uniform块
从应用程序访问uniform块
1 获取uniform的索引


2 buffer块
buffer BufferObject {
int mode;
vec4 points[];
};
3 in/out块
in Lighting {
// 多个小的对象放在同一位置
layout(location=1, component=0) vec2 offset;
layout(location=1, component=0) vec2 size;
}
着色器的编译
对于每个着色器对象,需要:
- 创建一个着色器对象
- 将着色器代码编译为对象
- 验证着色器的编译是否成功
然后,将多个着色器对象链接成一个着色器程序,需要:
- 创建一个着色器程序
- 将着色器对象关联到着色器程序
- 链接着色器程序
- 判断着色器的链接过程是否成功
- 使用着色器处理顶点和片元
1 创建着色器对象

2 将源代码关联到着色器对象

3 编译着色器的源代码

4 编译失败,获取错误信息

如果没有错误,就可以将着色器对象连接到着色器程序中。
5 创建着色器程序

6 将着色器对象关联着色器程序

如果需要从着色器程序删除某一个着色器

7 当所有着色器对象关联到着色器程序之后,可以链接对象生成可执行程序

如果链接失败,获取错误信息

8 启动着色器程序
9 删除着色器对象

判断是否删除成功

10 删除着色器程序

判断是否删除成功

SPIR-V与OpenGL
1 关联SPIR-V模块与着色器对象

2 关联SPIR-V入口点与着色器对象


之后,就可以使用glAttachShader()和glLinkProgram()。
OpenGL绘制方式
1 点
一个点就是一个四维的齐次坐标值。通过屏幕上的一个四边形区域来模拟的。
本文介绍了OpenGL的基本概念,包括模型、着色器、光栅化过程,展示了如何编写和链接第一个OpenGL程序,以及OpenGL的数据类型、渲染管线、着色器编程和SPIR-V整合。

711

被折叠的 条评论
为什么被折叠?



