GLSL着色问题:为什么我的球体是灰度而不是红色? (见代码)

时间:2011-02-08 08:27:48

标签: opengl graphics glsl lighting

我正在开发初学者级别的GLSL着色器程序。我正在关注this教程。但是我的球体总是以灰度显示,而不像我预期的那样是红色。

顶点着色器:

varying vec3 normal, lightDir;

void main() {

    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    normal = gl_NormalMatrix * gl_Normal;

    vec4 vertex_in_modelview_space = gl_ModelViewMatrx * gl_Vertex;

    lightDir = vec3(gl_LightSource[0].position – vertex_in_modelview_space);

}

Frag Shader:

varying vec3 normal, lightDir;

void main()
{

    const vec4 AmbientColor = vec4(0.1, 0.0, 0.0, 1.0);
    const vec4 DiffuseColor = vec4(1.0, 0.0, 0.0, 1.0);

    vec3 normalized_normal = normalize(normal);
    vec3 normalized_lightDir = normalize(lightDir);

    float DiffuseTerm = clamp(dot(normal, lightDir), 0.0, 1.0);
    gl_FragColor = AmbientColor + DiffuseColor * DiffuseTerm;
}

代码只是复制并粘贴教程。

从frag着色器中,漫反射颜色为红色,但我的球体为灰度。我知道着色器已正确加载,因为如果我取出frag着色器中的代码并使用以下内容:

gl_FragColor = vec4(0.0,1.0,0.0,1.0);

然后我的球体像预期的那样呈绿色。我不知道openGL代码(如Renderer.cpp)中是否存在导致冲突的问题,或者是否存在其他错误。

这是我第一次使用GLSL进行编码,我很担心gl_Enable需要打开/关闭才能使着色器正常工作。

感谢您的反馈!

修改 好吧,如果我在渲染之前调用glColor3f,我可以得到正确的颜色。但是光的颜色不会直接导致球体颜色的变化吗?我担心我实际上并没有在着色器中调用函数......

EDIT2: 所以事实证明,每当我在顶点着色器或frag着色器中放置任何代码(gl_Color = ...除外)时,我得到的纯色消失......我想这意味着我的着色器出现了可怕的错误?< / p>

EDIT3: 这是设置我的着色器的代码(由我的TA提供):

char *vs = NULL,*fs = NULL;

v = glCreateShader(GL_VERTEX_SHADER);

f = glCreateShader(GL_FRAGMENT_SHADER);

vs = textFileRead(vert);
fs = textFileRead(frag);

const char * ff = fs;
const char * vv = vs;

glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);

free(vs);
free(fs);

glCompileShader(v);
glCompileShader(f);

p = glCreateProgram();
glAttachShader(p,f);
glAttachShader(p,v);

glLinkProgram(p);

int infologLength = 0;
int charsWritten  = 0;
char *infoLog;

glGetProgramiv(p, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
    infoLog = (char *)malloc(infologLength);
    glGetProgramInfoLog(p, infologLength, &charsWritten, infoLog);
    printf("%s\n",infoLog);
    free(infoLog);
}

EDIT4: 使用kvark建议的着色器日志,我设法修复着色器中的错误(原来有几个错误)。如果您想查看最终代码,请发表评论或给我留言(这个问题已经很久了)。

2 个答案:

答案 0 :(得分:2)

不仅要检查链接日志,还要检查每个着色器的日志以及编译/链接结果,这是一个好主意:

glGetShaderInfoLog(...)
glGetShaderiv(...,GL_COMPILE_STATUS,...)
glGetProgramiv(...,GL_LINK_STATUS,...)

确保结果为正,日志为空(或好)。

在您的示例中,漫反射项的计算方法不正确。它应具有以下值:

float DiffuseTerm = max(0.0, dot(normalized_normal,normalized_lightDir) );

您不需要clamp(),因为标准化矢量的dot()结果不能超过1。

如果你确定着色器程序是正确链接的,那么在绘图上激活它并且结果仍然很奇怪,尝试选择最终颜色方程的不同组件以找出错误的组件:

gl_FragColor = DiffuseColor;       //can't be grayscale
gl_FragColor = vec4(DiffuseTerm);  //should be diffuse grayscale
BTW,glColor3f应该与你的着色器无关,因为你没有在里面使用gl_Color。如果调用时结果发生变化 - 这意味着着色器激活失败(它没有链接或根本没有使用)。

祝你好运!

答案 1 :(得分:0)

可能这是由于您的Alpha通道结果出现了不受欢迎的行为。

你实际上是在alpha通道上计算灯光,实际上有类似的东西:g

  

gl_FragColor.a = 1.0 + 1.0 * DiffuseTerm

将为您提供&gt; = 1.0值。

您应该注意不要在输出中包含Alpha通道(甚至在计算中)。

尝试确保禁用混合,或者将着色器修复为:

varying vec3 normal, lightDir;

void main()
{
    const vec3 AmbientColor = vec3(0.1, 0.0, 0.0);
    const vec3 DiffuseColor = vec3(1.0, 0.0, 0.0);

    vec3 normalized_normal = normalize(normal);
    vec3 normalized_lightDir = normalize(lightDir);

    float DiffuseTerm = clamp(dot(normal, lightDir), 0.0, 1.0);
    gl_FragColor = vec4(AmbientColor + DiffuseColor * DiffuseTerm, 1.0);
}