How can the following Gaussian blur shader be modified to compute shader?

#version 330 core

uniform sampler2D tex;
uniform int phase;
uniform int radius;
uniform float width;
uniform float height;

in vec2 uv;
out vec4 FragColor;

const float PI = 3.141592653589793;
const float sigma = 3.0f;
vec4 GaussianBlurV()
{
	float twoSigmaSqu = 2 * sigma * sigma;
	int r = radius; //int(ceil(sigma * 2.57));
	float allWeight = 0.0f;
	vec4 col = vec4(0.0f, 0.0f, 0.0f, 0.0f);
	for (int iy = -r; iy < (r + 1); iy++)
	{
		float weight = 1.0f / (PI * twoSigmaSqu) * exp(-(iy * iy) / twoSigmaSqu);
		vec2 offset = vec2(0.0f, 1.0f / height * iy);
		vec2 uv_offset = uv + offset;
		uv_offset.y = clamp(uv_offset.y, 0.0f, 1.0f);
		col += texture2D(tex, uv_offset) * weight;
		allWeight += weight;
	}
	col = col / allWeight;
	return col;
}

vec4 GaussianBlurH()
{
	float twoSigmaSqu = 2 * sigma * sigma;
	int r = radius; //int(ceil(sigma * 2.57));
	float allWeight = 0.0f;
	vec4 col = vec4(0.0f, 0.0f, 0.0f, 0.0f);//error X3014: incorrect number of arguments to numeric-type constructor
	for (int ix = -r; ix < (r + 1); ix++)
	{
		float weight = 1.0f / (PI * twoSigmaSqu) * exp(-(ix * ix) / twoSigmaSqu);
		vec2 offset = vec2(1.0f / width * ix, 0.0f);
		vec2 uv_offset = uv + offset;
		uv_offset.x = clamp(uv_offset.x, 0.0f, 1.0f);
		col += texture2D(tex, uv_offset) * weight;//get_texture0(uv_offset) * weight;// raw_tex.SampleLevel(SampleType, tc + offset , 0) * weight;
		allWeight += weight;
	}
	col = col / allWeight;
	return col;
}

void main()
{
	if(phase == 1) 
	{
		FragColor = GaussianBlurH();
	}
	else if(phase == 2) 
	{
		FragColor = GaussianBlurV();
	}
	else
	{
		FragColor = vec4(1,0,0,1);
	}
}

Please read the Forum Posting Guidelines. In particular Posting Guideline #4

#version 330 core

uniform sampler2D tex;
uniform int radius;
uniform float width;
uniform float height;

in vec2 uv;
out vec4 FragColor;

const float PI    = 3.141592653589793;
const float sigma = 3.0f;

vec4 GaussianBlurHV()
{
	float twoSigmaSqu = 2 * sigma * sigma;
	int r = radius; //int(ceil(sigma * 2.57));
	float allWeight = 0.0f;	
	vec4 col = vec4(0.0f, 0.0f, 0.0f, 0.0f);//error X3014: incorrect number of arguments to numeric-type constructor
	for (int ix = -r; ix < (r + 1); ix++)
	{
		for (int iy = -r; iy < (r + 1); iy++)
		{
			float weight   = 1.0f / (PI * twoSigmaSqu) * exp(-(ix * ix + iy * iy) / twoSigmaSqu);
			vec2 offset    = vec2(1.0f / width * ix, 1.0f / height * iy);
			vec2 uv_offset = uv + offset;
			uv_offset.x    = clamp(uv_offset.x, 0.0f, 1.0f);
			uv_offset.y    = clamp(uv_offset.y, 0.0f, 1.0f);
			col += texture2D(tex, uv_offset) * weight;
			allWeight += weight;
		}
	}
	col = col / allWeight;
	return col;
}


void main()
{
	FragColor = GaussianBlurHV();
}

// -----------------------------------------------------------------------------------

OpenGL 3.2
Linux archlinux 5.6.6-arch1-1
Intel® Core™ i7-6500U
NVIDIA GeForce 940M

Texture and FBO
Format = GL_RGBA32F_ARB
MinFilter = GL_LINEAR
MaxFilter = GL_LINEAR
TextureTarget = GL_TEXTURE_2D
Depth = false
Stencil = false
Samples = 0 // I've tried multisampling as well
WrapModeHorizontal = GL_CLAMP
WrapModeVertical = GL_CLAMP
#version 330 core

uniform sampler2D tex;
uniform int radius;
uniform float width;
uniform float height;

