Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenGL es 2.0三角形上的高斯模糊_C++_Opengl Es_Glsl_Shader_Gaussianblur - Fatal编程技术网

C++ OpenGL es 2.0三角形上的高斯模糊

C++ OpenGL es 2.0三角形上的高斯模糊,c++,opengl-es,glsl,shader,gaussianblur,C++,Opengl Es,Glsl,Shader,Gaussianblur,我最近学习了opengl es 2.0,现在我尝试在自己生成的三角形上制作高斯模糊。我在网上有一些难以理解的例子,大多数都是在图像上应用模糊。我知道我必须使用帧缓冲区,但我不知道如何在此基础上绘制三角形并应用模糊。 是否可以在C++中看到一个完整完整的代码? 编辑: #include <stdio.h> #include <stdlib.h> #include <iostream> #define GLFW_INCLUDE_ES2 #include <

我最近学习了opengl es 2.0,现在我尝试在自己生成的三角形上制作高斯模糊。我在网上有一些难以理解的例子,大多数都是在图像上应用模糊。我知道我必须使用帧缓冲区,但我不知道如何在此基础上绘制三角形并应用模糊。 是否可以在C++中看到一个完整完整的代码? 编辑:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
#include "shaders.hpp"
#include "camera.hpp"

unsigned int vbo, cbo, tbo;
GLuint _fbo, _fbo2, _tex, _tex2;


static const GLuint WIDTH = 800;
static const GLuint HEIGHT = 600;
GLuint pos, col, tex, normal;
camera * _camera = new camera();

static const GLfloat vertices[] = {
  0.0f,  1.0f, 0.0f,
  1.0f, -1.0f, 0.0f,
  -1.0f, -1.0f, 0.0f
};

static const GLfloat colors[] = {
  0.0f,  0.5f, 1.0f,
  0.5f,  0.5f, 1.0f,
  0.5f,  0.5f, 1.0f
};

static const GLfloat texture[] = {
  1.0f, 1.0f,
  1.0f, 0.0f,
  0.0f, 1.0f
};

int main(void){
  GLFWwindow* window;
  shaders * shaderBasic;
  GLuint pId;

  glm::mat4 projection; static glm::mat4 view; static glm::mat4 model;

  glfwInit();
  glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL);
  glfwMakeContextCurrent(window);

  printf("GL_VERSION  : %s\n", glGetString(GL_VERSION) );
  printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );

  std::string vs, fs;
  vs = "basic.vs";
  fs = "basic.fs";
  shaderBasic = new shaders(vs, fs);
  shaderBasic->CompileShader();
  shaderBasic->LinkShader();
  pId = shaderBasic->getProgramId();

  pos = glGetAttribLocation(pId, "position");
  col = glGetAttribLocation(pId, "colors");
  tex = glGetAttribLocation(pId, "tex");

  fs = "lastBlur.fs";
  shaders * blurShader;
  GLuint pIdBlur;
  blurShader = new shaders(vs, fs);
  blurShader->CompileShader();
  blurShader->LinkShader();
  pIdBlur = blurShader->getProgramId();

  _camera->setPositionCamera(glm::vec3(0, 0, -1));
  _camera->setLookAtCamera(glm::vec3(0, 0, 0));
  _camera->setFieldOfView(45);
  _camera->setAspect(WIDTH, HEIGHT);
  _camera->setViewport(WIDTH, HEIGHT);
  _camera->getMatricies(projection, view, model);

  glGenFramebuffers(1, &_fbo);
  glGenTextures(1, &_tex);
  glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
  glBindTexture(GL_TEXTURE_2D, _tex);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH/2, HEIGHT/2, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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, _tex, 0);
  glBindTexture(GL_TEXTURE_2D, 0);
  glBindFramebuffer(GL_FRAMEBUFFER, 0);

  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
  else{
    std::cout << "FRAMEBUFFER COMPLETE" << std::endl;
  }
  auto sampTex = glGetUniformLocation(pIdBlur, "texture0");
  std::cerr << "sampTex : " << sampTex << std::endl;
  glUniform1i(sampTex, 0);  
  while (!glfwWindowShouldClose(window)) {
    //    glViewport(0, 0, WIDTH, HEIGHT);

    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //    glViewport(0, 0, WIDTH/2, HEIGHT/2);
    glUseProgram(pIdBlur);
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(pos, 3, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(pos);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &cbo);
    glBindBuffer(GL_ARRAY_BUFFER, cbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
    glVertexAttribPointer(col, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(col);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(texture), texture, GL_STATIC_DRAW);
    glVertexAttribPointer(tex, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(tex);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glDrawArrays(GL_TRIANGLES, 0, 3);


    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUseProgram(pId);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _tex);
    glDrawArrays(GL_TRIANGLES, 0, 3);    

    glfwPollEvents();
    glfwSwapBuffers(window);
  }
  glDeleteBuffers(1, &vbo);
  glfwTerminate();
  return EXIT_SUCCESS;
}

