2013-09-07 8 views
5

Ok, ich kann also ein Basismodell mit Vertices, Texturkoordinaten und Normalen laden und es ohne Probleme rendern.Senden von Bone-Daten an den Glsl-Shader

Wenn ich jedoch einige Knocheninformationen einwerfe, scheinen die Knochendaten beschädigt zu sein (oder etwas?), Wenn ich versuche, sie im Shader zu manipulieren.

Hier ist mein Code für das Laden und die Daten in opengl Rendering (Einstellung der Shader und Senden der Ansicht Matrix, Welt Matrix, etc. werden in einer anderen Klasse durchgeführt):

/* 
* Mesh.cpp 
* 
* Created on: 2011-05-08 
*  Author: jarrett 
*/ 

#include <boost/log/trivial.hpp> 

#include "../common/utilities/AssImpUtilities.h" 

#include "Mesh.h" 

namespace glr { 
namespace glw { 
Mesh::Mesh(IOpenGlDevice* openGlDevice, 
     const std::string path, 
     std::vector<glm::vec3> vertices, 
     std::vector<glm::vec3> normals, 
     std::vector<glm::vec2> textureCoordinates, 
     std::vector<glm::vec4> colors, 
     std::vector<VertexBoneData > bones, 
     BoneData boneData) 
    : openGlDevice_(openGlDevice), vertices_(vertices), normals_(normals), textureCoordinates_(textureCoordinates), colors_(colors), bones_(bones), boneData_(boneData) 
{ 
    BOOST_LOG_TRIVIAL(debug) << "loading mesh into video memory..."; 

    // create our vao 
    glGenVertexArrays(1, &vaoId_); 
    glBindVertexArray(vaoId_); 

    // create our vbos 
    glGenBuffers(5, &vboIds_[0]); 

    glBindBuffer(GL_ARRAY_BUFFER, vboIds_[0]); 
    glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(glm::vec3), &vertices_[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, vboIds_[1]); 
    glBufferData(GL_ARRAY_BUFFER, textureCoordinates_.size() * sizeof(glm::vec2), &textureCoordinates_[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, vboIds_[2]); 
    glBufferData(GL_ARRAY_BUFFER, normals_.size() * sizeof(glm::vec3), &normals_[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    std::cout << "SIZE: " << vertices_.size() << " " << sizeof(glm::ivec4) << " " << bones_.size() << " " << sizeof(VertexBoneData) << std::endl; 

    // Convert data into simple vectors, then send to OpenGL 
    std::vector<glm::ivec4> boneIds = std::vector<glm::ivec4>(); 
    std::vector<glm::vec4> weights = std::vector<glm::vec4>(); 

    for (VertexBoneData& d : bones_) 
    { 
     boneIds.push_back(d.boneIds); 
     weights.push_back(d.weights); 
    } 

    glBindBuffer(GL_ARRAY_BUFFER, vboIds_[3]); 
    glBufferData(GL_ARRAY_BUFFER, boneIds.size() * sizeof(glm::ivec4), &boneIds[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(3); 
    glVertexAttribPointer(3, 4, GL_INT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, vboIds_[4]); 
    glBufferData(GL_ARRAY_BUFFER, weights.size() * sizeof(glm::vec4), &weights[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(4); 
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 0, 0); 

    // Disable our Vertex Array Object 
    //glEnableVertexAttribArray(0); 
    // Disable our Vertex Buffer Object 
    glBindVertexArray(0); 

    GlError err = openGlDevice_->getGlError(); 
    if (err.type != GL_NONE) 
    { 
     // TODO: throw error 
     BOOST_LOG_TRIVIAL(error) << "Error loading mesh in opengl"; 
     BOOST_LOG_TRIVIAL(error) << "OpenGL error: " << err.name; 
    } 
    else 
    { 
     BOOST_LOG_TRIVIAL(debug) << "Successfully loaded mesh."; 
    } 
} 

Mesh::~Mesh() 
{ 
} 

void Mesh::render() 
{ 
    glBindVertexArray(vaoId_); 

    glDrawArrays(GL_TRIANGLES, 0, vertices_.size()); 

    glBindVertexArray(0); 
} 

BoneData& Mesh::getBoneData() 
{ 
    return boneData_; 
} 
} 
} 

Meine eigentliche Shader ist dies:

#version 150 core 

struct Light { 
    vec4 ambient; 
    vec4 diffuse; 
    vec4 specular; 
    vec4 position; 
    vec4 direction; 
}; 


in vec3 in_Position; 
in vec2 in_Texture; 
in vec3 in_Normal; 
in ivec4 in_BoneIds; 
in vec4 in_BoneWeights; 

out vec2 textureCoord; 
out vec3 normalDirection; 
out vec3 lightDirection; 
out float bug; 

layout(std140) uniform Lights 
{ 
    Light lights[ 1 ]; 
}; 

void main() {   
    gl_Position = pvmMatrix * vec4(in_Position, 1.0); 

    vec4 lightDirTemp = viewMatrix * lights[0].direction; 

    textureCoord = in_Texture; 

    //vec4 normalDirTemp = boneTransform * vec4(in_Normal, 1.0); 
    //normalDirection = normalize(normalMatrix * normalDirTemp.xyz); 
    normalDirection = normalize(normalMatrix * in_Normal); 

    lightDirection = normalize(vec3(lightDirTemp)); 



    // If we have any bugs, should highlight the vertex red or green 
    bug = 0.0; 
    float sum = in_BoneWeights[0] + in_BoneWeights[1] + in_BoneWeights[2] + in_BoneWeights[3]; 
    if (sum > 1.5f) 
     bug = 1.0; 
    else if (sum < 0.95f) 
     bug = 2.0; 
    // disable bug highlighting 
    //bug = 0.0;   
} 

wenn bug = 1.0, dann werden die Eckpunkte rot gefärbt, und wenn but = 2.0, dann sind die Eckpunkte grün gefärbt. Ich sehe, dass alle Vertices gerade rot gefärbt sind, was bedeutet, dass sum größer ist als 1.5f.

Ich habe bestätigt, dass die Summe der einzelnen Gewichte in der Tat ist <= 1.0f ... so wie in der Welt ist dies nicht der Fall in den Shader?

Wer sieht etwas offensichtlich Ich vermisse?

EDIT: Sieht aus wie ich das Problem gefunden - ich glBindAttribLocation auf keinem meiner in Variablen nicht anrief - nach Zugabe:

glBindAttribLocation(programId_, 0, "in_Position"); 
    glBindAttribLocation(programId_, 1, "in_Texture"); 
    glBindAttribLocation(programId_, 2, "in_Color"); 
    glBindAttribLocation(programId_, 3, "in_BoneIds"); 
    glBindAttribLocation(programId_, 4, "in_BoneWeights"); 

meinem Shader-Laden-Code, es funktioniert gut. Sonderbare Sache ist - ich musste dies nicht für die ersten 3 (Position, Textur und Farbe) tun, und es hat gut funktioniert. Aber als ich die Knocheninformation hinzugefügt habe, brauche ich das plötzlich ... warum?

Antwort

3

Sie müssen glVertexAttribIPointer (...) verwenden, um Daten an ein Vertex-Attribut ivec<N> zu übergeben. Wenn Sie dachten, dass Sie "Korruption" vor dem Festlegen der Attributpositionen hatten, warten Sie einfach, bis Sie Code in Ihren Shader schreiben, der tatsächlich die Bone IDs benötigt ... Diese Werte sind bedeutungslos, da Sie den falschen API-Aufruf verwenden, um Ihr Attribut zuzuordnen Daten mit einem bestimmten Bindungsort.

Die glVertexAttribPointer (...) Variante hat keine Probleme bei der Übernahme eines GL_INT Datentyps, aber es wird in Fließkommawerte umgewandelt (und es kann Festkommawerte im Prozess normalisieren, daher der zusätzliche Parameter). Daher wird erwartet, dass diese Variante die Daten an ein Vertex-Attribut liefert, nicht ivec<N>.

Genauer gesagt, verwenden Sie glVertexAttribIPointer für Integer-Vertex-Attribute und glVertexAttribPointer für Fließkomma.

+0

Das war es - nachdem ich das getan hatte, konnte ich auch die 'glBindAttribLocation' Aufrufe entfernen. Ich habe jetzt Animation funktioniert! (zu einem gewissen Grad - es scheint an einigen Stellen zu verschwinden, also denke ich, dass die Normalen durcheinander kommen könnten.). Danke @Andon! – Jarrett

Verwandte Themen