From 7f81f26889b84542b0b35685b0e80383256cdc47 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 8 May 2021 20:31:42 +0300 Subject: [PATCH] Use non-random sequences to initialize ambient occlusion data This allows selecting the formulas to obtain a better distribution of values. --- source/effects/ambientocclusion.cpp | 21 +++++++++++---------- source/effects/ambientocclusion.h | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/source/effects/ambientocclusion.cpp b/source/effects/ambientocclusion.cpp index b4050aef..a407c2d9 100644 --- a/source/effects/ambientocclusion.cpp +++ b/source/effects/ambientocclusion.cpp @@ -41,11 +41,10 @@ const Texture2D &AmbientOcclusion::get_or_create_rotate_lookup() rotate_lookup->storage(RGBA8, 4, 4, 1); resources.add(name, rotate_lookup); - unsigned seed = 1; unsigned char data[64]; for(unsigned i=0; i<16; ++i) { - Geometry::Angle a = Geometry::Angle::from_turns(random(seed)); + Geometry::Angle a = Geometry::Angle::from_turns(i*7/16.0f); unsigned char c = (cos(a)*0.5f+0.5f)*255; unsigned char s = (sin(a)*0.5f+0.5f)*255; data[i*4 ] = c; @@ -58,11 +57,12 @@ const Texture2D &AmbientOcclusion::get_or_create_rotate_lookup() return *rotate_lookup; } -float AmbientOcclusion::random(unsigned &seed) +float AmbientOcclusion::radical_inverse(unsigned n) { - static const unsigned modulus = (1U<<31)-1; - seed = (static_cast(seed)*48271)%modulus; // minstd - return static_cast(seed)/(modulus-1); + unsigned inv = ((n&0x55)<<1) | ((n&0xAA)>>1); + inv = ((inv&0x33)<<2) | ((inv&0xCC)>>2); + inv = ((inv&0x0F)<<4) | ((inv&0xF0)>>4); + return inv/256.0f; } void AmbientOcclusion::set_n_samples(unsigned n) @@ -70,13 +70,14 @@ void AmbientOcclusion::set_n_samples(unsigned n) if(n<1 || n>32) throw out_of_range("AmbientOcclusion::set_n_samples"); - unsigned seed = 1; - float radius_divisor = (n-1)*(n-1); Vector3 sample_points[32]; for(unsigned i=0; i(i)/n; + float r = sqrt(1.0f-z*z); + float d = radical_inverse(i); + Geometry::Angle a = Geometry::Angle::from_turns(d); + sample_points[i] = Vector3(cos(a)*r, sin(a)*r, z)*(0.1f+0.9f*d*d); } shdata.uniform3_array("sample_points", n, &sample_points[0].x); shdata.uniform("n_samples", static_cast(n)); diff --git a/source/effects/ambientocclusion.h b/source/effects/ambientocclusion.h index 61d4d4f3..f186db3d 100644 --- a/source/effects/ambientocclusion.h +++ b/source/effects/ambientocclusion.h @@ -54,7 +54,7 @@ public: private: static const Texture2D &get_or_create_rotate_lookup(); - static float random(unsigned &); + static float radical_inverse(unsigned); public: void set_n_samples(unsigned); -- 2.43.0