Проблема затенения GLSL: почему моя сфера в оттенках серого вместо красной?(см код) - PullRequest
1 голос
/ 08 февраля 2011

Я работаю над шейдерной программой для начинающих 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: Вот код длянастройка моего шейдера (предоставляется моей 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 ]

2 голосов
/ 08 февраля 2011

Хорошей идеей будет проверить не только журнал ссылок, но также и журналы компиляции для каждого шейдера и результат компиляции / ссылки:

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

Убедитесь, что результаты положительные, а журналы пустые (или хорошие).

Диффузный термин рассчитывается неправильно в вашем примере. Оно должно иметь следующее значение:

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

Вам не нужно зажимать (), так как результат точки () нормализованных векторов не может превышать 1.

Если вы убедились, что шейдерная программа связана правильно, активировали ее при рисовании и результат все еще странный, попробуйте выбрать различные компоненты вашего окончательного цветового уравнения, чтобы найти неправильный:

gl_FragColor = DiffuseColor;       //can't be grayscale
gl_FragColor = vec4(DiffuseTerm);  //should be diffuse grayscale

Кстати, glColor3f не должен иметь ничего общего с вашим шейдером, поскольку вы не используете gl_Color внутри. Если результат изменится, когда вы его вызовите, это будет означать, что активация шейдера не удалась (она не связывалась или не использовалась вообще).

Удачи!

0 голосов
/ 08 февраля 2011

Может быть это связано с нежелательным поведением вашего альфа-канала.

Вы на самом деле вычисляете освещение на своем альфа-канале, фактически имея что-то вроде: g

gl_FragColor.a = 1,0 + 1,0 * DiffuseTerm

, что даст вам> = 1,0 значения.

Вы должны быть осторожны, чтобы не включать свой альфа-канал в свой вывод (или даже в свои расчеты).

Попробуйте убедиться, что смешивание отключено, или зафиксируйте ваш шейдер примерно так:

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