Jump to content

  • Log In with Google      Sign In   
  • Create Account

Problems with TransfromFeedback


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 shocobenn   Members   -  Reputation: 273

Like
0Likes
Like

Posted 30 July 2013 - 04:47 PM

Hi ! I'm not sure to really get transform feedback usage. They are used to modify a VBO from the GPU, so you can create particulesSystems which move without the CPU, isn't it?

 

So I tried to make a simple soft where I draw a point and I want to move it on his X axis. But It doesn't... i don't see why...

 

Here is the code

 

Instance.vert

#version 400

layout (location = 0) in vec4 position;

out vec4 vPosition;

void main(void)
{
   position.x += 0.5;
   vPosition = position;
}

Main.cpp

#include <stdlib.h>
#include <stdio.h>
#include <iostream>

#include <GL\glew.h>
#include <GL\freeglut.h>

#include <LoadShaders.h>


GLuint render_prog;

GLuint inputVBO;
GLuint outputVBO;
GLuint transformFeedbackObj;
	

GLint render_model_matrix_loc;
GLint render_projection_matrix_loc;

		// A single triangle
static const GLfloat vertex_positions[] =
{
    0, 0, 0.0f, 1.0f,
};

void createShader()
{
	render_prog = glCreateProgram();
	GLuint vsHandle = glCreateShader(GL_VERTEX_SHADER);
	const GLchar* source = ReadShader("instance.vert");
	glShaderSource(vsHandle, 1, &source, 0);
	glCompileShader(vsHandle);

	glAttachShader(render_prog, vsHandle);

	const char* varyings[1] = { "vPosition"};
	glTransformFeedbackVaryings(render_prog, 1, varyings, GL_INTERLEAVED_ATTRIBS);

	glLinkProgram(render_prog);
}


void init()
{
	createShader();

	glGenBuffers(1, &inputVBO);

	glGenBuffers(1, &outputVBO);
	glBindBuffer(GL_ARRAY_BUFFER, outputVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_positions) , (vertex_positions), GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glGenTransformFeedbacks(1, &transformFeedbackObj);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackObj);
	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, outputVBO); //So , as I understand outputVBO will be modified by the transfromFeedback using inputVBO
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);

    glClearColor(0.0f, 0.1f, 0.0f, 1.0f);
}

void moveThePoint()
{
	glEnable(GL_RASTERIZER_DISCARD);
	glUseProgram(render_prog);
	

	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackObj);
	glBeginTransformFeedback(GL_POINTS); //begin the transfromFeedback		
		glBindBuffer(GL_ARRAY_BUFFER, inputVBO); //draw into it
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_positions), vertex_positions, GL_STREAM_DRAW);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) 0);
		glDrawArrays(GL_POINTS,0, 1);
		
		glDisableVertexAttribArray(0); //clean
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	glEndTransformFeedback();
	glDisable(GL_RASTERIZER_DISCARD);
	glUseProgram(0);
}

void drawThePoint()
{
	glBindBuffer(GL_ARRAY_BUFFER, outputVBO);
	glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(4, GL_FLOAT, 0, 0);
	glDrawTransformFeedback(GL_POINTS, transformFeedbackObj);
	glDisableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void display() // Loop
{
    // Setup
	glPointSize(21.0);
    glDisable(GL_DEPTH_TEST);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	moveThePoint();
	drawThePoint();
	glutSwapBuffers();

}

void Reshape(int width, int height)
{
	glViewport(0, 0 , width, height);
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitContextFlags(GLUT_DEBUG);
    glutInitWindowSize(1024, 768);
	glutInitContextVersion(4, 0);
    glutInitWindowPosition (140, 140);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitContextProfile(GLUT_CORE_PROFILE);
	glutCreateWindow("hello");

	if (glewInit())
	{
		std::cout << "Une erreur est survenue lors de l'init de glew" << std::endl; 
		exit(EXIT_FAILURE);
	}

	init();

	glutDisplayFunc(display);
	glutReshapeFunc(Reshape);

	glutMainLoop();

	
	glDeleteBuffers(1, &inputVBO);
	glDeleteBuffers(1, &outputVBO);
	glDeleteTransformFeedbacks(1, &transformFeedbackObj);

	return 0;
}


Sponsor:

#2 kidman171   Members   -  Reputation: 498

Like
0Likes
Like

Posted 30 July 2013 - 10:39 PM

If I am not mistaken, you are required to have a vertex array object bound with 4.0 core profile.

 

I successfully used transform feedback in an experiment to flatten terrain a little while back. Here is the code I used to run the transform feedback portion. :

    _transformProgram.enable();
        glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _transformer);
            glBindVertexArray(_VAO);
                glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _yBuffer );
                glEnable(GL_RASTERIZER_DISCARD);
                    glBeginTransformFeedback(GL_POINTS);
                        glDrawArrays(GL_POINTS, 0, _vertexCount);
                    glEndTransformFeedback();
                glDisable(GL_RASTERIZER_DISCARD);
            glBindVertexArray(0);
        glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
    _transformProgram.disable();

