samplerBuffer example needed

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.

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
", 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, &len ) ;

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

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

    if ( trueLen > 0 && s [ 0 ] != '\0' )
      fprintf ( stderr, "%s:
%s
", 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, &src, 0 ) ;
  glCompileShader( handle ) ;

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

  if ( !compiled )
  {
    showShaderInfo ( type_str, handle ) ;
    fprintf ( stderr, "Failed to compile %s shader.
", 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.
" ) ;
    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, &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, &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            ( &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...
" );
  GLuint vsHandle = compileShader ( Vertex_src, GL_VERTEX_SHADER  );
  printf( "Compiling fragment shader...
" );
  GLuint fsHandle = compileShader ( Fragment_src, GL_FRAGMENT_SHADER);

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

  // Activate shader
  glUseProgram( handle ) ;

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

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

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.

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, &maxTex);

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

  // Generate and fill buffer object
  GLuint buffer;

  glGenBuffers   ( 1, &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, &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, &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, &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

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)               
"
  "{                             
"
  "  gl_Position = ftransform(); 
"
  "}                             
";

static const char Fragment_src[] = 
  "#version 140                           
"
  "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
", 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, &len ) ;

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

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

    if ( trueLen > 0 && s [ 0 ] != '\0' )
      fprintf ( stderr, "%s:
%s
", 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, &src, 0 ) ;
  glCompileShader( handle ) ;

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

  if ( !compiled )
  {
    showShaderInfo ( type_str, handle ) ;
    fprintf ( stderr, "Failed to compile %s shader.
", 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.
" ) ;
    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, &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, &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            ( &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...
" );
  GLuint vsHandle = compileShader ( Vertex_src, GL_VERTEX_SHADER  );
  printf( "Compiling fragment shader...
" );
  GLuint fsHandle = compileShader ( Fragment_src, GL_FRAGMENT_SHADER);

  // Link shaders
  printf( "Linking...
" );
  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 ;
}

You’re great! Working now like charm, I’ll try to apply this to my unsolwed problem after quite long time. THANKS!

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.