geojade
geojade

Reputation: 33

glGetUniformLocation() returns -1 on used uniform?

I'm trying to make the colours on a shape darken, and then brighten periodically. The way I thought of to do it was to use a uniform variable that changes periodically from 0 to 1 and back and multiply it by the inputted colours to form the output colour. I have a uniform variable ublackness which does that.

A check of whether it can be located always returns -1, however the previous variables and the next variable work as intended. I know the name is correct, and I know it is being used because with the multiplication there, the screen is black (presumably because the colours are getting multiplied by 0 or something) but without it it displays fine. Here is the relevant code in the cpp file

GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
shadeIndex = glGetUniformLocation(g_shaderProgramID, "ublackness");
if (shadeIndex = -1)
{
    cout << "it didn't work" << endl;
}
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");

And here is the relevant fragment shader file.

#version 330 core

// interpolated values from the vertex shaders
in vec3 vColor;

//thing
uniform float ublackness;

// output data
out vec3 fColor;

void main()
{
    // set output color
    fColor = vColor * ublackness;
}

And in case anyone tells me to use the vertex shader instead, I've tried that with the same results. I have also tried sending a vec3, and creating a temp vec3 and setting its colors to vcolor * blackness then outputting that.

I've also heard that nvidia graphics cards affect how functions like glUniform1f work, and I use that function, but that didn't seem relevant because it doesn't even get to that part of the code with a valid index. In case it is relevant, however, I have a NVIDIA Geforce GTX 1080. I've also heard that you need to use glUseProgram to get glGetUniformLocation to work, however the other functions work without it, and ublackness still doesn't work with it, so I didn't bother leaving it in. It is still used when rendering, however.


I highlighted the code I thought was relevant, but in case more is needed, here is all the main cpp code:

#include <cstdio>       // for C++ i/o
#include <iostream>
#include <string>
#include <time.h>
using namespace std;    // to avoid having to use std::

#define GLEW_STATIC     // include GLEW as a static library
#include <GLEW/glew.h>  // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp>  // include GLM (ideally should only use the GLM   headers that are actually used)
#include <glm/gtx/transform.hpp>
using namespace glm;    // to avoid having to use glm::

#include "shader.h"

                            // struct for vertex attributes
struct Vertex
{
    GLfloat position[3];
    GLfloat color[3];
};


Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f,  // position
1.0f, 0.0f, 1.0f,   // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f,   // colour
// vertex 3
0.5f, 0.5f, 0.5f,   // position
1.0f, 1.0f, 1.0f,   // colour
// vertex 4
0.5f, -0.5f, 0.5f,  // position
1.0f, 1.0f, 0.0f,   // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f,   // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f,   // colour
// vertex 7
0.5f, 0.5f, -0.5f,  // position
0.0f, 1.0f, 1.0f,   // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f,   // colour
 };

GLuint g_indices[] = {
0, 1, 2,    // triangle 1
2, 1, 3,    // triangle 2
4, 5, 0,    // triangle 3
0, 5, 1,    // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6,    // triangle 12
};


GLuint g_IBO = 0;               // index buffer object identifier
GLuint g_VBO = 0;               // vertex buffer object identifier
GLuint g_VAO = 0;               // vertex array object identifier
GLuint g_shaderProgramID = 0;   // shader program identifier
GLuint g_MVP_Index = 0;         // location in shader
GLuint shadeIndex = 0;
glm::mat4 g_modelMatrix[6];     // object's model matrix
glm::mat4 g_viewMatrix;         // view matrix
glm::mat4 g_projectionMatrix;   // projection matrix
float translation[6];
float scaling[6];
float rotation[6];
float totalRotation[6];
float orbit[6];
float totalOrbit[6];
float totalShade = 1;
int shadeChange = 1;




                    // function used to render the scene
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer

glUseProgram(g_shaderProgramID);    // use the shaders associated with the shader program

