2013-09-07 60 views
5

Ok, vì vậy tôi có thể tải một mô hình cơ bản với các đỉnh, tọa độ kết cấu và các tiêu chuẩn và hiển thị nó mà không có vấn đề.Gửi dữ liệu xương tới bóng đổ bóng mờ

Tuy nhiên, khi tôi thử ném một số thông tin về xương, dữ liệu xương dường như bị hỏng (hoặc cái gì đó?) Khi tôi thử và thao tác nó trong trình đổ bóng.

Dưới đây là mã của tôi để tải và render dữ liệu vào OpenGL (thiết lập các shader và gửi ma trận điểm, ma trận trên thế giới, vv được thực hiện trong lớp khác):

/* 
* 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_; 
} 
} 
} 

đổ bóng thực sự của tôi là thế này:

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

Nếu bug = 1.0, thì các đỉnh có màu đỏ và nếu but = 2.0 thì các đỉnh có màu xanh lục. Tôi thấy tất cả các đỉnh có màu đỏ ngay bây giờ, có nghĩa là sum lớn hơn 1.5f.

Tôi đã xác nhận rằng tổng của mỗi tập trọng số thực tế là <= 1.0f ... vậy làm thế nào trên thế giới này không phải là trường hợp trong trình đổ bóng?

Bất cứ ai nhìn thấy bất cứ điều gì rõ ràng tôi đang thiếu?

EDIT: Hình như tôi thấy vấn đề - Tôi đã không gọi glBindAttribLocation trên bất kỳ in biến của tôi - sau khi thêm:

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

mã shader tải của tôi, nó hoạt động tốt. Điều kỳ lạ là - Tôi không phải làm điều này cho 3 đầu tiên (vị trí, kết cấu và màu sắc) và nó hoạt động tốt. Nhưng khi tôi thêm thông tin về xương, tôi đột nhiên cần điều này ... tại sao?

Trả lời

3

Bạn cần sử dụng glVertexAttribIPointer (...) để cung cấp dữ liệu cho thuộc tính vertex ivec<N>. Nếu bạn nghĩ rằng bạn đang gặp phải "tham nhũng" trước khi thiết lập các vị trí thuộc tính, chỉ cần đợi cho đến khi bạn viết mã trong trình đổ bóng thực sự cần ID xương ... Các giá trị này sẽ vô nghĩa vì bạn đang sử dụng lệnh gọi API sai để liên kết thuộc tính của bạn dữ liệu có vị trí ràng buộc cụ thể.

Biến thể glVertexAttribPointer (...) không gặp sự cố khi chọn loại dữ liệu GL_INT, nhưng nó sẽ chuyển đổi thành dấu phẩy động (và có thể chuẩn hóa giá trị điểm cố định trong quá trình, do đó tham số bổ sung). Do đó, biến thể này dự kiến ​​sẽ cung cấp dữ liệu cho thuộc tính đỉnh vec<N>, không phải là ivec<N>.

Chính xác hơn, sử dụng glVertexAttribIPointer cho thuộc tính đỉnh số nguyên và glVertexAttribPointer cho dấu phẩy động.

+0

Đó là nó - sau khi làm điều đó tôi có thể loại bỏ các 'glBindAttribLocation' cuộc gọi là tốt. Tôi bây giờ có hoạt hình hoạt động! (đến một mức độ - nó dường như biến mất ở những nơi, vì vậy tôi nghĩ rằng các normals có thể nhận được messed up.). Cảm ơn @Andon! – Jarrett

Các vấn đề liên quan