1
votes

Ok. I'm getting into opengl 2.1(without the fixed function stuff) and I'm having troubles with shaders. I declare my uniform variable on my shader, and in my program I get the uniform location and assign it a value with gluniform but it doesn't seem to work.

These are my shaders

fragment shader: #version 120

varying float color;

void
main ()
{
    gl_FragColor = vec4(color, 0, 0, 1);
}

and my vertex shader: #version 120

attribute vec2 position;
varying float color;
uniform float pr_color;

void
main () 
{
    color = pr_color;
    gl_Position = vec4(position, 0.0, 1.0);
}

This is how I'm passing the data to the shader:

void 
display () 
{
     glClear(GL_COLOR_BUFFER_BIT);

     glUseProgram(g_program);

     pos_loc = glGetAttribLocation(g_program, "position");

     col_loc = glGetUniformLocation(g_program, "pr_color");

     glUniform1f(col_loc, 1.0);

     glBindBuffer(GL_ARRAY_BUFFER, vbo);
     glEnableVertexAttribArray(pos_loc);
     glVertexAttribPointer(pos_loc, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

     glDrawArrays(GL_TRIANGLES, 0, 3);

    glutPostRedisplay();
    glutSwapBuffers();
 }

and i don't think this is needed, but in any case, my initgl function

void 
init () 
{
     // Set clear color to black
     glClearColor(0.0,0.0,0.0,0.0);

     vshader = createShader(GL_VERTEX_SHADER, "vertex.glsl");
     fshader = createShader(GL_FRAGMENT_SHADER, "fragment.glsl");

     g_program = createProgram(vshader, fshader);

     // Create vbo and send it the vertex data
     glGenBuffers(1, &vbo);
     glBindBuffer(GL_ARRAY_BUFFER, vbo);
     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}

the thing is, my shaders are working, if I hardcode the color into the fragment sahder, then the triangle is drawn, but if I pass the color to the vertex shader, it doesn't work, the triangle is drawn to black, which is strange, because my position attribute works, but my color uniform is set to 0. As you can see, I'm setting useprogram() before passing the uniform value.

EDIT: I changed the gluniform1i(col_loc, 1) to glUniformif(col_loc, 1.0). Still doesn't work

EDIT: I'll add my shader loading function to make sure the problem is not in the shader

GLuint
createShader (GLenum type, char* filename)
{
    GLuint shader;

    // Load file
    FILE* file;
    file = fopen(filename, "r");
    if (file == NULL)
    {
        printf("Error reading file \n");
    }

    // Get Length
    fseek(file, 0, SEEK_END);
    long length = ftell(file);
    fseek(file, 0, SEEK_SET);

    // Get source
    char* source;
    source = malloc( (size_t) length + 1);
    if (source == NULL)
    {
        printf("Error alocating space for shader\n");
    }

    // Read file
    fread(source, 1, length, file);

    // Close file
    fclose(file);
    source[length] = '\n';

    // Create shader, attach it's source and compile it
    shader = glCreateShader(type);
    glShaderSource(shader, 1, (const GLchar*)&source, &length);
    free(source); // Free shader source, once it's attached
    glCompileShader(shader);

    // Check for errors
    GLint shader_status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_status);
    if (!shader_status) {
        fprintf(stderr, "Failed to compile %s:\n", filename);

        GLint log_length;
        char *log;

        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
        log = malloc(log_length);

        glGetShaderInfoLog(shader, log_length, NULL, log);
        fprintf(stderr, "%s", log);
        free(log);

        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

When there's an error in the shader, the program actually prints the error log, so I don't think the error is in here, but anyway, here it is.

EDIT: program linker code

GLuint
createProgram (GLuint vertexs, GLuint fragments)
{
    GLint program_ok;

    // Create program and attach to shaders
    GLuint program = glCreateProgram();
    glAttachShader(program, vertexs);
    glAttachShader(program, fragments);
    glLinkProgram(program);

    glGetProgramiv(program, GL_LINK_STATUS, &program_ok);
    if (!program_ok) {
        fprintf(stderr, "Failed to link shader program:\n");
        GLint log_length;
        char *log;

        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
        log = malloc(log_length);
        glGetProgramInfoLog(program, log_length, NULL, log);
        fprintf(stderr, "%s", log);
        free(log);

        glDeleteProgram(program);
        return 0;
    }

    return program;
}

Please tell me if there's anything wrong with my shaders/program, I was just starting to get the basics of programmable pipeline and now I can't even render a triangle

2
Why are you passing an integer value if the uniform is a float?Reto Koradi
just copied the code after making some changes, but I tried with 1.0f, 1.0, and it didn't work. I couldn't pass vector data neither, that's why I'm trying with simple floatstwkmz
Are you sure your shaders link correctly? Can't see you checking GL_LINK_STATUS.Andreas
I added the program code. Maybe the error is in there?twkmz

2 Answers

3
votes

You are using

glUniform1i(col_loc, 1);

To set the value of

uniform float pr_color;

1i stands for 1 int. Use 1f for 1 float.

glUniform1f(col_loc, 1.0f);
0
votes

OK, I got it working with glUnifrom4fv(). I am now passing a vec4 to the shader's color variable and it works!