#include #include "glut.h" #include "arith.h" using namespace std; void init(void) { glClearColor(0.0,0.0,0.0,0.0); } int windowWidth = 500, windowHeight = 500; const int cntSpheres = 1; const sphere Spheres[cntSpheres] = { { {233.0, 290.0, 0.0}, 100.0, 0 } }; const int cntMaterials = 1; const material Materials[cntMaterials] = { { 0.5, 1.0, 1.0, 1.0 } }; const int cntLights = 2; const light Lights[cntLights] = { { {0.0, 240.0, -100.0}, 1.0, 1.0, 1.0 }, { {640.0, 240.0, -10000.0}, 0.6, 0.7, 1.0 } }; bool hitSphere(const ray &r, const sphere &s, float &t) { vecteur dist = s.pos - r.start; float B = r.dir * dist; 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; } void display(void) { glClear(GL_COLOR_BUFFER_BIT); for (int y = 0; y < windowHeight; ++y) { for (int x = 0; x < windowWidth; ++x) { float red = 0, green = 0, blue = 0; float coef = 1.0f; int level = 0; ray viewRay = { {float(x), float(y), -1000.0f}, { 0.0f, 0.0f, 1.0f}}; do { float t = 2000.0f; int currentSphere= -1; for (int i = 0; i < cntSpheres; ++i) { if (hitSphere(viewRay, Spheres[i], t)) { currentSphere = i; } } if (currentSphere == -1) break; point newStart = viewRay.start + t * viewRay.dir; vecteur n = newStart - Spheres[currentSphere].pos; float temp = n * n; if (temp == 0.0f) break; temp = 1.0f / sqrtf(temp); n = temp * n; material currentMat = Materials[Spheres[currentSphere].materialId]; for (int j = 0; j < cntLights; ++j) { light current = Lights[j]; vecteur dist = current.pos - newStart; if (n * dist <= 0.0f) continue; float t = sqrtf(dist * dist); if ( t <= 0.0f ) continue; ray lightRay; lightRay.start = newStart; lightRay.dir = (1/t) * dist; bool inShadow = false; for (int i = 0; i < cntSpheres; ++i) { if (hitSphere(lightRay, Spheres[i], t)) { inShadow = true; break; } } if (!inShadow) { // lambert float lambert = (lightRay.dir * n) * coef; red += lambert * current.red * currentMat.red; green += lambert * current.green * currentMat.green; blue += lambert * current.blue * currentMat.blue; } } coef *= currentMat.reflection; float reflet = 2.0f * (viewRay.dir * n); viewRay.start = newStart; viewRay.dir = viewRay.dir - reflet * n; level++; } while ((coef > 0.0f) && (level < 10)); glPointSize(1.0); glBegin(GL_POINTS); glColor3f(red, green, blue); glVertex2i(x, y); glEnd(); } } glFlush(); } void reshape(int w, int h) { windowWidth = w; windowHeight = h; glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-windowWidth, windowWidth, -windowHeight, windowHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(windowWidth, windowHeight); glutInitWindowPosition(100,100); glutCreateWindow("Rendering a Lit Sphere"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; }