glBindVertexArray(g_VAO);       // make VAO active

for (int i = 0; i < 5; i++)
{
    g_modelMatrix[i]  = glm::rotate(totalOrbit[i], glm::vec3(0.0f, 1.0f, 0.0f))
        * glm::translate(glm::vec3(translation[i], 0.0f, 0.0f))
        * glm::rotate(totalRotation[i], glm::vec3(0.0f, 1.0f, 0.0f))
        * glm::scale(glm::vec3(scaling[i], scaling[i], scaling[i]));
    glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[i];
    // set uniform model transformation matrix
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);

    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
}

g_modelMatrix[5] = glm::rotate(totalOrbit[5], glm::vec3(0.0f, 1.0f, 0.0f))
    * glm::translate(glm::vec3(translation[5], 0.0f, 0.0f))
    * glm::rotate(totalOrbit[5], glm::vec3(0.0f, 1.0f, 0.0f))
    * glm::translate(glm::vec3(0.4, 0.0f, 0.0f))
    * glm::rotate(totalRotation[5], glm::vec3(0.0f, 1.0f, 0.0f))
    * glm::scale(glm::vec3(scaling[5], scaling[5], scaling[5]));
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[5];
// set uniform model transformation matrix
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type

//glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0];
// set uniform model transformation matrix
//glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);

glFlush();  // flush the pipeline
}

// error callback function
static void error_callback(int error, const char* description)
{
cerr << description << endl;    // output error description
}


// key press or release callback function
 static void key_callback(GLFWwindow* window, int key, int scancode, int     action, int mods)
{
// quit if the ESCAPE key was press
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
    // set flag to close the window
    glfwSetWindowShouldClose(window, GL_TRUE);
    return;
}
}

static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0);   // set clear background colour

glEnable(GL_DEPTH_TEST);    // enable depth buffer test
                            // create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("VertexShader.vert", "FragShader.frag");

// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
shadeIndex = glGetUniformLocation(g_shaderProgramID, "ublackness");
if (shadeIndex = -1)
{
    cout << "it didn't work" << endl;
}
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");

srand(time(NULL));

// initialise model matrix to the identity matrix
g_modelMatrix[0] = glm::mat4(1.0f); //sun
scaling[0] = 0.5f * (100 + ((rand() % 100)))/100;
translation[0] = 0.0f;
rotation[0] = 1.0f * (100 + ((rand() % 100))) / 100;
orbit[0] = 0.0f;

g_modelMatrix[1] = glm::mat4(1.0f); //tilted planet
scaling[1] = 0.1f * (100 + ((rand() % 100))) / 100;
translation[1] = 0.7f * (100 + ((rand() % 15))) / 100;
rotation[1] = 1.0f * (100 + ((rand() % 100))) / 100;
orbit[1] = 0.3f * (100 + ((rand() % 100))) / 100;

g_modelMatrix[2] = glm::mat4(1.0f); //ringed planet
scaling[2] = 0.1f * (100 + ((rand() % 100))) / 100;
translation[2] = 1.5f * (100 + ((rand() % 15))) / 100;
rotation[2] = 1.0f * (100 + ((rand() % 100))) / 100;
orbit[2] = 0.3f * (100 + ((rand() % 100))) / 100;

g_modelMatrix[3] = glm::mat4(1.0f); //moon planet
scaling[3] = 0.1f * (100 + ((rand() % 100))) / 100;
translation[3] = 2.8f * (100 + ((rand() % 15))) / 100;
rotation[3] = 1.0f * (100 + ((rand() % 100))) / 100;
orbit[3] = 0.3f * (100 + ((rand() % 100))) / 100;

g_modelMatrix[4] = glm::mat4(1.0f); //fading planet
scaling[4] = 0.1f * (100 + ((rand() % 100))) / 100;
translation[4] = 4.0f * (100 + ((rand() % 15))) / 100;
rotation[4] = 1.0f * (100 + ((rand() % 100))) / 100;
orbit[4] = 0.3f * (100 + ((rand() % 100))) / 100;

