[video(video-83qMkG9M-1628401078616)(type-bilibili)(url-.html?aid=762197327)(image-.png)(title-【opengl】高斯模糊)]
6+6次水平垂直高斯模糊效果:
12+12次水平垂直高斯模糊效果:
50+50次水平垂直高斯模糊效果:
#version 130out vec4 FragColor;
in vec2 TexCoords;uniform sampler2D image;uniform bool horizontal;uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);void main()
{ //模糊步长,最精细为像素级,补偿越小颗粒感越低,同时每次模糊的效果也越低 vec2 tex_offset = 2.0 / textureSize(image, 0); // gets size of single texelvec3 result = texture(image, TexCoords).rgb * weight[0]; // current fragment's contributionif(horizontal){for(int i = 1; i < 5; ++i){result += texture(image, TexCoords + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];result += texture(image, TexCoords - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];}}else{for(int i = 1; i < 5; ++i){result += texture(image, TexCoords + vec2(0.0, tex_offset.y * i)).rgb * weight[i];result += texture(image, TexCoords - vec2(0.0, tex_offset.y * i)).rgb * weight[i];}}FragColor = vec4(result, 1.0);
}
片段着色器中只是对所有像素乘以高斯核,完成一次水平或者垂直的模糊,要想控制模糊程度需要CPU代码进行多次模糊。
对应的顶点着色器程序:
#version 130
in vec3 aPos; // 位置变量的属性位置值为0
in vec3 aColor;
in vec2 aTexCoord;out vec3 ourColor;
out vec2 TexCoords;void main()
{gl_Position = vec4(aPos, 1.0);ourColor = aColor;TexCoords = vec2(aTexCoord.x, aTexCoord.y);
}
glGenFramebuffers(2, pingpongFBO);glGenTextures(2, pingpongBuffers);for (unsigned int i = 0; i < 2; i++){glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]);glBindTexture(GL_TEXTURE_2D, pingpongBuffers[i]);//大坑!!!这里的纹理尺寸需要与屏幕(视口)像素尺寸一致,当图片尺寸大于屏幕尺寸时,会导致纹理内存填不满glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongBuffers[i], 0);// also check if framebuffers are complete (no need for depth buffer)if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)std::cout << "Framebuffer not complete!" << std::endl;}
进行乒乓渲染片段:
void blur()
{GLboolean horizontal = true;GLboolean first_iteration = true;GLuint amount = 100;mshader.use();for (GLuint i = 0; i < amount; i++){glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); glUniform1i(glGetUniformLocation(mshader.ID, "horizontal"), horizontal);glBindTexture(GL_TEXTURE_2D, first_iteration ? texture1 : pingpongBuffers[!horizontal]); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);///* 测试单步效果glBindFramebuffer(GL_FRAMEBUFFER, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glutSwapBuffers();usleep(500 * 1000 );//*/horizontal = !horizontal;if (first_iteration)first_iteration = false;}//可以实现GPU渲染完成再返回,类似linux的barrier机制glFinish();
}
完整代码:
main.cpp
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"#include <shader.h>
#include <GL/glut.h>
#include <stdlib.h>#include <string>
#include <fstream>
#include <sstream>
#include <iostream>#include <unistd.h>
#include <sys/time.h>
#include<stdio.h>// settings
const unsigned int SCR_WIDTH = 960;
const unsigned int SCR_HEIGHT = 540;
static Shader mshader;
unsigned int texture1;
unsigned int VBO, VAO, EBO;
GLboolean horizontal = true;
GLuint pingpongFBO[2];
GLuint pingpongBuffers[2];void reshape(int w, int h);
void display();
void resourceready();
void blur();
int main(int argc, char **argv)
{#define MILLION 1000000struct timeval tv1,tv2;long sec,usec;glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);glutInitWindowPosition(100, 100);glutInitWindowSize(SCR_WIDTH, SCR_HEIGHT);glutCreateWindow("SHADER_RECTANGLE");glewInit();const GLubyte* name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬件平台const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回当前OpenGL实现的版本号const GLubyte* GLESVersion =glGetString(GL_SHADING_LANGUAGE_VERSION); //返回当前OpenGL实现的版本号printf("OpenGL实现厂商的名字:%sn", name);printf("渲染器标识符:%sn", biaoshifu);printf("OpenGL实现的版本号:%sn",OpenGLVersion );printf("GLES语法的版本号:%sn",GLESVersion );mshader= Shader("shader.vs", "shader.fs"); resourceready();gettimeofday(&tv1, NULL);blur();gettimeofday(&tv2, NULL);sec = (tv2.tv_sec - tv1.tv_sec);usec = (tv2.tv_usec - tv1.tv_usec);std::cout << "---------tmie cost---------------" << sec <<"(s) "<< usec<<"(us) " << std::endl;glutReshapeFunc(&reshape);glutDisplayFunc(&display);glutMainLoop();// optional: de-allocate all resources once they've outlived their purpose:// ------------------------------------------------------------------------//glDeleteVertexArrays(1, &VAO);//glDeleteBuffers(1, &VBO);//glDeleteBuffers(1, &EBO);return 0;
}void reshape(int w, int h)
{glViewport(0, 0,(GLsizei)w, (GLsizei)h);
}void resourceready()
{// set up vertex data (and buffer(s)) and configure vertex attributes// ------------------------------------------------------------------float vertices[] = {// positions // colors // texture coords1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left };unsigned int indices[] = { 0, 1, 3, // first triangle1, 2, 3 // second triangle};glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);// position attributeglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// color attributeglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);// texture coord attributeglVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));glEnableVertexAttribArray(2);// load and create a texture // -------------------------glGenTextures(1, &texture1);glBindTexture(GL_TEXTURE_2D, texture1); // all upcoming GL_TEXTURE_2D operations now have effect on this texture object// set the texture wrapping parametersglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); // set texture wrapping to GL_REPEAT (default wrapping method)glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);// set texture filtering parametersglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// load image, create texture and generate mipmapsint width, height, nrChannels;stbi_set_flip_vertically_on_load(true); unsigned char *data = stbi_load("1080.jpeg", &width, &height, &nrChannels, 0);if (data){glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);std::cout << "texture1 width " <<width << " hight " << height <<" nrChannels " << nrChannels<< std::endl;}else{std::cout << "Failed to load texture" << std::endl;}stbi_image_free(data);glGenFramebuffers(2, pingpongFBO);glGenTextures(2, pingpongBuffers);for (unsigned int i = 0; i < 2; i++){glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]);glBindTexture(GL_TEXTURE_2D, pingpongBuffers[i]);//大坑!!!这里的纹理尺寸需要与屏幕(视口)像素尺寸一致,当图片尺寸大于屏幕尺寸时,会导致纹理内存填不满glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongBuffers[i], 0);// also check if framebuffers are complete (no need for depth buffer)if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)std::cout << "Framebuffer not complete!" << std::endl;}}void blur()
{GLboolean first_iteration = true;GLuint amount = 100;mshader.use();for (GLuint i = 0; i < amount; i++){glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); glUniform1i(glGetUniformLocation(mshader.ID, "horizontal"), horizontal);glBindTexture(GL_TEXTURE_2D, first_iteration ? texture1 : pingpongBuffers[!horizontal]); //std::cout << "---------------------------loop:" << i << std::endl;glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);///* 测试单步效果glBindFramebuffer(GL_FRAMEBUFFER, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glutSwapBuffers();usleep(500 * 1000 );//*/horizontal = !horizontal;if (first_iteration)first_iteration = false;}glFinish();
}void display()
{glBindFramebuffer(GL_FRAMEBUFFER, 0);// render// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// bind TextureglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, pingpongBuffers[!horizontal]);// render containermshader.use();glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//glDisableVertexAttribArray(0);glutSwapBuffers();
}
依赖库:
stb_image.h下载
stb_image.h使用
实验步骤:
OpenGL实现厂商的名字:VMware, Inc.
渲染器标识符:SVGA3D; build: RELEASE; LLVM;
OpenGL实现的版本号:3.0 Mesa 18.0.5
GLES语法的版本号:1.30
texture1 width 1920 hight 1080 nrChannels 3
---------time cost---------------0(s) 72273(us)
本文发布于:2024-01-28 06:29:35,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063945795464.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |