vec3f Renderer::sample(Scene& scene, Ray ray, int num_bounces) { vec3f accum_radiance(0.0, 0.0, 0.0); vec3f rem_radiance(1.0, 1.0, 1.0); for (int b=0; b < num_bounces; b++) { TriangleHit hit_data = scene.m_tree->hit(ray); Triangle* tri = hit_data.tri; float dist = hit_data.dist; if (tri == nullptr) { return vec3f(0.0, 0.0, 0.0); } tinyobj::mesh_t mesh = tri->shape_data->mesh; Material mat = scene.m_mats[mesh.material_ids[tri->index / 3]]; // Material properties vec3f emittance = to_vec3f(mat.emission); vec3f diffuse = to_vec3f(mat.diffuse); // vec3f specular = to_vec3f(mat.specular); vec3f &norm = tri->norm; // Calculate BRDF vec3f brdf = 2 * diffuse; // Reflect in a random direction on the normal's unit hemisphere. ray.pos = ray.pos + dist * ray.dir; // ray.dir = rand_hemisphere_vec(norm); ray.dir = cos_dist_hemisphere_vec(norm); // Add accumulation of outgoing radiance. accum_radiance += rem_radiance.cwiseProduct(emittance); rem_radiance = rem_radiance.cwiseProduct(brdf); // For specular, reflect perfectly. // Ray spec_reflect_ray; // vec3f spec_reflected_amt; // spec_reflect_ray.pos = reflect_ray.pos; // spec_reflect_ray.dir = ray.dir + (2 * cos_theta * norm); // spec_reflected_amt = sample(scene, spec_reflect_ray, bounce + 1, // max_bounces); } return accum_radiance; }
int main() { int exit = 0, i, vnum, pnum; VEC3F pos = vec3f(0.0, 0.0, 0.3), ang = ZERO_VEC3F; MAT16F tmat; VERTEX *vertex; POLY3D *poly; init(); load_map("quake_map2.txt", &vertex, &poly, &vnum, &pnum, 0.2); LOCK_VARIABLE(fps); LOCK_VARIABLE(frame_count); LOCK_FUNCTION(update_fps); install_int(update_fps, 1000); VEC3F cam_pos = vec3f(0.0, 3.0, 0.0), cam_dir, cam_dir_normal, cam_ang = vec3f(0.0, 0.0, 0.0); while(!exit) { int mx, my; get_mouse_mickeys(&mx, &my); position_mouse(SCREEN_W / 2, SCREEN_H / 2); cam_ang.x += my * 0.001; cam_ang.y -= mx * 0.001; cam_dir.x = CAM_SPEED * cos(0.5 * M_PI + cam_ang.y); cam_dir.y = CAM_SPEED * cos(0.5 * M_PI + cam_ang.x); cam_dir.z = CAM_SPEED * sin(0.5 * M_PI + cam_ang.y); cam_dir_normal = vec3f(-cam_dir.z, 0.0, cam_dir.x); if(key[KEY_ESC]) { exit = 1; } if(key[KEY_W]) { cam_pos = VEC3F_SUM(cam_pos, cam_dir); } if(key[KEY_S]) { cam_pos = VEC3F_DIFF(cam_pos, cam_dir); } if(key[KEY_A]) { cam_pos = VEC3F_SUM(cam_pos, cam_dir_normal); } if(key[KEY_D]) { cam_pos = VEC3F_DIFF(cam_pos, cam_dir_normal); } set_fov(90.0); if(mouse_b > 1) set_fov(30.0); reset_mat16f(tmat); translate_mat16f(tmat, -cam_pos.x, -cam_pos.y, -cam_pos.z); rotate_z_mat16f(tmat, 0.0); rotate_y_mat16f(tmat, -cam_ang.y); rotate_x_mat16f(tmat, -cam_ang.x); for(i = 0; i < vnum; i++) { transform_vec3f(&vertex[i].trans, vertex[i].object, tmat); project_vertex(&vertex[i]); } clear_to_color(buffer, 0); clear_to_color(BASE_INT_z_buffer, BASE_INT_z_buffer_precision); for(i = 0; i < pnum; i++) { update_poly3d_normal(&poly[i], vertex); V0 = vertex[poly[i].vind[0]].trans; global_n = USCALE_VEC3F(NORMALIZED_VEC3F(poly[i].normal), -1.0); VEC3F N = global_n; DIST = -VEC3F_DOT_PRODUCT(V0, N); get_axes(vertex[poly[i].vind[0]].trans, vertex[poly[i].vind[1]].trans, vertex[poly[i].vind[2]].trans, to_vec3f(poly[i].texcoord[0]), to_vec3f(poly[i].texcoord[1]), to_vec3f(poly[i].texcoord[2]), &A, &B, &C); T0 = to_vec3f(poly[i].texcoord[0]); if(cull_backface(&poly[i], vertex)) render_poly3d(&poly[i], vertex); } textprintf_ex(buffer, font, 10, 10, makecol(255, 255, 255), 0, "FPS: %d", fps); blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); frame_count++; } for(i = 0; i < pnum; i++) destroy_poly3d(&poly[i]); free(vertex); deinit_engine(); return 0; }