关闭

OpenGL学习笔记之绘制三角形

标签: OpenGLGLSL绘制三角形
176人阅读 评论(0) 收藏 举报
分类:

参考https://learnopengl.com/

1、创建窗口

glfw是一个针对OpenGL的窗口管理库,这里使用glfw库创建窗口并处理输入,glfw库可以在它的官网上下载,提供了动态库和静态库供选择,也可以下载源码自己编译。

以官方下载的静态库glfw3.lib为例,将下载的静态库复制到自己方便管理的路径,这里放在工程路径下的lib文件夹内,并将该文件路径添加到工程属性的依赖库里


将glfw3.h复制到工程目录下的glfw文件夹内,并在.cpp文件内包含该头文件#include "glfw/glfw3.h"
创建窗口的步骤:
(1)初始化glfw
glfwInit();
(2)配置OpenGL属性项
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint设置相应的属性,GLFW_CONTEXT_VERSION_MAJOR和GLFW_CONTEXT_VERSION_MINOR设置需要使用的OpenGL版本,这里选择3.3版本,GLFW_OPENGL_CORE_PROFILE表示我们使用core-profile版本,不需要兼容低版本特性
(3)创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);//创建一个800x600大小的窗口
if (window == NULL)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//将window设置为当前窗口
(4)显示窗口并处理消息
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwWindowShouldClose判断窗口是否要关闭,点击关闭按钮的时候返回true,也就是退出循环
glfwSwapBuffers交换缓冲区,将要显示的像素颜色显示到屏幕
glfwPollEvents处理消息
(5)结束
最后调用glfwTerminate()即可。
最后代码合起来

#include "glfw/glfw3.h"
int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "OpenGL", NULL, NULL);
	if (window == NULL)
	{
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	while (!glfwWindowShouldClose(window))
	{
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwTerminate();
	return 0;
}


2、画三角形

窗口创建后就可以在窗口上画出三角形了,这里需要用到OpenGL的api接口,如果自己写代码获取OpenGL动态库中的函数就太麻烦了,而且OpenGL有很多版本,不同版本的api也有区别。
使用glad库可以解决这个问题,glad中包含了OpenGL不同版本的API,使用上面的glfwWindowHint指定版本后,就可以获取到指定版本的所有函数了。
glad文件获取:打开网址http://glad.dav1d.de/,如下图


Language选择C/C++,Specification选择OpenGL,gl选择你需要的版本,这里是Version 3.3,Profile选择Core,勾选Generate a loader,点击GENERATE按钮就会生成glad.zip文件。
将zip文件解压出来有src和include文件夹,分别有glad解压出来有src和include文件夹,分别有glad.h、khrplatform.h和glad.c,将include下面的两个文件夹glad和KHR复制到工程的包含目录,例如VS安装目录下的VC\inlcude目录,glad.c文件添加到工程中。
之后只要在需要使用的地方加上头文件包含#include "glad/glad.h",并在使用OpenGL函数之前加载所有函数指针gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)就可以了,glfwGetProcAddress位于glfw3.h中。
接下来就可以开始准备画三角形了
(1)编写顶点着色器(vertex shader)和片段着色器(fragment shader)
顶点着色器和片断着色器都是使用着色器编程语言GLSL编写
//顶点着色器代码:
#version 330 core	//版本
layout (location = 0) in vec3 vertexPos;	//顶点位置,由程序传入
void main()//着色器程序执行main函数
{
   gl_Position = vec4(vertexPos, 1.0);//gl_Position为内部定义变量,表示顶点的位置
}
//片段着色代码:
#version 330 core
void main()
{
   gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);//gl_FragColor为内部定义变量,表示像素的颜色
}
(2)创建和编译着色器
为了方便,将着色器创建和编译放到CreateShader函数内

GLuint CreateShader(GLuint type,const GLchar* source)
{
	GLuint shader = glCreateShader(type);
	glShaderSource(shader, 1, &source, NULL);
	glCompileShader(shader);
	GLint success;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &success);//获取编译结果
	if (!success)
	{
		char infoLog[512];
		glGetShaderInfoLog(shader, 512, NULL, infoLog);//获取具体错误描述infoLog
		std::cout << infoLog << std::endl;
	}
	return shader;
}
假设顶点着色器程序字符串为const GLchar* vsSource,片段着色器程序字符串为const GLchar* fsSource,则创建顶点着色器和片断着色器的代码分别为
GLuint vertexShader = CreateShader(GL_VERTEX_SHADER,vsSource);
GLuint fragmentShader = CreateShader(GL_FRAGMENT_SHADER,fsSource);
(3)创建着色器程序
这里将创建和编译着色器以及创建着色器程序一起放到CreateShaderProgram函数内

