有了這些着色器,你可以只是發出一個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;
}
這是OpenGL的一個非常有用的屬性。對於DX而言,OpenGl dat的Niiice無法做到這一點。 :O – 2013-04-12 03:16:05
謝謝!我有一個額外的懶惰的東西,放在某處去除'prog'參數(通過查詢OpenGL獲取當前程序ID)以及默認參數化一些較少使用的東西。我會盡力挖掘並編輯它。 – genpfault
如果只是爲了我,不要去那麼麻煩。實際上,我現在在DirectX上工作(並且讓我的屁股被延遲渲染踢掉)。我將盡快將所有內容移植到OpenGL上,所以當發生這種情況時,我一定會完全滑向這個答案,並在我需要使用屬性時抓住這一點。 :P – 2013-04-12 03:28:20