OpenGL——第一个 OpenGL 程序

Posted SweetLoverFT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL——第一个 OpenGL 程序相关的知识,希望对你有一定的参考价值。

1.完整代码

由 HelloWorld.cpp、HelloWorld-fs.glsl、HelloWorld-vs.glsl 构成。前者是 C++ 程式,后两者是 OpenGL Shader Language 语言的片段着色器和顶点着色器,具体代码请参考上一节: http://blog.csdn.net/sweetloverft/article/details/50344499

2.分解 main 函数


int main(int argc, char** argv)

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(400, 400);
	glutCreateWindow("Hello World");
	glutIdleFunc(&idleFunc);
	glutDisplayFunc(&displayFunc);

	glewInit();
	if (!GLEW_VERSION_2_0) 
		fprintf(stderr, "OpenGL 2.0 not available\\n");
		getchar();
	
	//与glew扩展库相关的函数要在glewInit()后执行
	installShaders();
	initBuffers();

	glutMainLoop();
	return 0;


初始化 glut:void __stdcall glutInit(int *argcp, char **argv);

设定 OpenGL 渲染模式以及色彩空间:void __stdcall glutInitDisplayMode(unsigned int mode);
比如:glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

初始化窗口大小:void __stdcall glutInitWindowSize(int width, int height);

创建指定标题的窗口:int __stdcall glutCreateWindow(const char *title);

设置窗口空闲回调函数:void __stdcall glutIdleFunc(void (*func)(void));
比如:glutIdleFunc(&idleFunc);

设置窗口绘制回调函数:void __stdcall glutDisplayFunc(void (*func)(void));
比如:glutDisplayFunc(&displayFunc);

初始化 glew:GLenum __stdcall glewInit (void);

然后加载 shader 和 buffer,就可以开启 OpenGL 绘制循环了:void __stdcall glutMainLoop(void);

3.加载 shader


static void installShaders(void)

	names.vertex_shader = initShader(GL_VERTEX_SHADER, "HelloWorld-vs.glsl");
	names.fragment_shader = initShader(GL_FRAGMENT_SHADER, "HelloWorld-fs.glsl");

	GLint program_ok;
	names.program = glCreateProgram();
	glAttachShader(names.program, names.vertex_shader);
	glAttachShader(names.program, names.fragment_shader);
	//把shader依附在同一个program上,以连接两个shader
	glLinkProgram(names.program);
	//链接program,在GPU端创建相应可执行文件,并初始化uniform变量及其地址
	glGetProgramiv(names.program, GL_LINK_STATUS, &program_ok);
	//查询program的状态,并导出可能的错误
	if (!program_ok) 
		fprintf(stderr, "Failed to link shader program:\\n");
		infoLog(names.program, glGetProgramiv, glGetProgramInfoLog);
		glDeleteProgram(names.program);
		getchar();
	
	glUseProgram(names.program);
	//激活program后才能为shader指定uniform变量的值


根据类型和 glsl 文件初始化 Shader,接着创建 OpenGL 程式:glCreateProgram(); // 注意这是一个宏,表示的是一个函数指针,以下不注明则同上;

把 shader 依附在同一个 program 上,以连接两个shader:glAttachShader(GLuint program, GLuint shader);

紧接着,把上述两个连接起来的 shader 所构成的整体放置到 program 中,从而在 GPU 端创建相应可执行文件,并初始化 uniform 变量及其地址:glLinkProgram(GLuint program);

完成后我们要及时查询 program 链接状态:glGetProgramiv(GLuint program, GLenum pname, GLint* param);// GL_LINK_STATUS

如果成功,那么激活 OpenGL 程式:glUseProgram(GLuint program);

如果失败,我们可以通过 glGetProgramiv 传递 GL_INFO_LOG_LENGTH 获取出错原因文本的长度,并分配相应长度的字符串存储文本;

然后获取这个文本予以显示:glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);

显示完毕记得删除这个错误的 OpenGL 程式:glDeleteProgram(GLuint program);

4.初始化 shader


static void initBuffers(void)

	names.attributes.position = glGetAttribLocation(names.program, "position");
	names.attributes.inColor = glGetAttribLocation(names.program, "inColor");
	//获取GPU端attribute变量的地址保存在本地变量中,用于值的传递

	glGenBuffers(1, &names.vertex_buffer);
	//产生1个buffer object的名称,并分配显存空间
	glBindBuffer(GL_ARRAY_BUFFER, names.vertex_buffer);
	//把产生的buffer object与相应target绑定,以改变其值
	glBufferData(GL_ARRAY_BUFFER, sizeof(position_data), position_data, GL_STATIC_DRAW);
	//GL_STATIC_DRAW其他可用参数:
	//STATIC - 长时间不更改的值		DYNAMIC - 需要频繁改变的值		STREAM - 需要偶尔重写整个buffer的值
	//DRAW - 保存于GPU用于绘制的值		READ - 保存于CPU用于读取的值		COPY - 折衷
	glVertexAttribPointer(names.attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, (void*)0);
	glEnableVertexAttribArray(names.attributes.position);

	glGenBuffers(1, &names.color_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, names.color_buffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(color_data), color_data, GL_STATIC_DRAW);
	glVertexAttribPointer(names.attributes.inColor, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (void*)0);
	glEnableVertexAttribArray(names.attributes.inColor);

	glGenBuffers(1, &names.element_buffer);
	glBindBuffer(GL_ARRAY_BUFFER, names.element_buffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, names.element_buffer);



以上是关于OpenGL——第一个 OpenGL 程序的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL - 动画是由着色器完成的吗?

第一个OpenGL程序

卐 2-第一个OpenGL程序

四第一个opengl的qt程序

OpenGL初学:安装配置与第一个程序

第一个openGL程序