通常,需要将要模糊的场景绘制为具有附加纹理的帧缓冲区对象(FBO)

  • 创建一个帧缓冲区
  • 创建空纹理(数据参数应为null)
  • 绑定帧缓冲区和纹理
  • 将纹理作为颜色附加到帧缓冲区
此时,图形的其余部分应与主缓冲区上的完全相同,但请确保设置了正确的视口。此过程将使您绘制到纹理

现在场景中有了纹理,您需要执行与模糊图像相同的步骤

  • 绑定主缓冲区(通常索引为0)
  • 绑定纹理
  • 使用模糊着色器将纹理绘制到主缓冲区
然后,您可以使用水平和垂直模糊着色器优化它,该着色器有2个调用,使用另一个FBO

因此,我将尝试在您的应用程序中执行以下步骤:

  • 创建绘制并显示三角形的场景
  • 创建一个FBO,绘制到它,然后在主缓冲区上绘制FBO纹理
  • 创建通过纹理绘制和显示模糊图像的场景
  • 创建绘制场景的FBO,然后从主缓冲区上的FBO绘制模糊纹理

如果您发现自己在上述任何一点上遇到了麻烦,您可能想问一个具体的问题。

我想您已经交换了
pIdBlur
pId

我将为您介绍高斯模糊着色器,它有两个过程。这是一个近似值,它首先在第一遍中沿X轴模糊,在第二遍中沿Y轴模糊。这将产生更好的强模糊性能。 “模糊”着色器使用“模糊”选项。对于这两个过程,使用相同的着色器程序,对这两个过程进行单独的方向设置,存储在uniform
vec2 u_dir
中。模糊效果的强度可随[0.0,1.0]范围内的均匀变量
float u_sigma
而变化

模糊顶点着色器

precision mediump float;
attribute vec2 inPos;
varying   vec2 pos;

void main()
{
    pos = inPos;
    gl_Position = vec4( inPos, 0.0, 1.0 );
}
模糊片段着色器

precision mediump float;
varying vec2 pos;

uniform sampler2D u_texture;
uniform vec2      u_textureSize;
uniform float     u_sigma;
uniform vec2      u_dir;

float CalcGauss( float x, float sigma )
{
    if ( sigma <= 0.0 )
        return 0.0;
    return exp( -(x*x) / (2.0 * sigma) ) / (2.0 * 3.14157 * sigma);
}

void main()
{
    vec2 texC     = pos.st * 0.5 + 0.5;
    vec4 texCol   = texture2D( u_texture, texC );
    vec4 gaussCol = vec4( texCol.rgb, 1.0 );
    vec2 step     = u_dir / u_textureSize;
    for ( int i = 1; i <= 32; ++ i )
    {
        float weight = CalcGauss( float(i) / 32.0, u_sigma * 0.5 );
        if ( weight < 1.0/255.0 )
            break;
        texCol    = texture2D( u_texture, texC + step * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
        texCol    = texture2D( u_texture, texC - step * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
    }
    gaussCol.rgb = clamp( gaussCol.rgb / gaussCol.w, 0.0, 1.0 );
    gl_FragColor = vec4( gaussCol.rgb, 1.0 );
}
必须创建一个顶点阵列对象,该对象包含一个四边形,稍后将在整个视口上绘制,用于屏幕空间模糊过程:

GLuint screenVAO;
glGenVertexArrays( 1, &screenVAO );
glBindVertexArray( screenVAO );
GLuint quadBuf;
glGenBuffers( 1, &quadBuf );
glBindBuffer( GL_ARRAY_BUFFER, quadBuf );
GLfloat screenRect[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f };
glBufferData( GL_ARRAY_BUFFER, 8 * sizeof( float ), screenRect, GL_STATIC_DRAW );
glEnableVertexAttribArray( attrInxPos );
glVertexAttribPointer( attrInxPos, 2, GL_FLOAT, GL_FALSE, 0, nullptr );
必须创建两个帧缓冲区,并将纹理附着到其颜色平面。在第一个场景中,绘制场景。这个 第二个用于第一个模糊过程。第二次模糊过程直接绘制到绘图缓冲区

GLuint texObj[2];
GLuint fbObj[2];
glGenTextures(2, texObj);
glGenFramebuffers(2, fbObj);
glActiveTexture(GL_TEXTURE0);
for ( int i = 0; i < 2; i ++ )
{
    glBindTexture(GL_TEXTURE_2D, texObj[i]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindFramebuffer(GL_FRAMEBUFFER, fbObj[i]);
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texObj[i], 0 );
    GLuint renderbuffer;
    glGenRenderbuffers(1, &renderbuffer);
    glBindRenderbuffer( GL_RENDERBUFFER, renderbuffer );
    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height );
    glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer );
}
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
并使用着色器程序绘制对象:

glUseProgram(pId);
现在绘制场景的对象

