本文介绍了OpenGL es 2.0 三角形上的高斯模糊的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

#include <stdio.h>#include <stdlib.h>#include <iostream>#define GLFW_INCLUDE_ES2#include <GLFW/glfw3.h>#include 着色器.hpp"#include camera.hpp"无符号整数 vbo、cbo、tbo;GLuint _fbo,_fbo2,_tex,_tex2;静态常量 GLuint WIDTH = 800;静态常量 GLuint HEIGHT = 600;GLuint pos, col, tex, normal;相机 * _camera = 新相机();静态常量 GLfloat 顶点[] = {0.0f, 1.0f, 0.0f,1.0f,-1.0f,0.0f,-1.0f,-1.0f,0.0f};静态常量 GLfloat 颜色[] = {0.0f, 0.5f, 1.0f,0.5f, 0.5f, 1.0f,0.5f、0.5f、1.0f};静态常量 GLfloat 纹理[] = {1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f};诠释主要(无效){GLFWwindow* 窗口;着色器 * 着色器基础;胶粘剂 pId;glm::mat4 投影;静态 glm::mat4 视图;静态 glm::mat4 模型;glfwInit();glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);窗口 = glfwCreateWindow(宽度,高度,__FILE__,NULL,NULL);glfwMakeContextCurrent(窗口);printf("GL_VERSION : %s
", glGetString(GL_VERSION) );printf("GL_RENDERER : %s
", glGetString(GL_RENDERER) );std::string 与 fs;vs = "基本.vs";fs = "basic.fs";shaderBasic = 新着色器(vs,fs);shaderBasic->CompileShader();shaderBasic->LinkShader();pId = shaderBasic->getProgramId();pos = glGetAttribLocation(pId, "位置");col = glGetAttribLocation(pId,颜色");tex = glGetAttribLocation(pId, "tex");fs = "lastBlur.fs";着色器 * 模糊着色器;GLuint pIdBlur;blurShader = 新着色器(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(投影、视图、模型);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);如果(glCheckFramebufferStatus(GL_FRAMEBUFFER)!= GL_FRAMEBUFFER_COMPLETE)std::cout <<错误::FRAMEBUFFER:: 帧缓冲区不完整!"<

模糊着色器:

#version 100精度 mediump 浮点数;统一的sampler2D texture0;不同的 vec3 vColor;不同的 vec2 TexCoords;vec4 blur13(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {vec4 颜色 = vec4(0.0);vec2 off1 = vec2(1.411764705882353) * 方向;vec2 off2 = vec2(3.2941176470588234) * 方向;vec2 off3 = vec2(5.176470588235294) * 方向;颜色+=纹理2D(图像,紫外线)* 0.1964825501511404;颜色 += texture2D(图像, uv + (off1/分辨率)) * 0.2969069646728344;颜色 += texture2D(图像, uv - (off1/分辨率)) * 0.2969069646728344;颜色 += texture2D(图像, uv + (off2/分辨率)) * 0.09447039785044732;颜色 += texture2D(图像, uv - (off2/分辨率)) * 0.09447039785044732;颜色 += texture2D(图像, uv + (off3/分辨率)) * 0.010381362401148057;颜色 += texture2D(图像, uv - (off3/分辨率)) * 0.010381362401148057;返回颜色;}无效的主要(){gl_FragColor = blur13(texture0, TexCoords, vec2(400, 300), vec2(1.0, 0.0));}
解决方案

我假设你已经交换了 pIdBlurpId.

我将向您介绍具有 2 个通道的高斯模糊着色器.这是一个近似值,它首先在第 1 遍中沿 X 轴模糊,在第 2 遍中沿 Y 轴模糊.这为强模糊带来了更好的性能.模糊着色器使用正态(或高斯)分布.对于 2 个通道,使用相同的着色器程序,2 个通道具有单独的方向设置,存储在统一的 vec2 u_dir 中.模糊效果的强度可以通过 [0.0, 1.0] 范围内的统一变量 float u_sigma 来改变.

模糊顶点着色器

精度 mediump float;属性 vec2 inPos;不同的 vec2 位置;无效的主要(){位置 = inPos;gl_Position = vec4(inPos, 0.0, 1.0);}

模糊片段着色器

精度 mediump float;不同的 vec2 位置;统一的sampler2D u_texture;统一 vec2 u_textureSize;统一浮点 u_sigma;统一 vec2 u_dir;浮点 CalcGauss(浮点 x,浮点 sigma){如果 ( 西格玛 <= 0.0 )返回 0.0;返回 exp( -(x*x)/(2.0 * sigma) )/(2.0 * 3.14157 * sigma);}无效的主要(){vec2 texC = pos.st * 0.5 + 0.5;vec4 texCol = texture2D(u_texture, texC);vec4 gaussCol = vec4(texCol.rgb, 1.0);vec2 步骤 = u_dir/u_textureSize;对于 (int i = 1; i <= 32; ++ i ){浮动权重 = CalcGauss(float(i)/32.0, u_sigma * 0.5);如果 ( 重量 < 1.0/255.0 )休息;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 = 钳位(gaussCol.rgb/gaussCol.w, 0.0, 1.0);gl_FragColor = vec4( gaussCol.rgb, 1.0 );}

程序链接后,可以从以下位置读取统一位置和属性索引:

GLint attrInxPos = glGetAttribLocation( pIdBlur, "inPos" );GLint locTexture = glGetUniformLocation( pIdBlur, "u_texture" );GLint locTexSize = glGetUniformLocation( pIdBlur, "u_textureSize" );GLint locSigma = glGetUniformLocation( pIdBlur, "u_sigma" );GLint locDir = glGetUniformLocation( pIdBlur, "u_dir" );

必须创建一个顶点数组对象,其中包含一个四边形,稍后将在整个视口上绘制,用于屏幕空间模糊通道:

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);

