OpenGL红宝书学习(1、概述)

OpenGL简介

OpenGL 全称Open Graphics Library,一种用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。由1992年成立的OpenGL架构评审委员会(ARB)维护。
OpenGL是使用“客户端—服务端”的形式实现的,我们编写的 应用程序 可以看作客户端,而计算机图形硬件厂商(如:英伟达)所提供的OpenGL实现可以看作服务端

OpenGL渲染管线

OpenGL实现了我们通常所说的渲染管线(rendering pipeline),它是一系列数据处理过程,并且将应用程序数据 转化到 最终渲染的 图像
OpenGL渲染管线 如下图所示:
OpenGL渲染管线
这里有一个OpenGL最本质的概念–着色器(Shader),它是图形硬件设备所执行的一类特殊函数。
理解 着色器 最好的方法是:把它看作专为 图形处理单元(GPU) 编译的一种小程序

OpenGL在其内部包含了所有的 编译器工具,可以直接从着色器源代码创建GPU所需的编译代码,并执行。

着色器编译命令序列 如下图所示:
着色器编译命令序列

/*关于上图 “着色器编译命令序列” 举例
*/
	#define GLSL_STR(a) (#a)

	const char* ShaderSource = GLSL_STR(
		#version 430 core\n
		layout(location=0)in vec4 vPosition;
		void main()
		{
			gl_Position = vPosition;
		}	
	);	
		
	GLuint program = glCreateProgram();
	
	GLuint shader = glCreateShader(GL_VERTEX_SHADER);//顶点着色器
	glShaderSource(shader, 1, &ShaderSource, 0);
	glCompileShader(shader);
			
	GLint complied;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &complied);

	if (!complied)
	{
		//do something when compile failed
	}
	glAttachShader(program, shader);

	glLinkProgram(program);
	GLint linked;
	glGetProgramiv(program, GL_LINK_STATUS, &linked);

	if (!linked)
	{
		//do something when link failed
	}

	glUseProgram(program);

第一个OpenGL程序

红宝书的第一个程序,两个蓝色三角形。
由于红宝书附带的源码牵扯一些其它文件,此处我稍做了修改,放到了同一个文件中,看起来更直观,可不用配置,直接编译运行。

#include <iostream>
#include <gl/glew.h>
#include <gl/glut.h>
#include <gl/freeglut_ext.h>

#pragma comment(lib, "glew32.lib")

namespace
{
//为了方便编写shader,定义一个宏
#define GLSL_STR(a)  (#a)
	
	GLuint VAO, VBO;
	const GLint NumVertices = 6;//顶点数量

	struct ShaderInfo
	{
		GLenum type;
		const char* source;
	};

//顶点着色器
	const char* vShader = GLSL_STR(
		#version 430 core\n
		layout(location = 0) in vec4 vPos;
	void main()
	{
		gl_Position = vPos;
	}
	);

//片元着色器
	const char* fShader = GLSL_STR(
		#version 430 core\n
		out vec4 fColor;
	void main()
	{
		fColor = vec4(0.0, 0.0, 1.0, 1.0);
	}
	);
	
// 着色器编译命令序列
	GLuint createProgram(ShaderInfo* shaders)
	{
		if (!shaders) return 0;
		GLuint program = glCreateProgram();
		while (shaders->type != GL_NONE)
		{
			GLuint shader = glCreateShader(shaders->type);
			glShaderSource(shader, 1, &shaders->source, 0);
			glCompileShader(shader);
			GLint compiled;
			glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
			if (!compiled)
			{
				return 0;
			}

			glAttachShader(program, shader);
			++shaders;
		}

		glLinkProgram(program);
		GLint linked;
		glGetProgramiv(program, GL_LINK_STATUS, &linked);
		if (!linked)
		{
			return 0;
		}
		return program;
	}

	void init()
	{
		ShaderInfo shaders[] =
		{
			{ GL_VERTEX_SHADER, vShader },
			{ GL_FRAGMENT_SHADER, fShader },
			{ GL_NONE, NULL }
		};
		
		GLfloat  vertices[NumVertices][2] = {
			{ -0.90, -0.90 },  // Triangle 1  左下部分
			{ 0.85, -0.90 },
			{ -0.90,  0.85 },
			{ 0.90, -0.85 },  // Triangle 2  右上部分
			{ 0.90,  0.90 },
			{ -0.85,  0.90 }
		};
		glGenVertexArrays(1, &VAO);
		glBindVertexArray(VAO);

		glGenBuffers(1, &VBO);
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		//将应用程序中的 数据 导入 GPU buffer
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

		GLuint program = createProgram(shaders);
		glUseProgram(program);

	//将buffer中的数据 与 顶点属性 0(layout(location = 0) in vec4 vPos;)关联
	//第一个参数0,对应location=0
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
		//启用顶点属性数组,默认关闭,0同上
		glEnableVertexAttribArray(0);

		glClearColor(0.8, 0.2, 0.0, 1.0);//设置暗红色背景
	}

	void display()
	{
		//清除颜色缓存,缓存类型还有 深度缓存(GL_DEPTH_BUFFER_BIT)、模板缓存(GL_STENCIL_BUFFER_BIT)
		glClear(GL_COLOR_BUFFER_BIT);
		
		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, NumVertices);//绘制三角形
		glFlush();
	}
}


