Как рассчитать глубину пиксельного шейдера для визуализации круга, нарисованного на точечном спрайте, в виде сферы, которая будет пересекаться с другими объектами?
Я пишу шейдер для рендеринга сфер на точечных спрайтах, рисуя заштрихованные круги, и мне нужно написать компонент глубины, а также цвет, чтобы сферы рядом пересекались правильно.
Я использую код, аналогичный написанномуДжона Холверда:
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
}
Видео по этой ссылке дает хорошее представление о том, какой эффект я испытываю после: эти сферы, нарисованные на точечных спрайтах, правильно пересекаются. Я добавил изображения ниже для иллюстрации.
Я могу рассчитать глубину точечного спрайта, сам отлично. Тем не менее, я не уверен, что показатьcalculate the thickness of the sphere at a pixel чтобы добавить его к глубине спрайта, дать окончательное значение глубины. (Приведенный выше код использует переменную, а не вычисляет ее.)
Я работал над этим и выключал в течение нескольких недель, но не понял этого - я уверен, что это просто, но это что-то, что мой мозг не шевелил.
Размеры точечных спрайтов в Direct3D 9 рассчитываются в пикселях, и мои спрайты имеют несколько размеров - оба из-за спада из-за расстояния (я реализовалтот же алгоритм, что и старый конвейер с фиксированной функцией, используемый для вычисления размера точки в моем вершинном шейдере), а также из-за того, что представляет собой спрайт.
How do I go from the data I have in a pixel shader (sprite location, sprite depth, original world-space radius, radius in pixels onscreen, normalised distance of the pixel in question from the centre of the sprite) to a depth value? Частичное решение простоsprite size to sphere thickness in depth coordinates было бы хорошо - это можно масштабировать на нормализованное расстояние от центра, чтобы получить толщину сферы в пикселе.
Я использую Direct3D 9 и HLSL с шейдерной моделью 3 в качестве верхнего предела SM.
In picturesЧтобы продемонстрировать технику и момент, когда у меня возникают проблемы:
Начните с двухточечных спрайтов, и в пиксельном шейдере нарисуйте круг на каждом, используяклип удалить фрагменты вне границы круга:
Один будет рендериться выше другого, так как в конце концов они являются плоскими поверхностями.
Теперь сделайте шейдер более продвинутым и нарисуйте круг, как будто это сфера с освещением. Следует отметить, что хотя плоские спрайты выглядят трехмерными, они по-прежнему рисуют одним полностью впереди другого, поскольку это иллюзия: они все еще плоские.
(Вышесказанное легко; это последний шаг, с которым у меня возникли проблемы, и я спрашиваю, как его достичь.)
Теперь вместо пиксельного шейдера, записывающего только значения цвета, он должен также записать глубину:
void SpherePS (...any parameters...
out float4 oBackBuffer : COLOR0,
out float oDepth : DEPTH0 <- now also writing depth
)
{
Обратите внимание, что теперь сферы пересекаются, когда расстояние между ними меньше их радиусов:
Как рассчитать правильное значение глубины, чтобы выполнить этот последний шаг?
Edit / NotesНесколько человек отметили, что реальная сфера будет искажаться из-за перспективы, которая может быть особенно заметна по краям экрана, и поэтому я должен использовать другую технику. Во-первых, спасибо за указание на то, что это не обязательно очевидно и полезно для будущих читателей! Во-вторых, моя цель состоит не в том, чтобы визуализировать правильную в перспективе сферу, а в том, чтобы быстро отрисовать миллионы точек данных, и визуально я думаю, что сферический объект выглядит лучше, чем плоский спрайт, и также лучше показывает пространственное положение. Незначительные искажения или отсутствие искажений не имеют значения. если тыпосмотреть демо-видео, вы можете увидеть, насколько это полезный визуальный инструмент. Я не хочу отображать реальные сферические сетки из-за большого количества треугольников по сравнению с простым аппаратным точечным спрайтом. Я действительно хочу использовать технику точечных спрайтов, и я просто хочу расширитьсуществующая демонстрационная техника для того, чтобы вычислить правильное значение глубины, которое в демонстрационной версии было передано как переменная без источника для того, как оно было получено.