必须创建 2 个帧缓冲区,并在其颜色平面上附加纹理.在第一个中,场景被绘制.这第一个模糊通道使用第二个.第二个模糊通道直接绘制到绘图缓冲区.

GLuint texObj[2];GLuint fbObj[2];glGenTextures(2, texObj);glGenFramebuffers(2, fbObj);glActiveTexture(GL_TEXTURE0);对于 (int i = 0; i < 2; i ++ ){glBindTexture(GL_TEXTURE_2D, texObj[i]);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 宽度, 高度, 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 渲染缓冲区;glGenRenderbuffers(1, &renderbuffer);glBindRenderbuffer(GL_RENDERBUFFER,渲染缓冲区);glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24,宽度,高度);glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,渲染缓冲区);}glBindTexture(GL_TEXTURE_2D, 0);glBindFramebuffer(GL_FRAMEBUFFER, 0);

现在模糊通道所需的一切都已生成.

要绘制和模糊场景,必须执行以下步骤.首先你必须绑定并清除第一帧缓冲区

glBindFramebuffer(GL_FRAMEBUFFER, fbObj[0]);glClearColor(0.0f, 0.0f, 0.4f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

使用着色器程序来绘制对象:

glUseProgram(pId);

现在绘制场景的对象.

.....glDrawArrays(GL_TRIANGLES, 0, 3);

第二步是第一个模糊通道.必须使用模糊程序,并且必须绑定第二帧缓冲区.释放第一帧缓冲区后,您可以使用附加到其颜色平面的纹理作为模糊着色器的输入.
注意,纹理不能同时作为源和目标,这将导致未定义的行为.
要将纹理绑定到着色器,您必须将纹理绑定到纹理单元,并将纹理单元的索引分配给着色器的统一采样器.

int texUnitIndex = 1;GLfloat texSize = { 宽度,高度 };GLfloat dirX[] = { 1.0f, 0.0f };GLfloat 西格玛 = .....;//0.0 <= 西格玛 <= 1.0glBindFramebuffer(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);

第二个也是最后一个模糊通道,类似于第一个模糊通道.第一个模糊通道的目标纹理是源纹理,目标是绘图缓冲区.必须为视口的 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 示例:

(function loadingscene() {var 调整大小,gl,progDraw,progBlur,vp_size,blurFB;var 画布,相机,bufCube = {},bufQuad = {};var 光泽度 = 10.0,辉光 = 10.0,西格玛 = 0.8,半径 = 1.0;函数渲染(deltaMS){变量滑块缩放 = 100;sigma = document.getElementById("sigma").value/sliderScale;radius = document.getElementById("radius").value/sliderScale;vp_size = [canvas.width, canvas.height];camera.Update(vp_size);gl.enable(gl.DEPTH_TEST);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.viewport(0, 0, blurFB[0].width, blurFB[0].height);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);//设置视图投影和模型var prjMat = camera.Perspective();var viewMat = camera.LookAt();var modelMat = RotateAxis(IdentM44(), Fract( deltaMS/13000.0 ) * 2.0 * Math.PI, 0 );modelMat = RotateAxis(modelMat, Fract( deltaMS/17000.0 ) * 2.0 * Math.PI, 1 );//设置绘图着色器ShProg.Use(progDraw);ShProg.SetM44(progDraw,u_projectionMat44",prjMat);ShProg.SetM44(progDraw,u_modelViewMat44",乘法(viewMat,modelMat));ShProg.SetF1( progDraw, "u_shininess", shininess );//绘制场景VertexBuffer.Draw(bufCube);//设置 blur-X 帧缓冲区并绑定帧缓冲区纹理gl.bindFramebuffer(gl.FRAMEBUFFER, blurFB[1]);gl.viewport(0, 0, blurFB[1].width, blurFB[1].height);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);var texUnit = 1;gl.activeTexture(gl.TEXTURE0 + texUnit);gl.bindTexture(gl.TEXTURE_2D, blurFB[0].color0_texture);//设置模糊 X 着色器ShProg.Use( progBlur );ShProg.SetI1(progBlur,u_texture",texUnit)ShProg.SetF2( progBlur, "u_textureSize", vp_size );ShProg.SetF1( progBlur, "u_sigma", sigma )ShProg.SetF1( progBlur, "u_radius", 半径)ShProg.SetF2( progBlur, "u_dir", [1.0, 0.0] )//绘制全屏空间gl.enableVertexAttribArray(progBlur.inPos);gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos);gl.vertexAttribPointer(progBlur.inPos, 2, gl.FLOAT, false, 0, 0);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx);gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);gl.disableVertexAttribArray(progBlur.inPos);//重置帧缓冲并绑定帧缓冲纹理gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.viewport(0, 0, vp_size[0], vp_size[1]);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);texUnit = 2;gl.activeTexture(gl.TEXTURE0 + texUnit);gl.bindTexture(gl.TEXTURE_2D, blurFB[1].color0_texture);//设置 pst 进程着色器ShProg.SetI1(progBlur,u_texture",texUnit)ShProg.SetF1( progBlur, "u_radius", 半径)ShProg.SetF2( progBlur, "u_dir", [0.0, 1.0] )//绘制全屏空间gl.enableVertexAttribArray(progBlur.inPos);gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos);gl.vertexAttribPointer(progBlur.inPos, 2, gl.FLOAT, false, 0, 0);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx);gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);gl.disableVertexAttribArray(progBlur.inPos);requestAnimationFrame(render);}函数初始化场景(){canvas = document.getElementById("canvas");gl = canvas.getContext("experimental-webgl");如果 ( !gl )返回空值;progDraw = ShProg.Create([{来源:draw-shader-vs",阶段:gl.VERTEX_SHADER},{ 来源:draw-shader-fs",阶段:gl.FRAGMENT_SHADER }]);如果(!progDraw.progObj)返回空值;progDraw.inPos = gl.getAttribLocation(progDraw.progObj,inPos");progDraw.inNV = gl.getAttribLocation(progDraw.progObj,inNV");progDraw.inCol = gl.getAttribLocation( progDraw.progObj, "inCol" );progBlur = ShProg.Create([{来源:post-shader-vs",阶段:gl.VERTEX_SHADER},{源:模糊着色器-fs",阶段:gl.FRAGMENT_SHADER}]);progBlur.inPos = gl.getAttribLocation( progBlur.progObj, "inPos" );如果(!progBlur.progObj)返回;//创建立方体变量立方体位置 = [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0,-1.0、-1.0、-1.0、1.0、-1.0、-1.0、1.0、1.0、-1.0、-1.0、1.0、-1.0];var cubeCol = [ 1.0, 0.0, 0.0, 1.0, 0.5, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ];var cubeHlpInx = [ 0, 1, 2, 3, 1, 5, 6, 2, 5, 4, 7, 6, 4, 0, 3, 7, 3, 2, 6, 7, 1, 0, 4,5];var cubePosData = [];for ( var i = 0; i < cubeHlpInx.length; ++ i ) {cubePosData.push( cubePos[cubeHlpInx[i]*3], cubePos[cubeHlpInx[i]*3+1], cubePos[cubeHlpInx[i]*3+2] );}var cubeNVData = [];for (var i1 = 0; i1 < cubeHlpInx.length; i1 += 4) {var nv = [0, 0, 0];对于 ( i2 = 0; i2  0){gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( 索引 ), gl.STATIC_DRAW);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);}返回缓冲区;},绘制:函数(bufObj){for (var i=0; i 0){gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx);gl.drawElements(bufObj.primitive_type, bufObj.inxLen, gl.UNSIGNED_SHORT, 0);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);}别的gl.drawArrays(bufObj.primitive_type, 0, bufObj.attr[0].no_of );for (var i=0; i
html,body { margin: 0;溢出:隐藏;}#gui { 位置:绝对;顶部:0;左:0;}
<script id="draw-shader-vs" type="x-shader/x-vertex">精度 mediump 浮点数;属性 vec3 inPos;vec3 inNV 属性;属性 vec3 inCol;改变 vec3 vertPos;改变vec3 vertNV;改变vec3 vertCol;统一 mat4 u_projectionMat44;统一 mat4 u_modelViewMat44;无效的主要(){vertNV = mat3(u_modelViewMat44)*归一化(inNV);vertCol = inCol;vec4 pos = u_modelViewMat44 * vec4(inPos, 1.0);vertPos = pos.xyz/pos.w;gl_Position = u_projectionMat44 * pos;}</脚本><script id="draw-shader-fs" type="x-shader/x-fragment">精度 mediump 浮点数;改变 vec3 vertPos;改变vec3 vertNV;改变vec3 vertCol;统一浮动 u_shininess;无效的主要(){vec3 颜色 = vertCol;vec3 normalV = normalize(vertNV);vec3 eyeV = 归一化(-vertPos);vec3 halfV = 归一化( eyeV + normalV );浮动 NdotH = max( 0.0, 点( normalV, halfV ) );浮动闪耀Fac =(u_shininess + 2.0)* pow(NdotH,u_shininess)/(2.0 * 3.14159265);gl_FragColor = vec4( color.rgb * (0.2 + NdotH), 1.0 );}</脚本><script id="post-shader-vs" type="x-shader/x-vertex">精度 mediump 浮点数;属性 vec2 inPos;不同的 vec2 位置;无效的主要(){位置 = inPos;gl_Position = vec4(inPos, 0.0, 1.0);}</脚本><script id="blur-shader-fs" type="x-shader/x-fragment">精度 mediump 浮点数;不同的 vec2 位置;统一的sampler2D u_texture;统一 vec2 u_textureSize;统一浮点 u_sigma;统一浮动 u_radius;统一 vec2 u_dir;浮点 CalcGauss(浮点 x,浮点 sigma){如果 ( 西格玛 <= 0.0 )返回 0.0;返回 exp( -(x*x)/(2.0 * sigma) )/(2.0 * 3.14157 * sigma);}无效的主要(){vec2 texC = pos.st * 0.5 + 0.5;vec4 texCol = texture2D(u_texture, texC);vec4 gaussCol = vec4(texCol.rgb, 1.0);vec2 步骤 = u_dir/u_textureSize;对于 (int i = 1; i <= 32; ++ i ){浮动权重 = CalcGauss(float(i)/32.0, u_sigma * 0.5);如果 ( 重量 < 1.0/255.0 )休息;texCol = texture2D(u_texture, texC + u_radius * step * float(i) );gaussCol += vec4( texCol.rgb * weight, weight );texCol = texture2D(u_texture, texC - u_radius * step * float(i) );gaussCol += vec4( texCol.rgb * weight, weight );}gaussCol.rgb = 钳位(gaussCol.rgb/gaussCol.w, 0.0, 1.0);gl_FragColor = vec4( gaussCol.rgb, 1.0 );}</脚本>

<form id="gui" name="inputs"><桌子><tr><td><字体颜色=#CCF>半径</font></td><td><input type="range" id="radius" min="1" max="1000" value="200"/></td></tr><tr><td><字体颜色=#CCF>模糊</font></td><td><input type="range" id="sigma" min="1" max="50" value="10"/></td></tr></表></表格></div><canvas id="canvas" style="border: none;"></canvas>

I recently learn opengl es 2.0, and now I try to make a gaussian blur on triangles generate by myself. I have some difficult to understand examples on the web and most apply the blur on an image. I know I have to use framebuffer but I don't know how to draw triangle on this and apply blur.Is it possible to see a real and complete code in C++ with good explication ?

EDIT :

#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
", glGetString(GL_VERSION) );
  printf("GL_RENDERER : %s
", 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;
}

Blur Shader:

#version 100
precision mediump float;

uniform sampler2D texture0;
varying vec3 vColor;
varying vec2 TexCoords;

vec4 blur13(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
    vec4 color = vec4(0.0);
    vec2 off1 = vec2(1.411764705882353) * direction;
    vec2 off2 = vec2(3.2941176470588234) * direction;
    vec2 off3 = vec2(5.176470588235294) * direction;
    color += texture2D(image, uv) * 0.1964825501511404;
    color += texture2D(image, uv + (off1 / resolution)) * 0.2969069646728344;
    color += texture2D(image, uv - (off1 / resolution)) * 0.2969069646728344;
    color += texture2D(image, uv + (off2 / resolution)) * 0.09447039785044732;
    color += texture2D(image, uv - (off2 / resolution)) * 0.09447039785044732;
    color += texture2D(image, uv + (off3 / resolution)) * 0.010381362401148057;
    color += texture2D(image, uv - (off3 / resolution)) * 0.010381362401148057;
    return color;
}

void main(){
    gl_FragColor = blur13(texture0, TexCoords, vec2(400, 300), vec2(1.0, 0.0));
}
解决方案

I assume you have swapped pIdBlur and pId.

I' will give you introductions for gaussian blur shader with 2 passes. This is an approximation which first blurs along the X-Axis in the 1st pass and along the Y-Axis in the 2nd pass. This results in a better performance for strong blurring.The blur shader uses a normal (or Gaussian) distribution. For the 2 passes is used the same shader program, with individual direction settings for the 2 passes, stored in the uniform vec2 u_dir. The strength of the blur effect can be varied with the uniform variable float u_sigma in the range [0.0, 1.0].

Blur Vertex shader

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

void main()
{
    pos = inPos;
    gl_Position = vec4( inPos, 0.0, 1.0 );
}

Blur Fragment shader

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 );
}

After the program has been linked the uniform locations and attribute indices can be read from:

GLint attrInxPos = glGetAttribLocation( pIdBlur, "inPos" );
GLint locTexture = glGetUniformLocation( pIdBlur, "u_texture" );
GLint locTexSize = glGetUniformLocation( pIdBlur, "u_textureSize" );
GLint locSigma   = glGetUniformLocation( pIdBlur, "u_sigma" );
GLint locDir     = glGetUniformLocation( pIdBlur, "u_dir" );

A vertex array object, containing a quad, which later will be drawn over the whole viewport, for a screen space blur pass, has to be created:

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 );

