Рисование карты нормалей сферы в фрагментном шейдере - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь нарисовать простую сферу с нормальным отображением в фрагментном шейдере с помощью GL_POINTS. В настоящее время я просто рисую одну точку на экране и применяю фрагментный шейдер для его «сферификации».

Однако у меня возникают проблемы с правильным окрашиванием сферы (или, по крайней мере, я так думаю). Кажется, я правильно вычисляю z, но когда я применяю «нормальные» цвета к gl_FragColor, это выглядит не совсем правильно (или это то, что можно ожидать от карты нормалей?). Я предполагаю, что есть некоторое несоответствие между gl_PointCoord и координатой фрагмента, но я не могу понять это.

Вершинный шейдер

precision mediump float;

attribute vec3 position;

void main() {
  gl_PointSize = 500.0;
  gl_Position = vec4(position.xyz, 1.0);
}

фрагментный шейдер

precision mediump float;

void main() {

  float x = gl_PointCoord.x * 2.0 - 1.0;
  float y = gl_PointCoord.y * 2.0 - 1.0;

  float z = sqrt(1.0 - (pow(x, 2.0) + pow(y, 2.0)));

  vec3 position = vec3(x, y, z);

  float mag = dot(position.xy, position.xy);
  if(mag > 1.0) discard;

  vec3 normal = normalize(position);

  gl_FragColor = vec4(normal, 1.0);
}

Фактическая выработка:

enter image description here

Ожидаемый результат:

enter image description here

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Цветовые каналы ограничены диапазоном [0, 1]. (0, 0, 0) черный, а (1, 1, 1) полностью белый.

Поскольку вектор нормали нормализован, его составляющая находится в диапазоне [-1, 1]. Чтобы получить ожидаемый результат, вы должны отобразить вектор нормалей из диапазона [-1, 1] в [0, 1]:

vec3 normal_col = normalize(position) * 0.5 + 0.5;
gl_FragColor    = vec4(normal_col, 1.0);

Если вы используете значение abs, то положительные и отрицательные значения с одинаковым размером имеют одинаковое представление цвета. Интенсивность цвета увеличивается с градацией значения:

vec3 normal_col = abs(normalize(position));
gl_FragColor    = vec4(normal_col, 1.0);

0 голосов
/ 13 ноября 2018

Прежде всего, нормальная сторона камеры [0,0,-1] должна иметь значения rgb: [0.5,0.5,1.0].Вы должны изменить масштаб, чтобы эти отрицательные значения были между 0 и 1.

Во-вторых, нормали сферы не будут меняться линейно, но в синусоидальной волне.Итак, вам нужна некоторая тригонометрия здесь.Для меня имеет смысл начать с перпендикулярной нормали [0,0,-1], а затем повернуть эту нормаль на угол, потому что angle - это то, что изменяется линейно.

В результате игрывокруг этого я придумал:

http://glslsandbox.com/e#50268.3

, который использует некоторую функцию поворота отсюда: https://github.com/yuichiroharai/glsl-y-rotate

...