glColor()
使用这些着色器,您可以在绘制之前发出 a :
glColor3f( r, g, b );
// draw geometry
gl_Color
但是,如果您已经使用通用顶点属性作为位置,那么固定函数互操作预定义变量(在顶点着色器中)有点毫无意义。
在这种情况下,您可以glUniform()
改用:
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include <vector>
using namespace std;
// RAII vertex attribute wrapper
struct Attrib
{
Attrib
(
const char* name, const GLint size, const GLsizei stride, const GLvoid* pointer,
const GLenum type = GL_FLOAT, const GLboolean normalized = GL_FALSE, const GLuint prog = GetProgram()
)
{
mLoc = glGetAttribLocation( prog, name );
if( mLoc < 0 ) return;
glVertexAttribPointer( mLoc, size, type, normalized, stride, pointer );
glEnableVertexAttribArray( mLoc );
}
~Attrib()
{
if( mLoc < 0 ) return;
glDisableVertexAttribArray( mLoc );
}
GLint mLoc;
private:
static GLuint GetProgram()
{
GLint program = 0;
glGetIntegerv( GL_CURRENT_PROGRAM, &program );
return program;
}
};
// GLSL shader program loader
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
120,
attribute vec2 position;
void main()
{
gl_Position = vec4( position, 0.0, 1.0 );
}
);
const char* frag = GLSL
(
120,
uniform vec3 uColor;
void main()
{
gl_FragColor = vec4( uColor, 1.0 );
}
);
float r = 1, g = 0, b = 0;
void keyboard( unsigned char key, int x, int y )
{
if( key == 'c' )
{
r = 1 - r;
g = 1 - g;
b = 1 - b;
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
// prepare to render
static GLuint prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
glUniform3f( glGetUniformLocation( prog, "uColor" ), r, g, b );
float verts[] = {
-1 / 2.0, -1 / 2.0,
1 / 2.0, -1 / 2.0,
1 / 2.0, 1 / 2.0,
-1 / 2.0, 1 / 2.0,
};
{
Attrib a1( "position", 2, 0, verts );
glDrawArrays( GL_QUADS, 0, 4 );
}
glutSwapBuffers();
}
void timer( int extra )
{
glutTimerFunc( 16, timer, 0 );
glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitWindowSize( 600, 600 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow( "GLUT" );
glewInit();
glutKeyboardFunc( keyboard );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}