Question

In general what I want is to read a specific vbo buffer in a custom way: i have a buffer-> an array of 3 of class Triangle

class Triangle {
public:
    CD_FLOAT3 a;
    CD_FLOAT3 b;
    CD_FLOAT3 c;

    CD_FLOAT3 direction;
    CD_FLOAT velocity;
    CD_FLOAT3 color;
}

This is how i generate the vbo:

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

And what I want from my render function is to render the 3 Vertices of the triangle than to skip for the stride as the sizeof(Triangle) (the next element). So i position the glVertexPointer to the 3 position of the points A,B,C accordingly. I only want one color ont the triangle as well, so i am using one glColorPointer

glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);

glVertexPointer( 3, GL_FLOAT, sizeof(Triangle),  0);
glVertexPointer(3, GL_FLOAT, sizeof(Triangle),  (void*)12);
glVertexPointer(3, GL_FLOAT, sizeof(Triangle),  (void*)24);

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, sizeof(Triangle), (void*)(sizeof(CD_FLOAT)*13));

glDrawArrays(GL_TRIANGLES, 0, numTriangles);
glDisableClientState(GL_COLOR_ARRAY);

The result of this function only draws one triangle, one point per stride, i think that the "glVertexPointer" only repositions the pointer so only the third triangle is drawn.

What i really want to know how can i make the reading of the buffer for the draw of the 3 triangles with:

  1. Triangle1: a; b; c; color; STRIDE:
  2. Triangle2: a; b; c; color; STRIDE
  3. Triangle3: a; b; c; color;
Was it helpful?

Solution

You can't do what you want with fixed-function OpenGL.

Best you can do is duplicate your color attribute information and split off your kinematics state:

class Vertex {
public:
    CD_FLOAT3 pos;
    CD_FLOAT3 color;
};

class State {
public:
    CD_FLOAT3 direction;
    CD_FLOAT velocity;
};

const unsigned int NumTris = ...;
std::vector< State > states( NumTris );
std::vector< Vertex > verts( NumTris * 3 );

PopulateAndBindVBO();

glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), 0 );
glColorPointer( 3, GL_FLOAT, sizeof(Vertex), sizeof(CD_FLOAT3) );
glDrawArrays(GL_TRIANGLES, 0, NumTris );    

You could use a geometry shader to split out an array of your Triangle structs into triangles though:

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <vector>
#include <cstddef>
using namespace std;

#include <glm/glm.hpp>
using namespace glm;

struct Program
{
    static GLuint Load( const char* vert, const char* geom, const char* frag )
    {
        GLuint prog = glCreateProgram();
        if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
        if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
        if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        exit( -1 );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

#define GLSL(version, shader) "#version " #version "\n" #shader

struct Triangle
{
    glm::vec3 a;
    glm::vec3 b;
    glm::vec3 c;
    glm::vec3 color;

    glm::vec3 direction;
    GLfloat velocity;
};


const char* vert = GLSL
(
    330 core,
    layout ( location = 0 ) in vec3 A;
    layout ( location = 1 ) in vec3 B;
    layout ( location = 2 ) in vec3 C;
    layout ( location = 3 ) in vec3 Color;

    out VertToGeom
    {
        vec3 A;
        vec3 B;
        vec3 C;
        vec3 Color;
    } outData;

    void main()
    {
        outData.A = A;
        outData.B = B;
        outData.C = C;
        outData.Color = Color;
    }
);

const char* geom = GLSL
(
    330 core,

    in VertToGeom
    {
        vec3 A;
        vec3 B;
        vec3 C;
        vec3 Color;
    } inData[];

    out GeomToFrag
    {
        vec3 Color;
    } outData;

    layout ( points ) in;
    layout ( triangle_strip, max_vertices = 3 ) out;
    void main()
    {
        gl_Position.xyz = inData[ 0 ].A;
        outData.Color = inData[ 0 ].Color;
        EmitVertex();
        gl_Position.xyz = inData[ 0 ].B;
        outData.Color = inData[ 0 ].Color;
        EmitVertex();
        gl_Position.xyz = inData[ 0 ].C;
        outData.Color = inData[ 0 ].Color;
        EmitVertex();
        EndPrimitive();
    }
);

const char* frag = GLSL
(
    330 core,
    in GeomToFrag
    {
        vec3 Color;
    } inData;

    void main()
    {
        gl_FragColor = vec4( inData.Color, 1.0 );
    }
);

GLuint vbo = 0;
void display()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    static GLuint prog = Program::Load( vert, geom, frag );
    glUseProgram( prog );

    vector< Triangle > tris( 2 );
    tris[0].a = glm::vec3( 0, 0, 0 );
    tris[0].b = glm::vec3( 1, 0, 0 );
    tris[0].c = glm::vec3( 1, 1, 0 );
    tris[0].color = glm::vec3( 1, 0, 0 );
    tris[1].a = glm::vec3( 0, 0, 0 );
    tris[1].b = glm::vec3( -1, 0, 0 );
    tris[1].c = glm::vec3( -1, -1, 0 );
    tris[1].color = glm::vec3( 0, 1, 0 );

    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, sizeof( Triangle ) * tris.size(), &tris[0], GL_STREAM_DRAW );

    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 0 ) );
    glEnableVertexAttribArray( 0 );
    glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 1 ) );
    glEnableVertexAttribArray( 1 );
    glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 2 ) );
    glEnableVertexAttribArray( 2 );
    glVertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 3 ) );
    glEnableVertexAttribArray( 3 );

    glDrawArrays( GL_POINTS, 0, tris.size() );

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    glutInit( &argc, argv );
    glutSetOption( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS );
    glutInitContextVersion( 3, 3 );
    glutInitContextProfile( GLUT_CORE_PROFILE );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );

    glewExperimental = GL_TRUE;
    glewInit();

    GLuint vao = 0;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    glGenBuffers( 1, &vbo );

    glutDisplayFunc( display );
    glutMainLoop();
    return 0;
}

OTHER TIPS

you can try "glVertexAttribPointer" https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml

I think you can store your data like this:

struct vertex
{
    //posision
    float x;
    float y;
    float z;
    //color
    float r;
    float g;
    float b;
}

GLuint buffer;
static const vertex vertices[]={....};
glGenBuffers(1,&buffer);
glBindBuffer(GL_ARRAY_BUFFER,buffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

//set up two vertex attributes---first positions
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(vertex),(void*)offsetof(vertex,x));
glEnableVertexAttribArray(0);
//now colors
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(vertex),(void*)offsetof(vertex,r));
glEnableVertexAttribArray(1);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top