0

I'm trying to get screenWidth and screenHeight into my fragment shader through uniform variables. Here's my main.cpp where the offender lies, I can get the location (non -1) but when it actually sets the uniform variable thingy I segfault.

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>

#include "math_3d.h"
#include "shader.h"

//  Global
GLuint VBO;

static void RenderSceneCB()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableVertexAttribArray(0);

    glutSwapBuffers();
}

static void CreateVertexBuffer()
{
    Vector3f Verticies[3];  
    Verticies[0] = Vector3f(-1.0f, -1.0f, 0.0f);
    Verticies[1] = Vector3f(1.0f, -1.0f, 0.0f);
    Verticies[2] = Vector3f(0.0f, 1.0f, 0.0f);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Verticies), Verticies, GL_STATIC_DRAW);
}


int main(int argc, char** argv)
{
    const int SCREEN_WIDTH = 800, SCREEN_HEIGHT = 600;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
    glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Test Window");

    glutDisplayFunc(RenderSceneCB);

    GLenum res = glewInit();
    if(res != GLEW_OK)
    {
        fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
        return 1;
    }   

    const GLubyte* renderer = glGetString(GL_RENDERER);
    const GLubyte* version = glGetString(GL_VERSION);
    printf("Renderer: %s\n", renderer);
    printf("Version: %s\n", version);   

    Shader vertexShader(GL_VERTEX_SHADER, "shader.vs");
    Shader fragShader(GL_FRAGMENT_SHADER, "shader.fs");

    GLuint program = glCreateProgram();
    glAttachShader(program, vertexShader.shader);
    glAttachShader(program, fragShader.shader);

    glLinkProgram(program);
    GLint status;
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
    {
        printf("No link\n");
    }

    glValidateProgram(program);
    glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
    if (status == GL_FALSE)
    {
        printf("No validate\n");
    }   

    glUseProgram(program);

    printf("UNIFORM\n");    

    //  Set uniform variables
    GLint location = glGetUniformLocation(program, "screenWidth");
    printf("loc: %d\n", location);
    glProgramUniform1i(program, location, 800);
    /*
    GLint location2 = glGetUniformLocation(program, "screenHeight");
    printf("loc: %d\n", location2);
    glProgramUniform1i(program, location2, 600);

    printf("uniform done\n");
    */
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

    glPointSize(10.0f);

    CreateVertexBuffer();

    glutMainLoop();

    return 0;
}

The shader looks like this:

#version 130

uniform int screenWidth = 800;
uniform int screenHeight = 600;

out vec4 FragColor;

void main()
{
    FragColor = vec4(gl_FragCoord.x/screenWidth, gl_FragCoord.y/screenHeight, 0.0, 1.0);
}
genpfault
  • 51,148
  • 11
  • 85
  • 139

2 Answers2

0

Changed how I set the uniform variables to this and everything worked out. I changed glProgramUniform1i to glUniform1i and took away the program parameter.

Here's the final main.cpp, look for the uniform section to see my changes.

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>

#include "math_3d.h"
#include "shader.h"

//  Global
GLuint VBO;

static void RenderSceneCB()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableVertexAttribArray(0);

    glutSwapBuffers();
}

static void CreateVertexBuffer()
{
    Vector3f Verticies[3];  
    Verticies[0] = Vector3f(-1.0f, -1.0f, 0.0f);
    Verticies[1] = Vector3f(1.0f, -1.0f, 0.0f);
    Verticies[2] = Vector3f(0.0f, 1.0f, 0.0f);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Verticies), Verticies, GL_STATIC_DRAW);
}


int main(int argc, char** argv)
{
    const int SCREEN_WIDTH = 800, SCREEN_HEIGHT = 600;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
    glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Test Window");

    glutDisplayFunc(RenderSceneCB);

    GLenum res = glewInit();
    if(res != GLEW_OK)
    {
        fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
        return 1;
    }   

    const GLubyte* renderer = glGetString(GL_RENDERER);
    const GLubyte* version = glGetString(GL_VERSION);
    printf("Renderer: %s\n", renderer);
    printf("Version: %s\n", version);   

    Shader vertexShader(GL_VERTEX_SHADER, "shader.vs");
    Shader fragShader(GL_FRAGMENT_SHADER, "shader.fs");

    GLuint program = glCreateProgram();
    glAttachShader(program, vertexShader.shader);
    glAttachShader(program, fragShader.shader);

    glLinkProgram(program);
    GLint status;
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
    {
        printf("No link\n");
    }

    glValidateProgram(program);
    glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
    if (status == GL_FALSE)
    {
        printf("No validate\n");
    }   

    glUseProgram(program);

    //  Set uniform variables
    GLint location = glGetUniformLocation(program, "screenWidth");
    glUniform1i(location, 800);

    GLint location2 = glGetUniformLocation(program, "screenHeight");
    glUniform1i(location2, 600);

    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

    glPointSize(10.0f);

    CreateVertexBuffer();

    glutMainLoop();

    return 0;
}
0

Your problem is actually that glProgramUniform1i (...) is relatively new. You have not come out and stated your OpenGL version explicitly, but your shader targets GLSL 1.30 (OpenGL 3.0) so chances are very good your implementation does not understand that function.

That function started out life in the Direct State Access extension (GL_EXT_direct_state_access), where it goes by the name glProgramUniform1iEXT (...) and was promoted to core when Separate Shader Objects were (GL 4.1).

The only difference between the two functions (glUniform1i (...) and glProgramUniform1i{EXT} (...)) is that one uses the currently bound program object, and the other lets you pass the one you need.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • More to the point, since you already call `glUseProgram (...)` 1 or 2 lines prior, you have no actual need for the function that does not require you to bind your program first. You should really check to see if function pointers are NULL in GL when you use GLEW; if you are not sure which extension a function is from but it is NULL in your debugger that is a pretty good indication that you don't have the right version. – Andon M. Coleman Jun 13 '14 at 01:10
  • I suspect version was the cause and also a good point that I don't have to use the one that specifies program. – Dan Brinkman Jun 14 '14 at 05:00