2 frame buffers, with a texture attached to its color plane, have to be created. In the 1st one the scene is drawn. The2nd one is used by the 1st blur pass. The 2nd blur pass draws directly to the drawing buffer.

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);

Now everything what is needed for the blur passes has been generated.

To draw and blur the scene the following steps have to be applied.First you have to bind and clear the 1st frame buffer

glBindFramebuffer(GL_FRAMEBUFFER, fbObj[0]);
glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

and use the shader program for drawing the objects:

glUseProgram(pId);

Now draw the object(s) of the scene.

.....
glDrawArrays(GL_TRIANGLES, 0, 3);

The second step is the 1st blur pass. The blur program has to be use and the 2nd framebuffer has to be bound.After the frame 1st buffer has been released, you can use the texture, that is attached to its color plane, as an input for the blur shader.
Note, a texture can't be source and destination at the same time, this would cause undefined behavior.
To bind the texture to the shader, you have to bind the texture to a texture unit and assign the index of the texture unit to the uniform sampler of the shader.

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);

To apply the blur pass a quad has to be drawn of the viewport area.

glBindVertexArray( screenVAO );
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );

The 2nd and final blur pass, is similar to the 1st blur pass. The target texture of the 1st blur pass is the source texture, and the target is the drawing buffer. The blur direction has to be set up for the Y axis of the viewport.

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);