.....
glDrawArrays(GL_TRIANGLES, 0, 3);
第二步是第一次模糊过程。必须使用模糊程序,并且必须绑定第二帧缓冲区。 释放第1帧缓冲区后,可以使用附加到其颜色平面的纹理作为模糊着色器的输入。
注意,纹理不能同时作为源和目标,这将导致未定义的行为。
要将纹理绑定到着色器,必须将纹理绑定到纹理单元,并将纹理单元的索引指定给着色器的统一采样器

int texUnitIndex = 1;
GLfloat texSize  = { width, height };
GLfloat dirX[]   = { 1.0f, 0.0f };  
GLfloat sigma    = .....; // 0.0 <= sigma <= 1.0

glBindFramebuffer(GL_FRAMEBUFFER, fbObj[1]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pIdBlur);
glActiveTexture(GL_TEXTURE0 + texUnitIndex);
glBindTexture(GL_TEXTURE_2D, texObj[0]);
glUniform1i(locTexture, texUnitIndex); 
glUniform2fv(locTexSize, texSize);
glUniform2fv(locTexSize, dirX);
glUniform1f(locTexSize, sigma);
第二个也是最后一个模糊过程类似于第一个模糊过程。第一个模糊过程的目标纹理是源纹理,目标是绘图缓冲区。必须为视口的Y轴设置模糊方向

GLfloat dirY[] = { 0.0f, 1.0f }; 

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texObj[1]);
glUniform2fv(locTexSize, dirY);
另见以下问题的答案:

请参见类似的WebGL示例:

(函数loadscene(){
变量调整大小、gl、progDraw、progBlur、vp_大小、blurFB;
var canvas,camera,bufCube={},bufQuad={};
光泽度=10.0,辉光=10.0,西格玛=0.8,半径=1.0;
函数渲染(deltaMS){
var滑块刻度=100;
sigma=document.getElementById(“sigma”).value/sliderScale;
radius=document.getElementById(“radius”).value/sliderScale;
vp_size=[canvas.width,canvas.height];
摄像机更新(vp_尺寸);
总帐启用(总帐深度测试);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//设置帧缓冲区
gl.bindFramebuffer(gl.FRAMEBUFFER,blurFB[0]);
gl.视口(0,0,blurFB[0]。宽度,blurFB[0]。高度);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//设置视图投影和模型
var prjMat=camera.Perspective();
var viewMat=camera.LookAt();
var modelMat=RotateAxis(IdentM44(),分形(deltaMS/13000.0)*2.0*Math.PI,0);
modelMat=旋转轴(modelMat,分形(deltaMS/17000.0)*2.0*Math.PI,1);
//设置绘图着色器
ShProg.用法(progDraw);
ShProg.SetM44(prograw,“u_projectionMat44”,prjMat);
ShProg.SetM44(progDraw,“u_modelViewMat44”,乘法(viewMat,modelMat));
ShProg.SetF1(程序图,“亮度”,亮度);
//画场景
VertexBuffer.Draw(bufCube);
//设置blur-X帧缓冲区并绑定frambuffer纹理
gl.bindFramebuffer(gl.FRAMEBUFFER,blurFB[1]);
gl.视口(0,0,blurFB[1]。宽度,blurFB[1]。高度);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var-texUnit=1;
gl.activeTexture(gl.TEXTURE0+texUnit);
gl.bindTexture(gl.TEXTURE\u 2D,blurFB[0].color0\u纹理);
//设置blur-X着色器
程序使用(程序模糊);
ShProg.SetI1(程序模糊,“u_纹理”,texUnit)
ShProg.SetF2(程序模糊,“u_纹理化”,vp_尺寸);
ShProg.SetF1(程序模糊,“u_西格玛”,西格玛)
ShProg.SetF1(程序模糊,“u_半径”,半径)
ShProg.SetF2(progBlur,“u_dir”[1.0,0.0])
//绘制全屏空间
gl.EnableVertexAttributeArray(progBlur.inPos);
gl.bindBuffer(gl.ARRAY\u BUFFER,bufQuad.pos);
顶点
.....
glDrawArrays(GL_TRIANGLES, 0, 3);
int texUnitIndex = 1;
GLfloat texSize  = { width, height };
GLfloat dirX[]   = { 1.0f, 0.0f };  
GLfloat sigma    = .....; // 0.0 <= sigma <= 1.0

glBindFramebuffer(GL_FRAMEBUFFER, fbObj[1]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pIdBlur);
glActiveTexture(GL_TEXTURE0 + texUnitIndex);
glBindTexture(GL_TEXTURE_2D, texObj[0]);
glUniform1i(locTexture, texUnitIndex); 
glUniform2fv(locTexSize, texSize);
glUniform2fv(locTexSize, dirX);
glUniform1f(locTexSize, sigma);
glBindVertexArray( screenVAO );
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
GLfloat dirY[] = { 0.0f, 1.0f }; 

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texObj[1]);
glUniform2fv(locTexSize, dirY);