Pretty sure this is a bug but thought I’d verify here first. Maybe this is undefined behavior.
This is what I tried (simple “find the correct bin” algorithm):
int i;
for ( i = 0; i < f_array.length(); i++ )
if ( myval >= f_array[i] )
break;
The problem is that on loop termination i is +1 the value it should be.
The attached test program demonstrates. As-is, it renders a red teapot (should be green). If you uncomment the #define ACTIVATE_KLUDGE then it activates a hacked loop that correctly renders green.
#include <stdio.h>
#include <stdlib.h>
#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
//#define ACTIVATE_KLUDGE
static const char Vertex_src[] =
"void main(void) { gl_Position=ftransform(); }";
static const char Fragment_src[] =
"#version 120
"
" void main(void)
"
" {
"
" float f[] = float[]( 3., 2., 1. );
"
"
"
#ifndef ACTIVATE_KLUDGE
" // FIXME: This doesn't work (NVidia 195.36.08)
"
" int i;
"
" for ( i = 0; i < f.length(); i++ )
"
" if ( 3.5 >= f[i] )
"
" break;
"
"
"
#else
" // FIXME: Kludge around suspected NVidia GLSL bug
"
" int i, val = 0;
"
" for ( i = 0; i < f.length(); i++ )
"
" if ( 3.5 >= f[i] )
"
" {
"
" val = i;
"
" break;
"
" }
"
" i = val;
"
#endif
"
"
" gl_FragColor = i == 0 ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);
"
" };
";
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 () ;
}
void showShaderInfo ( const char *what, GLhandleARB handle )
{
int len = 0 ;
showGLerror () ;
glGetObjectParameterivARB ( handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len ) ;
showGLerror () ;
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 ;
}
}
GLhandleARB installShader ( const char *src, GLenum type )
{
const char *type_str = type == GL_VERTEX_SHADER ? "vertex" : "fragment";
GLhandleARB handle = glCreateShaderObjectARB ( type ) ;
glShaderSource ( handle, 1, &src, 0 ) ;
glCompileShader ( handle ) ;
GLint stat ;
glGetObjectParameterivARB ( handle, GL_OBJECT_COMPILE_STATUS_ARB, & stat ) ;
showShaderInfo ( type_str, handle ) ;
if ( ! stat )
{
fprintf ( stderr, "Failed to compile %s shader.
", type_str );
exit ( 1 ) ;
}
return handle ;
}
GLhandleARB linkShaders ( GLhandleARB vsHandle, GLhandleARB fsHandle )
{
GLint stat ;
GLhandleARB handle = glCreateProgramObjectARB () ;
glAttachObjectARB ( handle, vsHandle ) ;
glAttachObjectARB ( handle, fsHandle ) ;
glLinkProgramARB ( handle ) ;
glGetObjectParameterivARB ( handle, GL_OBJECT_LINK_STATUS_ARB, &stat ) ;
showShaderInfo ( "Linking", handle ) ;
glValidateProgram ( handle ) ;
showShaderInfo ( "Validate", handle ) ;
if ( ! stat )
{
fprintf ( stderr, "Failed to link shader.
" ) ;
exit ( 1 ) ;
}
return handle ;
}
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 ) ;
// Load and compile shaders
printf( "Compiling vertex shader...
" );
GLhandleARB vsHandle = installShader ( Vertex_src, GL_VERTEX_SHADER );
printf( "Compiling fragment shader...
" );
GLhandleARB fsHandle = installShader ( Fragment_src, GL_FRAGMENT_SHADER);
// Link shaders
printf( "Linking...
" );
GLhandleARB handle = linkShaders ( vsHandle, fsHandle ) ;
// Activate shader
glUseProgramObjectARB ( handle ) ;
// Draw with shader
glutMainLoop () ;
return 0 ;
}