• Create Account

#ActualBacterius

Posted 14 December 2012 - 07:23 AM

Actually, it's the same. I normalized them both and the result is the same.

Yes, the vector you had before has the correct direction (the hitpoint - c part), but the length was incorrect. That's why you need to normalize it (or, divide by the radius, which is equivalent if the hitpoint is on the sphere's surface). Normalizing just sets the vector's length to 1, leaving its direction unchanged, so if two vectors have the same direction but different lengths, normalizing them both will produce the same result.

For your problem, look closely at your intersection code for every object. Notice hitInfo is a storage variable, which is trashed at every ray-sphere intersection. The actual closest intersection results are located in the variables t and closestObject. You correctly identify that in the loop, but upon shading (at line 26) you make a mistake and use hitInfo (which now contains the intersection data for the last sphere intersected, which is not necessarily the closest) instead of the correct variable t. You want to keep track of the distance in its own HitInfo structure, instead of just the distance, since you need the other stuff (intersection point, normal, etc...) too for shading. So something like this:

HitInfo current, closest;
Surface closestObject; // default initialized to null
closest.t = float.max;

foreach(obj; scene.objects)
{
if( obj.hit(r, 0.1f, 1000, current) && current.t < closest.t ) // hit?
{
closest = current;
closestObject = obj;
}
}

And then:

Vector3 color = closestObject.shade(closest);

Oh, I forgot. Why do the spheres look like ovals?

Aspect ratio. You are rendering your 1024x768 (or whatever) bitmap as if it was a square, with (x, y) coordinates between -1 and 1, which will stretch the spheres horizontally into ovals. To take into account aspect ratio, you need to either scale x and y to account for it, like so:

float aspectRatio = (float)SCREEN_WIDTH / SCREEN_HEIGHT; // [w/h]

Vector3 p = {aspectRatio * (x - SCREEN_WIDTH * 0.5f) / (SCREEN_WIDTH * 0.5f), (y - SCREEN_HEIGHT * 0.5f) / (SCREEN_HEIGHT * 0.5f), 0};

This can be simplified but you get the idea. You can also contract the height instead of expanding the width, these are conventions depending on your definition of "aspect ratio". Not something you want to worry about at this point.

#7Bacterius

Posted 14 December 2012 - 07:23 AM

Actually, it's the same. I normalized them both and the result is the same.

Yes, the vector you had before has the correct direction (the hitpoint - c part), but the length was incorrect. That's why you need to normalize it (or, divide by the radius, which is equivalent if the hitpoint is on the sphere's surface). Normalizing just sets the vector's length to 1, leaving its direction unchanged, so if two vectors have the same direction but different lengths, normalizing them both will produce the same result.

For your problem, look closely at your intersection code for every object. Notice hitInfo is a storage variable, which is trashed at every ray-sphere intersection. The actual closest intersection results are located in the variables t and closestObject. You correctly identify that in the loop, but upon shading (at line 26) you make a mistake and use hitInfo (which now contains the intersection data for the last sphere intersected, which is not necessarily the closest) instead of the correct variable t. You want to keep track of the distance in its own HitInfo structure, instead of just the distance, since you need the other stuff (intersection point, normal, etc...) too for shading. So something like this:

HitInfo current, closest;
Surface closestObject; // default initialized to null
closest.t = float.max;

foreach(obj; scene.objects)
{
if( obj.hit(r, 0.1f, 1000, current) && current.t < closest.t ) // hit?
{
closest = current;
closestObject = obj;
}
}

And then:

Vector3 color = closestObject.shade(closest);

Oh, I forgot. Why do the spheres look like ovals?

Aspect ratio. You are rendering your 1024x768 (or whatever) bitmap as if it was a square, with (x, y) coordinates between -1 and 1. To take into account aspect ratio, you need to either scale x and y to account for it, like so:

float aspectRatio = (float)SCREEN_WIDTH / SCREEN_HEIGHT; // [w/h]