See also the answers to the following question:

See alos a similar WebGL example:

(function loadscene() {

var resize, gl, progDraw, progBlur, vp_size, blurFB;
var canvas, camera, bufCube = {}, bufQuad = {};
var shininess = 10.0, glow = 10.0, sigma = 0.8, radius = 1.0;

function render(deltaMS){

  var sliderScale = 100;
  sigma  = document.getElementById( "sigma" ).value / sliderScale;
  radius = document.getElementById( "radius" ).value / sliderScale;

  vp_size = [canvas.width, canvas.height];
  camera.Update( vp_size );

  gl.enable( gl.DEPTH_TEST );
  gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
  gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );

  // set up framebuffer
  gl.bindFramebuffer( gl.FRAMEBUFFER, blurFB[0] );
  gl.viewport( 0, 0, blurFB[0].width, blurFB[0].height );
  gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );

  // setup view projection and model
  var prjMat = camera.Perspective();
  var viewMat = camera.LookAt();
  var modelMat = RotateAxis( IdentM44(), Fract( deltaMS / 13000.0 ) * 2.0 * Math.PI, 0 );
  modelMat = RotateAxis( modelMat, Fract( deltaMS / 17000.0 ) * 2.0 * Math.PI, 1 );

  // set up draw shader
  ShProg.Use( progDraw );
  ShProg.SetM44( progDraw, "u_projectionMat44", prjMat );
  ShProg.SetM44( progDraw, "u_modelViewMat44", Multiply(viewMat, modelMat) );
  ShProg.SetF1( progDraw, "u_shininess", shininess );

  // draw scene
  VertexBuffer.Draw( bufCube );

  // set blur-X framebuffer and bind frambuffer texture
  gl.bindFramebuffer( gl.FRAMEBUFFER, blurFB[1] );
  gl.viewport( 0, 0, blurFB[1].width, blurFB[1].height );
  gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
  var texUnit = 1;
  gl.activeTexture( gl.TEXTURE0 + texUnit );
  gl.bindTexture( gl.TEXTURE_2D, blurFB[0].color0_texture );

  // set up blur-X shader
  ShProg.Use( progBlur );
  ShProg.SetI1( progBlur, "u_texture", texUnit )
  ShProg.SetF2( progBlur, "u_textureSize", vp_size );
  ShProg.SetF1( progBlur, "u_sigma", sigma )
  ShProg.SetF1( progBlur, "u_radius", radius )
  ShProg.SetF2( progBlur, "u_dir", [1.0, 0.0] )

  // draw full screen space
  gl.enableVertexAttribArray( progBlur.inPos );
  gl.bindBuffer( gl.ARRAY_BUFFER, bufQuad.pos );
  gl.vertexAttribPointer( progBlur.inPos, 2, gl.FLOAT, false, 0, 0 );
  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx );
  gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
  gl.disableVertexAttribArray( progBlur.inPos );

  // reset framebuffer and bind frambuffer texture
  gl.bindFramebuffer( gl.FRAMEBUFFER, null );
  gl.viewport( 0, 0, vp_size[0], vp_size[1] );
  gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
  texUnit = 2;
  gl.activeTexture( gl.TEXTURE0 + texUnit );
  gl.bindTexture( gl.TEXTURE_2D, blurFB[1].color0_texture );

  // set up pst process shader
  ShProg.SetI1( progBlur, "u_texture", texUnit )
  ShProg.SetF1( progBlur, "u_radius", radius )
  ShProg.SetF2( progBlur, "u_dir", [0.0, 1.0] )

  // draw full screen space
  gl.enableVertexAttribArray( progBlur.inPos );
  gl.bindBuffer( gl.ARRAY_BUFFER, bufQuad.pos );
  gl.vertexAttribPointer( progBlur.inPos, 2, gl.FLOAT, false, 0, 0 );
  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx );
  gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
  gl.disableVertexAttribArray( progBlur.inPos );

  requestAnimationFrame(render);
}

