首页
关于
归档
留言
友链
Search
1
compute shader详解
60 阅读
2
Framebuffer用法
45 阅读
3
Blend用法
42 阅读
4
收集的OpenGL资源
35 阅读
5
流体模拟概述
32 阅读
opengl技术
物理引擎
vulkan技术
登录
Search
标签搜索
流体模拟
物理引擎基础
blend
compute shader
计算管线
vulkan基础
基础知识
framebuffer
混合
opengl资源
模板测试
stencil
坐标系
纹理
坐标系统
顶点缓冲
VBO
opengl入门
genius
累计撰写
14
篇文章
累计收到
0
条评论
首页
栏目
opengl技术
物理引擎
vulkan技术
页面
关于
归档
留言
友链
搜索到
9
篇与
opengl技术
的结果
2021-12-26
Framebuffer用法
Framebuffer介绍opengl中framebuffer称为帧缓冲,它是一个内存缓冲区,如果把渲染到屏幕的颜色缓冲,深度缓冲,模板缓冲都缓存到内存中,那么就叫帧缓冲。Framebuffer用法framebuffer通常用在离屏渲染或者后处理上,主要涉及这几个函数:glGenFramebuffers :创建framebufferglBindFramebuffer :绑定framebufferglFramebufferTexture2D :将纹理附加到framebuffer到,实现绘制到纹理示例代码我们模拟一个后处理操作,将Blend用法中的绘制结果画在屏幕中央,并且对结果的颜色取反向,让我们看看具体代码:05.FBTexture.fs内容:#version 330 core in vec2 TexCoord; uniform sampler2D tex1; out vec4 FragColor; void main() { FragColor = vec4(vec3(1.0 - texture(tex1, TexCoord)), 1.0); }实现代码:void display( GLFWwindow* window ) { // 1.绑定framebuffer,这样可以绘制到附加的纹理fbTexture上 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor( 0, 0, 0.4, 0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(boxProgramID); glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float) 5 / (float)5, 0.1f, 100.0f); glm::mat4 view = glm::lookAt(glm::vec3(1,2,3), glm::vec3(0,0,0), glm::vec3(0,1,0)); glm::mat4 model = glm::mat4(1.0f); glm::mat4 mvp = projection * view * model; // 2.画地面 GLuint mvpId = glGetUniformLocation(boxProgramID, "MVP"); glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glBindVertexArray(FloorVAO); glBindTexture(GL_TEXTURE_2D, floorTexture); glDrawArrays(GL_TRIANGLES, 0, 6); // 3.画立方体 glBindVertexArray(VAO); glBindTexture(GL_TEXTURE_2D, texture); glDrawArrays(GL_TRIANGLES, 0, 36); // 4.画blend物体 model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(0, 0, 1.01f)); mvp = projection * view * model; glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glBindTexture(GL_TEXTURE_2D, blendTexture); glDrawArrays(GL_TRIANGLES, 0, 6); // 5.对fbTexture采样后处理将绘制到屏幕 glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(0.3f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(screenProgramID); glBindVertexArray(screenVAO); glBindTexture(GL_TEXTURE_2D, fbTexture); glDrawArrays(GL_TRIANGLES, 0, 6); } void prepare() { boxProgramID = LoadShaders( "data/shader/03.MVP.vs", "data/shader/03.MVP.fs" ); const GLfloat g_vertex_buffer_data[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; float fllor_vertex_buffer_data[] = { 5.0f, -0.5f, 5.0f, 1.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 1.0f, 5.0f, -0.5f, 5.0f, 1.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 1.0f, 5.0f, -0.5f, -5.0f, 1.0f, 1.0f }; float blend_vertex_buffer_data[] = { 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.0f }; // 1.VAO、VBO的数据 glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); GLuint VBO1; glGenBuffers(1, &VBO1); glBindBuffer(GL_ARRAY_BUFFER, VBO1); glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // 2.地面贴图 glGenVertexArrays(1, &FloorVAO); glBindVertexArray(FloorVAO); GLuint VBO2; glGenBuffers(1, &VBO2); glBindBuffer(GL_ARRAY_BUFFER, VBO2); glBufferData(GL_ARRAY_BUFFER, sizeof(fllor_vertex_buffer_data), fllor_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // 3.blend贴图 glGenVertexArrays(1, &BlendVAO); glBindVertexArray(BlendVAO); GLuint VBO3; glGenBuffers(1, &VBO3); glBindBuffer(GL_ARRAY_BUFFER, VBO3); glBufferData(GL_ARRAY_BUFFER, sizeof(blend_vertex_buffer_data), blend_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // 纹理数据 floorTexture = loadTexture("data/img/33.png"); texture = loadTexture("data/img/11.jpg"); blendTexture = loadTexture("data/img/chick.png"); // 4.创建framebuffer以及附加的纹理 glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glGenTextures(1, &fbTexture); glBindTexture(GL_TEXTURE_2D, fbTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbTexture, 0); // 5.绘制到屏幕的shader和顶点数据 screenProgramID = LoadShaders( "data/shader/02.Texture.vs", "data/shader/05.FBTexture.fs" ); const GLfloat g_screen_vertex_buffer_data[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f }; // VAO、VBO的数据 GLuint screenVBO; glGenVertexArrays(1, &screenVAO); glBindVertexArray(screenVAO); glGenBuffers(1, &screenVBO); glBindBuffer(GL_ARRAY_BUFFER, screenVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(g_screen_vertex_buffer_data), g_screen_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); }最终显示结果:
2021年12月26日
45 阅读
0 评论
0 点赞
2021-12-16
Blend用法
Blend用法opengl的blend用于颜色混合 ,如果不用混合,两张贴图贴在一起时,前面的贴图会覆盖后面的贴图,加上混合功能,两张贴图可以很好的贴合在一起。用代码演示一下用法。blend开启方法blend主要使用下面几个函数:glEnable(GL_BLEND): 开启blend功能glBlendFunc(GLenum sfactor, GLenum dfactor): sfactor源因子,dfactor目标因子示例代码我们先画一个普通场景void display( GLFWwindow* window ) { glClearColor( 0, 0, 0.4, 0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(boxProgramID); glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float) 5 / (float)5, 0.1f, 100.0f); glm::mat4 view = glm::lookAt(glm::vec3(1,2,3), glm::vec3(0,0,0), glm::vec3(0,1,0)); glm::mat4 model = glm::mat4(1.0f); glm::mat4 mvp = projection * view * model; // 1.画地面 GLuint mvpId = glGetUniformLocation(boxProgramID, "MVP"); glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glBindVertexArray(FloorVAO); glBindTexture(GL_TEXTURE_2D, floorTexture); glDrawArrays(GL_TRIANGLES, 0, 6); // 2.画立方体 glBindVertexArray(VAO); glBindTexture(GL_TEXTURE_2D, texture); glDrawArrays(GL_TRIANGLES, 0, 36); // 3.画blend物体 model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(0, 0, 1.01f)); mvp = projection * view * model; glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glBindTexture(GL_TEXTURE_2D, blendTexture); glDrawArrays(GL_TRIANGLES, 0, 6); } void prepare() { boxProgramID = LoadShaders( "data/shader/03.MVP.vs", "data/shader/03.MVP.fs" ); const GLfloat g_vertex_buffer_data[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; float fllor_vertex_buffer_data[] = { 5.0f, -0.5f, 5.0f, 1.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 1.0f, 5.0f, -0.5f, 5.0f, 1.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 1.0f, 5.0f, -0.5f, -5.0f, 1.0f, 1.0f }; float blend_vertex_buffer_data[] = { 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.0f }; // 1.VAO1、VBO的数据 glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); GLuint VBO1; glGenBuffers(1, &VBO1); glBindBuffer(GL_ARRAY_BUFFER, VBO1); glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // 2.地面贴图 glGenVertexArrays(1, &FloorVAO); glBindVertexArray(FloorVAO); GLuint VBO2; glGenBuffers(1, &VBO2); glBindBuffer(GL_ARRAY_BUFFER, VBO2); glBufferData(GL_ARRAY_BUFFER, sizeof(fllor_vertex_buffer_data), fllor_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // 2.blend贴图 glGenVertexArrays(1, &BlendVAO); glBindVertexArray(BlendVAO); GLuint VBO3; glGenBuffers(1, &VBO3); glBindBuffer(GL_ARRAY_BUFFER, VBO3); glBufferData(GL_ARRAY_BUFFER, sizeof(blend_vertex_buffer_data), blend_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); // 纹理数据 floorTexture = loadTexture("data/img/33.png"); texture = loadTexture("data/img/11.jpg"); blendTexture = loadTexture("data/img/chick.png"); glEnable(GL_DEPTH_TEST); }都是普通贴图操作,显示效果如下:因为是直接贴图覆盖的,所以小鸡周边alpha为0的颜色显示为黑色,如果加上blend功能,则可以看到后面图片的内容了:glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);最终显示效果:
2021年12月16日
42 阅读
0 评论
0 点赞
2021-12-15
Stencil用法
模板测试opengl的stencil称为模板测试,和深度测试一样,是Opengl中常用的技术。概念就不解释了,直接演示用法。我们实现对一个立方体盒子进行高亮描边。stencil用法stencil最简单的用法是使用下面三个函数:glStencilMask(GLuint value): 位遮罩, 0x00设置模板缓冲不可写入;value=0xFF设置可以写入。glStencilFunc(GLenum func, GLint ref, GLuint mask): 用ref值与存储的模板值比较,func为比较方法。glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass): 模板值的写入策略简单来说,glStencilMask是开关,开了才可以写入模板值;glStencilFunc是写入模板值的前提条件;glStencilOp是模板值的具体写入方法。示例代码普通流程我们先准备好了画一个立方体盒子的代码:GLuint boxProgramID; void display( GLFWwindow* window ) { glClearColor( 0, 0, 0.4, 0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 设置好坐标变化的mvp glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float) 5 / (float)5, 0.1f, 100.0f); glm::mat4 view = glm::lookAt(glm::vec3(1,2,3), glm::vec3(0,0,0), glm::vec3(0,1,0)); glm::mat4 model = glm::mat4(1.0f); glm::mat4 mvp = projection * view * model; // 画立方体 glUseProgram(boxProgramID); GLuint mvpId = glGetUniformLocation(boxProgramID, "MVP"); glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glDrawArrays(GL_TRIANGLES, 0, 36); } void prepare() { boxProgramID = LoadShaders( "data/shader/03.MVP.vs", "data/shader/03.MVP.fs" ); // 立方体的顶点坐标,纹理坐标 const GLfloat g_vertex_buffer_data[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; // VAO、VBO的数据 GLuint VAO1; GLuint VBO1; glGenVertexArrays(1, &VAO1); glBindVertexArray(VAO1); glGenBuffers(1, &VBO1); glBindBuffer(GL_ARRAY_BUFFER, VBO1); glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理数据 GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); // 环绕方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // 加载图片数据 int width, height, channels; stbi_set_flip_vertically_on_load(true); unsigned char* data = stbi_load("data/img/test.jpg", &width, &height, &channels, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); stbi_image_free(data); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); glEnable(GL_DEPTH_TEST); } int main( int argc, char** argv ) { glfwInit(); GLFWwindow* window = glfwCreateWindow( 512, 512, "OpenGL_Tutorial", NULL, NULL ); glfwMakeContextCurrent( window ); gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress ); glfwSwapInterval( 1 ); glfwSetKeyCallback( window, keyboard ); glfwSetCursorPosCallback( window, motion ); glfwSetMouseButtonCallback( window, mouse ); prepare(); while (!glfwWindowShouldClose(window)) { display(window); glfwPollEvents(); glfwSwapBuffers(window); } glfwTerminate(); return 0; }显示效果如图:使用模板测试功能加入模板测试功能,流程描述:开启模板测试清除所有模板值画一个立方体盒子,将盒子区域的模板值设置可写,值为1画一个稍大点的盒子(盒子放大1.05倍),不贴图,fs里直接设置颜色固定值,进行模板测试,模板测试条件为模板值 != 1,设置模板值不可写。具体代码:void display( GLFWwindow* window ) { // 1.开启stencil功能 glEnable(GL_STENCIL_TEST); // 设置模板值可写,下面的clear GL_STENCIL_BUFFER_BIT操作才能执行 glStencilMask(0xFF); // 设置模板测试成功的写入方式为替换,即测试成功,使用glStencilFunc中的ref值写入模板值 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glClearColor( 0, 0, 0.4, 0 ); // 2.清除深度、模板值 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // 3.画立方体 glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float) 5 / (float)5, 0.1f, 100.0f); glm::mat4 view = glm::lookAt(glm::vec3(1,2,3), glm::vec3(0,0,0), glm::vec3(0,1,0)); glm::mat4 model = glm::mat4(1.0f); glm::mat4 mvp = projection * view * model; // 设置模板值的写入策略,GL_ALWAYS表示无条件写入 glStencilFunc(GL_ALWAYS, 1, 0xFF); glUseProgram(boxProgramID); GLuint mvpId = glGetUniformLocation(boxProgramID, "MVP"); glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glDrawArrays(GL_TRIANGLES, 0, 36); // 4.画描边 model = glm::mat4(1.0f); // 放大盒子为原来的1.05倍 model = glm::scale(model, glm::vec3(1.05, 1.05, 1.05)); mvp = projection * view * model; // 进行模板测试,只有不等于1的模板值才测试成功 glStencilFunc(GL_NOTEQUAL, 1, 0xFF); // 设置模板值不可写,此处无需更新模板值 glStencilMask(0x00); glUseProgram(stencilProgramID); mvpId = glGetUniformLocation(stencilProgramID, "MVP"); glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]); glDrawArrays(GL_TRIANGLES, 0, 36); }现在的效果:
2021年12月15日
25 阅读
0 评论
0 点赞
2021-12-12
MVP变换坐标
MVP概念在opengl中,MVP称为模型观察投影矩阵,它是模型(Model)、观察(View)和投影(Projection)矩阵作用在物体上组合作用,用于对物体的坐标系进行变换。如上图所示,物体的坐标系变化过程为:局部坐标系世界坐标系观察坐标系裁剪坐标系MVP公式$$ MVP=Mprojection⋅Mview⋅Mmodel$$在shader中用MVP * gl_Position 得到转换后的坐标。示例代码在OpenGL纹理中,介绍了纹理的使用方法,最终的运行效果为:修改vertext shader,添加MVP变量#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; uniform mat4 MVP; out vec2 TexCoord; void main() { gl_Position = MVP * vec4(aPos, 1.0); TexCoord = aTexCoord; }在绘制之前将MVP矩阵传入着色器:glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float) width / (float)height, 0.1f, 100.0f); glm::mat4 view = glm::lookAt(glm::vec3(1,2,3), glm::vec3(0,0,0), glm::vec3(0,1,0)); glm::mat4 model = glm::mat4(1.0f); glm::mat4 mvp = projection * view * model; GLuint mvpId = glGetUniformLocation(programID, "MVP"); glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]);现在的运行效果如下:
2021年12月12日
23 阅读
0 评论
0 点赞
2021-11-21
OpenGL纹理
简介opengl纹理简单来说就是贴图,像2D游戏,就是用大量的贴图拼起来组成丰富多彩的画面。下面我们详细地描述一下使用纹理的代码方式。示例代码顶点着色器输入两组坐标,顶点坐标和纹理坐标,纹理坐标直接传递给片段着色器//02.Texture.vs #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0); TexCoord = aTexCoord; }片段着色器定义一个纹理采样器text1,它与代码中绑定的TEXTURE0关联,使用传入的纹理坐标采样//02.Texture.fs #version 330 core in vec2 TexCoord; uniform sampler2D tex1; out vec4 FragColor; void main() { FragColor = texture(tex1, TexCoord); }实现代码逻辑GLuint programID = LoadShaders( "data/shader/02.Texture.vs", "data/shader/02.Texture.fs" ); glUseProgram(programID); // 顶点、纹理坐标 const GLfloat g_vertex_buffer_data[] = { -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下角 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // 右下角 -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, // 左上角 0.5f, 0.5f, 0.0f, 1.0f, 1.0f // 右上角 }; // 顶点索引 unsigned int indices[] = {0, 1, 2, 1, 2, 3}; // VAO1、VBO1、EBO1的数据 GLuint VAO1; GLuint VBO1; GLuint EBO1; glGenVertexArrays(1, &VAO1); glBindVertexArray(VAO1); glGenBuffers(1, &VBO1); glBindBuffer(GL_ARRAY_BUFFER, VBO1); glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); glGenBuffers(1, &EBO1); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO1); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); // 纹理数据 GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); // 环绕方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 加载图片数据 int width, height, channels; // 图像坐标系与纹理坐标系相反,翻转y轴 stbi_set_flip_vertically_on_load(true); unsigned char* data = stbi_load("data/img/test.jpg", &width, &height, &channels, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); stbi_image_free(data); // 纹理坐标 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));运行效果:环绕方式通过设置GL_TEXTURE_WRAP_参数来设置环绕方式GL_REPEAT: 超出纹理范围的坐标整数部分被忽略,形成重复效果。GL_MIRRORED_REPEAT: 超出纹理范围的坐标整数部分被忽略,但当整数部分为奇数时进行取反,形成镜像效果。GL_CLAMP_TO_EDGE: 超出纹理范围的坐标被截取成0和1,形成纹理边缘延伸的效果。GL_CLAMP_TO_BORDER: 超出纹理范围的部分被设置为边缘色。如果将纹理坐标改成如下:const GLfloat g_vertex_buffer_data[] = { -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下角 0.5f, -0.5f, 0.0f, 2.0f, 0.0f, // 右下角 -0.5f, 0.5f, 0.0f, 0.0f, 2.0f, // 左上角 0.5f, 0.5f, 0.0f, 2.0f, 2.0f // 右上角 };不同环绕方式对应的效果:GL_REPEATGL_MIRRORED_REPEATGL_CLAMP_TO_EDGEGL_CLAMP_TO_BORDER
2021年11月21日
24 阅读
0 评论
0 点赞
1
2