OpenGL TBO's - Texture Buffer Objects

This example will create a texture buffer object which is usable via glsl within the fragment shader (samplerBuffer uniform). The shader accesses the texel of the buffer object to alternate the fragment color. You can update the tbo by pressing ‘a’.

GLSLTextureBufferObjectExample.cpp:


#include
#include
#include
#include
#include “textfile.h”
#include
#include <GL/glew.h>
#include <GL/glut.h>

typedef float float44;

const unsigned int window_width = 512;
const unsigned int window_height = 512;

#define texture_height 256
#define texture_width 256

char *VertexShaderSource, *FragmentShaderSource;

float4* p;
GLuint tbo;
float anim = 0.0;

// mouse controls
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0, rotate_y = 0.0;
float translate_z = -2.0;

// vertex Shader
GLuint vertexShader;
GLuint fragmentShader;
GLuint shaderProgram;
GLuint vs_tboSampler;

//texture
GLuint displacementTex;

// declaration, forward
void runTest(int argc, char** argv);

// GL functionality
int initGL();
void initShader();
void createTBO(GLuint* tbo, GLuint* tex);
void deleteTBO(GLuint* tbo);
void setShaderUniforms();

void setTextureBufferData(float f);

// rendering callbacks
void display();
void keyboard(unsigned char key, int x, int y);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);

int main(int argc, char** argv) {
runTest(argc, argv);
}

void runTest(int argc, char** argv) {

// Create GL context
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(window_width, window_height);
glutCreateWindow(“TBO GL3 ATI Example”);

// initialize GL
if (false == initGL()) {
return;
}
initShader();

// register callbacks
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);

// create TBO
createTBO(&tbo, &displacementTex);

setTextureBufferData(0.9f);

//set shader uniforms
setShaderUniforms();

// start rendering mainloop
glutMainLoop();
}

int initGL() {
// initialize necessary OpenGL extensions
glewInit();
if (!glewIsSupported("GL_VERSION_2_0 "
“GL_ARB_pixel_buffer_object”)) {
fprintf(stderr,
ERROR: Support for necessary OpenGL extensions missing.”);
fflush(stderr);
return false;
}

// default initialization
glClearColor(0.0, 0.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);

// viewport
glViewport(0, 0, window_width, window_height);

// projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) window_width / (GLfloat) window_height, 0.1,
10.0);

return true;
}

void initShader() {

VertexShaderSource = textFileRead(“src/shader.vert”);
FragmentShaderSource = textFileRead(“src/shader.frag”);

const char * VS = VertexShaderSource;
const char * FS = FragmentShaderSource;

vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &VS, 0);

fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &FS, NULL);

glCompileShader(vertexShader);
glCompileShader(fragmentShader);

shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

// check for errors
GLint status;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
printf(“ERROR: Shader Compilation Error\n”);
char data1024;
int len;
glGetShaderInfoLog(vertexShader, 1024, &len, data);
printf(“%s”, data);
}
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
printf(“ERROR: Shader Program Link Error\n”);
}

// get shader variables
vs_tboSampler = glGetUniformLocation(shaderProgram, “tboSampler”);

//use shader and set the displacement map
glUseProgram(shaderProgram);
}

void createTBO(GLuint* tbo, GLuint* tex) {
// create buffer object
glGenBuffers(1, tbo);
glBindBuffer(GL_TEXTURE_BUFFER_EXT, *tbo);

// initialize buffer object
unsigned int size = texture_width * texture_height * 4 * sizeof(float);
glBufferData(GL_TEXTURE_BUFFER_EXT, size, 0, GL_DYNAMIC_DRAW);

//tex
glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_BUFFER_EXT, *tex);
glTexBufferEXT(GL_TEXTURE_BUFFER_EXT, GL_RGBA32F_ARB, *tbo);
glBindBuffer(GL_TEXTURE_BUFFER_EXT, 0);

}

void deleteTBO(GLuint* tbo) {
glBindBuffer(1, *tbo);
glDeleteBuffers(1, tbo);
*tbo = 0;
}

void setShaderUniforms() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER_EXT, displacementTex);
}