function initScene() {

  canvas = document.getElementById( "canvas");
  gl = canvas.getContext( "experimental-webgl" );
  if ( !gl )
      return null;

  progDraw = ShProg.Create(
  [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
      { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
  ] );
  if ( !progDraw.progObj )
      return null;
  progDraw.inPos = gl.getAttribLocation( progDraw.progObj, "inPos" );
  progDraw.inNV  = gl.getAttribLocation( progDraw.progObj, "inNV" );
  progDraw.inCol = gl.getAttribLocation( progDraw.progObj, "inCol" );

  progBlur = ShProg.Create(
  [ { source : "post-shader-vs", stage : gl.VERTEX_SHADER },
      { source : "blur-shader-fs", stage : gl.FRAGMENT_SHADER }
  ] );
  progBlur.inPos = gl.getAttribLocation( progBlur.progObj, "inPos" );
  if ( !progBlur.progObj )
      return;

  // create cube
  var cubePos = [
  -1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  1.0,  1.0,  1.0, -1.0,  1.0,  1.0,
  -1.0, -1.0, -1.0,  1.0, -1.0, -1.0,  1.0,  1.0, -1.0, -1.0,  1.0, -1.0 ];
  var cubeCol = [ 1.0, 0.0, 0.0, 1.0, 0.5, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ];
  var cubeHlpInx = [ 0, 1, 2, 3, 1, 5, 6, 2, 5, 4, 7, 6, 4, 0, 3, 7, 3, 2, 6, 7, 1, 0, 4, 5 ];
  var cubePosData = [];
  for ( var i = 0; i < cubeHlpInx.length; ++ i ) {
  cubePosData.push( cubePos[cubeHlpInx[i]*3], cubePos[cubeHlpInx[i]*3+1], cubePos[cubeHlpInx[i]*3+2] );
  }
  var cubeNVData = [];
  for ( var i1 = 0; i1 < cubeHlpInx.length; i1 += 4 ) {
  var nv = [0, 0, 0];
  for ( i2 = 0; i2 < 4; ++ i2 ) {
      var i = i1 + i2;
      nv[0] += cubePosData[i*3]; nv[1] += cubePosData[i*3+1]; nv[2] += cubePosData[i*3+2];
  }
  for ( i2 = 0; i2 < 4; ++ i2 )
  cubeNVData.push( nv[0], nv[1], nv[2] );
  }
  var cubeColData = [];
  for ( var is = 0; is < 6; ++ is ) {
  for ( var ip = 0; ip < 4; ++ ip ) {
      cubeColData.push( cubeCol[is*3], cubeCol[is*3+1], cubeCol[is*3+2] );
  }
  }
  var cubeInxData = [];
  for ( var i = 0; i < cubeHlpInx.length; i += 4 ) {
  cubeInxData.push( i, i+1, i+2, i, i+2, i+3 );
  }
  bufCube = VertexBuffer.Create(
  [ { data : cubePosData, attrSize : 3, attrLoc : progDraw.inPos },
  { data : cubeNVData,  attrSize : 3, attrLoc : progDraw.inNV },
  { data : cubeColData, attrSize : 3, attrLoc : progDraw.inCol } ],
  cubeInxData );

  bufQuad.pos = gl.createBuffer();
  gl.bindBuffer( gl.ARRAY_BUFFER, bufQuad.pos );
  gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0 ] ), gl.STATIC_DRAW );
  bufQuad.inx = gl.createBuffer();
  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx );
  gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( [ 0, 1, 2, 0, 2, 3 ] ), gl.STATIC_DRAW );

  camera = new Camera( [0, 3, 0.0], [0, 0, 0], [0, 0, 1], 90, vp_size, 0.5, 100 );

  window.onresize = resize;
  resize();
  requestAnimationFrame(render);
}