in vec2 uv;
out vec4 FragColor;

const float PI    = 3.141592653589793;
const float sigma = 3.0f;

vec4 GaussianBlurHV()
{
	float twoSigmaSqu = 2 * sigma * sigma;
	int r = radius; //int(ceil(sigma * 2.57));
	float allWeight = 0.0f;	
	vec4 col = vec4(0.0f, 0.0f, 0.0f, 0.0f);//error X3014: incorrect number of arguments to numeric-type constructor
	for (int ix = -r; ix < (r + 1); ix++)
	{
		for (int iy = -r; iy < (r + 1); iy++)
		{
			float weight   = 1.0f / (PI * twoSigmaSqu) * exp(-(ix * ix + iy * iy) / twoSigmaSqu);
			vec2 offset    = vec2(1.0f / width * ix, 1.0f / height * iy);
			vec2 uv_offset = uv + offset;
			uv_offset.x    = clamp(uv_offset.x, 0.0f, 1.0f);
			uv_offset.y    = clamp(uv_offset.y, 0.0f, 1.0f);
			col += texture2D(tex, uv_offset) * weight;
			allWeight += weight;
		}
	}
	col = col / allWeight;
	return col;
}

I am a novice.Please do not delete my post, thank you very much

Linux archlinux 5.6.6-arch1-1
Intel® Core™ i7-6500U
NVIDIA GeForce 940M

@mirro187, before you post anything else, I need you to read The Forum Posting Guidelines.

First, these forums are for asking specific technical questions about Khronos APIs, not posting one sentence with a block of code and hoping someone else will do your work for you. Again, read Posting Guideline #4. You haven’t taken the time to tell your reader anything here. So why would they take the time to answer you?

