1.opengl绘制三角形
- 顶点数组对象:Vertex Array Object,VAO,用于存储顶点状态配置信息,每当界面刷新时,则通过VAO进行绘制.
- 顶点缓冲对象:Vertex Buffer Object,VBO,通过VBO将大量顶点存储在GPU内存(通常被称为显存)中
- 注意:片段着色器也称为片元着色器

float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
//x y:定义视口的左下角开始位置
//width,height :定义这个视口矩形的宽度和高度

unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //把用户定义的数据复制到当前绑定缓冲对象上
//参数1:目标缓冲的类型
//参数2:传输数据的大小(以字节为单位)
//参数3:数据指针
//参数4:指定我们希望显卡如何管理给定的数据
- GL_STATIC_DRAW :数据不会或几乎不会改变(一次修改,多次使用)
- GL_DYNAMIC_DRAW:数据会频繁修改(多次修改,多次使用)
- GL_STREAM_DRAW :数据每次绘制时都会改变(每帧都不同,一次修改,一次使用)
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
- #version 330 core : 定义版本号,需要OpenGL 3.3或者更高版本
- layout (location = 0) in vec3 aPos : 使用in关键字来声明顶点属性输入,这里创建一个输入变量aPos(3分量),通过layout (location = 0)设定了输入变量的顶点属性的位置值(Location)为0,后面将会通过glVertexAttribPointer()函数来设置它.
- gl_Position : 设置顶点着色器的输出,这里gl_Position之所以为vec4类型,是因为3d图形演算要用到 4x4的矩阵(4行4列),而矩阵乘法要求n行m列 和 m行p列才能相乘,所以是vec4而不是vec3,由于position 是位置所以应该是 (x,y,z,1.0f),如果是方向向量,则就是 (x,y,z,0.0f).
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
//创建一个着色器,参数GL_VERTEX_SHADER 或者GL_FRAGMENT_SHADER,由于我们创建的是顶点shader,所以填入GL_VERTEX_SHADER ,否则就是片元shader
下一步我们把这个着色器源码附加到着色器对象上,然后编译它:
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //设置顶点源码
glCompileShader(vertexShader);//编译源码 int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);//检测着色器编译是否成功 if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);//返回着色器对象的信息日志
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
void glGetShaderiv(GLuint shader,GLenum pname,GLint *params);
//shader:要查询的着色器对象
//pname : 查询类型,可以设置的有GL_SHADER_TYPE、GL_DELETE_STATUS、GL_COMPILE_STATUS、GL_INFO_LOG_LENGTH.
//GL_SHADER_TYPE: 用来判断并返回着色器类型,若是顶点着色器则success=GL_VERTEX_SHADER,若是片元着色器success=GL_FRAGMENT_SHADER
//GL_DELETE_STATUS: 判断着色器是否被删除,success=GL_TRUE,否则success=GL_FALSE,
//GL_COMPILE_STATUS: 用于检测编译是否成功,success=GL_TRUE,否则success=GL_FALSE,
//GL_INFO_LOG_LENGTH: 获取着色器的信息日志的长度(information log length), 如果着色器没有信息日志,则success=0。
//GL_SHADER_SOURCE_LENGTH: 获取着色器源码长度,不存在则success=0;
//params:查询的内容
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";
- FragColor : 定义类型为out vec4 类型,表明是个要输出的变量,该变量值为 vec4(1.0f, 1.0f, 0.0f, 1.0f),表示的是RGBA为(1,1,0,1),所以为黄色,而alpha值为1.0,表示完全不透明
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //创建一个片元着色器
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);//设置片元源码
glCompileShader(fragmentShader); //编译
2.7 着色器Program对象
两个着色器现在都编译了,接下来就是把两个着色器对象链接到一个用来渲染(调用顶点shader和片元shader数据)的着色器Program对象中。
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader); //将附加vertexShader到的shaderProgram对象中
glAttachShader(shaderProgram, fragmentShader);//将附加fragmentShader到的shaderProgram对象中
glLinkProgram(shaderProgram); //将附加的shader链接到program对象中 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); ////检测链接是否成功
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
} glDeleteShader(vertexShader); //链接后不再需要它们,需要删除shader
glDeleteShader(fragmentShader);
glGetProgramiv(shaderProgram, GL_ATTACHED_SHADERS, &cnt); //获取着色器对象的数量
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//设置顶点属性
glEnableVertexAttribArray(0);//使能顶点属性(默认是禁止的)
glUseProgram(shaderProgram); //激活Program对象
someOpenGLFunctionThatDrawsOurTriangle();// 绘制物体
void glVertexAttribPointer(GLuint index , GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr);
//指定渲染时索引值为 index 的顶点属性数组的数据格式和位置。
//index:指定要修改的顶点位置的索引值,之前使用layout(location = 0)设置了顶点位置为0,
//size:指定每个顶点属性的组件数量。必须为1、2、3、4之一。(如我们这里顶点是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
//type:指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT
//normalized:是否希望数据被标准化。设置为GL_TRUE,所有数据都会被映射到0(对于有符号型signed数据是-1)到1之间。我们把它设置为GL_FALSEM,不需要。
//stride:步长,指定顶点之间的偏移量。我们这里是每3个float为一个顶点,所以偏移量为3 * sizeof(float)
//ptr:可以指向需要绑定的VBO,如果已经绑定VBO,并且位置数据在缓冲中起始位置为0,那么此项为0,否则填入开头的偏移量
当我们绘制好物体后,每当最大化,尺寸变化界面后,openGL就会进入刷新状态,所以我们需要把所有这些状态配置储存在一个顶点数组对象(Vertex Array Object, VAO)中,每次刷新时,就可以通过VAO来恢复状态.
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //设置清除颜色(背景色)为rgba(0.2f, 0.3f, 0.3f, 1.0f) // 初始化代码,初始化顶点shader、片元shader、program、vbo
// ... ..
// ... ... //1.初始化vao
unsigned int VAO;
glGenVertexArrays(1, &VAO); // 注册VAO
glBindVertexArray(VAO); // 绑定VAO //2. 把顶点数组复制到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把用户定义的顶点数据复制到vao上
//3. 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);//使能顶点属性(默认是禁止的)
//4. 解绑VAO
glBindVertexArray(0);
glClear(GL_COLOR_BUFFER_BIT); //开始清除,设置背景色
glUseProgram(shaderProgram); ////激活Program对象
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3); //绘制三角形
someOpenGLFunctionThatDrawsOurTriangle();// 绘制物体
glBindVertexArray(0); //绘制完成,便解绑,用来绑定下一个要绘制的物体
glDrawArrays(GLenum mode, GLint first, GLsizei count);
//函数根据顶点数组中的坐标数据和指定的模式,进行绘制。
//mode,绘制方式,如下图所示,提供以下参数:
//GL_POINTS(画点)、GL_LINES(每两个顶点为一条直线)、GL_LINE_LOOP(是个环状)、
//GL_LINE_STRIP(第一个顶点和最后一个顶点不相连)、GL_TRIANGLES(每三个顶点组成一个三角形)、
//GL_TRIANGLE_STRIP(共用多个顶点的一个三角形)、GL_TRIANGLE_FAN(共用一个原点为中心的一个三角形)。 //first,从数组缓存中的哪一位开始绘制,一般为0。
//count,数组中顶点的数量。
如下图所示:
//hello_triangle.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h> #include <iostream> void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window); // settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600; const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0"; int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif // glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
} // build and compile our shader program
// ------------------------------------
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader); // set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
}; unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
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(float), (void*)0);
glEnableVertexAttribArray(0); // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0); // uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window); // render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); // draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0, 3);
// glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
} // optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO); // glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
} // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
} // glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
未完待续 ,下章学习:
2.通过QOpenGLWidget绘制三角形
1.opengl绘制三角形的更多相关文章
- opengl绘制三角形
顶点数组对象:Vertex Array Object,VAO 顶点缓冲对象:Vertex Buffer Object,VBO 索引缓冲对象:Element Buffer Object,EBO或Inde ...
- 2.通过QOpenGLWidget绘制三角形
参考:1.opengl绘制三角形 1.QOpenGLWidget的早先版本 QGLWidget是遗留Qt OpenGL模块的一部分,和其他QGL类一样,应该在新的应用程序中避免使用.相反,从Qt 5. ...
- [Modern OpenGL系列(三)]用OpenGL绘制一个三角形
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51347008 在上一篇文章中已经介绍了OpenGL窗口的创建.本文接着说如 ...
- Android OpenGL ES(十)绘制三角形Triangle .
三角形为OpenGL ES支持的面,同样创建一个DrawTriangle Activity,定义6个顶点使用三种不同模式来绘制三角形: float vertexArray[] = { -0.8f, - ...
- Android OpenGL 入门示例----绘制三角形和正方形
Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况.本文记录OpenGL在Android上的入门级示例 ...
- Linux OpenGL 实践篇-3 绘制三角形
本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用. 顶点数组对象 顶点数组对象负责管理一组顶点属性,顶点属性包括位置.法线.纹理坐标等. OpenGL缓存 OpenGL缓存实质上 ...
- OpenGL学习(2)——绘制三角形
在创建窗口的基础上,添加代码实现三角形的绘制. 声明和定义变量 在屏幕上绘制一个三角形需要的变量有: 三角形的三个顶点坐标: Vertex Buffer Object 将顶点数据存储在GPU的内存中: ...
- 用OpenGL绘制平滑着色的三角形与相交区域的混合着色
一.三角形的绘制 在OpenGL中,面是由多边形构成的.三角形可能是最简单的多边形,它有三条边.可以使用GL_TRIANGLES模式通过把三个顶点连接到一起而绘出三角形. 使用GL_TRIANGLE_ ...
- OpenGL绘制一个三角形
应该建立一个vertex shader文件和一个pixel shader文件,分别命名为shader.vsh和shader.fsh. shader.vsh: attribute vec3 positi ...
随机推荐
- python判断链表是否有环
思路:使用快慢指针,快指针每次走两步,慢指针每次走一步,如果有环,则一定会快慢指针指向同一结点: 假设环的长度为n,先让一个指针走n步,另一个再开始走,当他们指针指向同一结点时,该结点就是环入口点 ( ...
- 阿里云docker部署mysql
看完我的上一个博客之后,对centos系统应该有一定的了解,话不多说,接下来我们来在docker容器中部署mysql. 1.下载mysql镜像,因为本人用的5.7版本,你也可以下载最新版,都是可以的 ...
- 使用vue-cli(vue脚手架)快速搭建项目-2
接上一篇文章,这篇文章对如何使用IDEA打开并运行项目做教程 1.将在窗口模式启动的Vue关闭 只需要按住Ctrl+C,输入Y就可以了 2.打开idea 3.复制你项目所在地址,然后点击OK 4.下面 ...
- Powershell编程基础-002-日期及日期格式化
在Powershell中,关于日期,时间计算与格式化,常用的如下: $today=Get-Date ...
- xss利用——BeEF#stage1
全文概览 简介 BeEF( The Browser Exploitation Framework) 是由Wade Alcorn 在2006年开始创建的,至今还在维护.是由ruby语言开发的专门针对浏览 ...
- python类中的__init__和__new__方法
Python中类: Python中在创建类的过程中最先调用的不是__init__方法而是__new__方法,__new__方法是一个静态方法,在创建一个类对象时其实是通过__new__方法首先创建出一 ...
- kafka面试总结
本文为复习期间面试总结 从以下方面对kafka面试进行总结:基本原理架构/项目实践/生产者/消费者/协调者/存储层/控制器 基本原理架构 简单讲下什么是kafka[一句话概括/架构图] 消息队列选型 ...
- burp suite之spider(爬虫)
spider (蜘蛛,这里的意思指爬行) 像蜘蛛一样在网站上爬行出网站的个个目录信息,并发送至Target. 1.Control(控制) Spider is paused :停止蜘蛛爬行 Clear ...
- 登陆页跳出iframe
1 if(top.location.href != location.href){ 2 top.location.href = location.href; 3 }
- 【CF1425H】Huge Boxes of Animal Toys 题解
原题链接 题意简介: 已知分别处在 \((-\infty,-1]\) H.\((-1,0)\) .\((0,1)\) .\([1,\infty)\) 的实数的数量(下记为集合 \(A,B,C,D\) ...