function resize() {
  //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
  vp_size = [window.innerWidth, window.innerHeight]
  //vp_size = [256, 256]
  canvas.width = vp_size[0];
  canvas.height = vp_size[1];

  var fbsize = Math.max(vp_size[0], vp_size[1]);
  fbsize = 1 << 31 - Math.clz32(fbsize); // nearest power of 2

  blurFB = [];
  for ( var i = 0; i < 2; ++ i ) {
    fb = gl.createFramebuffer();
    fb.width = fbsize;
    fb.height = fbsize;
    gl.bindFramebuffer( gl.FRAMEBUFFER, fb );
    fb.color0_texture = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, fb.color0_texture );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
    gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, fb.width, fb.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null );
    fb.renderbuffer = gl.createRenderbuffer();
    gl.bindRenderbuffer( gl.RENDERBUFFER, fb.renderbuffer );
    gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fb.width, fb.height );
    gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fb.color0_texture, 0 );
    gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, fb.renderbuffer );
    gl.bindTexture( gl.TEXTURE_2D, null );
    gl.bindRenderbuffer( gl.RENDERBUFFER, null );
    gl.bindFramebuffer( gl.FRAMEBUFFER, null );
    blurFB.push( fb );
  }
}

function Fract( val ) {
  return val - Math.trunc( val );
}
function CalcAng( deltaTime, intervall ) {
  return Fract( deltaTime / (1000*intervall) ) * 2.0 * Math.PI;
}
function CalcMove( deltaTime, intervall, range ) {
  var pos = self.Fract( deltaTime / (1000*intervall) ) * 2.0
  var pos = pos < 1.0 ? pos : (2.0-pos)
  return range[0] + (range[1] - range[0]) * pos;
}
function EllipticalPosition( a, b, angRag ) {
  var a_b = a * a - b * b
  var ea = (a_b <= 0) ? 0 : Math.sqrt( a_b );
  var eb = (a_b >= 0) ? 0 : Math.sqrt( -a_b );
  return [ a * Math.sin( angRag ) - ea, b * Math.cos( angRag ) - eb, 0 ];
}

