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();
}
}