Vector3 p = {aspectRatio * (x - SCREEN_WIDTH * 0.5f) / (SCREEN_WIDTH * 0.5f), (y - SCREEN_HEIGHT * 0.5f) / (SCREEN_HEIGHT * 0.5f), 0};

This can be simplified but you get the idea. You can also contract the height instead of expanding the width, these are conventions depending on your definition of "aspect ratio". Not something you want to worry about at this point.

#6Bacterius

Posted 14 December 2012 - 07:22 AM

Actually, it's the same. I normalized them both and the result is the same.

Yes, the vector you had before has the correct direction (the hitpoint - c part), but the length was incorrect. That's why you need to normalize it (or, divide by the radius, which is equivalent if the hitpoint is on the sphere's surface). Normalizing just sets the vector's length to 1, leaving its direction unchanged, so if two vectors have the same direction but different lengths, normalizing them both will produce the same result.

For your problem, look closely at your intersection code for every object. Notice hitInfo is a storage variable, which is trashed at every ray-sphere intersection. The actual closest intersection results are located in the variables t and closestObject. You correctly identify that in the loop, but upon shading (at line 26) you make a mistake and use hitInfo (which now contains the intersection data for the last sphere intersected, which is not necessarily the closest) instead of the correct variable t. You want to keep track of the distance in its own HitInfo structure, instead of just the distance, since you need those too for shading. So something like this:

HitInfo current, closest;
Surface closestObject; // default initialized to null
closest.t = float.max;

foreach(obj; scene.objects)
{
if( obj.hit(r, 0.1f, 1000, current) && current.t < closest.t ) // hit?
{
closest = current;
closestObject = obj;
}
}

And then:

Vector3 color = closestObject.shade(closest);

Oh, I forgot. Why do the spheres look like ovals?

Aspect ratio. You are rendering your 1024x768 (or whatever) bitmap as if it was a square, with (x, y) coordinates between -1 and 1. To take into account aspect ratio, you need to either scale x and y to account for it, like so:

float aspectRatio = (float)SCREEN_WIDTH / SCREEN_HEIGHT; // [w/h]

Vector3 p = {aspectRatio * (x - SCREEN_WIDTH * 0.5f) / (SCREEN_WIDTH * 0.5f), (y - SCREEN_HEIGHT * 0.5f) / (SCREEN_HEIGHT * 0.5f), 0};

This can be simplified but you get the idea. You can also contract the height instead of expanding the width, these are conventions depending on your definition of "aspect ratio". Not something you want to worry about at this point.

#5Bacterius

Posted 14 December 2012 - 07:21 AM

Actually, it's the same. I normalized them both and the result is the same.

Yes, the vector you had before has the correct direction (the hitpoint - c part), but the length was incorrect. That's why you need to normalize it (or, divide by the radius, which is equivalent if the hitpoint is on the sphere's surface). Normalizing just sets the vector's length to 1, leaving its direction unchanged, so if two vectors have the same direction but different lengths, normalizing them both will produce the same result.

For your problem, look closely at your intersection code for every object. Notice hitInfo is a storage variable, which is trashed at every ray-sphere intersection. The actual closest intersection results are located in the variables t and closestObject. You correctly identify that in the loop, but upon shading (at line 26) you make a mistake and use hitInfo (which now contains the intersection data for the last sphere intersected, which is not necessarily the closest) instead of the correct variable t. You want to keep track of the distance in its own HitInfo structure, instead of just the distance, since you need those too for shading.

Oh, I forgot. Why do the spheres look like ovals?

Aspect ratio. You are rendering your 1024x768 (or whatever) bitmap as if it was a square, with (x, y) coordinates between -1 and 1. To take into account aspect ratio, you need to either scale x and y to account for it, like so:

float aspectRatio = (float)SCREEN_WIDTH / SCREEN_HEIGHT; // [w/h]

