Beispiel #1
0
// Foley & vanDam: Computer Graphics: Principles and Practice, 
//     2nd Ed. pp 756ff.
Point3 SContext::RefractVector(float ior)
{
	Point3 N = Normal();
	float VN,nur,k;
	VN = DotProd(-viewDir,N);
	if (backFace) nur = ior;
	else nur = (ior!=0.0f) ? 1.0f/ior: 1.0f;
	k = 1.0f-nur*nur*(1.0f-VN*VN);
	if (k<=0.0f) {
		// Total internal reflection: 
		return ReflectVector();
	}
	else {
		return (nur*VN-(float)sqrt(k))*N + nur*viewDir;
	}
}
Beispiel #2
0
static void TraceLine( VECTOR *LinP, VECTOR *LinD, VECTOR *Color, int reccount )
{
    VECTOR  Pnt, Norm, LDir, NewDir, NewDir2, TmpCol, TmpCol2;
    VECTOR  TmpPnt, TmpNorm, D;
    double  t, A, cosfi;
    TEXTURE *txt, *tmptxt;
    int     i, shadowcount, usedist;

    Color->x = Color->y = Color->z = 0.0;

    if( reccount > 0 ) {
        /* Only use distributed tracing in higher nodes of the recursion tree */
        usedist = ( (MAXREC-reccount) < DISTLEVELS ) ? 1 : 0;

        /* Try intersection with objects */
        t = IntersectObjs( LinP, LinD, &Pnt, &Norm, &txt );

        /* Get light-intensity in intersection-point (store in cosfi) */
        if( t > EPSILON ) {
            LDir.x = Lightpos.x-Pnt.x;       /* Get line to light from surface */
            LDir.y = Lightpos.y-Pnt.y;
            LDir.z = Lightpos.z-Pnt.z;
            cosfi = LDir.x*Norm.x + LDir.y*Norm.y + LDir.z*Norm.z;
            if(cosfi > 0.0) {    /* If angle between lightline and normal < PI/2 */
                shadowcount = 0;
                if( usedist ) {
                    A = Lightr / VectorLength( &LDir );
                    for( i = 0; i < DISTRIB; i++ ) {
                        DistribVector( &D, &LDir, A, A );
                        NewDir = LDir;
                        NewDir.x += D.x; NewDir.y += D.y; NewDir.z += D.z;
                        /* Check for shadows (ignore hit info, may be used though) */
                        t = IntersectObjs( &Pnt, &NewDir, &TmpPnt, &TmpNorm, &tmptxt );
                        if( ( t < EPSILON ) || ( t > 1.0 ) ) shadowcount++;
                    }
                } else {
                    t = IntersectObjs( &Pnt, &LDir, &TmpPnt, &TmpNorm, &tmptxt );
                    if( ( t < EPSILON ) || ( t > 1.0 ) ) shadowcount = DISTRIB;
                }
                if( shadowcount > 0 ) {
                    A = Norm.x*Norm.x + Norm.y*Norm.y + Norm.z*Norm.z;
                    A *= LDir.x*LDir.x + LDir.y*LDir.y + LDir.z*LDir.z;
                    cosfi = (cosfi/sqrt(A))*txt->diffuse*(double)shadowcount/DISTRIB;
                } else {
                    cosfi = 0.0;
                }
            } else {
                cosfi = 0.0;
            }
            Color->x = txt->color.x*(Ambient+cosfi);
            Color->y = txt->color.y*(Ambient+cosfi);
            Color->z = txt->color.z*(Ambient+cosfi);
            if( txt->reflect > EPSILON ) {
                ReflectVector( &NewDir, LinD, &Norm );
                TmpCol.x = TmpCol.y = TmpCol.z = 0.0;
                if( usedist && ( txt->roughness > EPSILON ) ) {
                    for( i = 0; i < DISTRIB; i++ ) {
                        DistribVector( &D, &NewDir, txt->roughness, txt->roughness );
                        NewDir2 = NewDir;
                        NewDir2.x += D.x; NewDir2.y += D.y; NewDir2.z += D.z;
                        TraceLine( &Pnt, &NewDir2, &TmpCol2, reccount-1 );
                        TmpCol.x += TmpCol2.x;
                        TmpCol.y += TmpCol2.y;
                        TmpCol.z += TmpCol2.z;
                    }
                    ScaleVector( &TmpCol, 1.0/DISTRIB );
                } else {
                    TraceLine( &Pnt, &NewDir, &TmpCol, reccount-1 );
                }
                Color->x += TmpCol.x * txt->reflect;
                Color->y += TmpCol.y * txt->reflect;
                Color->z += TmpCol.z * txt->reflect;
            }
        } else {
            /* Get sky-color (interpolate between horizon and zenit) */
            A = sqrt( LinD->x*LinD->x + LinD->y*LinD->y );
            if( A > 0.0 ) A = atan( fabs( LinD->z ) / A )*0.63661977;
            else A = 1.0;
            Color->x = Skycolor[1].x*A + Skycolor[0].x*(1.0-A);
            Color->y = Skycolor[1].y*A + Skycolor[0].y*(1.0-A);
            Color->z = Skycolor[1].z*A + Skycolor[0].z*(1.0-A);
        }

        /* Make sure that the color does not exceed the maximum level */
        if(Color->x > 1.0) Color->x = 1.0;
        if(Color->y > 1.0) Color->y = 1.0;
        if(Color->z > 1.0) Color->z = 1.0;
    }
}