Reputation: 6360
I'm currently working on a ray tracer for a school project, and for this step of the course we need to implement object shading using an system of lights and the Blinn-Phong
algorithm.
Below is the final image if done correctly...
At this point I haven't gotten to the reflections and shadows yet, simply trying to get the shading working first and keep getting this resulting image...
As it's pretty obvious to see, the areas that should have the highest amount of specular are turning green, and I'm getting strange black artifacts in some places around the teapot. I've been reading and testing for hours and cant figure out why! I'm 90% sure I'm implementing the algorithm correctly.
Here is my code that is relevant for this issue...
void shade(RGB& shading, std::vector<Light> lights, Triangle t, Ray& r, Vector3 loc) {
float intensity = 1 / std::sqrt(lights.size());
for (std::size_t i = 0; i < lights.size(); ++i) {
Vector3 n = t.get_normal();
n.normalize();
Vector3 v = r.dir * -1;
v.normalize();
Vector3 l = lights[i].position - loc;
l.normalize();
Vector3 h = v + l;
h.normalize();
float diffuse = MAX(0, n.dot(l));
float spec = std::pow(MAX(0, n.dot(h)), t.fill.shine);
shading.r += (t.fill.kd * diffuse * t.fill.rgb.r + t.fill.ks * spec) * intensity;
shading.g += (t.fill.kd * diffuse * t.fill.rgb.g + t.fill.ks * spec) * intensity;
shading.b += (t.fill.kd * diffuse * t.fill.rgb.b + t.fill.ks * spec) * intensity;
}
}
// Main function
int main(int argc, char* argv[]) {
// Set input and output file names
std::string in_file = (argc > 1) ? argv[1] : "teapot-3.nff";
std::string out_file = (argc > 2) ? argv[2] : "output.ppm";
// Parse the NFF file and get the Viewpoint and Background data
NFFParser parser(in_file);
parser.read_file();
Viewpoint view = parser.getViewpoint();
Background background = parser.getBackground();
// Camera creation
Camera camera(view);
// Allocate array of pixels and create camera instance
Pixel* pixels = new Pixel[camera.x_res * camera.y_res];
// Collect object data to iterate over
std::vector<Polygon> polygons = parser.getPolygons();
std::vector<Patch> patches = parser.getPatches();
std::vector<Light> lights = parser.getLights();
std::vector<Triangle> triangles;
// Convert all polygons and patches to trianlges and
// build a vector of triangles to iterator over
for (std::size_t i = 0; i < polygons.size(); ++i) {
std::vector<Triangle> v = polygons[i].fan_to_triangles();
triangles.insert(triangles.end(), v.begin(), v.end());
}
for (std::size_t i = 0; i < patches.size(); ++i) {
std::vector<Triangle> v = patches[i].fan_to_triangles();
triangles.insert(triangles.end(), v.begin(), v.end());
}
std::cout << "Testing for intersections among objects..." << std::endl
<< "...this may take a moment..." << std::endl
<< "==========================================" << std::endl;
// Iterator over all pixels in the array
for (int y = 0; y < camera.y_res; ++y) {
for (int x = 0; x < camera.x_res; ++x) {
float t = INF;
Triangle closest;
// Map pixel to image plane coordinates
Vector3 image_location = camera.map_to_image(x, y);
Ray r(camera.e, image_location - camera.e);
// Iteration over Polygons
for (std::vector<Triangle>::iterator it = triangles.begin(); it != triangles.end(); ++it) {
if (it->intersects(&r, t) && t < r.t_min) {
closest = *it;
r.t_min = t;
}
}
if (r.t_min == INF) {
set_pixel(pixels, y, x, camera.y_res, background.rgb);
continue;
}
RGB shading;
shade(shading, lights, closest, r, image_location);
set_pixel(pixels, y, x, camera.y_res, shading);
}
}
// Write the array of pixels to the output PPM file
PPMWriter writer(out_file);
writer.write_pixels(pixels, camera.x_res, camera.y_res);
// Deallocate pixels array to avoid memory leaks
delete [] pixels;
return 0;
}
Any guidance or help would be greatly appreciated!
EDIT
Green coloring is fixed but RGB component capping, but black artifacting is still an issue.
Upvotes: 0
Views: 258
Reputation: 32732
For the green bits, in your color calculation, you're overflowing what can fit into the red component of a pixel. You can see this if you look at the RGB of the coppery color near the green (0xFE9E4E) vs what's in the green area (0x019D4F).
You'll need to include some overflow checking in your calculations.
Upvotes: 2