Page 1 of 1

[Pixelshader] extern arrays

Posted: Mon Jul 22, 2013 9:59 pm
by SCARD
Hi,

i'm trying to figure out how i can send an array to a pixel shader which size isnt constant. I want to make a lighting shader and want to send two arrays of vec3 to the shader. The first array of vec3 contains the x and y coordinate and the range of the light source, the second array contains the color. Thats what i got until now:

Code: Select all

extern number numlights;

extern vec3 lightposrange[numlights];
extern vec3 lightcolors[numlights];

float lengthSqr(float x, float y){
    return x*x + y*y;
}

float length(float x, float y){
    return sqrt(lengthSqr(x,y));
}

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords){
    vec4 pixel = Texel(texture, texture_coords);
    vec2 lightToPixel = pixel_coords - lightposrange.xy;
    
    for (int i = 0; i < numlights; i++){
        if (length(lightToPixel.x, lightToPixel.y) <= lightposrange.z) {
            pixel.r += lightcolors[i].r;
            pixel.g += lightcolors[i].g;
            pixel.b += lightcolors[i].b;
        }
    }

	return  pixel;
}

Well, as you probably noticed, the code won't compile :/
It says :
Line 4: error: non constant expression for array size
Line 5: error: non constant expression for array size
And some more errors that don't play a role for now.

By setting

Code: Select all

extern number numlights;
to

Code: Select all

const extern number numlights;
it says
Line 2: error: OpenGL requires constants to be initialized
Maybe you will need the love.draw function:

Code: Select all

function love.draw()
    -- draw unlighted scene in canvase
    love.graphics.setPixelEffect()
    love.graphics.setCanvas(unlightedSceneCanvas)
    drawScene()
    love.graphics.setCanvas()
    
    -- shade everything
    love.graphics.setPixelEffect(lightingShader)
   
   -- create lightdata for shader
    local lightposrange = {}
    local lightcolors = {}
    for i=1,#lights do
        lightposrange[#lightposrange+1] = {lights[i].x, lights[i].y, lights[i].range}
        lightcolors[#lightcolors+1] = lights[i].color
    end
    
    -- send lightdata to shader
    lightingShader:send("numlights", #lights)
    lightingShader:send("lightposrange", unpack(lightposrange))
    lightingShader:send("lightcolors", unpack(lightcolors))
    
    -- draw the unlighted scene with activated shader
    love.graphics.draw(unlightedSceneCanvas)
end
Has anyone an idea of how to set dynamically the size of an array in pixeleffects?

EDIT:
fixed some general problems, main problem still there

Re: [Pixelshader] extern arrays

Posted: Mon Jul 22, 2013 10:03 pm
by raidho36
Your numlights is a varaible, therefore cannot be used to create an array on the GPU. It must be a constant, and just marking variable a constant doesn't makes it such*. So for that, you use hard-coded values, I think 32 would be enough. As an option, you can use named constant in shader source and replace it with it's value right before you compile the shader.

*you have invalid syntax there anyway, it GLSL it goes as: const int myvectorsize = 32; that yields a constant "myvectorsize" with value 32

Re: [Pixelshader] extern arrays

Posted: Mon Jul 22, 2013 10:17 pm
by SCARD
Thanks raidho36 for your fast reply.

I also thought about doing this but isn't there a way doing this completely dynamically without hard-coding? I'm pretty sure i did this in pure GLSL once.

Re: [Pixelshader] extern arrays

Posted: Mon Jul 22, 2013 11:23 pm
by raidho36
Well this is pure GLSL actually, just with a bunch of aliases defined for the sake of simplicity.

Re: [Pixelshader] extern arrays

Posted: Tue Jul 23, 2013 9:20 pm
by RedHot
Until OpenGL 4.3 the array size used to be fixed. Now we can use shader storage buffer objects which get rid of the problem in a way.