c++ - OpenGL 顶点着色器变换,对象消失

标签 c++ opengl transform vertex-shader

我已经成功地为 OpenGL 设置了着色器和测试三角形。我想设置一个可以在顶点着色器中应用的转换制服。问题是,在我将 vec4 位置与 mat4 变换相乘后,我再也看不到我的对象了。我哪里做错了什么?

顶点着色器:

#version 120

attribute vec3 vertices;
attribute vec3 colors;
attribute vec2 texCoords;

uniform mat4 transform;

varying vec3 shared_colors;
varying vec2 shared_texCoords;

void main() {
    gl_Position = transform * vec4(vertices, 1.0);

    //Send data to fragment shader
    shared_colors = colors;
    shared_texCoords = texCoords;
}

片段着色器:

#version 120

uniform sampler2D diffuse;

varying vec3 shared_colors;
varying vec2 shared_texCoords;

void main() {
    gl_FragColor = vec4(shared_colors, 1);
    //gl_FragColor = texture2D(diffuse, shared_texCoords); //vec4(1, 0, 0, 1);
}

着色器类:

#include "Shader.h"



Shader::Shader(string fileName) {
    m_program = glCreateProgram();
    m_shaders[SHA_VERTEX] = createShader(loadShader(fileName + ".vs"), GL_VERTEX_SHADER);
    m_shaders[SHA_FRAGMENT] = createShader(loadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);

    for (int i = 0; i < SHA_COUNT; i++) {
        glAttachShader(m_program, m_shaders[i]);
    }

    glBindAttribLocation(m_program, VBO_VERTEX, "vertices");
    glBindAttribLocation(m_program, VBO_COLOR, "colors");
    glBindAttribLocation(m_program, VBO_TEXCORD, "texCoords");

    glLinkProgram(m_program);
    checkShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");

    glValidateProgram(m_program);
    checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");

    m_uniforms[UNI_TRANSFORM] = glGetUniformLocation(m_program, "transform");
}

Shader::~Shader() {
    for (int i = 0; i < SHA_COUNT; i++) {
        glDetachShader(m_program, m_shaders[i]);
        glDeleteShader(m_shaders[i]);
    }

    glDeleteProgram(m_program);
}

string Shader::loadShader(string filePath) {
    ifstream file;
    file.open((filePath).c_str());

    string output;
    string line;

    if(file.is_open()) {
        while(file.good()) {
            getline(file, line);
            output.append(line + "\n");
        }
    }
    else {
        printf("Unable to load shader: %s\n", filePath.c_str());
    }

    return output;
}

void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, string errorMessage) {
    GLint success = 0;
    GLchar error[1024] = {0};

    if (isProgram) {
        glGetProgramiv(shader, flag, &success);
    }
    else {
        glGetShaderiv(shader, flag, &success);
    }

    if (success == GL_FALSE) {
        if(isProgram) {
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        }
        else {
            glGetShaderInfoLog(shader, sizeof(error), NULL, error);
        }

        printf("%s: '%s'\n", errorMessage.c_str(), error);
    }
}

GLuint Shader::createShader(string text, unsigned int type) {
    GLuint shader = glCreateShader(type);
    if (shader == 0) {
        printf("Error compiling shader type %i\n", type);
    }

    const GLchar *p[1];
    p[0] = text.c_str();
    GLint lengths[1];
    lengths[0] = text.length();

    glShaderSource(shader, 1, p, lengths);
    glCompileShader(shader);

    checkShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!");

    return shader;
}

void Shader::update(Transform *matrix) {
    glm::mat4 model = matrix->getModel();
    glUniformMatrix4fv(m_uniforms[UNI_TRANSFORM], 1, GL_FALSE, &model[0][0]);
}

void Shader::enable(bool state) {
    if (state) {
        glUseProgram(m_program);
    }
    else {
        glUseProgram(NULL);
    }
}

网格类(或者,如果你更愿意称之为我的对象类):

#include "Mesh.h"



Mesh::Mesh() {
    initMesh();
}

Mesh::Mesh(ObjectData *obj) {
    initMesh();

    //Set object to parameter
    object = obj;
    initVBO();
}

Mesh::~Mesh() {
    delete transform;

    //Delete buffer
    glDeleteBuffers(VBO_COUNT, buffers);

    //Delete array
    glDeleteVertexArrays(1, &arrayObject);
}

void Mesh::draw() {
    if (initialized) {
        shader->update(transform);
        shader->enable(true);
        texture->enable(true);

        //Tell OpenGL which array to use
        glBindVertexArray(arrayObject);

        glDrawArrays(GL_TRIANGLES, 0, object->vertices.size());

        glBindVertexArray(NULL);
        shader->enable(false);
        texture->enable(false);
    }
}

void Mesh::initMesh() {
    initialized = false;
    shader = new Shader(DIR_SHADERS + "BasicShader");
    transform = new Transform();
}

