PDA

View Full Version : samplerBuffer example needed



DarkRaven
03-16-2011, 12:45 PM
I'm trying to work with samplerBuffers, but I couldn't get it right by myself and I think there's something wrong with them on my computer (driver bug?), so rather trying to find what's wrong after few days I decided to look up for some examples but I couldn't find any by myself. I could find some projects which use them, but they're way more complex than what I call example. So maybe anyone there tried to make test codes before using them and still have them somewhere on disc? Simplier = better, but anything is appreciated.

Dark Photon
03-16-2011, 06:33 PM
See below. Draws spinning teapot yellow. Search for "yellow" and swap the comments with another color to change the color of the teapot.

Most of this is just shader compile/link stuff. Very little of it has to do with buffer objects or texture buffers. Search for "buffer" for the relevant bits.



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

#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glut.h>

static const char Vertex_src[] =
"void main(void)"
"{"
" gl_Position = ftransform();"
"}";

static const char Fragment_src[] =
"uniform samplerBuffer tex;"
""
"void main(void)"
"{"
" gl_FragColor = texelFetch( tex, 0 );"
"}";


void keybd ( unsigned char, int, int )
{
exit ( 0 ) ;
}


void reshape(int wid, int ht)
{
glViewport(0, 0, wid, ht);
}

void showGLerror ()
{
GLenum err ;

while ( (err = glGetError()) != GL_NO_ERROR )
fprintf ( stderr, "OpenGL Error: %s\n", gluErrorString ( err ) ) ;
}

void display ( void )
{
static float a = 0.0f ;

a += 0.3f ;

glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity () ;
glFrustum ( -1.0f, 1.0f,
-1.0f / (640.0f/480.0f), 1.0f / (640.0f/480.0f),
3.0f, 10.0f) ;

glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
glTranslatef ( 0.0, 0.0, -5.0 ) ;
glRotatef ( a, 0.2, 0.7, 0 ) ;

glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;

glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;

glutSolidTeapot ( 1.0f ) ;

glutSwapBuffers () ;
glutPostRedisplay () ;

showGLerror () ;
}

void showShaderInfo ( const char *what, GLuint handle )
{
int len = 0 ;

glGetObjectParameterivARB ( handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &amp;len ) ;

if ( len > 0 )
{
int trueLen ;
char *s = new char [ len ] ;

glGetInfoLogARB ( handle, len, &amp;trueLen, s ) ;

if ( trueLen > 0 &amp;&amp; s [ 0 ] != '\0' )
fprintf ( stderr, "%s:\n%s\n", what, s ) ;

delete [] s ;
}
}

GLuint compileShader ( const char *src, GLenum type )
{
const char *type_str = type == GL_VERTEX_SHADER ? "vertex" : "fragment";

GLuint handle = glCreateShader( type ) ;

glShaderSource ( handle, 1, &amp;src, 0 ) ;
glCompileShader( handle ) ;

GLint compiled ;
glGetShaderiv( handle, GL_COMPILE_STATUS, &amp;compiled ) ;

if ( !compiled )
{
showShaderInfo ( type_str, handle ) ;
fprintf ( stderr, "Failed to compile %s shader.\n", type_str );
exit ( 1 ) ;
}

return handle ;
}

GLuint linkShaders ( GLuint vsHandle, GLuint fsHandle )
{
GLint linked ;
GLuint handle = glCreateProgram() ;

glAttachShader ( handle, vsHandle ) ;
glAttachShader ( handle, fsHandle ) ;
glLinkProgram ( handle ) ;
glGetProgramiv ( handle, GL_LINK_STATUS, & linked ) ;

if ( !linked )
{
showShaderInfo ( "Linking", handle ) ;
fprintf ( stderr, "Failed to link shader program.\n" ) ;
exit ( 1 ) ;
}

return handle ;
}

