Ejemplo n.º 1
0
void ambient_occlusion(vec *col, const Isect *isect)
{
	int      i, j;
	int      ntheta = AOBENCH_NAO_SAMPLES;
	int      nphi   = AOBENCH_NAO_SAMPLES;
	aobfloat eps = 0.0001;

	vec p;

	p.x = isect->p.x + eps * isect->n.x;
	p.y = isect->p.y + eps * isect->n.y;
	p.z = isect->p.z + eps * isect->n.z;

	vec basis[3];
	orthoBasis(basis, isect->n);

	aobfloat occlusion = 0.0;

	for (j = 0; j < ntheta; j++) {
		for (i = 0; i < nphi; i++) {
			aobfloat theta = sqrt(drand48());
			aobfloat phi   = 2.0 * M_PI * drand48();

			aobfloat x = cos(phi) * theta;
			aobfloat y = sin(phi) * theta;
			aobfloat z = sqrt(1.0 - theta * theta);

			// local -> global
			aobfloat rx = x * basis[0].x + y * basis[1].x + z * basis[2].x;
			aobfloat ry = x * basis[0].y + y * basis[1].y + z * basis[2].y;
			aobfloat rz = x * basis[0].z + y * basis[1].z + z * basis[2].z;

			Ray ray;

			ray.org = p;
			ray.dir.x = rx;
			ray.dir.y = ry;
			ray.dir.z = rz;

			Isect occIsect;
			occIsect.t   = 1.0e+17;
			occIsect.hit = 0;

			ray_sphere_intersect(&occIsect, &ray, &spheres[0]); 
			ray_sphere_intersect(&occIsect, &ray, &spheres[1]); 
			ray_sphere_intersect(&occIsect, &ray, &spheres[2]); 
			ray_plane_intersect (&occIsect, &ray, &plane); 

			if (occIsect.hit) occlusion += 1.0;
			
		}
	}

	occlusion = (ntheta * nphi - occlusion) / (aobfloat)(ntheta * nphi);

	col->x = occlusion;
	col->y = occlusion;
	col->z = occlusion;
}
Ejemplo n.º 2
0
static void
render_tile(unsigned char *img, int comps, float *fimg, int w, int h, int nsubsamples, int tilex, int tiley, int tilew, int tileh)
{
    int endx = tilex + min_i(tilew, w - tilex);
    int endy = tiley + min_i(tileh, h - tiley);
    
    int x, y;
    int u, v;
    
    for (y = tiley; y < endy; y++) {
        for (x = tilex; x < endx; x++) {
            
            for (v = 0; v < nsubsamples; v++) {
                for (u = 0; u < nsubsamples; u++) {
                    float px = (x + (u / (float)nsubsamples) - (w / 2.0)) / (w / 2.0);
                    float py = -(y + (v / (float)nsubsamples) - (h / 2.0)) / (h / 2.0);

                    Ray ray;

                    ray.org.x = 0.0;
                    ray.org.y = 0.0;
                    ray.org.z = 0.0;

                    ray.dir.x = px;
                    ray.dir.y = py;
                    ray.dir.z = -1.0;
                    vnormalize(&(ray.dir));

                    Isect isect;
                    isect.t   = 1.0e+17;
                    isect.hit = 0;

                    ray_sphere_intersect(&isect, &ray, &spheres[0]);
                    ray_sphere_intersect(&isect, &ray, &spheres[1]);
                    ray_sphere_intersect(&isect, &ray, &spheres[2]);
                    ray_plane_intersect (&isect, &ray, &plane);

                    if (isect.hit) {
                        vec col;
                        ambient_occlusion(&col, &isect);

                        fimg[3 * (y * w + x) + 0] += col.x;
                        fimg[3 * (y * w + x) + 1] += col.y;
                        fimg[3 * (y * w + x) + 2] += col.z;
                    }

                }
            }

            fimg[3 * (y * w + x) + 0] /= (float)(nsubsamples * nsubsamples);
            fimg[3 * (y * w + x) + 1] /= (float)(nsubsamples * nsubsamples);
            fimg[3 * (y * w + x) + 2] /= (float)(nsubsamples * nsubsamples);

            img[comps * (y * w + x) + 0] = clamp(fimg[3 *(y * w + x) + 0]);
            img[comps * (y * w + x) + 1] = clamp(fimg[3 *(y * w + x) + 1]);
            img[comps * (y * w + x) + 2] = clamp(fimg[3 *(y * w + x) + 2]);
        }
    }
}
Ejemplo n.º 3
0
/* Compute the image for the scanlines from [y0,y1), for an overall image
   of width w and height h.
 */