My draw call was just a few lines because all the buffers are associated with the VAO:

_renderProgram.enable();
_renderProgram.setUniform("ModelViewProjMat", modelViewProjMat);
glBindVertexArray(_VAO);
glDrawElements(GL_TRIANGLES, _elementCount, GL_UNSIGNED_INT, 0);
_renderProgram.disable();

Edit: see this example as well: https://github.com/progschj/OpenGL-Examples/blob/master/09transform_feedback.cpp


Edited by kidman171, 30 July 2013 - 10:42 PM.


#3 shocobenn   Members   -  Reputation: 273

Like
0Likes
Like

Posted 31 July 2013 - 06:31 PM

Hi ! I have tried to resolve my example by using a double buffer and double vao but nothing changed.

 

Then I copied you example but this is still not working.

 

BUT i have noticed something : I created a blank project where I only initialize Glew and I get back GL_INVALID_ENUM by using glewInit(). So I looked on the net and found gl3w which resolve those problems. I tried to run with python 2.6 the gl3w_gen.py but I get a 404 not found for the file which he is looking for on opengl.org.

 

Here is the "copied file" using freeglut && glew

#include <stdlib.h>
#include <stdio.h>
#include <iostream>

#include <GL\glew.h>
#include <GL\freeglut.h>
#include <glm.hpp>
#include <gtc\matrix_transform.hpp>
#include <gtc\type_ptr.hpp>

#include <time.h>

#include <vector>
#include <LoadShaders.h>
#define GLExitIfError()                                                         \
{                                                                               \
    GLenum Error = glGetError();                                                \
    switch(Error)                                                                \
    {                                                                            \
        case GL_NO_ERROR :                                                        \
            printf( "%s\n", "NO ERROR"    );                                                                \
        break;                                                                    \
        case GL_INVALID_ENUM :                                                  \
            printf( "%s\n", "GL_INVALID_ENUM" ); \
        break; \
        case GL_INVALID_VALUE : \
            printf("%s\n", "GL_INVALID_VALUE"); \
        break;\
        case GL_INVALID_OPERATION : \
            printf("%s\n", "GL_INVALID_OPERATION"); \
        break; \
        case GL_INVALID_FRAMEBUFFER_OPERATION : \
            printf("%s\n", "GL_INVALID_FRAMEBUFFER_OPERATION"); \
        break; \
        case GL_OUT_OF_MEMORY : \
            printf("%s\n", "GL_OUT_OF_MEMORY"); \
        break; \
        default :\
            printf("%s\n", "Unknow");\
        break;\
    } \
}


bool check_shader_compile_status(GLuint obj)
{
    GLint status;
    glGetShaderiv(obj, GL_COMPILE_STATUS, &status);
    if(status == GL_FALSE)
    {
        GLint length;
        glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
        std::vector<char> log(length);
        glGetShaderInfoLog(obj, length, &length, &log[0]);
        std::cerr << &log[0];
        return false;
    }
    return true;
}

bool check_program_link_status(GLuint obj)
{
    GLint status;
    glGetProgramiv(obj, GL_LINK_STATUS, &status);
    if(status == GL_FALSE)
    {
        GLint length;
        glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
        std::vector<char> log(length);
        glGetProgramInfoLog(obj, length, &length, &log[0]);
        std::cerr << &log[0];
        return false;
    }
    return true;
}

  // the vertex shader simply passes through data
std::string vertex_source =
    "#version 330\n"
    "layout(location = 0) in vec4 vposition;\n"
    "void main() {\n"
    " gl_Position = vposition;\n"
    "}\n";
    
// the geometry shader creates the billboard quads
std::string geometry_source =
    "#version 330\n"
    "uniform mat4 View;\n"
    "uniform mat4 Projection;\n"
    "layout (points) in;\n"
    "layout (triangle_strip, max_vertices = 4) out;\n"
    "out vec2 txcoord;\n"
    "void main() {\n"
    " vec4 pos = View*gl_in[0].gl_Position;\n"
    " txcoord = vec2(-1,-1);\n"
    " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
    " EmitVertex();\n"
    " txcoord = vec2( 1,-1);\n"
    " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
    " EmitVertex();\n"
    " txcoord = vec2(-1, 1);\n"
    " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
    " EmitVertex();\n"
    " txcoord = vec2( 1, 1);\n"
    " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
    " EmitVertex();\n"
    "}\n";
    
