Я пишу шейдер, чтобы отображать сферы на точечных спрайтах, рисуя заштрихованные круги, и вам нужно написать компонент глубины, а также цвет, чтобы сферы рядом друг с другом были правильно пересечены.
Я использую код, похожий на код, написанный Johna Holwerda:
void PS_ShowDepth(VS_OUTPUT input, out float4 color: COLOR0,out float depth : DEPTH)
{
float dist = length (input.uv - float2 (0.5f, 0.5f)); //get the distance form the center of the point-sprite
float alpha = saturate(sign (0.5f - dist));
sphereDepth = cos (dist * 3.14159) * sphereThickness * particleSize; //calculate how thick the sphere should be; sphereThickness is a variable.
depth = saturate (sphereDepth + input.color.w); //input.color.w represents the depth value of the pixel on the point-sprite
color = float4 (depth.xxx ,alpha ); //or anything else you might need in future passes
}
Видео по этой ссылке дает хорошее представление о влиянии, которое я получаю: те сферы, которые нарисованы на точечных спрайтах, пересекаются правильно. Я добавил изображения ниже, чтобы проиллюстрировать это.
Я могу точно рассчитать глубину точечного спрайта. Однако я не уверен, что рассчитает толщину сферы на пиксель, чтобы добавить ее к глубине спрайта, чтобы дать окончательное значение глубины. (Приведенный выше код использует переменную, а не вычисляет ее.)
Я работаю над этим в течение нескольких недель, но не понял это - я уверен, что это просто, но это то, что мой мозг не взмахнул.
Размеры спрайта Direct3D 9 точек вычисляются в пикселях, а мои спрайты имеют несколько размеров - как путем спада из-за расстояния (я реализовал тот же алгоритм, что и старый континент с фиксированной функцией, используемый для вычислений размера точки в моем вершинном шейдере), а также из-за того, что представляет спрайт.
Как я могу перейти от данных, которые у меня есть в пиксельном шейдере (расположение спрайтов, глубины спрайта, исходный радиус мирового пространства, радиус в пикселях на экране, нормализованное расстояние от пикселя, о котором идет речь, от центра спрайта ) до значения глубины? Частичное решение просто размера спрайта по толщине шара в координатах глубины было бы точным - это можно масштабировать по нормализованному расстоянию от центра, чтобы получить толщину сфера в пикселе.
Я использую Direct3D 9 и HLSL с шейдерной моделью 3 в качестве верхнего предела SM.
На снимках
Чтобы продемонстрировать технику и точку, в которой у меня возникают проблемы:
Начните с двух точечных спрайтов, а в пиксельном шейдере нарисуйте круг на каждом, используя clip, чтобы удалить фрагменты вне границы круга:
Один будет изображать над другим, так как в конце концов они являются плоскими поверхностями.
Теперь сделайте шейдер более продвинутым и нарисуйте круг, как если бы он был сферой, с освещением. Обратите внимание, что даже если плоские спрайты выглядят 3D, они все еще рисуют один полностью перед другим, поскольку это иллюзия: они все еще плоские.
(Это легко, это последний шаг, с которым у меня возникают проблемы, и я спрашиваю, как это сделать.)
Теперь вместо пиксельного шейдера, записывающего только значения цвета, он также должен написать глубину:
void SpherePS (...any parameters...
out float4 oBackBuffer : COLOR0,
out float oDepth : DEPTH0 <- now also writing depth
)
{
Заметим, что теперь сферы пересекаются, когда расстояние между ними меньше их радиусов:
Как вычислить правильное значение глубины для достижения этого последнего шага?
Изменить/Примечания
Несколько человек отметили, что реальная сфера будет искажаться из-за перспективы, которая может быть особенно заметна по краям экрана, и поэтому я должен использовать другую технику. Во-первых, спасибо за указание, что это не обязательно очевидно и хорошо для будущих читателей! Во-вторых, моя цель состоит не в том, чтобы сделать перспективную сферу, а в том, чтобы быстро отображать миллионы точек данных, и визуально я думаю, что сфероподобный объект выглядит лучше, чем плоский спрайт, и лучше показывает пространственное положение. Небольшое искажение или отсутствие искажения не имеет значения. Если вы смотрите демонстрационное видео, вы можете увидеть, как это полезный визуальный инструмент. Я не хочу отображать реальные сетки сферы из-за большого количества треугольников по сравнению с простым аппаратным точечным спрайтом. Я действительно хочу использовать технику точечных спрайтов, и я просто хочу расширить существующую демонстрационную технику, чтобы вычислить правильное значение глубины, которое в демо было передан как переменная без источника для того, как она была получена.