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;
}
Triangle
for each triangle rendered? – legends2kglVertexPointer()
three times? Only the last call beforeglDrawArrays()
will have any effect. – genpfault