void init()
{
// The color to put in the buffer object
const GLfloat color[4] = { 1, 1, 0, 1 }; // Yellow
//const GLfloat color[4] = { 1, 0, 0, 1 }; // Red
//const GLfloat color[4] = { 0, 1, 1, 1 }; // Cyan

const size_t size = sizeof( color );

// Generate and fill buffer object
GLuint buffer;

glGenBuffers ( 1, &amp;buffer );
glBindBuffer ( GL_TEXTURE_BUFFER, buffer );
glBufferData ( GL_TEXTURE_BUFFER, size, NULL, GL_STATIC_DRAW ); // Alloc
glBufferSubData( GL_TEXTURE_BUFFER, 0, size, color ); // Fill

// Generate texture "wrapper" around buffer object
GLuint tex;

glGenTextures ( 1, &amp;tex );
glActiveTexture( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_BUFFER, tex );
glTexBuffer ( GL_TEXTURE_BUFFER, GL_RGBA32F, buffer );
}


int main ( int argc, char **argv )
{
// Init GL context
glutInit ( &amp;argc, argv ) ;
glutInitDisplayMode ( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE ) ;
glutInitWindowSize ( 500, 500 ) ;
glutCreateWindow ( "Shader Test" ) ;
glutDisplayFunc ( display ) ;
glutKeyboardFunc ( keybd ) ;
glutReshapeFunc ( reshape ) ;

// Create buffer object and its texture buffer object wrapper
init();

// Load and compile shaders
printf( "Compiling vertex shader...\n" );
GLuint vsHandle = compileShader ( Vertex_src, GL_VERTEX_SHADER );
printf( "Compiling fragment shader...\n" );
GLuint fsHandle = compileShader ( Fragment_src, GL_FRAGMENT_SHADER);

// Link shaders
printf( "Linking...\n" );
GLuint handle = linkShaders ( vsHandle, fsHandle ) ;

// Activate shader
glUseProgram( handle ) ;

// Draw with shader
glutMainLoop () ;
return 0 ;
}

Red_Riot
03-16-2011, 06:47 PM
Here's the best example I could find of getting samplers to work in a shader, in this instance a texture.

http://www.swiftless.com/tutorials/glsl/7_texturing.html

arekkusu
03-16-2011, 11:14 PM
That fragment shader should fail to compile in a compliant driver. It's missing #version, so should default to 1.10 where samplerBuffer isn't defined.

DarkRaven
03-18-2011, 12:52 PM
I quite agree with arekkusu, but it's working though.
But I got another problem, tried to run shader with multiple samplerBuffers(which was my real problem but I wasn't sure if I got even working with one right), first I had to add call

glUniform1i ( glGetUniformLocation(gHandle, "tex"), 0 );
which had have to specify texture unit for samplerBuffer as now I have 2, but I couldn't get it working. Also trying to draw teapot with second buffer started to cause problems, don't know why because triangle draws fine, only without effect of second buffer.. So this is the modified code(included only changed parts), could someone please tell me what I do wrong? thanks


static const char Fragment_src[] =
"uniform samplerBuffer tex;"
"uniform samplerBuffer tex1;"
""
"void main(void)"
"{"
" gl_FragColor = vec4(texelFetch( tex, 0 ).rgb+texelFetch( tex1, 0 ).rgb,1);"
"}";

//in display() procedure add intead of glutTeapot
glBegin(GL_TRIANGLES);
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glVertex3f(0,1,0);
glEnd();
showGLerror () ;

void init()
{
glewInit();
// The color to put in the buffer object
//const GLfloat color[4] = { 1, 1, 0, 1 }; // Yellow
const GLfloat color[4] = { 1, 0, 0, 1 }; // Red
const GLfloat color1[4] = { 0, 1, 1, 1 }; // Cyan

int maxTex;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &amp;maxTex);

const size_t size = sizeof( color );
const size_t size1 = sizeof( color1 );

// Generate and fill buffer object
GLuint buffer;

glGenBuffers ( 1, &amp;buffer );
glBindBuffer ( GL_TEXTURE_BUFFER, buffer );
glBufferData ( GL_TEXTURE_BUFFER, size, NULL, GL_STATIC_DRAW ); // Alloc
glBufferSubData( GL_TEXTURE_BUFFER, 0, size, color ); // Fill

// Generate texture "wrapper" around buffer object
GLuint tex;

glGenTextures ( 1, &amp;tex );
glActiveTexture( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_BUFFER, tex );
glTexBuffer ( GL_TEXTURE_BUFFER, GL_RGBA32F, buffer );
glUniform1i ( glGetUniformLocation(gHandle, "tex"), 0 );

// Generate and fill buffer object
GLuint buffer1;

glGenBuffers ( 1, &amp;buffer1 );
glBindBuffer ( GL_TEXTURE_BUFFER, buffer1 );
glBufferData ( GL_TEXTURE_BUFFER, size1, NULL, GL_STATIC_DRAW ); // Alloc
glBufferSubData( GL_TEXTURE_BUFFER, 0, size1, color1 ); // Fill

// Generate texture "wrapper" around buffer object
GLuint tex1;

glGenTextures ( 1, &amp;tex1 );
glActiveTexture( GL_TEXTURE0+1 );
glBindTexture ( GL_TEXTURE_BUFFER, tex1 );
glTexBuffer ( GL_TEXTURE_BUFFER, GL_RGBA32F, buffer1 );
glUniform1i ( glGetUniformLocation(gHandle, "tex1"), 1 );
showGLerror () ;
}