function IdentM44() {
  return [ 1, 0, 0, 0,    0, 1, 0, 0,    0, 0, 1, 0,    0, 0, 0, 1 ];
};

function RotateAxis(matA, angRad, axis) {
  var aMap = [ [1, 2], [2, 0], [0, 1] ];
  var a0 = aMap[axis][0], a1 = aMap[axis][1];
  var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
  var matB = matA.slice(0);
  for ( var i = 0; i < 3; ++ i ) {
      matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;
      matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;
  }
  return matB;
}

function Rotate(matA, angRad, axis) {
  var s = Math.sin(angRad), c = Math.cos(angRad);
  var x = axis[0], y = axis[1], z = axis[2];
  matB = [
      x*x*(1-c)+c,   x*y*(1-c)-z*s, x*z*(1-c)+y*s, 0,
      y*x*(1-c)+z*s, y*y*(1-c)+c,   y*z*(1-c)-x*s, 0,
      z*x*(1-c)-y*s, z*y*(1-c)+x*s, z*z*(1-c)+c,   0,
      0,             0,             0,             1 ];
  return Multiply(matA, matB);
}

function Multiply(matA, matB) {
  matC = IdentM44();
  for (var i0=0; i0<4; ++i0 )
      for (var i1=0; i1<4; ++i1 )
          matC[i0*4+i1] = matB[i0*4+0] * matA[0*4+i1] + matB[i0*4+1] * matA[1*4+i1] + matB[i0*4+2] * matA[2*4+i1] + matB[i0*4+3] * matA[3*4+i1]
  return matC;
}

function Cross( a, b ) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0 ]; }
function Dot( a, b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
function Normalize( v ) {
  var len = Math.sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
  return [ v[0] / len, v[1] / len, v[2] / len ];
}

Camera = function( pos, target, up, fov_y, vp, near, far ) {
this.Time = function() { return Date.now(); }
this.pos = pos;
this.target = target;
this.up = up;
this.fov_y = fov_y;
this.vp = vp;
this.near = near;
this.far = far;
this.Perspective = function() {
    var n = this.near;
    var f = this.far;
    var fn = f + n;
    var f_n = f - n;
    var r = this.vp[0] / this.vp[1];
    var t = 1 / Math.tan( Math.PI * this.fov_y / 360 );
    return [
        t/r, 0, 0,          0,
        0,   t, 0,          0,
        0,   0, -fn/f_n,   -1,
        0,   0, -2*f*n/f_n, 0 ];
};
this.LookAt = function() {
    var mz = Normalize( [ this.pos[0]-this.target[0], this.pos[1]-this.target[1], this.pos[2]-this.target[2] ] );
    var mx = Normalize( Cross( this.up, mz ) );
    var my = Normalize( Cross( mz, mx ) );
    var tx = Dot( mx, this.pos );
    var ty = Dot( my, this.pos );
    var tz = Dot( [-mz[0], -mz[1], -mz[2]], this.pos );
    return [mx[0], my[0], mz[0], 0, mx[1], my[1], mz[1], 0, mx[2], my[2], mz[2], 0, tx, ty, tz, 1];
};
this.Update = function(vp_size) {
    if (vp_size)
        this.vp = vp_size;
};
}

var ShProg = {
Create: function (shaderList) {
  var shaderObjs = [];
  for (var i_sh = 0; i_sh < shaderList.length; ++i_sh) {
    var shderObj = this.Compile(shaderList[i_sh].source, shaderList[i_sh].stage);
    if (shderObj) shaderObjs.push(shderObj);
  }
  var prog = {}
  prog.progObj = this.Link(shaderObjs)
  if (prog.progObj) {
    prog.attrInx = {};
    var noOfAttributes = gl.getProgramParameter(prog.progObj, gl.ACTIVE_ATTRIBUTES);
    for (var i_n = 0; i_n < noOfAttributes; ++i_n) {
      var name = gl.getActiveAttrib(prog.progObj, i_n).name;
      prog.attrInx[name] = gl.getAttribLocation(prog.progObj, name);
    }
    prog.uniLoc = {};
    var noOfUniforms = gl.getProgramParameter(prog.progObj, gl.ACTIVE_UNIFORMS);
    for (var i_n = 0; i_n < noOfUniforms; ++i_n) {
      var name = gl.getActiveUniform(prog.progObj, i_n).name;
      prog.uniLoc[name] = gl.getUniformLocation(prog.progObj, name);
    }
  }
  return prog;
},
AttrI: function (prog, name) { return prog.attrInx[name]; },
UniformL: function (prog, name) { return prog.uniLoc[name]; },
Use: function (prog) { gl.useProgram(prog.progObj); },
SetI1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1i(prog.uniLoc[name], val); },
SetF1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1f(prog.uniLoc[name], val); },
SetF2: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform2fv(prog.uniLoc[name], arr); },
SetF3: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform3fv(prog.uniLoc[name], arr); },
SetF4: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform4fv(prog.uniLoc[name], arr); },
SetM33: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix3fv(prog.uniLoc[name], false, mat); },
SetM44: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix4fv(prog.uniLoc[name], false, mat); },
Compile: function (source, shaderStage) {
  var shaderScript = document.getElementById(source);
  if (shaderScript)
    source = shaderScript.text;
  var shaderObj = gl.createShader(shaderStage);
  gl.shaderSource(shaderObj, source);
  gl.compileShader(shaderObj);
  var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
  if (!status) alert(gl.getShaderInfoLog(shaderObj));
  return status ? shaderObj : null;
},
Link: function (shaderObjs) {
  var prog = gl.createProgram();
  for (var i_sh = 0; i_sh < shaderObjs.length; ++i_sh)
    gl.attachShader(prog, shaderObjs[i_sh]);
  gl.linkProgram(prog);
  status = gl.getProgramParameter(prog, gl.LINK_STATUS);
  if ( !status ) alert(gl.getProgramInfoLog(prog));
  return status ? prog : null;
} };

