• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
shocobenn

Problems with TransfromFeedback

3 posts in this topic

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;
}
0

Share this post


Link to post
Share on other sites

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
0

Share this post


Link to post
Share on other sites

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
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0