OpenGL(2)——第一个 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);
}


NEHE的OPENGL教程 第42课 多视窗口… NEHE的OPENGL教程 第42课 多视窗口… NeHe的OPENGL中文教程:第41课 体… NeHe的OPENGL中文教程:第40课 绳… NeHe的OPENGL中文教程:第39课 物… NeHe的OPENGL中文教程:第39课 物… NeHe的OPENGL中文教程:第38课 从… NeHe的OPENGL中文教程:第37课 卡… 愚人节十大IT假新闻:Opera浏览器… NeHe的OPENGL中文教程:第36课 放… NeHe的OPENGL中文教程:第35课 AVI… NeHe的OPENGL中文教程:第35课 AVI… NeHe的OPENGL中文教程:第34课 从… NeHe的OPENGL中文教程:第33课 加… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第31课 模… NEHE的OPENGL中文教程:第30课 碰… NEHE的OPENGL中文教程:第30课 碰… NeHe的OPENGL中文教程:第29课 Bli… NeHe的OPENGL中文教程:第28课 贝… NeHe的OPENGL中文教程:第27课 影… NeHe的OPENGL中文教程:第26课剪裁… NeHe的OPENGL中文教程:第25课 变… NeHe的OPENGL中文教程:第24课 TAG… NeHe的OPENGL中文教程:第23课 球… NeHe的OPENGL中文教程:第22课 凸… NeHe的OPENGL中文教程:第22课 凸… NeHe的OPENGL中文教程:第21课 反… NeHe的OPENGL中文教程:第21课 反… NeHe的OPENGL中文教程:第20课 蒙… NeHe的OPENGL中文教程:第19课 粒… NeHe的OPENGL中文教程:第18课 二… NeHe的OPENGL中文教程:第17课 2D… NeHe的OPENGL中文教程:第16课 雾 NeHe的OPENGL中文教程:第15课 图… NeHe的OPENGL中文教程:第14课 图… NeHe的OPENGL中文教程:第13课 位… NeHe的OPENGL中文教程:第12课 显… NeHe的OPENGL中文教程:第11课 飘… NeHe的OPENGL中文教程:第十课 漫… NeHe的OPENGL中文教程:第九课 漂… NeHe的OPENGL中文教程:第八课 Alp… NeHe的OPENGL中文教程:第七课 纹… NeHe的OPENGL中文教程:第七课 纹… NeHe的OPENGL中文教程:第六课 纹… NeHe的OPENGL中文教程:第五课 向3… NeHe的OPENGL中文教程:第四课 旋… NeHe的OPENGL中文教程:第三课 着… NeHe的OPENGL中文教程:第二课 多… NeHe的OPENGL中文教程:第一课 新… NeHe的OPENGL中文教程:第一课 新… DirectX与OpenGL方面的经典电子书… VC++ 6.0下OpengGL配置以及glut配… 怎样开始学习OpenGL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值