g_modelMatrix[5] = glm::mat4(1.0f); //moon
scaling[5] = 0.02f * (100 + ((rand() % 100))) / 100;
translation[5] = translation[3];
rotation[5] = 1.0f * (100 + ((rand() % 100))) / 100;
orbit[5] = orbit[3];


g_viewMatrix = glm::lookAt(glm::vec3(0, 6, 1), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));

int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;

g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);

// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);

// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);

// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO);

// create VAO and specify VBO data
glBindVertexArray(g_VAO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));

glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
}

static void update_scene(GLFWwindow* window, float frameTime)
{
// declare variables to transform the object
for (int i = 0; i < 6; i++)
{
    totalOrbit[i] += orbit[i] * frameTime;
    totalRotation[i] += rotation[i] * frameTime;
}
if (totalShade = 1)
{
    shadeChange = -0.05f;
}
else if (totalShade = 0)
{
    shadeChange = 0.05f;
}
totalShade += shadeChange;
glUniform1f(shadeIndex, totalShade);
}

int main(void)
{
GLFWwindow* window = NULL;  // pointer to a GLFW window handle

glfwSetErrorCallback(error_callback);   // set error callback function

                                        // initialise GLFW
if (!glfwInit())
{
    // if failed to initialise GLFW
    exit(EXIT_FAILURE);
}

// minimum OpenGL version 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

// create a window and its OpenGL context
window = glfwCreateWindow(800, 600, "Creating a Window", NULL, NULL);

// if failed to create window
if (window == NULL)
{
    glfwTerminate();
    exit(EXIT_FAILURE);
}

glfwMakeContextCurrent(window); // set window context as the current context
glfwSwapInterval(1);            // swap buffer interval

                                // initialise GLEW
if (glewInit() != GLEW_OK)
{
    // if failed to initialise GLEW
    cerr << "GLEW initialisation failed" << endl;
    exit(EXIT_FAILURE);
}

// set key callback function
glfwSetKeyCallback(window, key_callback);

/*
// if not using key or mouse callback functions
// use sticky mode to avoid missing state changes from polling
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GL_TRUE);
*/

// initialise rendering states
init(window);

double lastUpdateTime = glfwGetTime();  // last update time
double elapsedTime = lastUpdateTime;    // time elapsed since last update
float frameTime = 0.0f;             // frame time
int frameCount = 0;
                                    // the rendering loop
while (!glfwWindowShouldClose(window))
{
    update_scene(window, frameTime);    // update the scene
    render_scene();             // render the scene

    glfwSwapBuffers(window);    // swap buffers
    glfwPollEvents();           // poll for events

    frameCount++;
    elapsedTime = glfwGetTime() - lastUpdateTime;   // current time - last update time

    if (elapsedTime >= 1.0f)    // if time since last update >= to 1 second
    {
        frameTime = static_cast<float>(1.0f / frameCount);  // calculate frame time

        string str = "FPS = " + to_string(frameCount) + "; FT = " + to_string(frameTime);

        glfwSetWindowTitle(window, str.c_str());    // update window title

        frameCount = 0;                 // reset frame count
        lastUpdateTime += elapsedTime;  // update last update time
    }
}

// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO);
glDeleteVertexArrays(1, &g_VAO);

// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();

exit(EXIT_SUCCESS);
}

here is all the vertex shader code:

#version 330 core

// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;

// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;

// output data (will be interpolated for each fragment)
out vec3 vColor;

void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);

// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}

And here is all the shader cpp code:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#define GLEW_STATIC     // include GLEW as a static library
#include <GLEW/glew.h>  // include GLEW

#include "shader.h"

