为 glm 翻译添加统一向量在 OpenGL 中不起作用

Posted

技术标签:

【中文标题】为 glm 翻译添加统一向量在 OpenGL 中不起作用【英文标题】:Adding uniform vector for glm translation doesn't work in OpenGL 【发布时间】:2019-12-05 08:36:04 【问题描述】:

如果我删除 uniform 变量和以下行:

//in CompileShaders function:
uniformModel = glGetUniformLocation(shader,"model"); 
  ...
//defined in the main draw loop after glfwPollEvents():
//and the shader has  compiled, linked and activated at this point
glm::mat4 modelMatrix;
modelMatrix = glm::translate(modelMatrix, glm::vec3(triOffset, 0.0f, 0.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE,glm::value_ptr(modelMatrix));  

程序显示正常,但是一旦我添加了统一变量并使用矩阵来平移三角形,我就找不到为什么会出现红屏,为了便于参考,着色器是:

static const char* vShader = 
"#version 330\n"
"layout (location = 0) in vec3 pos;\n"
"uniform mat4 model;\n"
"void main()\n"
"   gl_Position = model * vec4(pos, 1.0);\n"
"\n";

// fragment shader
static const char* fShader = ""
"#version 330\n"
"out vec4 color;\n"
"void main()\n"
"   color = vec4(1.0, 1.0, 0.0, 1.0);\n"
"\n";  

整个源代码为:

#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <string.h>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"


// Window Dimensions
const GLint WIDTH=800, HEIGHT=600;
GLuint VAO, VBO, shader;
GLint uniformModel ;
GLfloat triOffset ;
GLfloat triMaxOffset 5.0f;
bool direction = true;
// vertex shader
static const char* vShader = 
"#version 330\n"
"layout (location = 0) in vec3 pos;\n"
"uniform mat4 model;\n"
"void main()\n"
"   gl_Position = model * vec4(pos, 1.0);\n"
"\n";

// fragment shader
static const char* fShader = ""
"#version 330\n"
"out vec4 color;\n"
"void main()\n"
"   color = vec4(1.0, 1.0, 0.0, 1.0);\n"
"\n";

void AddShader(GLuint theProgram, const char* ShaderCode, GLenum shaderType, std::string info)
    std::cerr <<"DEBUG: Adding "<<info<<" Shader"<<std::endl;
    GLuint theShader = glCreateShader(shaderType);

    const GLchar* theCode[1];
    theCode[0] = ShaderCode;

    GLint codeLength[1];
    codeLength[0] = strlen(ShaderCode);

    glShaderSource(theShader, 1, theCode, codeLength);
    glCompileShader(theShader);

    GLint result =0;
    GLchar eLog[1024] =0;

    glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
    if(!result)
        glGetShaderInfoLog(shader, sizeof(eLog), NULL, eLog);
        std::cerr<<"Error compiling program"<<std::endl;
        return;
    
    glAttachShader(theProgram, theShader);



void CompileShader()
    shader = glCreateProgram();
    if(!shader)
        std::cerr<<"Error creating shader"<<std::endl;
        return;
    

    AddShader(shader, vShader, GL_VERTEX_SHADER, "vertex");
    AddShader(shader, fShader, GL_FRAGMENT_SHADER, "fragment");

    GLint result =0;
    GLchar eLog[1024] =0;

    glLinkProgram(shader);
    glGetProgramiv(shader, GL_LINK_STATUS, &result);
    if(!result)
        glGetProgramInfoLog(shader, sizeof(eLog), NULL, eLog);
        std::cerr<<"Error linking program"<<std::endl;
        return;
    

    glValidateProgram(shader);
    glGetProgramiv(shader, GL_VALIDATE_STATUS, &result);
    if(!result)
        glGetProgramInfoLog(shader, sizeof(eLog), NULL, eLog);
        std::cerr<<"Error Validating program"<<std::endl;
        return;
    

    uniformModel = glGetUniformLocation(shader,"model");



void CreateTriangles()
    GLfloat vertices[]=
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        0.0f, 1.0f, 0.0f
    ;

    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*9,vertices, GL_STATIC_DRAW);
        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
        glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);



int main()
    //initialize GLFW
    if(!glfwInit())
        std::cerr << "GLFW initialization failed!" << std::endl;
        glfwTerminate();
        return 1;
    

    //Setup GLFW window properties
    //openGL version
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    // core profile = no backward compatibility
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //allow forward compatibility
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    GLFWwindow *mainWindow = glfwCreateWindow(WIDTH, HEIGHT, "TEST WINDOW", NULL, NULL);

    if(!mainWindow)
        std::cerr << "GLFW Window creation failed" << std::endl;
        glfwTerminate();
        return 1;
    

    // get Buffer size information
    int bufferWidth, bufferHeight;
    glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
    // set context for GLEW to use
    glfwMakeContextCurrent(mainWindow);

    // allow modern extension features

    if(glewInit()!=GLEW_OK)
        std::cerr << "GLEW initialization failed" << std::endl;
        glfwDestroyWindow(mainWindow);
        glfwTerminate();
        return 1;
    

    // setup viewport size
    glViewport(0, 0, bufferWidth, bufferHeight);
    CreateTriangles();
    CompileShader();




    while(!glfwWindowShouldClose(mainWindow))
        // get and handle user input events
        glfwPollEvents();

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

        if(direction)
            triOffset += 0.0005f;
        else
            triOffset -= 0.0005f;
            triOffset = abs(triOffset);
        

        if(direction<=0.0 || direction> triMaxOffset)
            direction = !direction;
        

        glUseProgram(shader);

        glm::mat4 modelMatrix;
        modelMatrix = glm::translate(modelMatrix, glm::vec3(triOffset, 0.0f, 0.0f));
        glUniformMatrix4fv(uniformModel, 1, GL_FALSE,glm::value_ptr(modelMatrix));
            glBindVertexArray(VAO);
                glDrawArrays(GL_TRIANGLES,0,3);
            glBindVertexArray(0);
        glUseProgram(0);
        // swap buffers
        glfwSwapBuffers(mainWindow);
    


    return 0;
  

如何确定问题所在?

【问题讨论】:

modelMatrix; 必须被初始化:glm::mat4 modelMatrix(1.0f); 【参考方案1】:

模型矩阵变量glm::mat4 modelMatrix必须由Identity matrix初始化。

glm API documentation 指的是The OpenGL Shading Language specification。

5.4.2 向量和矩阵构造函数

如果向量构造函数有一个标量参数,它用于将构造向量的所有组件初始化为该标量的值。如果矩阵构造函数只有一个标量参数,则它用于初始化矩阵对角线上的所有分量,其余的 组件初始化为 0.0。

一个Identity matrix可以通过单个参数1.0初始化:

glm::mat4 modelMatrix(1.0f);

【讨论】:

我不知道为什么在教程中这个家伙能够在没有这个初始化的情况下运行,虽然他在 windows 上运行,我在 linux 上运行,但这确实做到了。谢谢。 :-)

以上是关于为 glm 翻译添加统一向量在 OpenGL 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

理解 GLM-openGL 中的相机翻译

C ++ / OpenGL glm无法将矩阵插入着色器中的统一

OpenGL统一名称指针作为字符串[重复]

旋转矩阵未正确应用于向量

子弹物理和 OpenGL 将方向转换为前、上和右

GLM四元数反向偏航