//in main() procedure add
// Activate shader
glUseProgram( handle ) ;
gHandle = handle;

result should be white triangle spining just like teapot but what I get is red one, so cyan buffer is like ignored

Dark Photon
03-20-2011, 04:59 PM
result should be white triangle spining just like teapot but what I get is red one

That's because you're calling glUniform1i with gHandle before you've linked your shader program (when gHandle doesn't refer to your program). See below for where you should move it to.

Here's an update of my original program with the above errors you guys flagged fixed. Thanks! Sorry for the oversights. When I googled for an example, didn't find one either so I whipped one up for you -- apparently too quickly. :o

But yes, you both have valid points. The sampler uniform does need to be populated with the texture unit number first. And samplerBuffer seems to require GLSL 1.4 or a #extension to add this (e.g. "#extension GL_EXT_gpu_shader4 : enable". "#extension ARB_texture_buffer_object : enable" would probably be just fine too.).




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

#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glut.h>

static const char Vertex_src[] =
"void main(void) \n"
"{ \n"
" gl_Position = ftransform(); \n"
"} \n";

static const char Fragment_src[] =
"#version 140 \n"
"uniform samplerBuffer tex; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_FragColor = texelFetch( tex, 0 ); \n"
"}";


void keybd ( unsigned char, int, int )
{
exit ( 0 ) ;
}


void reshape(int wid, int ht)
{
glViewport(0, 0, wid, ht);
}

void showGLerror ()
{
GLenum err ;

while ( (err = glGetError()) != GL_NO_ERROR )
fprintf ( stderr, "OpenGL Error: %s\n", gluErrorString ( err ) ) ;
}

void display ( void )
{
static float a = 0.0f ;

a += 0.3f ;

glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity () ;
glFrustum ( -1.0f, 1.0f,
-1.0f / (640.0f/480.0f), 1.0f / (640.0f/480.0f),
3.0f, 10.0f) ;

glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
glTranslatef ( 0.0, 0.0, -5.0 ) ;
glRotatef ( a, 0.2, 0.7, 0 ) ;

glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;

glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;

glutSolidTeapot ( 1.0f ) ;

glutSwapBuffers () ;
glutPostRedisplay () ;

showGLerror () ;
}

