2014-04-18 6 views
1

Я успешно настроил шейдер и тестовый треугольник для OpenGL. И я хочу создать униформа преобразования, которая может применяться в вершинном шейдере. Проблема в том, что я больше не вижу свой объект после того, как я умножу свою позицию vec4 на преобразование mat4. Где я делаю что-то не так?Преобразование вершинного шейдера OpenGL, исчезающий объект

Vertex шейдеров:

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

Shader класс:

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

Mesh класса (или, мой объект класса, если вы достаточно назвать):

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

Transform класс:

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

ответ

1

Из кода:

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

GL униформы в программе состоянии, и установление единообразного будет влиять на объект программы в настоящее время связаны. Поскольку у вас нет объекта программы, связанного в то время, когда вы пытаетесь установить униформу, униформа остается в состоянии по умолчанию (все нули). Просто переключите эти две строки ...

+0

@AleksanderFimreite: существует также 'glProgramUniform4fv (...)', который начал жизнь в расширении Direct State Access, но стал ядром, когда делали отдельные шейдерные объекты (GL 4.1) и делает не требуется привязывать программу для установки униформы. Поскольку вы используете GLSL 1.20, можно с уверенностью предположить, что у вас есть доступ к ни одной из этих вещей. Вы можете серьезно подумать о переименовании своего класса 'Program' или' ShaderProgram' вместо 'Shader', так как это действительно так. У вас даже есть переменная-член, называемая 'm_shaders', которая указывает, что класс не является шейдером, а содержит шейдеры. –

Смежные вопросы