Sign in to follow this  
lonewolff

Problems with GLSL ES Shader

Recommended Posts

lonewolff    1183
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. :)

Share this post


Link to post
Share on other sites
Hodgman    51334

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/

Share this post


Link to post
Share on other sites
WiredCat    1450
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this