/* This file belongs to the Ray tracing tutorial of http://www.codermind.com/ It is free to use for educational purpose and cannot be redistributed outside of the tutorial pages. Any further inquiry : mailto:info@codermind.com */ #include #include #include #include #include #include using namespace std; #include "Raytrace.h" #include "Scene.h" #include "Srgb.h" bool hitPlane(const ray &r, const sphere& s, float &t) { return false; } bool hitSphere(const ray &r, const sphere& s, float &t) { // Intersection of a ray and a sphere // Check the articles for the rationale // NB : this is probably a naive solution // that could cause precision problems // but that will do it for now. vecteur dist = s.pos - r.start; float B = (r.dir.x * dist.x + r.dir.y * dist.y + r.dir.z * dist.z); float D = B*B - dist*dist + s.size * s.size; if (D < 0.0f) return false; float t0 = B - sqrtf(D); float t1 = B + sqrtf(D); bool retvalue = false; if ((t0 > 0.1f ) && (t0 < t)) { t = t0; retvalue = true; } if ((t1 > 0.1f ) && (t1 < t)) { t = t1; retvalue = true; } return retvalue; } color addRay(ray viewRay, scene &myScene) { color output = {0.0f, 0.0f, 0.0f}; float coef = 1; int level = 0; while( (coef > 0.0f) && (level < recursionLevels) ) { point ptHitPoint; int currentObjectGroup = -1; int currentObject = -1; float t = 2000.0f; for(int i=0; i 0.0f) && (level < 5)); return output; } bool draw(char* outputName, scene &myScene) { int x, y; ofstream imageFile(outputName,ios_base::binary); if (!imageFile) return false; // Addition of the TGA header imageFile.put(0).put(0); imageFile.put(2); /* RGB not compressed */ imageFile.put(0).put(0); imageFile.put(0).put(0); imageFile.put(0); imageFile.put(0).put(0); /* origin X */ imageFile.put(0).put(0); /* origin Y */ imageFile.put((unsigned char)(myScene.sizex & 0x00FF)).put((unsigned char)((myScene.sizex & 0xFF00) / 256)); imageFile.put((unsigned char)(myScene.sizey & 0x00FF)).put((unsigned char)((myScene.sizey & 0xFF00) / 256)); imageFile.put(24); /* 24 bit bitmap */ imageFile.put(0); // end of the TGA header // Scanning for (y = 0; y < myScene.sizey; ++y){ for (x = 0 ; x < myScene.sizex; ++x){ color output = {0.0f, 0.0f, 0.0f}; for (float fragmentx = float(x) ; fragmentx < x + 1.0f; fragmentx += 0.5f ) for (float fragmenty = float(y) ; fragmenty < y + 1.0f; fragmenty += 0.5f ) { float sampleRatio=0.25f; ray viewRay = { {fragmentx, fragmenty, -1000.0f},{ 0.0f, 0.0f, 1.0f}}; color temp = addRay (viewRay, myScene); // pseudo photo exposure float exposure = -1.00f; // random exposure value. TODO : determine a good value automatically temp.blue = (1.0f - expf(temp.blue * exposure)); temp.red = (1.0f - expf(temp.red * exposure)); temp.green = (1.0f - expf(temp.green * exposure)); output += sampleRatio * temp; } // gamma correction output.blue = srgbEncode(output.blue); output.red = srgbEncode(output.red); output.green = srgbEncode(output.green); imageFile.put((unsigned char)min(output.blue*255.0f,255.0f)).put((unsigned char)min(output.green*255.0f, 255.0f)).put((unsigned char)min(output.red*255.0f, 255.0f)); } } return true; } int __cdecl main(int argc, char* argv[]) { if (argc < 3) { cout << "Usage : Raytrace.exe Scene.txt Output.tga" << endl; return -1; } scene myScene; if (!init(argv[1], myScene)) { cout << "Failure when reading the Scene file." << endl; return -1; } if (!draw(argv[2], myScene)) { cout << "Failure when creating the image file." << endl; return -1; } return 0; cout << "Done." << endl; }