1
0
mirror of https://github.com/ssloy/tinyraytracer.git synced 2025-01-17 06:08:14 +01:00

random dot autostereogram

This commit is contained in:
Dmitry V. Sokolov 2019-02-03 15:11:43 +01:00
parent 6842f67bb7
commit 7a2599f76e
2 changed files with 33 additions and 1 deletions

BIN
doc/autostereogram.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -68,6 +68,20 @@ void compute_depthmap(const size_t width, const size_t height, const float fov,
zbuffer[i] = 1-(std::min(zbuffer[i],far)-minval)/(maxval-minval);
}
int parallax(const float z) {
const float eye_separation = 400.; // interpupillary distance in pixels
const float mu = .33; // if the far plane is a distance D behind the screen, then the near plane is a distance mu*D in front of the far plane
return static_cast<int>(eye_separation*((1.-z*mu)/(2.-z*mu))+.5);
}
size_t uf_find(std::vector<size_t> &same, size_t x) {
return same[x]==x ? x : uf_find(same, same[x]);
}
void uf_union(std::vector<size_t> &same, size_t x, size_t y) {
if ((x=uf_find(same, x)) != (y=uf_find(same, y))) same[x] = y;
}
int main() {
std::vector<Sphere> spheres = { {{-3,0,-16}, 2}, {{-1,-1.5,-12}, 2}, {{1.5,-.5,-18}, 3}, {{7,5,-18}, 4} };
const size_t width = 1024;
@ -79,12 +93,30 @@ int main() {
std::vector<unsigned char> framebuffer(width*height*3);
for (size_t j=0; j<height; j++) { // generate a random-ish image
for (size_t i=0; i<width; i++) {
framebuffer[(i+j*width)*3 + 0] = (rand()%256)*(sin(i*2*M_PI/200)+1)/2; // the sine generates vertical strips to ease focusing
framebuffer[(i+j*width)*3 + 0] = (rand()%256)*(sin(i*2*M_PI/parallax(0))+1)/2; // the sine generates vertical strips to ease focusing
framebuffer[(i+j*width)*3 + 1] = (rand()%256);
framebuffer[(i+j*width)*3 + 2] = (rand()%256);
}
}
for (size_t j=0; j<height; j++) { // autostereogram rendering loop
std::vector<size_t> same(width);
std::iota(same.begin(), same.end(), 0); // initialize the union-find data structure (same[i]=i)
for (size_t i=0; i<width; i++) { // put the constraints
int par = parallax(zbuffer[i+j*width]);
int left = i - par/2;
int right = left + par; // works better than i+par/2 for odd values of par
if (left>=0 && right<(int)width)
uf_union(same, left, right); // left and right pixels will have the same color
}
for (size_t i=0; i<width; i++) { // resolve the constraints
size_t root = uf_find(same, i);
for (size_t c=0; c<3; c++)
framebuffer[(i+j*width)*3+c] = framebuffer[(root+j*width)*3+c];
}
}
std::ofstream ofs("./out.ppm"); // save the framebuffer to file
ofs << "P6\n" << width << " " << height << "\n255\n";
ofs.write(reinterpret_cast<char *>(framebuffer.data()), 3*height*width);