// function to load shaders
GLuint loadShaders(const string vertexShaderFile, const string fragmentShaderFile)
{
GLint status;   // for checking compile and linking status

// load vertex shader code from file
string vertexShaderCode;    // to store shader code
ifstream vertexShaderStream(vertexShaderFile, ios::in); // open file stream

// check whether file stream was successfully opened
if(vertexShaderStream.is_open())
{
    // read from stream line by line and append it to shader code
    string line = "";
    while(getline(vertexShaderStream, line))
        vertexShaderCode += line + "\n";

    vertexShaderStream.close();     // no longer need file stream
}
else
{
    // output error message and exit
    cout << "Failed to open vertex shader file - " << vertexShaderFile << endl;
    exit(EXIT_FAILURE);
}

// load fragment shader code from file
string fragmentShaderCode;  // to store shader code
ifstream fragmentShaderStream(fragmentShaderFile, ios::in); // open file stream

// check whether file stream was successfully opened
if(fragmentShaderStream.is_open())
{
    // read from stream line by line and append it to shader code
    string line = "";
    while(getline(fragmentShaderStream, line))
        fragmentShaderCode += line + "\n";

    fragmentShaderStream.close();   // no longer need file stream
}
else
{
    // output error message and exit
    cout << "Failed to open fragment shader file - " << fragmentShaderFile << endl;
    exit(EXIT_FAILURE);
}

// create shader objects
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

// provide source code for shaders
const GLchar* vShaderCode = vertexShaderCode.c_str();
const GLchar* fShaderCode = fragmentShaderCode.c_str();
glShaderSource(vertexShaderID, 1, &vShaderCode, NULL);
glShaderSource(fragmentShaderID, 1, &fShaderCode, NULL);

// compile vertex shader
glCompileShader(vertexShaderID);

// check compile status
status = GL_FALSE;
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &status);

if(status == GL_FALSE)
{
    // output error message
    cout << "Failed to compile vertex shader - " << vertexShaderFile  << endl;

    // output error information
    int infoLogLength;
    glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
    char* errorMessage = new char[infoLogLength + 1];
    glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, errorMessage);
    cout << errorMessage << endl;
    delete[] errorMessage;

    exit(EXIT_FAILURE);
}

// compile fragment shader
glCompileShader(fragmentShaderID);

// check compile status
status = GL_FALSE;
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &status);

if(status == GL_FALSE)
{
    // output error message
    cout << "Failed to compile fragment shader - " << fragmentShaderFile << endl;

    // output error information
    int infoLogLength;
    glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
    char* errorMessage = new char[infoLogLength + 1];
    glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, errorMessage);
    cout << errorMessage << endl;
    delete[] errorMessage;

    exit(EXIT_FAILURE);
}

// create program
GLuint programID = glCreateProgram();

// attach shaders to the program object
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);

// flag shaders for deletion (will not be deleted until detached from program)
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);

// link program object
glLinkProgram(programID);

// check link status
status = GL_FALSE;
glGetProgramiv(programID, GL_LINK_STATUS, &status);

if(status == GL_FALSE)
{
    // output error message
    cout << "Failed to link program object." << endl;

    // output error information
    int infoLogLength;
    glGetShaderiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
    char* errorMessage = new char[infoLogLength + 1];
    glGetShaderInfoLog(programID, infoLogLength, NULL, errorMessage);
    cout << errorMessage << endl;
    delete[] errorMessage;

    exit(EXIT_FAILURE);
}

return programID;
}

In case you are wondering what the code does, it creates a cube, then transforms it to make a solar system. I was trying to make 1 cube go dark then bright but I wanted to make sure it worked first by using it on all of them.

Upvotes: 1

Views: 1141

Answers (1)

Nicolas Tisserand
Nicolas Tisserand

Reputation: 488

I believe:

if (shadeIndex = -1)

should be:

if (shadeIndex == -1)

And then you will need to add a call to glUniform1f in your code, in order to actually set the uniform value, of course.

Upvotes: 3

Related Questions