void Mesh::initVBO() {
    glGenVertexArrays(1, &arrayObject);

    //Tell OpenGL which vertex array to use from now
    glBindVertexArray(arrayObject);

    glGenBuffers(VBO_COUNT, buffers);

    //Set buffer data
    glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);

    //Set shader attribute data
    glEnableVertexAttribArray(VBO_VERTEX);
    glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);

    //Set buffer data
    glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_COLOR]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->colors.size(), &object->colors.front(), GL_STATIC_DRAW);

    //Set shader attribute data
    glEnableVertexAttribArray(VBO_COLOR);
    glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL);

    if (object->texCoords.size()) {
        //Set buffer data
        glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);

        //Set shader attribute data
        glEnableVertexAttribArray(VBO_TEXCORD);
        glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
    }

    //Unbind vertex array
    glBindVertexArray(NULL);
    initialized = true;
}

void Mesh::updateVBO() {
    //Tell OpenGL which vertex array to use from now
    glBindVertexArray(arrayObject);

    //Set buffer data
    glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);

    //Set shader attribute data
    glEnableVertexAttribArray(VBO_VERTEX);
    glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);

    //Set buffer data
    glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_COLOR]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->colors.size(), &object->colors.front(), GL_STATIC_DRAW);

    //Set shader attribute data
    glEnableVertexAttribArray(VBO_COLOR);
    glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL);

    if (object->texCoords.size()) {
        //Set buffer data
        glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);

        //Set shader attribute data
        glEnableVertexAttribArray(VBO_TEXCORD);
        glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
    }

    //Unbind vertex array
    glBindVertexArray(NULL);
}

void Mesh::setShader(string file) {
    shader = new Shader(file);
}

void Mesh::setTexture(string file) {
    texture = new Texture(file);
}

void Mesh::loadObject(string file) {
    //Example object
    object = new ObjectData();

    object->vertices.push_back(glm::vec3(-0.5, -0.5, 0));
    object->vertices.push_back(glm::vec3(0, 0.5, 0));
    object->vertices.push_back(glm::vec3(0.5, -0.5, 0));
    //object->texCoords.push_back(glm::vec2(0, 0));
    //object->texCoords.push_back(glm::vec2(0.5, 1));
    //object->texCoords.push_back(glm::vec2(1, 0));
    object->colors.push_back(glm::vec3(255, 0, 0));
    object->colors.push_back(glm::vec3(255, 0, 0));
    object->colors.push_back(glm::vec3(255, 0, 0));

    //object->vertices.push_back(glm::vec3(0.5, 0.5, 0));
    //object->vertices.push_back(glm::vec3(0.75, 1, 0));
    //object->vertices.push_back(glm::vec3(1, 0.5, 0));
    //object->texCoords.push_back(glm::vec2(0, 0));
    //object->texCoords.push_back(glm::vec2(0.5, 1));
    //object->texCoords.push_back(glm::vec2(1, 0));
    //object->colors.push_back(glm::vec3(0, 255, 0));
    //object->colors.push_back(glm::vec3(0, 255, 0));
    //object->colors.push_back(glm::vec3(0, 255, 0));

    if (initialized) {
        updateVBO();
    }
    else {
        initVBO();
    }
}

转换类:

#include "Transform.h"



Transform::Transform() {
    position = glm::vec3();
    rotation = glm::vec3();
    scale = glm::vec3(1, 1, 1);
}

Transform::~Transform() {

}

void Transform::setPosition(glm::vec3 pos) {
    position = pos;
}

void Transform::setRotation(glm::vec3 rot) {
    rotation = rot;
}

void Transform::setScale(glm::vec3 sca) {
    scale = sca;
}

glm::vec3 Transform::getPosition() {
    return position;
}

glm::vec3 Transform::getRotation() {
    return rotation;
}

glm::vec3 Transform::getScale() {
    return scale;
}

glm::mat4 Transform::getModel() {
    glm::mat4 pos = glm::translate(position);
    glm::mat4 rotX = glm::rotate(rotation.x, glm::vec3(1, 0, 0));
    glm::mat4 rotY = glm::rotate(rotation.y, glm::vec3(0, 1, 0));
    glm::mat4 rotZ = glm::rotate(rotation.z, glm::vec3(0, 0, 1));
    glm::mat4 sca = glm::scale(scale);

    glm::mat4 rot = rotZ * rotY * rotX;
    glm::mat4 finalMatrix = pos * rot * sca;

    return finalMatrix;
}

最佳答案

来自您的代码:

void Mesh::draw() {
    if (initialized) {
        shader->update(transform);
        shader->enable(true);

GL 制服是每个程序 状态,设置制服会影响当前绑定(bind) 程序对象。由于您在尝试设置制服时没有绑定(bind)程序对象,因此制服处于默认状态(全为零)。只需切换这两行...

关于c++ - OpenGL 顶点着色器变换,对象消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23163683/

相关文章:

android - 在 Android 上裁剪图像的透视变换

c++ - lower_bound(v.begin(), v.end(), x)

Java CryptUnprotectData Windows WiFi 密码

html - firefox 的 3d 变换中的口吃/闪烁

c++ - 在 OpenGL 中旋转一个对象在它自己的轴上

c++ - 标识符 "in"未定义

javascript - 非 webkit 浏览器,旋转 div 中相邻图像之间的间隙

C++ 函数需要 size_t 参数

c++ - 复制赋值运算符不起作用

c++ - OpenGL 的图形伪像?