GLuint CreateShaderProgram(const GLchar* vsSource,const GLchar* fsSource)
{
	GLuint vertexShader = CreateShader(GL_VERTEX_SHADER,vsSource);
	GLuint fragmentShader = CreateShader(GL_FRAGMENT_SHADER,fsSource);
	GLuint program = glCreateProgram();
	glAttachShader(program, vertexShader);
	glAttachShader(program, fragmentShader);
	glLinkProgram(program);
	GLint success;
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success) 
	{
		char infoLog[512];
		glGetProgramInfoLog(program, 512, NULL, infoLog);
		std::cout << infoLog << std::endl;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
	return program;
}
(4)将三角形顶点数据传入着色器
GLfloat vertices[] = 
{
	-0.5f,  0.5f, 0.0f,  // 1
	-0.5f, -0.5f, 0.0f,  // 2
	0.5f, -0.5f, 0.0f,  // 3
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);//创建顶点数组对象
glGenBuffers(1, &VBO);//创建顶点缓冲
glBindVertexArray(VAO);//设置当前顶点数组对象为VAO
{
	glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定VBO到GL_ARRAY_BUFFER
	{
		//将定点数据赋值给GL_ARRAY_BUFFER,也就是VBO
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
		//将缓冲中的顶点数据和vertexPos关联起来,这里是通过第一个参数0和着色器中的location=0关联的
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
		glEnableVertexAttribArray(0);
	}
	glBindBuffer(GL_ARRAY_BUFFER, 0);//取消VBO绑定
}
glBindVertexArray(0);//取消VAO绑定
为了看起来清晰,将部分代码用{}括起来,后面只要使用VAO就可以获取到顶点数据,OpenGL的坐标范围为-1到1
glVertexAttribPointer参数说明:
第一个参数表示变量的位置,也就是着色器中的location=n中的n;
第二个参数表示一个顶点的数据个数,这里是3个;
第三个参数为数据类型,这里为GL_FLOAT;
第四个参数表示数据是否要做标准化处理,如果为true,数据将被映射到-1到1之间,false则不做处理;
第五个参数为顶点数据间隔,就是相邻两个数据的起始地址之间的间隔,这里一个顶点3个GLfloat数据,所以间隔也是3*sizeof(GLfloat);
第六个参数为顶点数据起始地址偏移,这里从0位置开始所以就是(void*)0;
(5)渲染三角形
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//设置清除颜色
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);//shaderProgram为CreateShaderProgram返回的着色器程序
glBindVertexArray(VAO);		//绑定VAO
glDrawArrays(GL_TRIANGLES, 0, 3);//画三角形
(6)结束
程序退出前执行相应的清理工作,这里只要删除VAO、VBO和shaderProgram
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);

运行结果:


附上完整代码:
#include "glad/glad.h"
#include "glfw/glfw3.h"
#include<iostream>

const GLchar *vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 vertexPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(vertexPos, 1.0);\n"
"}\0";
const GLchar *fragmentShaderSource =
"#version 330 core\n"
"void main()\n"
"{\n"
"   gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
"}\n\0";

GLuint CreateShader(GLuint type, const GLchar* source)
{
	GLuint shader = glCreateShader(type);
	glShaderSource(shader, 1, &source, NULL);
	glCompileShader(shader);
	GLint success;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		char infoLog[512];
		glGetShaderInfoLog(shader, 512, NULL, infoLog);
		std::cout << infoLog << std::endl;
	}
	return shader;
}

GLuint CreateShaderProgram(const GLchar* vsSource, const GLchar* fsSource)
{
	GLuint vertexShader = CreateShader(GL_VERTEX_SHADER, vsSource);
	GLuint fragmentShader = CreateShader(GL_FRAGMENT_SHADER, fsSource);
	GLuint program = glCreateProgram();
	glAttachShader(program, vertexShader);
	glAttachShader(program, fragmentShader);
	glLinkProgram(program);
	GLint success;
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success)
	{
		char infoLog[512];
		glGetProgramInfoLog(program, 512, NULL, infoLog);
		std::cout << infoLog << std::endl;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
	return program;
}

