Как рассчитать глубину пиксельного шейдера для визуализации круга, нарисованного на точечном спрайте, в виде сферы, которая будет пересекаться с другими объектами?

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

Я использую код, аналогичный написанномуДжона Холверда:

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

Чтобы продемонстрировать технику и момент, когда у меня возникают проблемы:

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

enter image description here

Один будет рендериться выше другого, так как в конце концов они являются плоскими поверхностями.

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

enter image description here

(Вышесказанное легко; это последний шаг, с которым у меня возникли проблемы, и я спрашиваю, как его достичь.)

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

void SpherePS (...any parameters...
    out float4 oBackBuffer : COLOR0,
    out float oDepth : DEPTH0 <- now also writing depth
   )
{

Обратите внимание, что теперь сферы пересекаются, когда расстояние между ними меньше их радиусов:

enter image description here

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

Edit / Notes

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

Ответы на вопрос(3)

Ваш ответ на вопрос