/** * Raster the color triangle to the screen. Points are in * NDC coordinates (converted to screen coordinates). * * colors correspond to the respective points. */ void raster_triangle(point *a, point *b, point *c, color ca, color cb, color cc, int xres, int yres, color** grid, float** depth_grid) { point screen_a = NDC_to_screen(a, xres, yres); point screen_b = NDC_to_screen(b, xres, yres); point screen_c = NDC_to_screen(c, xres, yres); float x_min = min_x(&screen_a, &screen_b, &screen_c); float x_max = max_x(&screen_a, &screen_b, &screen_c); float y_min = min_y(&screen_a, &screen_b, &screen_c); float y_max = max_y(&screen_a, &screen_b, &screen_c); x_max = x_max > xres ? xres : x_max; y_max = y_max > yres ? yres : y_max; for (int x = x_min; x < x_max; x++) { for (int y = y_min; y < y_max; y++) { point curr_point = create_point(x, y, 0); float alpha = compute_alpha(&screen_a, &screen_b, &screen_c, &curr_point); float beta = compute_beta(&screen_a, &screen_b, &screen_c, &curr_point); float gamma = compute_gamma(&screen_a, &screen_b, &screen_c, &curr_point); curr_point.z = alpha * screen_a.z + beta * screen_b.z + gamma * screen_c.z; if (valid_parameters(alpha, beta, gamma) && depth_grid[x][y] > curr_point.z) { color col = compute_color(ca, cb, cc, alpha, beta, gamma); grid[x][y].r = col.r; grid[x][y].g = col.g; grid[x][y].b = col.b; depth_grid[x][y] = curr_point.z; } } } }
int main(int argc, char *argv[]) { int nx = 450; int ny = 450; int ns = 300; camera cam(M_PI/3.7, float(nx)/float(ny)); hitable_list list; mk_cornell_box(list); set_cornell_view(cam, nx, ny); #ifdef _WIN32 setmode(fileno(stdout), O_BINARY); #endif // Don't stack allocate this, it is usually way larger than the compiler's set // stack size. unsigned char *img = new unsigned char[nx * ny * 3]; //std::cout << "P3\n" << nx << " " << ny << "\n255\n"; for (int j = ny - 1; j >= 0; j--) { for (int i = 0; i < nx; i++) { vec3 col(0,0,0); for (int s=0; s < ns; s++) { float u = float(i + random1d()) / float(nx); float v = float(j + random1d()) / float(ny); ray r = cam.get_ray(u, v); col += compute_color(r, &list, 0); } col /= float(ns); col = gamma_corrected_clamp(col); /*if (col.x() > 1 || col.y() > 1 || col.z() > 1) std::cout << "# channel greater than 1 at " << i << "," << j << "\n"; */ img[((ny - 1 - j) * nx + i) * 3 + 0] = (unsigned char)(254.99 * col[0]); img[((ny - 1 - j) * nx + i) * 3 + 1] = (unsigned char)(254.99 * col[1]); img[((ny - 1 - j) * nx + i) * 3 + 2] = (unsigned char)(254.99 * col[2]); //std::cout << ir << " " << ig << " " << ib << "\n"; } } if (!stbi_write_png_to_func(stbi_write_to_stdout, 0, nx, ny, 3, img, 3 * sizeof(char) * nx)) std::cerr << "Failed to write anything at all.\n"; delete[] img; }
color compute_color(ray const &r, hitable *world, int depth) { hit_record rec = {}; if (world->hit(r, 0.0001f, FLT_MAX, rec)) { ray scattered; color attenuation; if (rec.mat_ptr == 0) std::cerr << "SCHEISSE!"; color emitted = rec.mat_ptr->emitted(rec.u, rec.v, rec.P); if (depth < 50 && rec.mat_ptr->scatter(r, rec, attenuation, scattered)) { return emitted + attenuation * compute_color(scattered, world, depth+1); } else return emitted; } return color(0,0,0); }