static void ao_scanlines(int y0, int y1, int w, int h, int nsubsamples,
                         float image[]) {
    static Plane plane = { vec(0.0f, -0.5f, 0.0f), vec(0.f, 1.f, 0.f) };
    static Sphere spheres[3] = {
        { vec(-2.0f, 0.0f, -3.5f), 0.5f },
        { vec(-0.5f, 0.0f, -3.0f), 0.5f },
        { vec(1.0f, 0.0f, -2.2f), 0.5f } };

    srand48(y0);

    for (int y = y0; y < y1; ++y) {
        for (int x = 0; x < w; ++x)  {
            int offset = 3 * (y * w + x);
            for (int u = 0; u < nsubsamples; ++u) {
                for (int v = 0; v < nsubsamples; ++v) {
                    float px = (x + (u / (float)nsubsamples) - (w / 2.0f)) / (w / 2.0f);
                    float py = -(y + (v / (float)nsubsamples) - (h / 2.0f)) / (h / 2.0f);

                    // Scale NDC based on width/height ratio, supporting non-square image output
                    px *= (float)w / (float)h;

                    float ret = 0.f;
                    Ray ray;
                    Isect isect;

                    ray.org = vec(0.f, 0.f, 0.f);

                    ray.dir.x = px;
                    ray.dir.y = py;
                    ray.dir.z = -1.0f;
                    vnormalize(ray.dir);

                    isect.t   = 1.0e+17f;
                    isect.hit = 0;

                    for (int snum = 0; snum < 3; ++snum)
                        ray_sphere_intersect(isect, ray, spheres[snum]);
                    ray_plane_intersect(isect, ray, plane);

                    if (isect.hit)
                        ret = ambient_occlusion(isect, plane, spheres);

                    // Update image for AO for this ray
                    image[offset+0] += ret;
                    image[offset+1] += ret;
                    image[offset+2] += ret;
                }
            }
            // Normalize image pixels by number of samples taken per pixel
            image[offset+0] /= nsubsamples * nsubsamples;
            image[offset+1] /= nsubsamples * nsubsamples;
            image[offset+2] /= nsubsamples * nsubsamples;
        }
    }
}
Ejemplo n.º 4
0
// modified to only render one row (specified by parameter y) per function call
void
aobench_render(unsigned char *img, int w, int h, int nsubsamples, int y)
{
	int x, u, v;

	for (x = 0; x < w; x++) {
		aobfloat r = 0.0, g = 0.0, b = 0.0;
		
		for (v = 0; v < nsubsamples; v++) {
			for (u = 0; u < nsubsamples; u++) {
				aobfloat px =  (x + (u / (aobfloat)nsubsamples) - (w / 2.0)) / (w / 2.0);
				aobfloat py = -(y + (v / (aobfloat)nsubsamples) - (h / 2.0)) / (h / 2.0);

				Ray ray;

				ray.org.x = 0.0;
				ray.org.y = 0.0;
				ray.org.z = 0.0;

				ray.dir.x = px;
				ray.dir.y = py;
				ray.dir.z = -1.0;
				vnormalize(&(ray.dir));

				Isect isect;
				isect.t   = 1.0e+17;
				isect.hit = 0;

				ray_sphere_intersect(&isect, &ray, &spheres[0]);
				ray_sphere_intersect(&isect, &ray, &spheres[1]);
				ray_sphere_intersect(&isect, &ray, &spheres[2]);
				ray_plane_intersect (&isect, &ray, &plane);

				if (isect.hit) {
					vec col;
					ambient_occlusion(&col, &isect);

					r += col.x;
					g += col.y;
					b += col.z;
				}

			}
		}

		r /= (aobfloat)(nsubsamples * nsubsamples);
		g /= (aobfloat)(nsubsamples * nsubsamples);
		b /= (aobfloat)(nsubsamples * nsubsamples);
	
		img[3 * (y * w + x) + 0] = clamp(r);
		img[3 * (y * w + x) + 1] = clamp(g);
		img[3 * (y * w + x) + 2] = clamp(b);
	}
}
Ejemplo n.º 5
0
static float
ambient_occlusion(Isect &isect, Plane &plane,
                  Sphere spheres[3]) {
    float eps = 0.0001f;
    vec p, n;
    vec basis[3];
    float occlusion = 0.0;

    p = isect.p + eps * isect.n;

    orthoBasis(basis, isect.n);

    static const int ntheta = NAO_SAMPLES;
    static const int nphi   = NAO_SAMPLES;
    for (int j = 0; j < ntheta; j++) {
        for (int i = 0; i < nphi; i++) {
            Ray ray;
            Isect occIsect;

            float theta = sqrtf(drand48());
            float phi   = 2.0f * M_PI * drand48();
            float x = cosf(phi) * theta;
            float y = sinf(phi) * theta;
            float z = sqrtf(1.0f - theta * theta);

            // local . global
            float rx = x * basis[0].x + y * basis[1].x + z * basis[2].x;
            float ry = x * basis[0].y + y * basis[1].y + z * basis[2].y;
            float rz = x * basis[0].z + y * basis[1].z + z * basis[2].z;

            ray.org = p;
            ray.dir.x = rx;
            ray.dir.y = ry;
            ray.dir.z = rz;

            occIsect.t   = 1.0e+17f;
            occIsect.hit = 0;

            for (int snum = 0; snum < 3; ++snum)
                ray_sphere_intersect(occIsect, ray, spheres[snum]);
            ray_plane_intersect (occIsect, ray, plane);

            if (occIsect.hit) occlusion += 1.f;
        }
    }

    occlusion = (ntheta * nphi - occlusion) / (float)(ntheta * nphi);
    return occlusion;
}
Ejemplo n.º 6
0
static void
render(unsigned char *img, int comps, int w, int h, int nsubsamples)
{
    int x, y;
    int u, v;

    //float *fimg = (float *)malloc(sizeof(float) * w * h * 3);
    vec *fimg = (vec *)malloc(sizeof(vec) * w * h);
    memset((void *)fimg, 0, sizeof(vec) * w * h);

    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            
            for (v = 0; v < nsubsamples; v++) {
                for (u = 0; u < nsubsamples; u++) {
                    float px = (x + (u / (float)nsubsamples) - (w / 2.0)) / (w / 2.0);
                    float py = -(y + (v / (float)nsubsamples) - (h / 2.0)) / (h / 2.0);

                    Ray ray;

                    ray.org.x = 0.0;
                    ray.org.y = 0.0;
                    ray.org.z = 0.0;

                    ray.dir.x = px;
                    ray.dir.y = py;
                    ray.dir.z = -1.0;
                    vnormalize(&(ray.dir));

                    Isect isect;
                    isect.t   = 1.0e+17;
                    isect.hit = 0;

                    ray_sphere_intersect(&isect, &ray, &spheres[0]);
                    ray_sphere_intersect(&isect, &ray, &spheres[1]);
                    ray_sphere_intersect(&isect, &ray, &spheres[2]);
                    ray_plane_intersect (&isect, &ray, &plane);

                    if (isect.hit) {
                        vec col;
                        ambient_occlusion(&col, &isect);

                        vadd(&fimg[y * w + x], fimg[y * w + x], col);
/*
                        fimg[y * w + x].x += col.x;
                        fimg[y * w + x].y += col.y;
                        fimg[y * w + x].z += col.z;
*/
                    }

                }
            }

            vdivs(&fimg[y * w + x], fimg[y * w + x], (float)(nsubsamples * nsubsamples));
/*
            fimg[y * w + x].x /= (float)(nsubsamples * nsubsamples);
            fimg[y * w + x].y /= (float)(nsubsamples * nsubsamples);
            fimg[y * w + x].z /= (float)(nsubsamples * nsubsamples);
*/
            img[comps * (y * w + x) + 0] = clamp(fimg[y * w + x].x);
            img[comps * (y * w + x) + 1] = clamp(fimg[y * w + x].y);
            img[comps * (y * w + x) + 2] = clamp(fimg[y * w + x].z);
        }
    }
}
Ejemplo n.º 7
0
static bool ray_surface_intersect(Ray ray, const Surface *surf, Hit *hit)
{
	float ts[2] = {-HUGE_VAL, -HUGE_VAL}, t;
	Vec3 tnormals[2] = {{0,0,0},{0,0,0}}, tnormal;
	Ray tray;
	Mat4 normal_matrix;
	Shape *shape = surf->shape;
	int hits;

	mat4_copy(normal_matrix, surf->world_to_model);
	mat4_transpose(normal_matrix);

	tray.origin = mat4_transform3_homo(surf->world_to_model, ray.origin);
	tray.direction = mat4_transform3_hetero(surf->world_to_model, ray.direction);
	tray.near = ray.near;
	tray.far = ray.far;

	switch(shape->type)
	{
	case SHAPE_PLANE:
		hits = ray_plane_intersect(tray, shape->u.plane, ts, tnormals);
		break;
	case SHAPE_DISK:
		hits = ray_disk_intersect(tray, shape->u.disk, ts, tnormals);
		break;
	case SHAPE_SPHERE:
		hits = ray_sphere_intersect(tray, shape->u.sphere, ts, tnormals);
		break;
	case SHAPE_CYLINDER:
		hits = ray_cylinder_intersect(tray, shape->u.cylinder, ts, tnormals);
		break;
	case SHAPE_CONE:
		hits = ray_cone_intersect(tray, shape->u.cone, ts, tnormals);
		break;
	case SHAPE_MESH:
		hits = ray_mesh_intersect(tray, shape->u.mesh, ts, tnormals);
		break;
	default:
		printf("Unknown shape\n");
		return false;
		break;
	}

	/* We're looking for the smallest hit that is between the near and far
	 * planes of the ray. */
	if (hits == 0)
		return false;
	if (hits == 1)
	{
		if (ts[0] < ray.near || ts[0] > ray.far)
			return false;

		t = ts[0];
		tnormal = tnormals[0];
	} else if (hits == 2)
	{
		bool t0_ok = ts[0] >= ray.near && ts[0] <= ray.far;
		bool t1_ok = ts[1] >= ray.near && ts[1] <= ray.far;

		     if (!t0_ok && !t1_ok)
		{
			return false;
		}
		else if (t0_ok && !t1_ok)
		{
			t = ts[0];
			tnormal = tnormals[0];
		}
		else if (!t0_ok && t1_ok)
		{
			t = ts[1];
			tnormal = tnormals[1];
		}
		else
		{
			if (ts[0] < ts[1])
			{
				t = ts[0];
				tnormal = tnormals[0];
			} else
			{
				t = ts[1];
				tnormal = tnormals[1];
			}
		}
	} else
	{
		printf("General t finding code unimplemented\n");
		return false;
	}

	hit->t = t;
	hit->position = vec3_add(ray.origin, vec3_scale(t, ray.direction));
	hit->normal = vec3_normalize(mat4_transform3_hetero(normal_matrix, tnormal));
	return true;
}
Ejemplo n.º 8
0
static void ambient_occlusion(vec *col, const Isect *isect)
{
    int    i, j;
    int    ntheta = NAO_SAMPLES;
    int    nphi   = NAO_SAMPLES;
    double eps = 0.0001;

    vec p;
    ao_vmultsadd(&p, isect->n, eps, isect->p);
/*
    p.x = isect->p.x + eps * isect->n.x;
    p.y = isect->p.y + eps * isect->n.y;
    p.z = isect->p.z + eps * isect->n.z;
*/
    vec basis[3];
    orthoBasis(basis, isect->n);

    double occlusion = 0.0;

    for (j = 0; j < ntheta; j++) {
        for (i = 0; i < nphi; i++) {
            double theta = sqrt(drand48());
            double phi   = 2.0 * M_PI * drand48();

            double x = cos(phi) * theta;
            double y = sin(phi) * theta;
            double z = sqrt(1.0 - theta * theta);

            // TODO
            // local -> global
            double rx = x * basis[0].x + y * basis[1].x + z * basis[2].x;
            double ry = x * basis[0].y + y * basis[1].y + z * basis[2].y;
            double rz = x * basis[0].z + y * basis[1].z + z * basis[2].z;

            Ray ray;

            ray.org = p;
            ray.dir.x = rx;
            ray.dir.y = ry;
            ray.dir.z = rz;

            Isect occIsect;
            occIsect.t   = 1.0e+17;
            occIsect.hit = 0;

            ray_sphere_intersect(&occIsect, &ray, &spheres[0]); 
            ray_sphere_intersect(&occIsect, &ray, &spheres[1]); 
            ray_sphere_intersect(&occIsect, &ray, &spheres[2]); 
            ray_plane_intersect (&occIsect, &ray, &plane); 

            if (occIsect.hit) occlusion += 1.0;
            
        }
    }

    occlusion = (ntheta * nphi - occlusion) / (double)(ntheta * nphi);

    col->x = occlusion;
    col->y = occlusion;
    col->z = occlusion;
}