I recently wrote the program displayed below to play around with transform feedback under GL 3.3. Unfortunately it doesn’t work and a weekend of searching the web + the forums didn’t deliver much useful information.
In the program below, the lines commented with “/* feedback */” contain a call to glDrawArrays which appears to generate an invalid value error, despite not matching any of the conditions for such an error in the man-page of glBeginTransformFeedback(no geometry shader, same primitive mode).
I appreciate any help, but please don’t comment on me dropping references to objects and not doing any cleanups. It is just for playing around and I didn’t want to clutter the code with cleanups.
The test program itself:
#include "OpenGL.h"
#include "window.h"
#include "matrix.h"
#include "tools.h"
#include <stdio.h>
#include <stdlib.h>
#define WIDTH 800
#define HEIGHT 600
#define NUM_PARTICLES 100
GLfloat initial_particles[ NUM_PARTICLES*8 ];
const char* vars[] = { "gl_Position", "velocity" };
void generate_initial_particles( );
int main( void )
{
char *vert_source, *frag_source;
GLfloat matrix[16];
GLuint vao, vbo[2];
GLuint vertex_shader, fragment_shader;
GLuint feedback_program, draw_program;
GLuint uniform_projection, uniform_modelview;
/********************* window initialisation *********************/
window_init( );
if( !window_open( WIDTH, HEIGHT, 0, GL_FALSE ) )
return -1;
window_set_vsync( GL_TRUE );
/********************* OpenGL initialisation *********************/
glViewport( 0, 0, WIDTH, HEIGHT );
/* VBOs & VAO */
generate_initial_particles( );
glGenVertexArrays( 1, &vao );
glGenBuffers( 2, vbo );
glBindVertexArray( vao );
glBindBuffer( GL_ARRAY_BUFFER, vbo[1] );
glBufferData( GL_ARRAY_BUFFER, NUM_PARTICLES*8*sizeof(GLfloat),
NULL, GL_STREAM_COPY );
glBindBuffer( GL_ARRAY_BUFFER, vbo[0] );
glBufferData( GL_ARRAY_BUFFER, NUM_PARTICLES*8*sizeof(GLfloat),
initial_particles, GL_STREAM_COPY );
glEnableVertexAttribArray( 0 ); /* position */
glEnableVertexAttribArray( 1 ); /* velocity */
glVertexAttribPointer( 0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, 0 );
glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8,
(GLvoid*)(sizeof(GLfloat)*4) );
/* feedback program */
vert_source = load_file_into_string( "p_feedback.vert" );
vertex_shader = glCreateShader( GL_VERTEX_SHADER );
feedback_program = glCreateProgram( );
glShaderSource( vertex_shader, 1, (const GLchar**)&vert_source, NULL );
free( vert_source );
glCompileShader( vertex_shader );
glAttachShader( feedback_program, vertex_shader );
glTransformFeedbackVaryings( feedback_program, 2, vars,
GL_INTERLEAVED_ATTRIBS );
glLinkProgram( feedback_program );
/* drawing program */
vert_source = load_file_into_string( "p_draw.vert" );
frag_source = load_file_into_string( "p_draw.frag" );
vertex_shader = glCreateShader( GL_VERTEX_SHADER );
fragment_shader = glCreateShader( GL_FRAGMENT_SHADER );
draw_program = glCreateProgram( );
glShaderSource( vertex_shader, 1, (const GLchar**)&vert_source, NULL );
glShaderSource( fragment_shader, 1, (const GLchar**)&frag_source, NULL );
free( vert_source );
free( frag_source );
glCompileShader( vertex_shader );
glCompileShader( fragment_shader );
glAttachShader( draw_program, vertex_shader );
glAttachShader( draw_program, fragment_shader );
glLinkProgram( draw_program );
uniform_projection = glGetUniformLocation( draw_program, "projection" );
uniform_modelview = glGetUniformLocation( draw_program, "modelview" );
glUseProgram( draw_program );
mat4_set_projection_perspective( matrix, 60.0f,
(float)WIDTH/(float)HEIGHT,
0.1f, 500.0f );
glUniformMatrix4fv( uniform_projection, 1, GL_FALSE, matrix );
mat4_set_identity( matrix );
mat4_translate( matrix, 0.0, 0.0, -10.0f );
glUniformMatrix4fv( uniform_modelview, 1, GL_FALSE, matrix );
/********************* rendering loop *********************/
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glPointSize( 5.0f );
while( window_handle_messages( ) )
{
GLuint temp;
glClear( GL_COLOR_BUFFER_BIT );
glBindBuffer( GL_ARRAY_BUFFER, vbo[0] );
glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo[1] );
/* draw */
glUseProgram( draw_program );
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
/* feedback */
glEnable( GL_RASTERIZER_DISCARD );
glUseProgram( feedback_program );
glBeginTransformFeedback( GL_POINTS );
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
glEndTransformFeedback( );
glDisable( GL_RASTERIZER_DISCARD );
/* swap the buffers */
temp = vbo[0];
vbo[0] = vbo[1];
vbo[1] = temp;
window_swap_buffers( );
}
window_close( );
window_cleanup( );
return 0;
}
void generate_initial_particles( )
{
size_t i;
for( i=0; i<NUM_PARTICLES; ++i )
{
initial_particles[ i*8 ] = 0.0f;
initial_particles[ i*8 + 1 ] = 0.0f;
initial_particles[ i*8 + 2 ] = 0.0f;
initial_particles[ i*8 + 3 ] = 1.0f;
initial_particles[ i*8 + 4 ] = 1.0f;
initial_particles[ i*8 + 5 ] = 10.0f;
initial_particles[ i*8 + 6 ] = 0.0f;
initial_particles[ i*8 + 7 ] = 0.0f;
}
}
The feedback vertex shader “p_feedback.vert”:
#version 330
layout(location=0) in vec4 V_POSITION;
layout(location=1) in vec4 V_VELOCITY;
out vec4 velocity;
void main( )
{
velocity = V_VELOCITY - vec4(0.0,9.81,0.0,0.0) / 60.0;
gl_Position = V_POSITION + V_VELOCITY / 60.0;
}
The drawing vertex shader “p_draw.vert”:
#version 330
uniform mat4 projection;
uniform mat4 modelview;
layout(location=0) in vec4 V_POSITION;
layout(location=1) in vec4 V_VELOCITY;
void main( )
{
gl_Position = projection * modelview * V_POSITION;
}
The drawing fragment shader “p_draw.vert”:
#version 330
layout(location=0) out vec3 COLOR0;
void main( )
{
COLOR0 = vec3( 1.0, 0.0, 0.0 );
}
OS: Debian Lenny GNU/Linux (i686)
Graphics Card: nvidia gtx 285
Driver version: 280.13
Thanks in advance,
Dave