int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA); //显示模式
	glutInitWindowSize(720, 576);//窗口宽 高
	glutInitWindowPosition(100, 100);//窗口坐标
	glutInitContextProfile(GLUT_CORE_PROFILE);//核心模式,还有一种“兼容模式GLUT_COMPATIBILITY_PROFILE"
	glutInitContextVersion(4, 3);//OpenGL版本,对应shader程序#version 430 core
	glutCreateWindow("Triangles");//创建窗口,名称Triangles

	glewExperimental = true;
	if (glewInit())//初始化GLEW
	{
		std::cout << "glew init failed..." << std::endl;
	}

	init();
	glutDisplayFunc(display);//显示回调函数,每次更新窗口内容时,自动调用
	glutMainLoop();//无限执行循环
	return 0;
}

运行结果如下:
程序运行结果

着色器程序说明

上述程序中使用了两个着色器程序:顶点着色器程序、片元着色器程序,下面我们就这两个程序,简单做个说明。

顶点着色器

	const char* vShader = GLSL_STR(
		#version 430 core\n
		layout(location = 0) in vec4 vPos;
	void main()
	{
		gl_Position = vPos;
	}
	);

这是一个传递着色器(pass-through shader)的例子,它只负责将数据拷贝到输出数据中。

第一行”#version 430 core“ ,指定OpenGL 4.3 版本对应的GLSL语言,core代表OpenGL核心模式。每个着色器程序第一行都应设置”#version …“, 否则系统会默认使用”110“版本,这与OpenGL核心模式不兼容。

第二行”layout(location = 0) in vec4 vPos;“,分配了一个着色器变量,着色器变量是着色器与外部世界的联系所在。
在着色器内部,直接获取输入类型着色器变量的数据,在外部(应用程序中),设置输入类型着色器变量的值。
此处,着色器变量名为vPos, 着色器流向为in,即输入类型, 数据类型为vec4,布局设定的位置属性为0

第三行“void main()”,着色器在main()函数中去实现主体部分,无论哪种类型的着色器,都必须有一个空类型(void)的main()函数。

第五行:“gl_Position = vPos;”,将我们声明的输入着色器变量数据,传入OpenGL内置着色器变量中,OpenGL内置了很多着色器变量,均以 gl_ 作为前缀,如想了解,可翻阅红宝书附录 C。

片元着色器

	const char* fShader = GLSL_STR(
		#version 430 core\n
		out vec4 fColor;
	void main()
	{
		fColor = vec4(0.0, 0.0, 1.0, 1.0);
	}
	);

第二行“out vec4 fColor;”,声明一个输出类型的变量fColor,着色器将会把fColor对应的数值输出,而这也就是片元所对应的颜色值。

第五行“fColor = vec4(0.0, 0.0, 1.0, 1.0);”,片元的颜色值(蓝色)。OpenGL中的颜色是通过RGBA颜色空间来设定的,每个颜色分量的范围都是[0,1],如fColor( R=0.0, G=0.0, B=1.0, A=1.0),此处 A(alpha值) 代表透明度,1.0代表完全不透明。

一些名词

  1. VA0(vertex-array object)顶点数组对象,用来管理vbo。

  2. VBO(vertex buffer object)顶点缓冲对象,用来缓存用户传入的顶点数据。

  3. EBO(element buffer object)索引缓冲对象,用来存放顶点索引数据。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用:在学习OpenGL 2D方面,有一个可以参考的工程是使用Qt实现的一个将2D纹理贴到球面的项目。该项目还包括混合光和采用了OpenGL ES 3.0。初学者可以通过学习这个项目来了解OpenGL 2D的应用和实现方法。 如果你对OpenGL 2D的学习感兴趣,你可以尝试以下几个步骤来深入学习: 1. 理解OpenGL的基本概念和原理。OpenGL是一个跨平台的图形库,用于渲染2D和3D图形。了解OpenGL的基本概念和工作原理是学习OpenGL 2D的重要基础。可以通过阅读相关的教程或书籍来学习这些概念。 2. 学习OpenGL的绘图函数和API。OpenGL提供了一系列的函数和API,用于绘制2D和3D图形。学习这些函数和API的使用方法,可以帮助你实现各种2D效果。可以通过阅读OpenGL的官方文档或者参考一些教程来学习这些函数和API的使用方法。 3. 熟悉OpenGL的着色器语言。OpenGL使用着色器语言来编写图形的渲染代码。了解如何编写着色器代码可以帮助你实现各种自定义的渲染效果。可以通过阅读相关的教程或者参考一些示例代码来学习这个语言。 4. 参考一些开源项目或者示例代码。通过参考一些已经实现的项目或者示例代码,可以帮助你更好地理解OpenGL 2D的实现方法和技巧。可以尝试去理解这些项目的代码,并且根据自己的需求进行修改和扩展。 总之,学习OpenGL 2D需要一定的基础知识和实践经验。通过阅读教程、参考文档、学习示例代码和实践项目,你可以逐步提升自己的OpenGL 2D编程能力。祝你学习顺利!<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [qt opengl 2d纹理到球面](https://download.csdn.net/download/wanghualin033/10698789)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [基于OpenGL的计算机图形学实验NURBS曲线算法](https://download.csdn.net/download/weixin_53249260/88236784)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值