void setTextureBufferData(float f) {
glBindBuffer(GL_TEXTURE_BUFFER_EXT, tbo);
p = (float4*) glMapBuffer(GL_TEXTURE_BUFFER_EXT, GL_WRITE_ONLY);

for (int u = 0; u < texture_height; u++) {
for (int v = 0; v < texture_width; v++) {
float d =f;
//printf("P[%i][%i] = %f\n ",u,v,f);
if (u == 125 && v == 125) {
d= 0.325;
}
p[u + (v * texture_width)]0 = ((float) d);

p[u + (v * texture_width)]1 = ((float) v / texture_width) * 2 – (1.0);
p[u + (v * texture_width)]2 = 0.0f;
p[u + (v * texture_width)]3 = 1.0f;
}
}
glUnmapBuffer(GL_TEXTURE_BUFFER_EXT);
glBindBuffer(GL_TEXTURE_BUFFER_EXT, 0);

}

void display() {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// set view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, translate_z);
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);

glMatrixMode(GL_MODELVIEW);

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(-2.0, -1.0, 0.0);
glTexCoord2f(0.0, 3.0);
glVertex3f(-2.0, 1.0, 0.0);
glTexCoord2f(3.0, 3.0);
glVertex3f(0.0, 1.0, 0.0);
glTexCoord2f(3.0, 0.0);
glVertex3f(0.0, -1.0, 0.0);

glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(0.0, 3.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(3.0, 3.0);
glVertex3f(2.41421, 1.0, -1.41421);
glTexCoord2f(3.0, 0.0);
glVertex3f(2.41421, -1.0, -1.41421);
glEnd();
glFlush();

glutSwapBuffers();
glutPostRedisplay();

anim += 0.01;
//printf(“Anim: %f\n”, anim);

if (anim > 1.0) {
anim = 0.0f;
}

}

void keyboard(unsigned char key, int /x/, int /y/) {
switch (key) {
case (27):
deleteTBO(&tbo);
exit(0);
case (97):
setTextureBufferData(anim);
break;
}
}

void mouse(int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
mouse_buttons |= 1 << button;
} else if (state == GLUT_UP) {
mouse_buttons = 0;
}

mouse_old_x = x;
mouse_old_y = y;
glutPostRedisplay();
}

void motion(int x, int y) {
float dx, dy;
dx = x – mouse_old_x;
dy = y – mouse_old_y;

if (mouse_buttons & 1) {
rotate_x += dy * 0.2;
rotate_y += dx * 0.2;
} else if (mouse_buttons & 4) {
translate_z += dy * 0.01;
}

mouse_old_x = x;
mouse_old_y = y;
}

textfile.cpp:


#include
#include
#include
#include
#include <sys/types.h>
#include

char *textFileRead(char *fn) {

FILE *fp;
char *content = NULL;

int f,count;
f = open(fn, O_RDONLY);

count = lseek(f, 0, SEEK_END);

close(f);

if (fn != NULL) {
fp = fopen(fn,“rt”);

if (fp != NULL) {

if (count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content,sizeof(char),count,fp);
content[count] = ‘\0’;
}
fclose(fp);
}
}
return content;
}

int textFileWrite(char *fn, char *s) {

FILE *fp;
int status = 0;

if (fn != NULL) {
fp = fopen(fn,“w”);

if (fp != NULL) {

if (fwrite(s,sizeof(char),strlen(s),fp) == strlen(s))
status = 1;
fclose(fp);
}
}
return(status);
}

textfile.h:


char *textFileRead(char *fn);
int textFileWrite(char *fn, char *s);

shader.frag:


#extension EXT_gpu_shader4 : enable
uniform samplerBuffer tboSampler;

float texelFetch(ivec2 coords)
{
int width = int( sqrt(textureSizeBuffer(tboSampler)));
float pixel = texelFetchBuffer(tboSampler, int((coords.x*width)+coords.y)).r;
return pixel;
}

void main() {

float pixel = texelFetch(ivec2(124,125));

/*
if( pixel == 0.325 ) {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
else {
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
*/

vec4 color = vec4(pixel,0.5,0.2,0.1);
gl_FragColor = color;
}

shader.vert:


void main()
{
gl_Position = ftransform();
gl_FrontColor = vec4(0.0, 1.0, 1.0, 0.0);
}

Posted in Technik | Tagged with  |