PDA

View Full Version : not able to send array using uniform buffer object



juanito
03-17-2014, 04:25 PM
Hi,
I'm trying to send an array to the fragment shader via a uniform buffer object, but it seems that the fragment shader is not receiving the values of the array.
The idea is that the fragment shader receives an array, and, depending on the values on the array, polygons are colored red or blue.
In each frame the values on the array change; I also expect that the colors on the polygons change. Since this is not the case, I'm guessing that the problem is how do I send the array via the uniform buffer object.

Could you please have a look at what is wrong in this code?
The relevant code is commented as: //uniforn buffer object//



class World {
private:
glm::vec2 ballsCenter[500];
...
}


//executed once


void World::initOpengl() {

GLuint buffer[2];
glGenBuffers(2 , buffer );

...

//uniforn buffer object//
glBindBuffer(GL_UNIFORM_BUFFER, buffer[1]);
glBufferData(GL_UNIFORM_BUFFER, sizeof(ballsCenter),NULL, GL_DYNAMIC_DRAW);

programID = InitShader( "vshader32.glsl", "fshader32.glsl" );
glUseProgram( programID );

...

//uniforn buffer object//
GLuint myArrayBlockIdx = glGetUniformBlockIndex (programID, "BallsCenter");
glUniformBlockBinding(programID, myArrayBlockIdx, 0);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer[1]);

...
}

//each frame


int World::render() {
...
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glUniformMatrix4fv(orthoID, 1, GL_FALSE, &control.orthoProjection[0][0]);

moveParticles();
for(int32 index=0; index<particlesCount; ++index) {
const float32 xBall = particle[index].x;
const float32 yBall = particle[index].y;

ballCenter[index] = glm::vec2(xBall, yBall);
...
}

//uniforn buffer object//
glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(ballCenter) *particlesCount ,ballCenter);
glDrawArrays(GL_TRIANGLES, 0, particlesCount*6);

...

glfwSwapBuffers();

return 0;
}

//Vertex shader

#version 400
in vec2 vPosition;

uniform mat4 ortho;

void main() {
gl_Position =ortho * vec4(vPosition.x, vPosition.y ,0.0, 1.0);
}


//Fragment shader

#version 400
in float color;
uniform float resolutionHeight;
uniform float resolutionWidth;
uniform mat4 ortho;

//uniforn buffer object//
layout (std140) uniform BallsCenter {
vec2 ballsCenter[500];
};


void main() {
float threshold = 1.0;
bool red=false;
for(int i=0; i<50; ++i){
vec4 centerV4= ortho * vec4(ballsCenter[i],0,1);

//uniforn buffer object//

float dist = length( centerV4.xy - vec2(gl_FragCoord.x/resolutionWidth,gl_FragCoord.y/resolutionHeight) );
if (dist < threshold){
red=true;
break;
}
}

if(red)
gl_FragColor = vec4(1,0,0,1); //red
else
gl_FragColor = vec4(0,0,1,1); //blue
}

juanito
03-21-2014, 10:08 PM
bump ...

Brokenmind
03-21-2014, 11:48 PM
Unfortunately, I'm not familiar with uniform buffer objects, but I have a different approach that could work for you:

With what I coded so far, I found out that shaders seem to have a problem with large arrays of data transmitted to them. Large in this case means something between 170 and 250, where my shaders stop compiling. The solution is storing the floats in textures and interpreting its pixels not as colors, but as uniform information to be read with some other variable (in my case gl_instanceID). Maybe you could try to lower your array size until it works (to find out the restrictions and whether my assumption is correct) and switch to using a texture instead.

juanito
03-25-2014, 11:18 AM
Thanks for the prompt reply; On Arcsynthesis there's a good tutorial about it.