var VertexBuffer = {
Create: function(attribs, indices, type) {
  var buffer = { buf: [], attr: [], inx: gl.createBuffer(), inxLen: indices.length, primitive_type: type ? type : gl.TRIANGLES };
  for (var i=0; i<attribs.length; ++i) {
    buffer.buf.push(gl.createBuffer());
    buffer.attr.push({ size : attribs[i].attrSize, loc : attribs[i].attrLoc, no_of: attribs[i].data.length/attribs[i].attrSize });
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( attribs[i].data ), gl.STATIC_DRAW);
  }
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  if ( buffer.inxLen > 0 ) {
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
  }
  return buffer;
},
Draw: function(bufObj) {
  for (var i=0; i<bufObj.buf.length; ++i) {
    gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]);
    gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray( bufObj.attr[i].loc);
  }
  if ( bufObj.inxLen > 0 ) {
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx);
    gl.drawElements(bufObj.primitive_type, bufObj.inxLen, gl.UNSIGNED_SHORT, 0);
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
  }
  else
    gl.drawArrays(bufObj.primitive_type, 0, bufObj.attr[0].no_of );
  for (var i=0; i<bufObj.buf.length; ++i)
    gl.disableVertexAttribArray(bufObj.attr[i].loc);
  gl.bindBuffer( gl.ARRAY_BUFFER, null );
} };

initScene();

})();
html,body { margin: 0; overflow: hidden; }
#gui { position : absolute; top : 0; left : 0; }
<script id="draw-shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec3 inPos;
attribute vec3 inNV;
attribute vec3 inCol;

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

uniform mat4 u_projectionMat44;
uniform mat4 u_modelViewMat44;

void main()
{
    vertNV      = mat3( u_modelViewMat44 ) * normalize( inNV );
    vertCol     = inCol;
    vec4 pos    = u_modelViewMat44 * vec4( inPos, 1.0 );
    vertPos     = pos.xyz / pos.w;
    gl_Position = u_projectionMat44 * pos;
}
</script>

<script id="draw-shader-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

uniform float u_shininess;

void main()
{
    vec3 color = vertCol;
    vec3  normalV  = normalize( vertNV );
    vec3  eyeV     = normalize( -vertPos );
    vec3  halfV    = normalize( eyeV + normalV );
    float NdotH    = max( 0.0, dot( normalV, halfV ) );
    float shineFac = ( u_shininess + 2.0 ) * pow( NdotH, u_shininess ) / ( 2.0 * 3.14159265 );
    gl_FragColor   = vec4( color.rgb * (0.2 + NdotH), 1.0 );
}
</script>

<script id="post-shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec2 inPos;

varying   vec2 pos;

void main()
{
    pos = inPos;
    gl_Position = vec4( inPos, 0.0, 1.0 );
}
</script>

<script id="blur-shader-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec2 pos;

uniform sampler2D u_texture;
uniform vec2      u_textureSize;
uniform float     u_sigma;
uniform float     u_radius;
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 + u_radius * step * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
        texCol    = texture2D( u_texture, texC - u_radius * 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 );
}
</script>

<div>
<form id="gui" name="inputs">
<table>
<tr> <td> <font color= #CCF>radius</font> </td>
        <td> <input type="range" id="radius" min="1" max="1000" value="200"/></td> </tr>
<tr> <td> <font color= #CCF>blur</font> </td>
        <td> <input type="range" id="sigma" min="1" max="50" value="10"/></td> </tr>
</table>
</form>
</div>

<canvas id="canvas" style="border: none;"></canvas>

这篇关于OpenGL es 2.0 三角形上的高斯模糊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 00:22