Second, you’ve reposted the same or nearly the same content repeatedly in separate threads. Please stop. This just clutters the forums and is akin to cross-posting (see Forum Posting Guideline #3). As you may have noticed, I’ve combined all your posts here in this one single thread.

Try following up to this thread detailing information such as: why you’re trying to do this, what you’ve tried already, what specific GLSL or OpenGL related problems you’ve hit, and any specific GLSL or OpenGL related questions you’ve come up related to your learning or investigation.

1 Like

My god, I repeat posts because I can’t edit the topic again.
Can you change gaussian blur to Computeshader?

I don’t know why you can’t edit the topic, nor do I know how to fix that. However, if you were to change “Gaussian blur” to “Computeshader”, then the title would become “How can the following Computeshader shader be modified to compute shader?” Even if you remove the repeated “shader” word, it still makes no sense.

Also, you should answer the other points that Dark Photon raised.

Are you asking how to output a result from a compute shader? If so:

  1. Remove
  1. Use gl_GlobalInvocationID.xy instead of uv (the values are integer pixel coordinates; you might want to use texelFetch rather than texture2D).
  2. In the shader, add an image2D uniform for the output. From the client side, bind the output texture to an image (glBindImageTexture) and assign the image unit index to the uniform.
  3. Replace the assignment to FragColor with an imageStore call.
  4. Instead of rendering a quad with a texture bound to a FBO, call glDispatchCompute.

Sorry,I am a novice…

I modified it myself, I don’t know why the display is black…

#include <osg/Texture2D>
#include <osg/BindImageTexture>
#include <osg/DispatchCompute>
#include <osg/Geode>
#include <osgDB/ReadFile>
#include <osgGA/StateSetManipulator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

static const char* computeSrc = {
“#version 430\n”
“precision highp float;\n”
“precision highp int;\n”
“layout (rgba32f, binding =0) highp uniform image2D uImageIn;\n”
“layout (rgba32f, binding =1) highp uniform image2D uImageOut;\n”
“layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;\n”
“void main() {\n”
" ivec2 id = ivec2(gl_GlobalInvocationID.xy); \n"
" ivec2 size = imageSize(uImageOut); \n"
" if (id.x >= size.x || id.y >= size.y) { \n"
" return; \n"
" } \n"
" const int uSigma = 15;\n"
" // 0.9544 \n"
" int kernel = int(ceil(2.0 * uSigma)); \n"
" \n"
" vec4 pixel = vec4(0.0); \n"
" float coef = 0.0; \n"
" for (int dx = -kernel; dx <= kernel; dx++) { \n"
" for (int dy = -kernel; dy <= kernel; dy++) { \n"
" int x = id.x + dx; \n"
" int y = id.y + dy; \n"
" if (x < 0 || x >= size.x || \n"
" y < 0 || y >= size.y) { \n"
" continue; \n"
" } \n"
" float c = exp(-float(dx * dx + dy * dy) / (2.0 * uSigma * uSigma + 1e-5)); \n"
" pixel += (imageLoad(uImageIn, ivec2(x, y)) * c); \n"
" coef += c; \n"
" } \n"
" } \n"
" imageStore(uImageOut, id, pixel / (coef + 1e-5)); \n"
“}\n”
};

int main( int argc, char** argv )
{
osg::ArgumentParser arguments( &argc, argv );
// Create the texture as both the output of compute shader and the input of a normal quad
osg::ref_ptrosg::Texture2D tex2D = new osg::Texture2D;
osg::Image* pImage = osgDB::readImageFile(“Images/man.png”);
pImage->setDataVariance(osg::Object::DYNAMIC);
tex2D->setImage(pImage);
tex2D->setTextureSize( 512, 512 );
tex2D->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
tex2D->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
tex2D->setInternalFormat(GL_RGBA32F_ARB);
tex2D->setSourceFormat(GL_RGBA);
tex2D->setSourceType( GL_FLOAT );
// So we can use ‘image2D’ in the compute shader
osg::ref_ptrosg::BindImageTexture imagbinding = new osg::BindImageTexture(0, tex2D.get(), osg::BindImageTexture::READ_WRITE, GL_RGBA32F_ARB);
osg::ref_ptrosg::Texture2D tex2D2 = new osg::Texture2D;
tex2D2->setTextureSize(512, 512);
tex2D2->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
tex2D2->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
tex2D2->setInternalFormat(GL_RGBA32F_ARB);
tex2D2->setSourceFormat(GL_RGBA);
tex2D2->setSourceType(GL_FLOAT);
// So we can use ‘image2D’ in the compute shader
osg::ref_ptrosg::BindImageTexture imagbinding2 = new osg::BindImageTexture(0, tex2D2.get(), osg::BindImageTexture::READ_WRITE, GL_RGBA32F_ARB);
// The compute shader can’t work with other kinds of shaders
// It also requires the work group numbers. Setting them to 0 will disable the compute shader
osg::ref_ptrosg::Program computeProg = new osg::Program;
computeProg->addShader( new osg::Shader(osg::Shader::COMPUTE, computeSrc) );
// Create a node for outputting to the texture.
// It is OK to have just an empty node here, but seems inbuilt uniforms like osg_FrameTime won’t work then.
// TODO: maybe we can have a custom drawable which also will implement glMemoryBarrier?
osg::ref_ptrosg::Node sourceNode = new osg::DispatchCompute(512/16, 512/16, 1 );
sourceNode->setDataVariance( osg::Object::DYNAMIC );
sourceNode->getOrCreateStateSet()->setAttributeAndModes( computeProg.get() );
sourceNode->getOrCreateStateSet()->addUniform( new osg::Uniform(“uImageIn”, (int)0) );
sourceNode->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex2D.get() );
sourceNode->getOrCreateStateSet()->addUniform(new osg::Uniform(“uImageOut”, (int)1));
sourceNode->getOrCreateStateSet()->setTextureAttributeAndModes(1, tex2D2.get());
// Display the texture on a quad. We will also be able to operate on the data if reading back to CPU side
osg::Geometry* geom = osg::createTexturedQuadGeometry(
osg::Vec3(), osg::Vec3(1.0f,0.0f,0.0f), osg::Vec3(0.0f,0.0f,1.0f) );
osg::ref_ptrosg::Geode quad = new osg::Geode;
quad->addDrawable( geom );
quad->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
quad->getOrCreateStateSet()->setTextureAttributeAndModes( 0, tex2D2.get() );
quad->getOrCreateStateSet()->setAttributeAndModes(imagbinding2.get());
// Create the scene graph and start the viewer
osg::ref_ptrosg::Group scene = new osg::Group;
scene->addChild( sourceNode );
scene->addChild( quad.get() );
osgViewer::Viewer viewer;
viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
viewer.addEventHandler( new osgViewer::StatsHandler );
viewer.addEventHandler( new osgViewer::WindowSizeHandler );
viewer.setSceneData( scene.get() );
return viewer.run();
}

Sorry,I am a novice…My environment is win10 osg3.6.4 GTX1660Ti.
Is there an example of Gaussian blur ComputeShader?