int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);

	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		return -1;
	}
	GLuint shaderProgram = CreateShaderProgram(vertexShaderSource,fragmentShaderSource);
	GLfloat vertices[] = {
		-0.5f,  0.5f, 0.0f,  // 1
		-0.5f, -0.5f, 0.0f,  // 2
		0.5f, -0.5f, 0.0f,  // 3
	};
	GLuint VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	glBindVertexArray(VAO);
	{
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		{
			glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
			glEnableVertexAttribArray(0);
		}
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}
	glBindVertexArray(0);

	while (!glfwWindowShouldClose(window))
	{
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glUseProgram(shaderProgram);
		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 3);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteProgram(shaderProgram);
	glfwTerminate();
	return 0;
}




0
0
查看评论
发表评论
* 以上用户言论只代表其个人钱柜娱乐开户,不代表CSDN网站的钱柜娱乐开户或立场

OpenGL学习脚印: 绘制一个三角形

写在前面 接着上一节内容,开发环境搭建好后,我们当然想立即编写3D应用程序了。不过我们还需要些耐心,因为OpenGL是一套底层的API,因而我们要掌握的基本知识稍微多一点,在开始绘制...
  • ziyuanxiazai123
  • ziyuanxiazai123
  • 2016-05-04 23:10
  • 14749

OpenGL_Qt学习笔记之_02(绘制简单平面几何图形)

文章来源:http://www.cnblogs.com/tornadomeet/archive/2012/08/23/2652592.html
  • y601500359
  • y601500359
  • 2014-11-14 16:56
  • 1199

从零开始学习OpenGL ES之二 – 简单绘图概述

还有许多理论知识需要讨论,但与其花许多时间在复杂的数学公式或难以理解的概念上,还不如让我们开始熟悉OpenGL ES的基本绘图功能。 请下载OpenGL Xcode项目模板。我们使用此模板而...
  • eqera
  • eqera
  • 2014-02-05 12:52
  • 3496

opengl es3.0游戏开发学习笔记1-绘制旋转的三角形

前段时间一直在看opengl es2.0游戏开发的知识 ,这几天买了本opengl es3.0游戏开发的书   打算一边学习一边整理学习笔记,我的开发环境是钱柜娱乐开户 studio 2.1.3...
  • qq_28637193
  • qq_28637193
  • 2016-11-13 22:06
  • 1373

OpenGL 学习笔记3_3(绘制三角形相关)

蓝宝书 第三章 画三角形 triangle 1)绘制三角形(三个点确定一个三角形) glBegin(GL_TRIANGLES); glVertex2f(0.0f, 0.0f); // 点a ...
  • sanyun0606
  • sanyun0606
  • 2017-02-07 11:47
  • 139

钱柜娱乐开户 OpenGL学习笔记(二)之----三角形的绘制.

前面讲了一些钱柜娱乐开户 OpenGl 的概念问题,这一节讲给大家讲一下如何画一个三角现出来. 一、新建一个钱柜娱乐开户工程命名为:OpenGL_Lesson2. 二、修改OpenGL_Lesso...
  • ruanjianxiong
  • ruanjianxiong
  • 2011-07-07 14:45
  • 401

OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

前话 前面分别介绍了OpenGL+GLAD+GLFW组成与平台无关的OpenGL工程,根据不同的开发平台和系统平台,选择自己去配置开发环境,有需要读者可参考笔记五六七。 本章节开始,我们将继续前行,不...
  • qq21497936
  • qq21497936
  • 2017-12-24 23:00
  • 175

OpenGL ES2学习笔记(7)-- 三角形

Triangle、Triangle Strip、Triangle Fan
  • SpiderDog
  • SpiderDog
  • 2013-10-10 11:33
  • 1711

openGl超级宝典学习笔记 (1)第一个三角形

运行效果 代码及解析: // // Triangle.cpp // Triangle // // Created by fengsser on 15/6/20. // Copyright ...
  • fengsser
  • fengsser
  • 2015-06-28 16:45
  • 1469

openGL画三角形---openGL学习笔记(四)

在openGL中,所有面状图形的绘制都是使用画三角形方法,而针对不同需求,openGL给出三种不同的画三角形方法: ①traingles:画三角形集 ②traingle_strip:画三角...
  • a358333644
  • a358333644
  • 2016-02-29 15:53
  • 1174
    个人资料
    • 访问:5465次
    • 积分:213
    • 等级:
    • 排名:千里之外
    • 原创:14篇
    • 转载:7篇
    • 译文:1篇
    • 评论:1条
    文章分类
    最新评论