OpenGL知识点整理(1)

您所在的位置:网站首页 opengl投影矩阵推导 OpenGL知识点整理(1)

OpenGL知识点整理(1)

#OpenGL知识点整理(1)| 来源: 网络整理| 查看: 265

欢迎关注公众号:sumsmile /专注图形学

花了几天时间,整理了以前写的learnopengl笔记,做了删减、补充。

learnopengl地址:learnopengl-英文-pdf、learnopengl-中文、learnopengl-在线英文

入门 图形管线

顶点数据

是用顶点属性(Vertex Attribute)表示的,它可以包含任何我们想用的数据,如坐标、颜色、法线等

图元(Primitive),告诉GL如何解释顶点

GL_POINTS 点 GL_TRIANGLES 三角形 GL_LINE_STRIP 线条

在片段着色器运行之前会执行裁切(Clipping)。裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。

顶点缓冲对象(Vertex Buffer Objects, VBO),存放顶点数据 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 复制代码 GPU管理数据三种方式: GL_STATIC_DRAW :数据不会或几乎不会改变。 GL_DYNAMIC_DRAW:数据会被改变很多。 GL_STREAM_DRAW :数据每次绘制时都会改变。 顶点数据使用 // 0. 复制顶点数组到缓冲中供OpenGL使用 glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 1. 设置顶点属性指针 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // 2. 当我们渲染一个物体时要使用着色器程序 glUseProgram(shaderProgram); // 3. 绘制物体 someOpenGLFunctionThatDrawsOurTriangle(); 复制代码 顶点数组对象

顶点数组对象(Vertex Array Object, VAO):可以同时绑定一组缓冲

glEnableVertexAttribArray和glDisableVertexAttribArray的调用。

绘制三角形的三种方式

GL_TRIANGLES GL_TRIANGLE_STRIP,每次增加一个点 GL_TRIANGLE_FAN 扇形 draw有两种方式 drawArray drawElement glUseProgram(shaderProgram); // drawArrays glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); // drawElements glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 复制代码 着色器 能声明的顶点属性是有上限的

OpenGL确保至少有16个包含4分量的顶点属性可用。

但是有些硬件或许允许更多的顶点属性,你可以查询GL_MAX_VERTEX_ATTRIBS来获取具体的上限

int nrAttributes; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes); std::cout second); shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); } 复制代码

**注意:**源代码中,地板的纹理设置超过了2,实现repeat的地板

地板的顶点属性

float planeVertices[] = { // positions // texture Coords 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; 复制代码

地板的环绕方式设置为repeat

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT); // for this tutorial: use GL_CLAMP_TO_EDGE to prevent semi-transparent borders. Due to interpolation it takes texels from next repeat glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 复制代码

源代码参考:learningOpenGl-blending_discard

更高级的技术还有次序无关透明度(Order Independent Transparency, OIT),参考OIT,后面有时间研究下

面剔除

默认会剔除顺时针方向的面

启用面剔除 glEnable(GL_CULL_FACE); 复制代码 设置默认的正面 GL_BACK:只剔除背向面。 GL_FRONT:只剔除正向面。 GL_FRONT_AND_BACK:剔除正向面和背向面 glCullFace(GL_FRONT); 复制代码

glCullFace(GL_FRONT_AND_BACK)后,所有的多边形都将被剔除,所以看见的就只有点和直线

例子,实现一个前面剔除,两种实现

剔除前面 glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); 复制代码 剔除背面,但是定义clock-wise(顺时针为前面) glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CW); 复制代码 帧缓冲

帧缓冲

一个完整的帧缓冲需要满足以下的条件: 附加至少一个缓冲(颜色、深度或模板缓冲)。 至少有一个颜色附件(Attachment)。 所有的附件都必须是完整的(保留了内存)。 每个缓冲都应该有相同的样本数。

检查帧缓冲是否完整

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) // 执行胜利的舞蹈 复制代码 Renderbuffer Object(渲染缓冲对象)

一种更适合GPU读写的缓冲格式,相比纹理,效率更高。缺点是readpix效率比较低

如果不需要作为纹理采样处理,可以使用Renderbuffer Object,比如深度、模板缓冲

参考 stackoverflow上的解释:What's the concept of and differences between Framebuffer and Renderbuffer in OpenGL?

看一个framebuffer的例子,理解framebuffer的流程 // 1. 创建帧缓冲,绑定 unsigned int framebuffer; glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); // 2. 创建纹理,设置参数,后面需要以它采样,用纹理的格式 // 生成纹理 unsigned int texColorBuffer; glGenTextures(1, &texColorBuffer); glBindTexture(GL_TEXTURE_2D, texColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); // 将它附加到当前绑定的帧缓冲对象 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0); // 3. 创建一个深度和模板渲染缓冲对象 unsigned int rbo; glGenRenderbuffers(1, &rbo); glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); glBindRenderbuffer(GL_RENDERBUFFER, 0); // 4. 渲染缓冲对象附加到帧缓冲的深度和模板附件上 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // 5. 检查帧缓冲 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3