// the fragment shader creates a bell like radial color distribution
std::string fragment_source =
    "#version 330\n"
    "in vec2 txcoord;\n"
    "layout(location = 0) out vec4 FragColor;\n"
    "void main() {\n"
    " \n"
    " FragColor = vec4(1.0,0.0,0.0,1);\n"
    "}\n";


GLuint render_program;
GLint View_location;
GLint Projection_location;

void createRenderProgram()
{
    GLuint vertex_shader, geometry_shader, fragment_shader;

    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length);
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {

        return;
    }
    
    // create and compiler geometry shader
    geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
    source = geometry_source.c_str();
    length = geometry_source.size();
    glShaderSource(geometry_shader, 1, &source, &length);
    glCompileShader(geometry_shader);
    if(!check_shader_compile_status(geometry_shader))
    {
        return;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return;
    }

    // create program
    render_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(render_program, vertex_shader);
    glAttachShader(render_program, geometry_shader);
    glAttachShader(render_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(render_program);
    check_program_link_status(render_program);
    
    View_location = glGetUniformLocation(render_program, "View");
    Projection_location = glGetUniformLocation(render_program, "Projection");
}

 // the transform feedback shader only has a vertex shader
std::string transform_vertex_source =
    "#version 330\n"
    "uniform vec3 center[3];\n"
    "uniform float radius[3];\n"
    "uniform vec3 g;\n"
    "uniform float dt;\n"
    "uniform float bounce;\n"
    "uniform int seed;\n"
    "layout(location = 0) in vec3 inposition;\n"
    "layout(location = 1) in vec3 invelocity;\n"
    "out vec3 outposition;\n"
    "out vec3 outvelocity;\n"
        
    "float hash(int x) {\n"
    " x = x*1235167 + gl_VertexID*948737 + seed*9284365;\n"
    " x = (x >> 13) ^ x;\n"
    " return ((x * (x * x * 60493 + 19990303) + 1376312589) & 0x7fffffff)/float(0x7fffffff-1);\n"
    "}\n"
        
    "void main() {\n"
    " outvelocity = invelocity;\n"
    " for(int j = 0;j<3;++j) {\n"
    " vec3 diff = inposition-center[j];\n"
    " float dist = length(diff);\n"
    " float vdot = dot(diff, invelocity);\n"
    " if(dist<radius[j] && vdot<0.0)\n"
    " outvelocity -= bounce*diff*vdot/(dist*dist);\n"
    " }\n"
    " outvelocity += dt*g;\n"
    " outposition = inposition + dt*outvelocity;\n"
    " if(outposition.y < -30.0)\n"
    " {\n"
    " outvelocity = vec3(0,0,0);\n"
    " outposition = 0.5-vec3(hash(3*gl_VertexID+0),hash(3*gl_VertexID+1),hash(3*gl_VertexID+2));\n"
    " outposition = vec3(0,20,0) + 5.0*outposition;\n"
    " }\n"
    "}\n";

GLuint transform_shader_program;
GLint center_location;
GLint radius_location;
GLint g_location;
GLint dt_location;
GLint bounce_location ;
GLint seed_location;
void createUpdateProgram()
{
    GLuint transform_vertex_shader;
    
    const char *source;
    int length;

    transform_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = transform_vertex_source.c_str();
    length = transform_vertex_source.size();
    glShaderSource(transform_vertex_shader, 1, &source, &length);
    glCompileShader(transform_vertex_shader);
    if(!check_shader_compile_status(transform_vertex_shader))
    {
        return;
    }
     // create program
    transform_shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(transform_shader_program, transform_vertex_shader);
    
    // specify transform feedback output
    const char *varyings[] = {"outposition", "outvelocity"};
    glTransformFeedbackVaryings(transform_shader_program, 2, varyings, GL_INTERLEAVED_ATTRIBS);
    
    // link the program and check for errors
    glLinkProgram(transform_shader_program);
    check_program_link_status(transform_shader_program);

    center_location = glGetUniformLocation(transform_shader_program, "center");
    radius_location = glGetUniformLocation(transform_shader_program, "radius");
    g_location = glGetUniformLocation(transform_shader_program, "g");
    dt_location = glGetUniformLocation(transform_shader_program, "dt");
    bounce_location = glGetUniformLocation(transform_shader_program, "bounce");
    seed_location = glGetUniformLocation(transform_shader_program, "seed");
}