void showShaderInfo ( const char *what, GLuint handle )
{
int len = 0 ;

glGetObjectParameterivARB ( handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &amp;len ) ;

if ( len > 0 )
{
int trueLen ;
char *s = new char [ len ] ;

glGetInfoLogARB ( handle, len, &amp;trueLen, s ) ;

if ( trueLen > 0 &amp;&amp; s [ 0 ] != '\0' )
fprintf ( stderr, "%s:\n%s\n", what, s ) ;

delete [] s ;
}
}

GLuint compileShader ( const char *src, GLenum type )
{
const char *type_str = type == GL_VERTEX_SHADER ? "vertex" : "fragment";

GLuint handle = glCreateShader( type ) ;

glShaderSource ( handle, 1, &amp;src, 0 ) ;
glCompileShader( handle ) ;

GLint compiled ;
glGetShaderiv( handle, GL_COMPILE_STATUS, &amp;compiled ) ;

if ( !compiled )
{
showShaderInfo ( type_str, handle ) ;
fprintf ( stderr, "Failed to compile %s shader.\n", type_str );
exit ( 1 ) ;
}

return handle ;
}

GLuint linkShaders ( GLuint vsHandle, GLuint fsHandle )
{
GLint linked ;
GLuint handle = glCreateProgram() ;

glAttachShader ( handle, vsHandle ) ;
glAttachShader ( handle, fsHandle ) ;
glLinkProgram ( handle ) ;
glGetProgramiv ( handle, GL_LINK_STATUS, & linked ) ;

if ( !linked )
{
showShaderInfo ( "Linking", handle ) ;
fprintf ( stderr, "Failed to link shader program.\n" ) ;
exit ( 1 ) ;
}

return handle ;
}

void init()
{
// The color to put in the buffer object
const GLfloat color[4] = { 1, 1, 0, 1 }; // Yellow
//const GLfloat color[4] = { 1, 0, 0, 1 }; // Red
//const GLfloat color[4] = { 0, 1, 1, 1 }; // Cyan

const size_t size = sizeof( color );

// Generate and fill buffer object
GLuint buffer;

glGenBuffers ( 1, &amp;buffer );
glBindBuffer ( GL_TEXTURE_BUFFER, buffer );
glBufferData ( GL_TEXTURE_BUFFER, size, NULL, GL_STATIC_DRAW ); // Alloc
glBufferSubData( GL_TEXTURE_BUFFER, 0, size, color ); // Fill

// Generate texture "wrapper" around buffer object
GLuint tex;

glGenTextures ( 1, &amp;tex );
glActiveTexture( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_BUFFER, tex );
glTexBuffer ( GL_TEXTURE_BUFFER, GL_RGBA32F, buffer );
}


int main ( int argc, char **argv )
{
// Init GL context
glutInit ( &amp;argc, argv ) ;
glutInitDisplayMode ( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE ) ;
glutInitWindowSize ( 500, 500 ) ;
glutCreateWindow ( "Shader Test" ) ;
glutDisplayFunc ( display ) ;
glutKeyboardFunc ( keybd ) ;
glutReshapeFunc ( reshape ) ;

// Create buffer object and its texture buffer object wrapper
init();

// Load and compile shaders
printf( "Compiling vertex shader...\n" );
GLuint vsHandle = compileShader ( Vertex_src, GL_VERTEX_SHADER );
printf( "Compiling fragment shader...\n" );
GLuint fsHandle = compileShader ( Fragment_src, GL_FRAGMENT_SHADER);

// Link shaders
printf( "Linking...\n" );
GLuint handle = linkShaders ( vsHandle, fsHandle ) ;

// Activate shader
glUseProgram( handle ) ;

// Populate uniform
// (buffer texture will be on TEXUNIT 0)
glUniform1i( glGetUniformLocation( handle, "tex" ), 0 );

// Draw with shader
glutMainLoop () ;
return 0 ;
}

DarkRaven
03-21-2011, 11:56 AM
You're great! Working now like charm, I'll try to apply this to my unsolwed problem after quite long time. THANKS!