lundi 30 janvier 2017

How to fix Ray tracing Phong, reflections and color saturation?

I have a scene looking like this: enter image description here

But I can't seem to wrap my head around how to keep the reflections from being brighter than the real object.

Vec3f fireRaysRec(Ray& ray, unsigned int recdepth, unsigned int& iTests) {
        Vec3f retcolor;
        HitRec hitRec;

        retcolor.set(0.0f, 0.0f, 0.0f);
        hitRec.tHit = Ray::tMax;
        hitRec.anyHit = false;
        hitRec.primIndex = -1;

        if(recdepth <= recursionMaxDepth_UI) {
            searchClosestHit(ray, hitRec, iTests);
            if(hitRec.anyHit) {
                retcolor = scene->objects_VPP[hitRec.primIndex]->getMaterialAmbient(); //Apply material ambient

                //Lighting (Phong)
                for(int i = 0; i < (int)scene->lights_VPL.size(); ++i) {
                    if(!fireShadowRay(hitRec, scene->lights_VPL[i], iTests)) { //Check if NOT in shadow from light #i
                        //Calculate lighting/color (phong)
                        //Vectors needed: to light (L), to viewer/camera (V), normal (n), reflector (R)
                        //matAmb*lightAmb + matDiff*lightDiff*(N.L) + matSpec*lightSpec*(R.V)^shine
                        //R = 2(l . n)n - l
                        float dotnl, dotrv, dotln;
                        Vec3f L, V, N, R;

                        N = hitRec.n;
                        V = (-ray.d).normalize();
                        //retcolor = retcolor.multCoordwise(scene->lights_VPL[i].getAmbientLight());
                        L = (scene->lights_VPL[i].getPosition() - hitRec.p).normalize();
                        dotln = L.dot(N);
                        if(dotln < 0.0f) { dotln = 0.0f; }
                        R = ((N * (2 * dotln)) - L).normalize(); //R = (2 * L.dot(N) * N - L)
                        dotnl = N.dot(L);
                        if(dotnl < 0.0f) { dotnl = 0.0f; }
                        dotrv = R.dot(V);
                        if(dotrv < 0.0f) { dotrv = 0.0f; }
                        //retcolor += scene->objects_VPP[hitRec.primIndex]->getMaterialAmbient().multCoordwise(scene->lights_VPL[i].getAmbientLight());
                        if(scene->objects_VPP[hitRec.primIndex]->getTexture() == NULL) {
                            retcolor += (scene->objects_VPP[hitRec.primIndex]->getMaterialDiffuse().multCoordwise(scene->lights_VPL[i].getDiffuseLight()) * dotnl);
                        }
                        else {
                            Vec2i texcoords = scene->objects_VPP[hitRec.primIndex]->calculateTexCoords(hitRec);
                            Vec3f texcol = scene->objects_VPP[hitRec.primIndex]->getTexture()->getPixel(texcoords.getX(), texcoords.getY());
                            //std::cout << "TexCol: " << texcol.r << ", " << texcol.g << ", " << texcol.b << std::endl;
                            retcolor += (texcol.multCoordwise(scene->lights_VPL[i].getDiffuseLight()) * dotnl);
                        }
                        retcolor += (scene->objects_VPP[hitRec.primIndex]->getMaterialSpecular().multCoordwise(scene->lights_VPL[i].getSpecularLight()) * pow(dotrv, scene->objects_VPP[hitRec.primIndex]->getMaterialShininess()));
                    }
                    else { } //In shadow from light #i - dont apply light from light #i
                }

                //Reflection
                if(scene->objects_VPP[hitRec.primIndex]->getMaterialReflective()) {
                    //Vectors needed: to camera/viewer (V), normal (N), reflector (R)
                    //R = 2(v . n)n - v
                    float dotvn;
                    Vec3f reflectioncolor;
                    Vec3f V, N, R;
                    Ray refray;

                    V = (-ray.d).normalize();
                    N = hitRec.n;
                    dotvn = V.dot(N);
                    if(dotvn < 0.0f) { dotvn = 0.0f; }
                    R = (N * (2 * dotvn) - V).normalize(); //R = (2 * (-ray.d.dot(hitRec.n));

                    refray.o = (hitRec.p + (hitRec.n * 0.01f)); //Move out along the normal a little bit to avoid self-hit
                    refray.d = R;

                    reflectioncolor = (fireRaysRec(refray, (recdepth + 1), iTests) * scene->objects_VPP[hitRec.primIndex]->getMaterialReflection());

                    retcolor += (scene->objects_VPP[hitRec.primIndex]->getMaterialSpecular().multCoordwise(reflectioncolor));
                }

                //Clamping
                if(retcolor.r < 0.0f) { retcolor.r = 0.0f; } if(retcolor.r > 1.0f) { /*retcolor.r = 1.0f; std::cout << "OVER 1 R!" << std::endl;*/ }
                if(retcolor.g < 0.0f) { retcolor.g = 0.0f; } if(retcolor.g > 1.0f) { /*retcolor.g = 1.0f; std::cout << "OVER 1 G!" << std::endl;*/ }
                if(retcolor.b < 0.0f) { retcolor.b = 0.0f; } if(retcolor.b > 1.0f) { /*retcolor.b = 1.0f; std::cout << "OVER 1 B!" << std::endl;*/ }
            }
        }

        return retcolor;
    }

Any help would be greatly appriciated.





Aucun commentaire:

Enregistrer un commentaire