2016-01-28 32 views
0

我试图用一个简单的弹簧质量系统的动画开始学习现代openGL的。OpenGL的:两个顶点数组+双数组索引

我已经在我的课弹簧和质量,每次使用索引阵列中得出,当我这样做无论是单独他们都很好地工作。当我将两者都画在一起时,顶点位置都是错误的。我猜测它与我如何对顶点缓冲区和索引数组进行编号有关,但我不明白内部工作足以解决问题。

#include "Spring.hpp" 
#include "ShaderPaths.hpp" 
#include "atlas\gl\Shader.hpp" 
#include "atlas\core\Macros.hpp" 
#include <atlas/utils/Geometry.hpp> 
const int NUM_VERTICES_PER_LINE = 3; 
const int NUMFLOATSPERVERTICES = 6; 
const int VERTEX_BYTE_SIZE = NUMFLOATSPERVERTICES * sizeof(float); 
GLint numSpringIndices, numMassIndices; 
#define NUM_ARRAY_ELEMENTS(a) sizeof(a)/sizeof(*a); 
Spring::Spring() : anchorPosition{ 0.0f, 1.0f, 0.0f }, mPosition{0.0f, 0.0f, 0.0f} { 
    USING_ATLAS_GL_NS; //Short for atlas GL namespace 
    USING_ATLAS_MATH_NS; 
    glGenVertexArrays(1, &mVertexArrayObject); 
    glBindVertexArray(mVertexArrayObject); 


    ShapeData Spring = ObjectGenerator::makeSpring(anchorPosition, stretch, d); 
    ShapeData Mass = ObjectGenerator::makeMass(calculateConnectionPoint(anchorPosition), massWidth, massHeight); 
    ShapeData Triangle = ObjectGenerator::makeTriangle(); 
    numSpringIndices = Spring.numIndices; 
    numMassIndices = Mass.numIndices; 
    //======= Spring Buffer ======// 
    glGenBuffers(1, &mSpringBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, mSpringBuffer); 
    glBufferData(GL_ARRAY_BUFFER, Spring.vertexBufferSize(), Spring.vertices, GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0); 
    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3)); 
    glGenBuffers(1, &springIndexBufferID); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, springIndexBufferID); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, Spring.indexBufferSize(), Spring.indices, GL_STATIC_DRAW); 

    //======= Mass Buffer ======// 
    glGenBuffers(1, &mMassBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, mMassBuffer); 
    glBufferData(GL_ARRAY_BUFFER, Mass.vertexBufferSize(), Mass.vertices, GL_STATIC_DRAW); 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0); 
    glEnableVertexAttribArray(3); 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3)); 
    glGenBuffers(1, &massIndexBuffer); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, massIndexBuffer); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, Mass.indexBufferSize(), Mass.indices, GL_STATIC_DRAW); 

    //======= Shaders ======// 
    std::string shaderDir = generated::ShaderPaths::getShaderDirectory(); 
    std::vector<ShaderInfo> springShaders 
    { 
     ShaderInfo{ GL_VERTEX_SHADER, shaderDir + "Spring.vs.glsl" }, 
     ShaderInfo{ GL_FRAGMENT_SHADER, shaderDir + "Spring.fs.glsl" } 
    }; 
    mShaders.push_back(ShaderPointer(new Shader)); 
    mShaders[0]->compileShaders(springShaders); 
    mShaders[0]->linkShaders(); 

    //===== Clean ups to prevent memory leaks =====// 
    Spring.cleanup(); 
    Mass.cleanup(); 
} 

Spring::~Spring() 
{ 
    glDeleteVertexArrays(1, &mVertexArrayObject); 
    glDeleteBuffers(1, &mSpringBuffer); 
} 

