Capture To Multiple Buffers

Vertex Shader:

#version 450 core

layout (location = 0) in vec3 in_vertex;

layout (xfb_buffer = 0, xfb_offset = 0, xfb_stride = 12) out vec3 transformed_vertex;

layout (xfb_buffer = 1, xfb_offset = 0, xfb_stride = 4) out uint transformed_index;

void main()

{

transformed_vertex = in_vertex * 2;

transformed_index = 12345;

}

Main.cpp

#include <GL/glew.h>

#include <GLFW/glfw3.h>

#include <glm/glm.hpp>

#include <glm/gtc/type_ptr.hpp>

#include <iostream>

#include <vector>

#include "Shader.h"

using namespace std;

using namespace glm;

/* main functions */

void Initialize();

void Render();

void CleanUp();

void CheckForGLError();

/* variables */

GLuint program = 0;

GLuint vertexshader = 0;

GLuint vertexarray = 0;

GLuint vertexbuffer = 0;

GLuint transformfeedback = 0;

GLuint transformfeedbackbuffer1 = 0;

GLuint transformfeedbackbuffer2 = 0;

int main(void)

{

/* Initialize the library */

if (!glfwInit())

return 1;

/* Create a windowed mode window and its OpenGL context */

GLFWwindow* window = glfwCreateWindow(800, 600, "Hello World", NULL, NULL);

if (!window)

{

glfwTerminate();

return 1;

}

/* Make the window's context current */

glfwMakeContextCurrent(window);

/* Initialize GLEW */

if (glewInit() != GLEW_OK)

{

glfwTerminate();

return 1;

}

Initialize();

/* Loop until the user closes the window */

while (!glfwWindowShouldClose(window))

{

/* Render here */

Render();

/* Swap front and back buffers */

glfwSwapBuffers(window);

/* Poll for and process events */

glfwPollEvents();

}

CleanUp();

glfwTerminate();

return 0;

}

void Initialize()

{

/* show some infos about transform feedback */

GLint max_transform_feedback_buffers = 0;

GLint max_transform_feedback_separate_attribs = 0;

GLint max_transform_feedback_separate_components = 0;

GLint max_transform_feedback_interleaved_components = 0;

glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);

glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);

glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);

glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);

cout << "max buffers: " << max_transform_feedback_buffers << endl;

cout << "max variables: " << max_transform_feedback_separate_attribs << endl;

cout << "max components per variable: " << max_transform_feedback_separate_components << endl;

cout << "max interleaved components: " << max_transform_feedback_interleaved_components << endl;

// background color = gray

glClearColor(0.5f, 0.5f, 0.5f, 0.0f);

// create all objects

program = glCreateProgram();

vertexshader = glCreateShader(GL_VERTEX_SHADER);

glGenVertexArrays(1, &vertexarray);

glGenBuffers(1, &vertexbuffer);

glGenTransformFeedbacks(1, &transformfeedback);

glGenBuffers(1, &transformfeedbackbuffer1);

glGenBuffers(1, &transformfeedbackbuffer2);

// shader source code

string vertexshader_source = {

"#version 450 core\n"

"layout (location = 0) in vec3 in_vertex;"

"layout (xfb_buffer = 0, xfb_offset = 0, xfb_stride = 12) out vec3 transformed_vertex;"

"layout (xfb_buffer = 1, xfb_offset = 0, xfb_stride = 4) out uint transformed_index;"

"void main () {"

"transformed_vertex = in_vertex * 2;"

"transformed_index = 12345;"

"}"

};

/* compile shader and link program */

CompileShader(vertexshader, vertexshader_source);

LinkProgram(program, { vertexshader });

/* setup vertex array */

glBindVertexArray(vertexarray);

glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glEnableVertexAttribArray(0);

glBindVertexArray(0);

/* setup vertex buffer */

vec3 testvalue = vec3(1, 2, 3);

glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

glBufferData(GL_ARRAY_BUFFER, sizeof(vec3), value_ptr(testvalue), GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);

/* setup transform feedback */

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformfeedback);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformfeedbackbuffer1);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, transformfeedbackbuffer2);

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);

/* setup transform feedback buffer */

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformfeedbackbuffer1);

glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(vec3), NULL, GL_DYNAMIC_COPY);

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformfeedbackbuffer2);

glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(unsigned int), NULL, GL_DYNAMIC_COPY);

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

/* execute the program once, do not rasterize any primitives (not needed here) */

glEnable(GL_RASTERIZER_DISCARD);

glUseProgram(program);

glBindVertexArray(vertexarray);

/* start capturing */

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformfeedback);

glBeginTransformFeedback(GL_POINTS);

/* send 1 point to the program */

glDrawArrays(GL_POINTS, 0, 1);

/* stop capturing */

glEndTransformFeedback();

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);

glBindVertexArray(0);

glUseProgram(0);

glDisable(GL_RASTERIZER_DISCARD);

/* check the captured value */

vec3 result = vec3(0, 0, 0);

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformfeedbackbuffer1);

glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(vec3), value_ptr(result));

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

GLuint resultindex = 0;

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformfeedbackbuffer2);

glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(GLuint), &resultindex);

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

cout << "test value = " << testvalue.x << " "<< testvalue.y << " "<< testvalue.z << " and index " << 0 << endl;

cout << "captured value = " << result.x << " "<< result.y << " "<< result.z << " and index " << resultindex << endl;

CheckForGLError();

}

void Render()

{

/* clear frame buffer */

glClear(GL_COLOR_BUFFER_BIT);

/* ... do nothing ... */

}

void CleanUp()

{

/* destroy all objects */

glDeleteProgram(program);

glDeleteShader(vertexshader);

glDeleteVertexArrays(1, &vertexarray);

glDeleteBuffers(1, &vertexbuffer);

glDeleteTransformFeedbacks(1, &transformfeedback);

glDeleteBuffers(1, &transformfeedbackbuffer1);

glDeleteBuffers(1, &transformfeedbackbuffer2);

}

void CheckForGLError()

{

for (GLenum error; (error = glGetError()) != GL_NO_ERROR;)

{

cout << "OpenGL Error: \t";

if (error == GL_INVALID_ENUM)

cout << "GL_INVALID_ENUM";

if (error == GL_INVALID_VALUE)

cout << "GL_INVALID_VALUE";

if (error == GL_INVALID_OPERATION)

cout << "GL_INVALID_OPERATION";

if (error == GL_STACK_OVERFLOW)

cout << "GL_STACK_OVERFLOW";

if (error == GL_STACK_UNDERFLOW)

cout << "GL_STACK_UNDERFLOW";

if (error == GL_OUT_OF_MEMORY)

cout << "GL_OUT_OF_MEMORY";

if (error == GL_INVALID_FRAMEBUFFER_OPERATION)

cout << "GL_INVALID_FRAMEBUFFER_OPERATION";

if (error == GL_CONTEXT_LOST)

cout << "GL_CONTEXT_LOST";

cout << (char)7 << endl; /*play sound*/

cin.get();

}

}