1

我有一个应用程序,我在 GLUT 窗口上绘制了一堆点。我有一个顶点着色器和一个片段着色器,我给了一个颜色输入。我的顶点着色器看起来像:

#version 120
attribute vec2 position;

varying vec4 vColor;

void main()
{
   vColor = gl_Color;
   gl_Position = vec4( position, 0.0, 1.0 );
}

我的碎片着色器看起来像:

#version 120

varying vec4 vColor;
void main()
{
    gl_FragColor = vColor;
}

我希望用户能够根据按键更改点的颜色。所以,我有一些按键处理功能:

void handleKeyPress(unsigned char key, int x, int y)
{
    if (key == 'c')
       //todo: change the point colors to green
}

我该如何做那个“待办事项”?

4

2 回答 2

2

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;
}
于 2013-04-12T03:14:47.363 回答
0

有一个名为glVertexAttrib的 OpenGL 函数,允许您将顶点属性设置为整个绘制调用的固定值,而不是从顶点缓冲区对象中获取每个顶点的值。与使用颜色指定统一变量相比,使用它的优势在于,您可以使用单独的每个顶点颜色渲染几何图形,也可以使用相同的顶点/片段着色器对渲染没有此类属性的几何图形。

于 2013-05-07T20:38:52.537 回答