void Spring::renderGeometry(atlas::math::Matrix4 projection, atlas::math::Matrix4 view) { 
    // To avoid warnings from unused variables, you can use the 
    //UNUSED macro. 
    UNUSED(projection); 
    UNUSED(view); 
    mShaders[0]->enableShaders(); 
    glBindVertexArray(mVertexArrayObject); 
    GLint dominatingColorUniformLocation = mShaders[0]->getUniformVariable("dominatingColor"); 
    //========== Draw Spring ===============// 
    glm::vec3 springColor(0.0f, 1.0f, 0.0f); 
    glUniform3fv(dominatingColorUniformLocation, 1, &springColor[0]); //Send the location of the first float 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, springIndexBufferID); 
    glDrawElements(GL_LINES, numSpringIndices, GL_UNSIGNED_SHORT, 0); 
    //======================================// 

    //========= Draw Mass =================// 
    glm::vec3 massColor(1.0f, 0.0f, 0.0f); 
    glUniform3fv(dominatingColorUniformLocation, 1, &massColor[0]); //Send the location of the first float 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, massIndexBuffer); 
    glDrawElements(GL_TRIANGLES, numMassIndices, GL_UNSIGNED_SHORT, 0); 
    //======================================// 
    mShaders[0]->disableShaders(); 
} 
void Spring::updateGeometry(atlas::utils::Time const& t) { 
    mModel = glm::translate(Matrix4(1.0f), mPosition); 
} 

glm::vec3 Spring::calculateConnectionPoint(glm::vec3 anchorPosition) { 
    glm::vec3 temp = glm::vec3(anchorPosition.x, anchorPosition.y - (18 * d), 0.0f); 
    return temp; 
} 

的ObjectGenerator类看起来像这样任何好奇

#include "ObjectGenerator.h" 
#define NUM_ARRAY_ELEMENTS(a) sizeof(a)/sizeof(*a); 

ShapeData ObjectGenerator::makeSpring(glm::vec3 anchorPosition, GLfloat stretch, GLfloat d) { 
    ShapeData ret; 
    static const Vertex vertices[] = { 
     glm::vec3(anchorPosition.x, anchorPosition.y, 0.0f), // 0 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x, anchorPosition.y - d,0.0f), // 1 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (2 * d), 0.0f), // 2 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (4 * d), 0.0f), // 3 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (6 * d), 0.0f), // 4 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (8 * d), 0.0f), // 5 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (10 * d), 0.0f), // 6 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (12 * d), 0.0f), // 7 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (14 * d), 0.0f), // 8 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (16 * d), 0.0f), // 9 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x, anchorPosition.y - (17 * d), 0.0f), // 10 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
     glm::vec3(anchorPosition.x, anchorPosition.y - (18 * d), 0.0f), // 11 
     glm::vec3(1.0f, 0.0f, 0.0f), // Spring Color 
    }; 
    ret.numVertices = NUM_ARRAY_ELEMENTS(vertices); 
    ret.vertices = new Vertex[ret.numVertices]; 
    memcpy(ret.vertices, vertices, sizeof(vertices)); //memcpy(dest, source, size); 

    GLushort indices[] = { 0,1 ,1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11 }; 
    ret.numIndices = NUM_ARRAY_ELEMENTS(indices); 
    ret.indices = new GLushort[ret.numIndices]; 
    memcpy(ret.indices, indices, sizeof(indices)); 

    return ret; 
} 

ShapeData ObjectGenerator::makeMass(glm::vec3 connectionPoint, GLfloat width, GLfloat height) { 
    ShapeData ret; 
    static const Vertex vertices[] = { 
     //=================Mass==============// 
     glm::vec3(connectionPoint.x - width, connectionPoint.y, 0.0f), //top Left 0 
     glm::vec3(0.0f, 1.0f, 0.0f), // Mass Color 
     glm::vec3(connectionPoint.x + width, connectionPoint.y, 0.0f), //top Right 1 
     glm::vec3(0.0f, 1.0f, 0.0f), // Mass Color 
     glm::vec3(connectionPoint.x + width, connectionPoint.y - height, 0.0f), // bottom right 2 
     glm::vec3(0.0f, 1.0f, 0.0f), // Mass Color 
     glm::vec3(connectionPoint.x - width, connectionPoint.y - height, 0.0f), // bottom left 3 
     glm::vec3(0.0f, 1.0f, 0.0f), // Mass Color 

    }; 
    ret.numVertices = NUM_ARRAY_ELEMENTS(vertices); 
    ret.vertices = new Vertex[ret.numVertices]; 
    memcpy(ret.vertices, vertices, sizeof(vertices)); //memcpy(dest, source, size); 

    GLushort indices[] = {0,1,3, 1,2,3 }; 
    ret.numIndices = NUM_ARRAY_ELEMENTS(indices); 
    ret.indices = new GLushort[ret.numIndices]; 
    memcpy(ret.indices, indices, sizeof(indices)); 

    return ret; 
} 
+0

