glGetUniformLocation() 在使用过的制服上返回 -1?

Posted

技术标签:

【中文标题】glGetUniformLocation() 在使用过的制服上返回 -1?【英文标题】:glGetUniformLocation() returns -1 on used uniform? 【发布时间】:2018-04-05 14:25:23 【问题描述】:

我正在尝试使形状上的颜色变暗,然后定期变亮。我想到的方法是使用一个从 0 到 1 周期性变化并返回的统一变量,并将其乘以输入的颜色以形成输出颜色。我有一个统一的变量 ublackness 可以做到这一点。

检查是否可以定位总是返回-1,但是前面的变量和下一个变量按预期工作。我知道这个名字是正确的,我知道它正在被使用,因为在那里乘法,屏幕是黑色的(大概是因为颜色被乘以 0 或其他东西)但没有它显示正常。这是cpp文件中的相关代码

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");

这里是相关的片段着色器文件。

#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;

如果有人告诉我改用顶点着色器,我已经尝试过,结果相同。我还尝试发送vec3,并创建一个临时vec3 并将其颜色设置为vcolor * blackness,然后输出。

我还听说 nvidia 显卡会影响 glUniform1f 等函数的工作方式,我使用了该函数,但这似乎无关紧要,因为它甚至没有到达具有有效索引的代码部分。但是,如果它是相关的,我有一个 NVIDIA Geforce GTX 1080。我还听说你需要使用 glUseProgram 才能让glGetUniformLocation 工作,但是没有它其他功能也可以工作,而且 ublackness 仍然不起作用有了它,所以我没有费心把它留在里面。但是,它仍然在渲染时使用。


我突出显示了我认为相关的代码,但如果需要更多,这里是所有主要的 cpp 代码:

#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);

这是所有顶点着色器代码:

#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;

这里是所有着色器 cpp 代码:

#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;

如果您想知道代码的作用,它会创建一个立方体,然后将其转换为一个太阳系。我试图让 1 个立方体变暗然后变亮,但我想通过在所有立方体上使用它来确保它首先起作用。

【问题讨论】:

为什么在if (shadeIndex = -1) 中使用= 而不是== 【参考方案1】:

我相信:

if (shadeIndex = -1)

应该是:

if (shadeIndex == -1)

然后,您当然需要在代码中添加对glUniform1f 的调用,以便实际设置统一值。

【讨论】:

谢谢,就是这样。我总是觉得自己被困在简单的事情上寻找不同的问题很愚蠢,但老实说我没有考虑过。

以上是关于glGetUniformLocation() 在使用过的制服上返回 -1?的主要内容,如果未能解决你的问题,请参考以下文章

每帧调用 glGetUniformLocation()

glGetUniformLocation() 在使用过的制服上返回 -1?

即使我在着色器中使用了变量,glGetUniformLocation 仍返回 -1

glGetUniformLocation为第一个以外的采样器返回-1?

bundler:不支持在使​​用系统 gem 时使用自定义路径

在使线性布局容器无效后未调用子视图的 ondraw()