Vector3 p = {aspectRatio * (x - SCREEN_WIDTH * 0.5f) / (SCREEN_WIDTH * 0.5f), (y - SCREEN_HEIGHT * 0.5f) / (SCREEN_HEIGHT * 0.5f), 0};

This can be simplified but you get the idea. You can also contract the height instead of expanding the width, these are conventions depending on your definition of "aspect ratio". Not something you want to worry about at this point.

#4Bacterius

Posted 14 December 2012 - 07:19 AM

Actually, it's the same. I normalized them both and the result is the same.

Yes, the vector you had before has the correct direction (the hitpoint - c part), but the length was incorrect. That's why you need to normalize it (or, divide by the radius, which is equivalent if the hitpoint is on the sphere's surface). Normalizing just sets the vector's length to 1, leaving its direction unchanged, so if two vectors have the same direction but different lengths, normalizing them both will produce the same result.

For your problem, look closely at your intersection code for every object. Notice hitInfo is a storage variable, which is trashed at every ray-sphere intersection. The actual closest intersection results are located in the variables t and closestObject. You correctly identify that in the loop, but upon shading (at line 26) you make a mistake and use hitInfo (which now contains the intersection data for the last sphere intersected, which is not necessarily the closest) instead of the correct variable t. You want to do this:

hitInfo.t = t;

Vector3 color = closestObject.shade(hitInfo);

Oh, I forgot. Why do the spheres look like ovals?

Aspect ratio. You are rendering your 1024x768 (or whatever) bitmap as if it was a square, with (x, y) coordinates between -1 and 1. To take into account aspect ratio, you need to either scale x and y to account for it, like so:

float aspectRatio = (float)SCREEN_WIDTH / SCREEN_HEIGHT; // [w/h]

Vector3 p = {aspectRatio * (x - SCREEN_WIDTH * 0.5f) / (SCREEN_WIDTH * 0.5f), (y - SCREEN_HEIGHT * 0.5f) / (SCREEN_HEIGHT * 0.5f), 0};

This can be simplified but you get the idea. You can also contract the height instead of expanding the width, these are conventions depending on your definition of "aspect ratio". Not something you want to worry about at this point.

#3Bacterius

Posted 14 December 2012 - 07:18 AM

Actually, it's the same. I normalized them both and the result is the same.

Yes, the vector you had before has the correct direction (the hitpoint - c part), but the length was incorrect. That's why you need to normalize it (or, divide by the radius, which is equivalent if the hitpoint is on the sphere's surface). Normalizing just sets the vector's length to 1, leaving its direction unchanged, so if two vectors have the same direction but different lengths, normalizing them both will produce the same result.

For your problem, look closely at your intersection code for every object. Notice hitInfo is a storage variable, which is trashed at every ray-sphere intersection. The actual closest intersection results are located in the variables t and closestObject. You correctly identify that in the loop, but upon shading (at line 26) you make a mistake and use hitInfo (which now contains the intersection data for the last sphere intersected, which is not necessarily the closest) instead of the correct variable t. You want to do this:

hitInfo.t = t;

Vector3 color = closestObject.shade(hitInfo);

Oh, I forgot. Why do the spheres look like ovals?

Aspect ratio. You are rendering your 1024x768 (or whatever) bitmap as if it was a square, with (x, y) coordinates between 0 and 1. To take into account aspect ratio, you need to either scale x and y to account for it, like so:

float aspectRatio = (float)SCREEN_WIDTH / SCREEN_HEIGHT; // [w/h]

Vector3 p = {aspectRatio * (x - SCREEN_WIDTH * 0.5f) / (SCREEN_WIDTH * 0.5f), (y - SCREEN_HEIGHT * 0.5f) / (SCREEN_HEIGHT * 0.5f), 0};

This can be simplified but you get the idea. You can also contract the height instead of expanding the width, these are conventions depending on your definition of "aspect ratio". Not something you want to worry about at this point.

PARTNERS