GLSL на пиксель, затемнение света - PullRequest
4 голосов
/ 16 декабря 2011

VC ++, OpenGL, SDL

Мне интересно, есть ли способ добиться более плавного затенения в одном квадрате геометрии. Прямо сейчас, затенение выглядит гладким с моим точечным светом, однако интенсивность возрастает вдоль диагонального подразделения лица [/]. Освещение в основном не видно между вершинами.

enter image description here

enter image description here

enter image description here

Вот что происходит, когда свет движется слева направо

Когда я перемещаю свет по поверхности, он делает это последовательно. Становится ярче в каждой вершине и оттуда исчезает.

Я вынужден поднять подразделение, чтобы получить более гладкий, более радиальный оттенок? или есть способ обойти это?

Вот шейдеры, которые я использую:

верт

varying vec3 vertex_light_position;
varying vec3 vertex_normal;

void main() 
{            
    vertex_normal = normalize(gl_NormalMatrix * gl_Normal);
    vertex_light_position = normalize(gl_LightSource[0].position.xyz);

    gl_FrontColor = gl_Color;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

фраг

varying vec3 vertex_light_position;
varying vec3 vertex_normal;

void main() 
{
    float diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0);
    gl_FragColor = gl_Color * diffuse_value;
}

Моя геометрия, если кому-то интересно:

glBegin(GL_QUADS);
    glNormal3f(0.0f, 0.0f, 1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(pos_x, pos_y - size_y, depth);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(pos_x + size_x, pos_y - size_y, depth);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(pos_x + size_x, pos_y, depth);
    glTexCoord2f(0.0f, 0.0f); glVertex3f(pos_x, pos_y, depth);
glEnd();

Ответы [ 3 ]

5 голосов
/ 16 декабря 2011

Есть несколько вещей, которые я считаю возможными.

Если я не ошибаюсь, вы используете normalize(gl_LightSource[0].position.xyz); для расчета вектора света, но он основан исключительно на положении света, а не на вершине, с которой вы работаете. Это означает, что значение будет одинаковым для каждой вершины и будет меняться только в зависимости от текущей матрицы вида модели и положения источника света. Я бы подумал, что вычисление вектора света с помощью чего-то вроде normalize(glLightSource[0].position.xyz - (gl_ModelViewMatrix * gl_Vertex).xyz) будет ближе к тому, что вы хотели бы.

Во-вторых, вы должны нормализовать свои векторы в фрагментном шейдере, а также в вершинном шейдере, поскольку интерполяция двух единичных векторов не обязательно является самим единичным вектором.

2 голосов
/ 16 декабря 2011

Я думаю, что проблема со светлым вектором ...

Я предлагаю использовать:

vec3 light_vector = normalize(gl_LightSource[0].position.xyz - vertex_pos)

vertex_pos можно рассчитать с помощью:

vertex_pos = gl_ModelViewMatrix * gl_Vertex

Обратите внимание, что все векторы должны находиться в одном пространстве (камера, мир, объект)

1 голос
/ 16 декабря 2011

Я вынужден поднять подразделение, чтобы добиться более плавного, более радиального тень? или есть способ обойти это?

Нет, вы можете делать все, что хотите. Единственный код, который вам нужно изменить, это фрагментный шейдер. Попробуйте поиграть с ним и посмотрите, получите ли вы лучший результат.

Например, вы можете сделать это:

diffuse_value = pow(diffuse_value, 3.0);

как объяснено здесь .

...