您是否使用核心OpenGL配置文件? –

+0

你是什么意思,当你一起画画时? – immibis

+0

如果你看我的renderGeometry,我试图绘制弹簧和质量(质量只是一个矩形)。现在,由注释“Draw Spring”和“Draw Mass”强调的部分未被注释,以及构造函数中相应的缓冲区初始化器。这意味着这两个对象正在绘制。如果我注释掉renderGeometry方法中的“Draw Spring”部分和构造函数中的“Spring Buffer”部分,则只会绘制出按预期工作的质量。同样的,当我做相反的事情时,春天会像预期的那样呈现。 – nhoughto

回答

2

有一对夫妇在你的代码相当基本的问题,这似乎是基于一种误解OpenGL的状态管理是如何工作的,以及不同类型的对象是如何连接。

来说明你的代码的一个基本问题,最明显的方法是这样的顺序在你的代码(有部分略):

//======= Spring Buffer ======// 
... 
glBindBuffer(GL_ARRAY_BUFFER, mSpringBuffer); 
... 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0); 

//======= Mass Buffer ======// 
... 
glBindBuffer(GL_ARRAY_BUFFER, mMassBuffer); 
... 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0); 

如果你看一下这两个glVertexAttribPointer()电话,他们都设置相同的顶点属性(0)。既然他们都设置了相同的状态,那么第二个“胜利”,将覆盖您在第一次调用时设置的状态。在调用的参数是相同的,但glVertexAttribPointer()也隐含地拿起当前绑定GL_ARRAY_BUFFER,该数据将从采购。其结果是,属性0将使用的数据来自mMassBuffer从未mSpringBuffer

解决这一问题,最好的方法是使用两个顶点数组对象(VAOs)。 VAO跟踪glVertexAttribPointer()设置的状态。所以如果你使用两个不同的VAO,其中一个可以跟踪春季所用的状态,一个用于质量的状态。删除当前VAO创建/绑定代码之后,这样做:

//======= Spring Buffer ======// 
glGenVertexArrays(1, &mSpringVao); 
glBindVertexArray(mSpringVao); 
... 

//======= Spring Buffer ======// 
glGenVertexArrays(1, &mMassVao); 
glBindVertexArray(mMassVao); 
... 

然后,在抽奖代码,您不必再绑定任何缓冲,因为所有的状态设置为属性在被跟踪对应的VAO。相反,每个绘图调用之前,结合相应的VAO:

glBindVertexArray(mSpringVao); 
glDrawElements(GL_LINES, numSpringIndices, GL_UNSIGNED_SHORT, 0); 

glBindVertexArray(mMassVao); 
glDrawElements(GL_LINES, numMassIndices, GL_UNSIGNED_SHORT, 0); 

当然,你仍然需要设置制服等

有一个在这里设置代码的另一个小而重要的问题:

glEnableVertexAttribArray(2); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0); 
glEnableVertexAttribArray(3); 
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3)); 

两个glEnableVertexAttribArray()调用的值是错在这里。他们需要匹配所有其他调用中使用的顶点属性的位置:

glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0); 
glEnableVertexAttribArray(1); 
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3)); 
0

的代码似乎不具有约束力ARRAY_BUFFER,设置相应的ELEMENT_ARRAY_BUFFER绘制之前。恩,下面是有缺失的

glBindBuffer(GL_ARRAY_BUFFER, mMassBuffer);