1

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

顶点着色器:

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);

}

片段着色器:

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;
}

代码只是从教程中复制和粘贴。

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

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

然后我的球体如预期的那样是纯绿色的。我不知道是不是 openGL 代码中的某些东西(例如 Renderer.cpp)导致了冲突,或者是否还有其他问题。

这是我第一次在 GLSL 中编码,我很困惑我需要打开/关闭什么 gl_Enable 才能使着色器正常工作。

感谢您的任何反馈!

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

EDIT2: 所以事实证明,每当我将任何代码放入顶点着色器或片段着色器(除了 gl_Color = ...)时,我得到的纯色就会消失......我想这意味着我的着色器出了问题?

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

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 建议的着色器日志,我设法修复了着色器中的错误(结果发现有几个错误)。如果您想查看最终代码,请发表评论或给我留言(这个问题越来越长)。

4

2 回答 2

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

顺便说一句, glColor3f 应该与您的着色器无关,因为您不使用 gl_Color 内部。如果调用时结果发生变化 - 这意味着着色器激活失败(它没有链接或根本没有使用)。

祝你好运!

于 2011-02-08T19:40:48.947 回答
0

也许这是由于您的 Alpha 通道结果出现了不希望的行为。

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

gl_FragColor.a = 1.0 + 1.0 * DiffuseTerm

这将为您提供 >= 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);
}
于 2011-02-08T19:53:32.080 回答