const int buffercount = 2;
const int particles = 128*1024;
std::vector<glm::vec3> vertexData(2*particles);
GLuint vao[buffercount], vbo[buffercount];

const int spheres = 3;
glm::vec3 center[spheres];
float radius[spheres];

// physical parameters
float dt = 1.0f/60.0f;
glm::vec3 g(0.0f, -9.81f, 0.0f);
float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f

int current_buffer=0;

void init()
{
    
    createRenderProgram();
        
    createUpdateProgram();
    for(int i = 0;i<particles;++i)
    {
        // initial position
        vertexData[2*i+0] = glm::vec3(
                                0.5f-float(std::rand())/RAND_MAX,
                                0.5f-float(std::rand())/RAND_MAX,
                                0.5f-float(std::rand())/RAND_MAX
                            );
        vertexData[2*i+0] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[2*i+0];
        
        // initial velocity
        vertexData[2*i+1] = glm::vec3(0,0,0);
    }

    for(int i = 0;i<buffercount;++i)
    {
        glBindVertexArray(vao[i]);
        
        glBindBuffer(GL_ARRAY_BUFFER, vbo[i]);

        // fill with initial data
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
                        
        // set up generic attrib pointers
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
        // set up generic attrib pointers
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    }

     // "unbind" vao
    glBindVertexArray(0);
    
    glEnable(GL_BLEND);
    // and set the blend function to result = 1*source + 1*destination
    glBlendFunc(GL_ONE, GL_ONE);

    center[0] = glm::vec3(0,12,1);
    radius[0] = 3;
    center[1] = glm::vec3(-3,0,0);
    radius[1] = 7;
    center[2] = glm::vec3(5,-10,0);
    radius[2] = 12;
}



void display()
{
    long t = time(NULL);

    glUseProgram(transform_shader_program);

    // set the uniforms
        glUniform3fv(center_location, 3, reinterpret_cast<GLfloat*>(center));
        glUniform1fv(radius_location, 3, reinterpret_cast<GLfloat*>(radius));
        glUniform3fv(g_location, 1, glm::value_ptr(g));
        glUniform1f(dt_location, dt);
        glUniform1f(bounce_location, bounce);
        glUniform1i(seed_location, std::rand());

        // bind the current vao
        glBindVertexArray(vao[(current_buffer+1)%buffercount]);

        // bind transform feedback target
        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo[current_buffer]);

        glEnable(GL_RASTERIZER_DISCARD);

        // perform transform feedback
        glBeginTransformFeedback(GL_POINTS);
        glDrawArrays(GL_POINTS, 0, particles);
        glEndTransformFeedback();

        glDisable(GL_RASTERIZER_DISCARD);
   
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(render_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f));
        View = glm::rotate(View, -22.5f, glm::vec3(0.0f, 1.0f, 0.0f));
        
        // set the uniform
        glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View));
        glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection));
        
        // bind the current vao
        glBindVertexArray(vao[current_buffer]);

        // draw
        glDrawArrays(GL_POINTS, 0, particles);
       
        // check for errors

    
        // finally swap buffers
        glutSwapBuffers();
        
        // advance buffer index
        current_buffer = (current_buffer + 1) % buffercount;
}

void Reshape(int width, int height)
{
    glViewport(0, 0 , width, height);
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);

    glutInitContextFlags(GLUT_DEBUG);
    glutInitWindowSize(1024, 768);
    glutInitContextVersion(3, 3);
    glutInitWindowPosition (140, 140);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutCreateWindow("hello");

    glewExperimental = true;
    if (glewInit() != GLEW_OK)
    {
        std::cout << "Une erreur est survenue lors de l'init de glew" << std::endl;
        exit(EXIT_FAILURE);
    }

    GLExitIfError();
    
    init();

    glutDisplayFunc(display);
    glutReshapeFunc(Reshape);

    glutMainLoop();

    glDeleteVertexArrays(buffercount, vao);
    glDeleteBuffers(buffercount, vbo);
    
    return 0;
}

Maybe someone could help me for debugging ? Because of glew GL_INVALID_ENUM I can't place a glGetError where I want sad.png. Is someone having the same probleme with gl3w? (I 'm on window8).


Edited by shocobenn, 31 July 2013 - 06:35 PM.


#4 Sponji   Members   -  Reputation: 1248

Like
0Likes
Like

Posted 01 August 2013 - 12:13 AM

Here's some explanation about that invalid enum, http://www.opengl.org/wiki/OpenGL_Loading_Library#GLEW

You could probably just ignore the errors from glewInit.


Derp




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS