我有一个应用程序,我在GLUT窗口上绘制一堆点。我有一个顶点着色器和一个frag着色器,我给它一个颜色输入。我的顶点着色器看起来像:
#version 120
attribute vec2 position;
varying vec4 vColor;
void main()
{
vColor = gl_Color;
gl_Position = vec4( position, 0.0, 1.0 );
}
我的frag shader看起来像:
#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
}
我该怎么做“todo”?
答案 0 :(得分:2)
使用这些着色器,您可以在绘制之前发出glColor()
:
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;
}
答案 1 :(得分:0)
有一个名为glVertexAttrib的OpenGL函数,允许您将顶点属性设置为整个绘制调用的固定值,而不是从顶点缓冲区对象中提取每顶点值。使用此方法优于使用颜色指定统一变量的优点是,您可以使用单独的每顶点颜色渲染两个几何体,并且使用相同的顶点/片段着色器对来渲染没有此类属性的几何体。