Пример #1
0
/* Not really the best or most accurate way, but it works... */
double AutoExposure(scene *myScene)
{
#define ACCUMULATION_SIZE 256
        double exposure = -1.0f;
        double accumulationfactor = (double)max(myScene->width, myScene->height);
        double projectionDistance = 0.0f;

        if ((myScene->persp.type == CONIC) && myScene->persp.FOV > 0.0f && myScene->persp.FOV < 189.0f) {
                projectionDistance = 0.5f * myScene->width / tanf ((double)(PIOVER180) * 0.5f * myScene->persp.FOV);
        }

        accumulationfactor = accumulationfactor / ACCUMULATION_SIZE;
        colour mediumPoint = {0.0f, 0.0f, 0.0f};
        const double mediumPointWeight = 1.0f / (ACCUMULATION_SIZE*ACCUMULATION_SIZE);
        int x,y;
        for (y = 0; y < ACCUMULATION_SIZE; ++y) {
                for (x = 0 ; x < ACCUMULATION_SIZE; ++x) {

                        if (myScene->persp.type == ORTHOGONAL || projectionDistance == 0.0f) {

                                ray viewRay = { {(double)x*accumulationfactor, (double)y * accumulationfactor, -10000.0f}, { 0.0f, 0.0f, 1.0f}};
                                colour currentColor = raytrace(&viewRay, myScene);
                                colour tmp = colourMul(&currentColor, &currentColor);
                                tmp = colourCoefMul(mediumPointWeight, &tmp);
                                mediumPoint = colourAdd(&mediumPoint,&tmp);
                        } else {
                                vector dir = {((double)(x)*accumulationfactor - 0.5f * myScene->width) / projectionDistance,
                                              ((double)(y)*accumulationfactor - 0.5f * myScene->height) / projectionDistance,
                                              1.0f
                                             };
                                double norm = vectorDot(&dir,&dir);
                                if (norm == 0.0f)
                                        break;
                                dir = vectorScale(invsqrtf(norm), &dir);
                                ray viewRay = { {0.5f * myScene->width,  0.5f * myScene->height, 0.0f}, {dir.x, dir.y, dir.z} };
                                colour currentColor = raytrace(&viewRay, myScene);
                                colour tmp = colourMul(&currentColor, &currentColor);
                                tmp = colourCoefMul(mediumPointWeight, &tmp);
                                mediumPoint = colourAdd(&mediumPoint,&tmp);
                        }
                }
        }

        double mediumLuminance = sqrtf(0.2126f * mediumPoint.red + 0.715160f * mediumPoint.green + 0.072169f * mediumPoint.blue);
        if (mediumLuminance > 0.001f) {
                // put the medium luminance to an intermediate gray value
                exposure = logf(0.6f) / mediumLuminance;
        }
        return exposure;
}
__declspec(noinline) void GetOptionPrices(float *pT, float *pK, float *pS0, float *pC)
{
  int i;
  float d1, d2, erf1, erf2, invf;
  float sig2 = sig * sig;

#pragma simd
  for (i = 0; i < N; i++)
  {
    invf = invsqrtf(sig2 * pT[i]);
    d1 = (logf(pS0[i] / pK[i]) + (r + sig2 * 0.5f) * pT[i]) / invf;
    d2 = (logf(pS0[i] / pK[i]) + (r - sig2 * 0.5f) * pT[i]) / invf;
    erf1 = 0.5f + 0.5f * erff(d1 * invsqrt2);
    erf2 = 0.5f + 0.5f * erff(d2 * invsqrt2);
    pC[i]  = pS0[i] * erf1 - pK[i] * expf((-1.0f) * r * pT[i]) * erf2;
  }
}
Пример #3
0
void *renderThread(void *arg)
{

        int x,y;
        thread_info *tinfo = (thread_info *)arg;

        /* Calculate which part to render based on thread id */
        int limits[]={(tinfo->thread_num*sectionsize),(tinfo->thread_num*sectionsize)+sectionsize};

        /* Autoexposure */
        double exposure = AutoExposure(myScene);

        double projectionDistance = 0.0f;
        if ((myScene->persp.type == CONIC) && myScene->persp.FOV > 0.0f && myScene->persp.FOV < 189.0f) {
                projectionDistance = 0.5f * myScene->width / tanf((double)(PIOVER180) * 0.5f * myScene->persp.FOV);
        }


        for (y = limits[0]; y < limits[1]; ++y) {
                for (x = 0; x < myScene->width; ++x) {
                        colour output = {0.0f, 0.0f, 0.0f};
                        double fragmentx, fragmenty;

                        /* Antialiasing */
                        for (fragmentx = x; fragmentx < x + 1.0f; fragmentx += 0.5f) {
                                for (fragmenty = y; fragmenty < y + 1.0f; fragmenty += 0.5f) {
                                        double sampleRatio=0.25f;
                                        colour temp = {0.0f, 0.0f, 0.0f};
                                        double totalWeight = 0.0f;

                                        if (myScene->persp.type == ORTHOGONAL || projectionDistance == 0.0f) {
                                                ray viewRay = { {fragmentx, fragmenty, -10000.0f},{ 0.0f, 0.0f, 1.0f}};
                                                int i;
                                                for (i = 0; i < myScene->complexity; ++i) {
                                                        colour result = raytrace(&viewRay, myScene);
                                                        totalWeight += 1.0f;
                                                        temp = colourAdd(&temp,&result);
                                                }
                                                temp = colourCoefMul((1.0f/totalWeight), &temp);
                                        } else {
                                                vector dir = {(fragmentx - 0.5f * myScene->width) / projectionDistance,
                                                              (fragmenty - 0.5f * myScene->height) / projectionDistance,
                                                              1.0f
                                                             };

                                                double norm = vectorDot(&dir,&dir);
                                                if (norm == 0.0f)
                                                        break;

                                                dir = vectorScale(invsqrtf(norm),&dir);

                                                vector start = {0.5f * myScene->width,  0.5f * myScene->height, 0.0f};

                                                vector tmp = vectorScale(myScene->persp.clearPoint,&dir);
                                                vector observed = vectorAdd(&start,&tmp);

                                                int i;
                                                for (i = 0; i < myScene->complexity; ++i) {
                                                        ray viewRay = { {start.x, start.y, start.z}, {dir.x, dir.y, dir.z} };

                                                        if (myScene->persp.dispersion != 0.0f) {
                                                                vector disturbance;
                                                                disturbance.x = (myScene->persp.dispersion / RAND_MAX) * (1.0f * rand());
                                                                disturbance.y = (myScene->persp.dispersion / RAND_MAX) * (1.0f * rand());
                                                                disturbance.z = 0.0f;

                                                                viewRay.start = vectorAdd(&viewRay.start, &disturbance);
                                                                viewRay.dir = vectorSub(&observed, &viewRay.start);
                                                                norm = vectorDot(&viewRay.dir,&viewRay.dir);

                                                                if (norm == 0.0f)
                                                                        break;

                                                                viewRay.dir = vectorScale(invsqrtf(norm),&viewRay.dir);
                                                        }
                                                        colour result = raytrace(&viewRay, myScene);
                                                        totalWeight += 1.0f;
                                                        temp = colourAdd(&temp,&result);
                                                }
                                                temp = colourCoefMul((1.0f/totalWeight), &temp);
                                        }

                                        temp.blue = (1.0f - expf(temp.blue * exposure));
                                        temp.red =  (1.0f - expf(temp.red * exposure));
                                        temp.green = (1.0f - expf(temp.green * exposure));

                                        colour adjusted = colourCoefMul(sampleRatio, &temp);
                                        output = colourAdd(&output, &adjusted);
                                }
                        }

                        /* gamma correction */
                        double invgamma = 0.45f; //Fixed value from sRGB standard
                        output.blue = powf(output.blue, invgamma);
                        output.red = powf(output.red, invgamma);
                        output.green = powf(output.green, invgamma);

                        img[(x+y*myScene->width)*3+2] = (unsigned char)min(output.red*255.0f, 255.0f);
                        img[(x+y*myScene->width)*3+1] = (unsigned char)min(output.green*255.0f, 255.0f);
                        img[(x+y*myScene->width)*3+0] = (unsigned char)min(output.blue*255.0f,255.0f);
                }
        }
        pthread_exit((void *) arg);
}
Пример #4
0
colour raytrace(ray *viewRay, scene *myScene)
{
        colour output = {0.0f, 0.0f, 0.0f};
        double coef = 1.0f;
        int level = 0;
	
        do {
                vector hitpoint,n;
                int currentSphere = -1;
                int currentTriangle = -1;
                material currentMat;
                double t = 20000.0f;
                double temp;
                vector n1;

                unsigned int i;
                for (i = 0; i < myScene->numSpheres; ++i) {
                        if (collideRaySphere(viewRay, &myScene->spheres[i], &t)) {
                                currentSphere = i;
                        }
                }

                for (i = 0; i < myScene->numTriangles; ++i) {
                        if (collideRayTriangle(viewRay, &myScene->triangles[i], &t, &n1)) {
                                currentTriangle = i;
                                currentSphere = -1;
                        }
                }

                if (currentSphere != -1) {
                        vector scaled = vectorScale(t, &viewRay->dir);
                        hitpoint = vectorAdd(&viewRay->start, &scaled);
                        n = vectorSub(&hitpoint, &myScene->spheres[currentSphere].pos);
                        temp = vectorDot(&n,&n);
                        if (temp == 0.0f) break;
                        temp = invsqrtf(temp);
                        n = vectorScale(temp, &n);
                        currentMat = myScene->materials[myScene->spheres[currentSphere].material];
                } else if (currentTriangle != -1) {
                        vector scaled = vectorScale(t, &viewRay->dir);
                        hitpoint = vectorAdd(&viewRay->start, &scaled);
                        n=n1;
                        temp = vectorDot(&n,&n);
                        if (temp == 0.0f) break;
                        temp = invsqrtf(temp);
                        n = vectorScale(temp, &n);
                        currentMat = myScene->materials[myScene->triangles[currentTriangle].material];
                } else {
                        /* No hit - add background */
                       	colour test = {0.05,0.05,0.35};
                        colour tmp = colourCoefMul(coef, &test);
                        output = colourAdd(&output,&tmp);
                        break;
                }

                /* Bump mapping using Perlin noise */
                if (currentMat.bump != 0.0) {

                        double noiseCoefx = noise(0.1 * hitpoint.x, 0.1 * hitpoint.y, 0.1 * hitpoint.z, myNoise);
                        double noiseCoefy = noise(0.1 * hitpoint.y, 0.1 * hitpoint.z, 0.1 * hitpoint.x, myNoise);
                        double noiseCoefz = noise(0.1 * hitpoint.z, 0.1 * hitpoint.x, 0.1 * hitpoint.y, myNoise);


                        n.x = (1.0f - currentMat.bump ) * n.x + currentMat.bump * noiseCoefx;
                        n.y = (1.0f - currentMat.bump ) * n.y + currentMat.bump * noiseCoefy;
                        n.z = (1.0f - currentMat.bump ) * n.z + currentMat.bump * noiseCoefz;

                        temp = vectorDot(&n, &n);
                        if (temp == 0.0f) {
                                break;
                        }
                        temp = invsqrtf(temp);
                        n = vectorScale(temp, &n);
                }

                bool inside;

                if (vectorDot(&n,&viewRay->dir) > 0.0f) {
                        n = vectorScale(-1.0f,&n);
                        inside = TRUE;
                } else {
                        inside = FALSE;
                }

                if (!inside) {

                        ray lightRay;
                        lightRay.start = hitpoint;

                        /* Find the value of the light at this point */
                        unsigned int j;
                        for (j = 0; j < myScene->numLights; ++j) {
                                light currentLight = myScene->lights[j];
                                lightRay.dir = vectorSub(&currentLight.pos,&hitpoint);

                                double lightprojection = vectorDot(&lightRay.dir,&n);

                                if ( lightprojection <= 0.0f ) continue;

                                double lightdist = vectorDot(&lightRay.dir,&lightRay.dir);
                                double temp = lightdist;

                                if ( temp == 0.0f ) continue;
                                temp = invsqrtf(temp);
                                lightRay.dir = vectorScale(temp,&lightRay.dir);
                                lightprojection = temp * lightprojection;

                                /* Calculate the shadows */
                                bool inshadow = FALSE;
                                double t = lightdist;

                                unsigned int k;

                                for (k = 0; k < myScene->numSpheres; ++k) {
                                        if (collideRaySphere(&lightRay, &myScene->spheres[k], &t)) {
                                                inshadow = TRUE;
                                                break;
                                        }

                                }

                                for (k = 0; k < myScene->numTriangles; ++k) {
                                        if (collideRayTriangle(&lightRay, &myScene->triangles[k], &t, &n1)) {
                                                inshadow = TRUE;
                                                break;
                                        }
                                }


                                if (!inshadow) {
                                        /* Diffuse refraction using Lambert */
                                        double lambert = vectorDot(&lightRay.dir, &n) * coef;
                                        double noiseCoef = 0.0f;
                                        int level = 0;
                                        switch (currentMat.MatType) {

                                        case TURBULENCE:
                                                for (level = 1; level < 10; level++) {
                                                        noiseCoef += (1.0f / level )
                                                                     * fabsf(noise(level * 0.05 * hitpoint.x,
                                                                                   level * 0.05 * hitpoint.y,
                                                                                   level * 0.05 * hitpoint.z,
                                                                                   myNoise));
                                                }
                                                colour diff1 = colourCoefMul(noiseCoef,&currentMat.diffuse);
                                                colour diff2 = colourCoefMul((1.0f - noiseCoef), &currentMat.mdiffuse);
                                                colour temp1 = colourAdd(&diff1, &diff2);
                                                output = colourAdd(&output, &temp1);
                                                break;

                                        case MARBLE:
                                                for (level = 1; level < 10; level ++) {
                                                        noiseCoef +=  (1.0f / level)
                                                                      * fabsf(noise(level * 0.05 * hitpoint.x,
                                                                                    level * 0.05 * hitpoint.y,
                                                                                    level * 0.05 * hitpoint.z,
                                                                                    myNoise));
                                                }
                                                noiseCoef = 0.5f * sinf( (hitpoint.x + hitpoint.y) * 0.05f + noiseCoef) + 0.5f;
                                                colour diff3 = colourCoefMul(noiseCoef,&currentMat.diffuse);
                                                colour diff4 = colourCoefMul((1.0f - noiseCoef), &currentMat.mdiffuse);
                                                colour tmp1 = colourAdd(&diff3, &diff4);

                                                colour lamint = colourCoefMul(lambert, &currentLight.intensity);
                                                colour lamint_scaled = colourCoefMul(coef, &lamint);

                                                colour temp2 = colourMul(&lamint_scaled, &tmp1);
                                                output = colourAdd(&output, &temp2);
                                                break;

                                                /* Basically Gouraud */
                                        default:

                                                output.red += lambert * currentLight.intensity.red * currentMat.diffuse.red;
                                                output.green += lambert * currentLight.intensity.green * currentMat.diffuse.green;
                                                output.blue += lambert * currentLight.intensity.blue * currentMat.diffuse.blue;
                                                break;
                                        }

                                        /* Blinn */
                                        double viewprojection = vectorDot(&viewRay->dir, &n);
                                        vector blinnDir = vectorSub(&lightRay.dir, &viewRay->dir);
                                        double temp = vectorDot(&blinnDir, &blinnDir);
                                        if (temp != 0.0f ) {
                                                double blinn = invsqrtf(temp) * max(lightprojection - viewprojection , 0.0f);
                                                blinn = coef * powf(blinn, currentMat.power);
                                                colour tmp_1 = colourCoefMul(blinn, &currentMat.specular);
                                                colour tmp_2 = colourMul(&tmp_1, &currentLight.intensity);
                                                output = colourAdd(&output, &tmp_2);
                                        }

                                }
                        }
                        /* Iterate over the reflection */

                        coef *= currentMat.reflection;
                        double reflect = 2.0f * vectorDot(&viewRay->dir, &n);
                        viewRay->start = hitpoint;

                        vector tmp = vectorScale(reflect, &n);
                        viewRay->dir = vectorSub(&viewRay->dir, &tmp);
                }
                level++;
                /* Limit iteration depth to 10 */
        } while ((coef > 0.0f) && (level < 10));
        return output;
}