OpenGL编程指南第九版学习总结

本文介绍了OpenGL的基本概念,包括模型、着色器、光栅化过程,展示了如何编写和链接第一个OpenGL程序,以及OpenGL的数据类型、渲染管线、着色器编程和SPIR-V整合。

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类型
b8位整数signed charGLbyte
s16位整数shortGLshort
i32位整数int或longGLint, GLsizei
f32位浮点数floatGLfloat, GLclampf
d64位浮点数doubleGLdouble, GLclampd
ub8位无符号整数unsigned charGLubyte, GLboolean
us16位无符号整数insigned shortGLushort
ui32位无符号整数unsigned int 或 unsigned longGLuint, GLenum, GLbitfield
v向量类型

OpenGL渲染管线

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. 验证着色器的编译是否成功

然后,将多个着色器对象链接成一个着色器程序,需要:

  1. 创建一个着色器程序
  2. 将着色器对象关联到着色器程序
  3. 链接着色器程序
  4. 判断着色器的链接过程是否成功
  5. 使用着色器处理顶点和片元

1 创建着色器对象
在这里插入图片描述
2 将源代码关联到着色器对象
在这里插入图片描述
3 编译着色器的源代码
在这里插入图片描述
4 编译失败,获取错误信息
在这里插入图片描述
如果没有错误,就可以将着色器对象连接到着色器程序中。

5 创建着色器程序
在这里插入图片描述
6 将着色器对象关联着色器程序
在这里插入图片描述
如果需要从着色器程序删除某一个着色器
在这里插入图片描述
7 当所有着色器对象关联到着色器程序之后,可以链接对象生成可执行程序
在这里插入图片描述
如果链接失败,获取错误信息
在这里插入图片描述
8 启动着色器程序在这里插入图片描述

9 删除着色器对象
在这里插入图片描述
判断是否删除成功
在这里插入图片描述

10 删除着色器程序
在这里插入图片描述
判断是否删除成功
在这里插入图片描述

SPIR-V与OpenGL

1 关联SPIR-V模块与着色器对象
在这里插入图片描述
2 关联SPIR-V入口点与着色器对象
在这里插入图片描述在这里插入图片描述
之后,就可以使用glAttachShader()和glLinkProgram()。

OpenGL绘制方式

1 点

一个点就是一个四维的齐次坐标值。通过屏幕上的一个四边形区域来模拟的。

前言 第1章OpenGL简介 1.1什么是OpenGL? 1.2一段简单的OpenGL代码 1.3OpenGL函数的语法 1.4OpenGL是个状态机 1.5OpenGL渲染管线 1.5.1显示列表 1.5.2求值器 1.5.3基于顶点的操作 1.5.4图元装配 1.5.5像素操作 1.5.6纹理装配 1.5.7光栅化 1.5.8片断操作 1.6与OpenGL相关的函数库 1.6.1包含文件 1.6.2GLUT,OpenGL实用工具包 1.7动画 1.7.1暂停刷新 1.7.2动画=重绘+交换 第2章状态管理和绘制几何物体 2.1绘图工具箱 2.1.1清除窗口 2.1.2指定颜色 2.1.3强制完成绘图操作 2.1.4坐标系统工具箱 2.2描述点、直线和多边形 2.2.1什么是点、直线和多边形? 2.2.2指定顶点 2.2.3OpenGL几何图元 2.3基本状态管理 2.4显示点、直线和多边形 2.4.1点的细节 2.4.2直线的细节 2.4.3多边形的细节 2.5法线向量 2.6顶点数组 2.6.1步骤1:启用数组 2.6.2步骤2:指定数组的数据 2.6.3步骤3:解引用和渲染 2.7缓冲区对象 2.7.1创建缓冲区对象 2.7.2激活缓冲区对象 2.7.3用数据分配和初始化缓冲区对象 2.7.4更新缓冲区对象的数据值 2.7.5清除缓冲区对象 2.7.6使用缓冲区对象存储顶点数据数据 2.8属性组 2.9关于创建多边形表面模型的一些提示 2.9.1例子:创建一个二十面体 第3章视图 3.1简介:照相机比喻 3.2.1一个简单的例子:绘制立方体 3.1.2通用的变换函数 3.2视图和模型变换 3.2.1对变换进行思考 3.2.2模型变换 3.2.3视图变换 3.3投影变换 3.3.1透视投影 …… 第4章颜色 第5章光照 第6章混合、抗锯齿、雾和多边形偏移 第7章显示列表 第8章绘制像素、位图、字体和图像 第9章纹理贴图 第10章帧缓冲区 第11章分格化和二次方程表面 第12章求值器和NURBS 第13章选择和反馈 第14章OpenGL高级技巧 第15章OpenGL着色语言 附录A操作顺序 附录B状态变量 附录COpenGL和窗口系统 附录DGLUT(OpenGL实用工具库)基础知识 附录E计算法线向量 附录F齐次坐标和变换矩阵 附录G编程提示 附录HOpenGL的不变性规则 附录IOpenGL着色语言内置的变量和函数 术语表
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值