-0.5 w wzorze zapewnia nam centrowanie punktów na środkach pikseli.
Sekwencja ta degraduje się dla wyższych wymiarów. W przypadku 2D bardzo szybko.
Przykłady:
2
3
4
5
Widzimy, że być może i jest to sekwencja o niskiej dyspersji, ale punkty zdecydowanie układają się w wzór, który jak każda powtarzalność w próbkowaniu podatny jest na aliasing. Widać to też na poniższym periodogramie.
Przykład pierodogramu dla bazy 3:
Kod:
public static class LowDiscrepancyMath
{
public static double RadicalInverse(int a_n, int a_base)
{
double y = 0;
double b = a_base;
while (a_n > 0)
{
int d_i = a_n % a_base;
y += d_i / b;
a_n /= a_base;
b *= a_base;
}
return y;
}
}
public class HammersleySampler : LowDiscrepancySequenceSampler
{
private int m_n = 1;
private List<Vector2>[,] m_samples;
private int m_count;
public int BaseY = 3;
private double NextX()
{
return (m_n - 0.5) / m_count;
}
public override IEnumerable<Vector2> GetSamples(Rectangle a_rect)
{
foreach (var p in a_rect.EnumPixels())
{
if (m_samples[p.X, p.Y] == null)
continue;
foreach (var s in m_samples[p.X, p.Y])
yield return s;
}
}
public override SamplerType SamplerType
{
get
{
return SamplerType.Hammersley;
}
}
internal override void RenderStart(RenderStartPhase a_phase)
{
base.RenderStart(a_phase);
if (a_phase == RenderStartPhase.PrepareObjectToRender)
PrepareSamples();
}
private void PrepareSamples()
{
m_samples = new List<Vector2>[Film.Width, Film.Height];
m_count = Film.Width * Film.Height * Subresolution * Subresolution;
for (int i=0; i<m_count; i++)
{
Vector2 s = new Vector2(
NextX() * Film.Width,
LowDiscrepancyMath.RadicalInverse(m_n, BaseY) * Film.Height);
Point p = new Point((int)s.X, (int)s.Y);
if (m_samples[p.X, p.Y] == null)
m_samples[p.X, p.Y] = new List<Vector2>();
m_samples[p.X, p.Y].Add(s);
m_n++;
}
}
}





Brak komentarzy:
Prześlij komentarz