Problems with GLSL ES Shader

Started by
2 comments, last by _WeirdCat_ 6 years, 10 months ago
Hi Guys,

I am having a problem with a gaussian blur shader that I am working on. At present the shader works perfectly and give a nice even blur.

The problem I am having is when I try to send the radius to the shader through v_vAttributes.z, I get the following errors;

I'd like to be able to control the radius from the application so I can control it at runtime.

warning X3550: array reference cannot be used as an l-value; not natively addressable, forcing loop to unroll
warning X3550: array reference cannot be used as an l-value; not natively addressable, forcing loop to unroll
warning X3553: can't use gradient instructions in loops with break, forcing loop to unroll
error X4505: maximum temp register index exceeded



varying vec2 v_vTexcoord;
varying vec3 v_vAttributes;
 
void main()
{
    float width=v_vAttributes.x;
    float height=v_vAttributes.y;
    float inRadius=20.0;      //v_vAttributes.z;    ** PROBLEM OCCURS HERE **
    
    int inDiameter=(int(inRadius)*2)+1;
    float gaussian_kernel[99];
    float twoRadiusSquaredRecip=1.0/(2.0*inRadius*inRadius);
    float sqrtTwoPiTimesRadiusRecip=1.0/(sqrt(2.0*3.141)*inRadius);
 
    // Create Gaussian Kernel
    float rr=-inRadius;
    float sum=0.0;
    
    for (int i=0;i<inDiameter;i++)
    {
        float v=sqrtTwoPiTimesRadiusRecip*exp(-rr*rr*twoRadiusSquaredRecip);
        gaussian_kernel[i]=v;
        sum+=v;
        rr++;
    }
 
    // Normalize distribution
    for (int i=0;i<inDiameter;i++)
        gaussian_kernel[i]/=sum;
        
    gl_FragColor = vec4(0.0);
    for(int i=0;i<(inDiameter);i++)
        gl_FragColor += texture2D(gm_BaseTexture, vec2(v_vTexcoord)-vec2(((float(inDiameter+i)-(float(inDiameter))/2.0)/width)-((inRadius*2.0)/width), 0.0))*gaussian_kernel[i];
}
I am the using GLSL ES shader model if that helps.

Any advice would be greatly appreciated. :)
Advertisement

I'm guessing that "array reference cannot be used as an l-value" basically means "this GPU does not have a "write to register" instruction that takes a base register ID plus an offset -- or in other words, you can't write to an array using indices that are not known at compile time.

On this kind of old GPU, you should use a fixed number of samples in your loop (e.g. every pixel uses 7 texture fetches). You can then either dynamically scale the texture coordinates, or dynamically change the weights so that some of them are ignored.

Also, I'm guessing that a GPU that is lacking this kind of feature is also going to be a very slow GPU... so you really don't want to be constructing your gaussian kernel per pixel anyway. I would even avoid writing code like yours on a modern GPU, as it's a lot of extra work to be doing :wink:

For a super efficient gaussian blur shader, you should also use bilinear filtering to reduce the number of taps required -- e.g. https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/06/faster_filters.pdf http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/

What you're trying to do is known as shader dynamic control flow, and it is forbidden to do in the pixel shader in GLES 2.0 (most ES2 hardware is incapable of doing it), and IIRC also in ES 3.0 (not sure about that last one).

First of all you pass attributes from vertex shader to fragment shader - looks like you did this


Now show me your buffer data structure and how you set up vertex attrib pointer then we can fix this I assume dat ur using an arrray of vec3 to fill data and not texture

This topic is closed to new replies.

Advertisement