Corrupted Vertex Buffer

Started by
6 comments, last by akaitora 8 years, 7 months ago

Hi! I am trying to render 2 vertex buffers. Each is setup a bit different. The first only has positions whereas the second has both positions and uv coordinates. If I only try to render one, the one I render looks great. It doesn't matter which I render. But if I render both together, both vertex buffer become corrupt. On screen, they both look like triangles even though they are suppose to be quads. When I try making both use the same vertex format, (I.E. verts and uvs) they render correctly. This almost makes me think that they are somehow referencing each other somehow which is breaking the stride. I am not explicitly unbinding my VBOs. According to the OpenGL docs, I shouldn't need to. However even when I do, it causes a crash. Below are the classes for the 2 VBOs in question.

#include "QuadGeometry.h"
 
#include <iostream>
using namespace std;
 
const float QuadGeometry::verts[] =
{
    -1.0f, 1.0f, 0.0f,
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,
    -1.0f, 1.0f, 0.0f,
    1.0, 1.0, 0.0f
};
 
//---------------------------------------------------------------------
void QuadGeometry::Initialize()
{
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
}
 
//---------------------------------------------------------------------
void QuadGeometry::Render()
{
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
}

//---------------------------------------------------------------------
DisplayText::DisplayText()
{
    shaderFx = new ShaderFx();
    shaderFx->Load( "shaders/font/vertex.glsl", "shaders/font/fragment.glsl", true );
    
    vertexBuffer = 0;
    
    textureSurface = nullptr;
    textureSurface = SDL_LoadBMP("assets/textures/ddrsmall.bmp");
    if( !textureSurface )
    {
        cout<< "Failed to Load Texture!\n";
    }
    
    /*
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    
    glTexImage2D(GL_TEXTURE_2D , 0 , 3 , textureSurface->w,
                 textureSurface->h , 0 , GL_RGB , GL_UNSIGNED_BYTE ,
                 textureSurface->pixels);
    
    glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR);
    */
}
 
//---------------------------------------------------------------------
void DisplayText::CreateNewVertexBuffer()
{
    float verts[] =
    {
        //x    //y    //z   //u   //v
        -1.0f,  1.0f,  0.0f, 0.0,  1.0,
        -1.0f, -1.0f,  0.0f, 0.0,  0.0,
         1.0f, -1.0f,  0.0f, 1.0,  0.0,
        -1.0f,  1.0f,  0.0f, 0.0,  1.0,
         1.0f,  1.0f,  0.0f, 1.0,  1.0
    };
    
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
}
 
 
//---------------------------------------------------------------------
void DisplayText::DrawString(std::string string, int x, int y)
{
    if( vertexBuffer <= 0 )
    {
        CreateNewVertexBuffer();
    }
    
    shaderFx->BeginPass();
    
    glm::mat4 Projection = glm::perspective(45.0f, 800.0f/600.0f, 0.1f, 1000.f);
    glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -7.0f));
    glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f));
    glm::mat4 modelViewMat = View * Model;
    
    shaderFx->SetMatrix4x4Parameter("modelViewMatrix", &modelViewMat[0][0]);
    shaderFx->SetMatrix4x4Parameter("projectionMatrix", &Projection[0][0]);
    
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
    
    shaderFx->EndPass();
    
    oldString = string;
}

Any ideas would be helpful! Thanks!

xdpixel.com - Practical Computer Graphics

Advertisement

In one of them, you are binding a shader. In the other, it doesn't look like you are, so the same bound shader is getting used by both of them. If the shader is expecting UVs and positions, and you are only passing it positions, then it might be messing things up.

If you bind one shader, you can't unbind it and expect to be able to render something else correctly without binding a new one.

Good catch! Unfortunately I forgot to mention that I am handing the shader for the QuadGeom in a higher level class like so.

 
void onRenderImage(ApplicationContext &context)
{
    glClearColor(0.0, 0.3, 0, 1);
    glEnable(GL_DEPTH_TEST);
    
    glViewport(0, 0, context.ResolutionWidth, context.ResolutionHeight);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    context.ShaderFx->BeginPass();
    
    context.ShaderFx->SetVector2Parameter("resolution", context.ResolutionWidth, context.ResolutionHeight);
    
    context.ShaderFx->SetFloatParameter("time", context.TimeInSecondsSinceStartup);
    
    
    float mouseX = (float)((context.MouseX - context.WindowPosX)) / context.ResolutionWidth;
    float mouseY = (float)(-(context.MouseY - context.WindowPosY)) / context.ResolutionHeight;
    
    context.ShaderFx->SetVector2Parameter("mouse", mouseX, mouseY);
    
    context.QuadGeo->Render();
    
    context.ShaderFx->EndPass();
    
    glDisable(GL_DEPTH_TEST);
    context.DisplayText->DrawString("", 0, 0);
}
 

Any other ideas? Thanks!

xdpixel.com - Practical Computer Graphics

btw, for my Begin/End shader code, I am doing the following

 
//---------------------------------------------------------------------
void ShaderFx::BeginPass()
{
    glUseProgram(shaderProgram);
    
    if( !modelHasUvs )
    {
        GLint vertexAttribLocation = glGetAttribLocation(shaderProgram, "vertex");
        glEnableVertexAttribArray(vertexAttribLocation);
        glVertexAttribPointer(vertexAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
    }
    else
    {
        
        GLint vertexAttribLocation = glGetAttribLocation(shaderProgram, "vertex");
        glEnableVertexAttribArray(vertexAttribLocation);
        glVertexAttribPointer(vertexAttribLocation, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
        
        GLuint texCoordAttribLocation = glGetAttribLocation(shaderProgram, "uv");
        glEnableVertexAttribArray(texCoordAttribLocation);
        glVertexAttribPointer(texCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));
        
    }
}
 
//---------------------------------------------------------------------
void ShaderFx::EndPass()
{
    GLint vertexAttribLocation = glGetAttribLocation(shaderProgram, "vertex");
    GLuint texCoordAttribLocation = glGetAttribLocation(shaderProgram, "uv");
    
    glDisableVertexAttribArray(vertexAttribLocation);
    glDisableVertexAttribArray(texCoordAttribLocation);
}
 

xdpixel.com - Practical Computer Graphics

Any ideas?

xdpixel.com - Practical Computer Graphics

Nothing stands out to me.

You're saying that if you draw just the Position triangle-pair, it looks fine.

And if you draw just the UV+Position triangle-pair, it looks fine.

Have you tried drawing two Position triangle-pairs in different locations, with no UV+Position pair?

That might help narrow it down.

Someone else might have a better idea.

Your glVertexAttribPointer calls depend on the currently bound buffer object. So you must therefore call glBindBuffer before you call glVertexAttribPointer; you're calling them the in the wrong order so hence things get messed-up.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

mhagain, thanks for the solution! That fixed it! I didn't realized that glVertexAttribPointer required the buffer to be bound before use. Thanks for the heads up!

xdpixel.com - Practical Computer Graphics

This topic is closed to new replies.

Advertisement