Początkowo miałem otrzymać taką samą odpowiedź, jak wszyscy inni i przypisać to do problemów rand(). Jednak pomyślałem, że lepiej to zrobić i zamiast tego przeanalizowałem rozkład, który faktycznie generuje twoja matematyka.
TL; DR: Wzorzec, który widzisz nie ma nic wspólnego z podstawowym generatorem liczb losowych, a zamiast tego jest po prostu spowodowany sposobem, w jaki twój program manipuluje liczbami.
Będę trzymał się twojej niebieskiej funkcji, ponieważ wszystkie są podobne.
uint8_t blue(uint32_t x, uint32_t y) {
return (rand() % 2) ? (x + y) % rand() :
((x * y % 1024) % rand()) % 2 ? (x - y) % rand() :
rand();
}
Każda wartość piksela jest wybrany z jednej z trzech funkcji: (x + y) % rand(), (x - y) % rand()i rand();
Spójrzmy na obrazy utworzone przez każde z nich samodzielnie.
Tego można się spodziewać, po prostu hałasu. Nazwij to „Obrazem C”

Tutaj dodajesz współrzędne pikseli, a resztę bierzesz z dzielenia przez liczbę losową. Jeśli obraz ma rozmiar 1024x1024, to suma mieści się w zakresie [0-2046]. Losowa liczba, według której nurkujesz, mieści się w zakresie [0, RAND_MAX], gdzie RAND_MAX wynosi co najmniej 32 tys., Aw niektórych systemach wynosi 2 miliardy. Innymi słowy, jest co najwyżej 1 na 16 szans, że reszta nie jest po prostu (x + y). Więc w większości ta funkcja po prostu wytworzy gradient rosnącego niebieskiego w kierunku + x + y.
Jednak używasz tylko najniższych 8 bitów, ponieważ zwracasz a uint8_t, więc będziesz mieć paski gradientów o szerokości 256 pikseli.
Nazwij to „Obrazem A”

Tutaj robisz coś podobnego, ale z odejmowaniem. Dopóki x jest większe niż y, będziesz mieć coś podobnego do poprzedniego obrazu. Ale gdy y jest większe, wynikiem jest bardzo duża liczba, ponieważ xi ysą bez znaku (wyniki ujemne zawijają się do początku zakresu typu bez znaku), a następnie % rand()kopnięcia i faktycznie pojawia się szum.
Nazwij to „Obrazem B”

Każdy piksel końcowego obrazu jest pobierany z jednego z tych trzech obrazów przy użyciu funkcji rand() % 2i ((x * y % 1024) % rand()) % 2. Pierwszy z nich można odczytać jako wybieranie z 50% prawdopodobieństwem (ignorowanie problemów z rand()bitami o najniższej kolejności).
Oto zbliżenie miejsca, w którym rand() % 2jest prawdziwe (białe piksele), więc wybrano Obraz A.

Druga funkcja ((x * y % 1024) % rand()) % 2znowu ma problem, gdzie rand()jest zwykle większa niż (x * y % 1024)dzielona rzecz , która wynosi co najwyżej 1023. Wtedy (x*y%1024)%2nie daje równorzędnie 0 i 1. Każda liczba nieparzysta pomnożona przez dowolną liczbę parzystą jest parzysta. Każda liczba parzysta pomnożona przez dowolną liczbę parzystą jest również parzysta. Tylko liczba nieparzysta pomnożona przez liczbę nieparzystą jest nieparzysta, a zatem %2wartości parzyste w trzech czwartych czasu dadzą 0 w trzech czwartych czasu.
Oto zbliżenie miejsca, w którym ((x * y % 1024) % rand()) % 2jest prawdziwe, aby można było wybrać obraz B. Wybiera dokładnie, gdzie obie współrzędne są nieparzyste.

A oto zbliżenie miejsca, w którym można wybrać Obraz C:

Na koniec łącząc warunki, tutaj wybrano Obraz B:

A gdzie wybrany jest Obraz C:

Wynikową kombinację można odczytać jako:
Z prawdopodobieństwem 50% użyj piksela z obrazu A. Reszta czasu wybierz między obrazem B a obrazem C, B, gdzie obie współrzędne są nieparzyste, C, gdzie jedna z nich jest parzysta.
Wreszcie, ponieważ robisz to samo dla trzech różnych kolorów, ale przy różnych orientacjach, wzory są zorientowane inaczej w każdym kolorze i tworzą przecinające się paski lub wzór siatki, który widzisz.