Glsl webgl误差中的高斯模糊

Glsl webgl误差中的高斯模糊,glsl,shader,webgl,fragment-shader,gaussianblur,Glsl,Shader,Webgl,Fragment Shader,Gaussianblur,我正在尝试在webgl中编写一个简单的高斯模糊着色器。我已经搜索了很多关于这一点,我想我理解它背后的想法。 给定此3X3内核。如何将其应用于顶点着色器 特别是如何获得相邻像素 这种逻辑有意义吗 precision mediump float; varying vec2 vUV; uniform sampler2D uTexture; void main(){ gl_FragColor = texture2D(uTexture, vUV + vec2(????,????)*0.06

我正在尝试在webgl中编写一个简单的高斯模糊着色器。我已经搜索了很多关于这一点,我想我理解它背后的想法。 给定此3X3内核。如何将其应用于顶点着色器

特别是如何获得相邻像素

这种逻辑有意义吗

precision mediump float;
varying vec2 vUV;

uniform sampler2D uTexture;

void main(){
     gl_FragColor = texture2D(uTexture, vUV + vec2(????,????)*0.0625;


}
我应该在上面的vec2()中添加什么?如果我想得到内核的左上角纹理值。 假设vUv是(20,20)得到(19,19)我应该写吗

     gl_FragColor = vec4(0.0);
     gl_FragColor += texture2D(uTexture, vUV  +  vec2(vUV.x-1.0,vUV.y-1.0))*0.0625;
     gl_FragColor += texture2D(uTexture, vUV + vec2(vUV.x,vUV.y-1.0))*0.125;    
     gl_FragColor += texture2D(uTexture, vUV + vec2(vUV.x+1.0,vUV.y-1.0))*0.0625;

     gl_FragColor += texture2D(uTexture, vUV  +  vec2(vUV.x-1.0,vUV.y))*0.125;
     gl_FragColor += texture2D(uTexture, vUV + vec2(vUV.x,vUV.y))*0.25; 
     gl_FragColor += texture2D(uTexture, vUV + vec2(vUV.x+1.0,vUV.y))*0.125;    


     gl_FragColor += texture2D(uTexture, vUV  +  vec2(vUV.x-1.0,vUV.y+1.0))*0.0625;
     gl_FragColor += texture2D(uTexture, vUV + vec2(vUV.x,vUV.y+1.0))*0.125;    
     gl_FragColor += texture2D(uTexture, vUV + vec2(vUV.x+1.0,vUV.y+1.0))*0.0625;   

用于通过
texture2D
查找纹理的纹理坐标必须在[0.0,1.0]范围内

另见

要使着色器正常工作,必须定义一个统一变量,该变量包含用于创建模糊效果的纹理偏移:

uniform vec2 offs_blur;
将此偏移用于9个纹理查找:

gl_FragColor = vec4(0.0);
gl_FragColor += texture2D(uTexture, vUV + vec2(-offs_blur.x, -offs_blur.y))*0.0625;
gl_FragColor += texture2D(uTexture, vUV + vec2(         0.0, -offs_blur.y))*0.125;  
gl_FragColor += texture2D(uTexture, vUV + vec2( offs_blur.x, -offs_blur.y))*0.0625;

gl_FragColor += texture2D(uTexture, vUV + vec2(-offs_blur.x,          0.0))*0.125;
gl_FragColor += texture2D(uTexture, vUV + vec2(         0.0,          0.0))*0.25;   
gl_FragColor += texture2D(uTexture, vUV + vec2( offs_blur.x,          0.0))*0.125;  


gl_FragColor += texture2D(uTexture, vUV + vec2(-offs_blur.x, offs_blur.y))*0.0625;
gl_FragColor += texture2D(uTexture, vUV + vec2(         0.0, offs_blur.y))*0.125;   
gl_FragColor += texture2D(uTexture, vUV + vec2( offs_blur.x, offs_blur.y))*0.0625;  
相邻纹理的偏移量是纹理大小的倒数(1/宽度,1/高度)。
但是偏移量不需要精确到相邻纹理的偏移量,就可以获得模糊效果。 如果增加偏移,模糊效果将增加。当然,这将导致质量损失。随着偏移量的增加,瑕疵和带状效果将增大。为了避免这种情况,您必须增加查找的texel数(例如查找5x5 texel)

按如下方式设置制服:

offs_blur = gl.getUniformLocation(program,"offs_blur");

var blur = 20.0;
gl.uniform2fv(offs_blur,[blur/image.width, blur/image.height]);
请参见示例,该示例将答案中的建议应用于您问题的原始代码:

var canvas=document.createElement('canvas')
canvas.width=window.innerWidth
canvas.height=window.innerHeight
document.body.appendChild(画布)
var gl=canvas.getContext('webgl')
//用你想要的任何颜色清除画布
gl.clearColor(0.75,0.85,0.8,1.0)
总账清除(总账颜色\u缓冲\u位)
函数main(){
var image=新图像();
image.crossOrigin=“匿名”;
image.src=”https://i.imgur.com/GdkFHnw.jpg";
image.onload=函数(){
渲染(图像);
}
}
//创建着色器的通用函数
函数createShader(gl、源、类型){
var shader=gl.createShader(类型);
gl.shaderSource(着色器,源);
gl.compileShader(着色器);
if(!gl.getShaderParameter(着色器,gl.COMPILE_状态)){
console.error('error compileding shader type=>'+type,gl.getShaderInfoLog(shader));
返回;
}
返回着色器
}
函数createBuffer(数据){
数据=Float32Array的数据实例?数据:新的Float32Array(数据);
var buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY\u BUFFER,BUFFER);
总账缓冲数据(总账数组缓冲、数据、总账静态绘图);
返回缓冲区;
}
//函数,该函数从编译的顶点和片段着色器返回“程序”
函数createProgram(gl、vertexShader、fragmentShader){
var program=gl.createProgram();
gl.attachShader(程序,顶点着色器);
gl.attachShader(程序、碎片着色器);
总账链接程序(程序);
var success=gl.getProgramParameter(程序,gl.LINK\u状态);
如果(!成功){
//链接出了问题
抛出(“程序文件到链接:+gl.getProgramInfoLog(程序));
}
返回程序;
};
变量纹理宽度=1,纹理高度=1;
//从现有画布或HTMLImage(新图像())创建纹理
//不需要宽度和高度,或使用具有
//指定的宽度和高度
//例如。
//createTexture(HTMLImageElement)可以正常工作
//createTexture(Uint8Array,width,height),记住一个纹理需要四个值来表示一个像素
函数createTexture(图像、宽度、高度){
var texture=gl.createTexture();
//将活动纹理窗设置为0
//WebGL有大约30个纹理槽,这意味着您可以一次绑定大约30个纹理
//可以将其视为一个包含30个指针的数组,指向可以设置的纹理对象
gl.activeTexture(gl.TEXTURE0);//设置当前的“索引”
gl.bindTexture(gl.TEXTURE_2D,纹理);//将选定纹理对象绑定到当前指针
//采样时需要调整纹理大小时如何过滤纹理
//(拉伸时会变得模糊吗?)
//(gl.最近表示无模糊)
gl.texParameteri(gl.TEXTURE\u 2D,gl.TEXTURE\u MIN\u FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE\u 2D,gl.TEXTURE\u MAG\u FILTER,gl.NEAREST);
//如果UV坐标超出纹理大小,该怎么办
//gl.CLAMP_TO_EDGE在纹理边界重复像素。
gl.texParameteri(gl.TEXTURE\u 2D、gl.TEXTURE\u WRAP\u S、gl.CLAMP\u TO\u EDGE);
gl.texParameteri(gl.TEXTURE\u 2D、gl.TEXTURE\u WRAP\u T、gl.CLAMP\u TO\u EDGE);
宽度===未定义和高度===未定义?
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_字节,图像):
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,宽度,高度,0,gl.RGBA,gl.UNSIGNED_字节,图像);
返回纹理;
}
函数渲染(图像){
//警报('呈现…')
//顶点着色器源
常量vertexShaderSource=[
'属性向量2位置;',
'属性vec2 aUV;',
'可变vec2 vUV;',
“void main(){”,
“gl_位置=vec4(位置,0.0,1.0);”,
“vUV=aUV;”,
'}',
].加入(“\n”);
//片段着色器源
常量fragShaderSource=`
精密中泵浮子;
可变vec2 vUV;
均匀的二维纹理;
void main(){
浮动亮度=1.1;
gl_FragColor=纹理2D(纹理,vUV);
gl_FragColor.rgb*=亮度;
}`
常量模糊着色器=`
精密中泵浮子;
可变vec2 vUV;
均匀的二维纹理;
均匀的矢量模糊;
//[ 0.0625  0.125  0.0625 ]
//[ 0.125   0.25   0.125  ]
//[ 0.0625  0.125  0.0625 ]
void main(){
gl_FragColor=vec4(0.0);
gl_FragColor+=纹理2D(纹理,vUV+vec2(-offs_blur.x,-offs_blur.y))*0.0625;
gl_FragColor+=纹理2D(纹理,vUV+vec2(0.0,-offs_blur.y))*0.125;
gl_FragColor+=texture2D(纹理,vUV+vec2(offs_blur.x,-offs_blur.y))*0.0625;
gl_FragColor+=纹理2D(纹理,vUV+vec2(-offs_blur.x,
offs_blur = gl.getUniformLocation(program,"offs_blur");

var blur = 20.0;
gl.uniform2fv(offs_blur,[blur/image.width, blur/image.height]);