Exemplo n.º 1
0
/*!
SLCamera::calcMinMax calculates the axis alligned minimum and maximum point of
the camera position and the 4 near clipping plane points.
*/
void SLCamera::calcMinMax(SLVec3f &minV, SLVec3f &maxV)
{
    SLVec3f P[5];
    SLfloat tanFov = tan(_fov*SL_DEG2RAD*0.5f);
    SLfloat tN = tanFov * _clipNear; //top near
    SLfloat rN = tN * _aspect;       //right near

    // frustum pyramid lines
    P[0].set(0,0,0);

    // around near clipping plane
    P[1].set( rN, tN,-_clipNear);
    P[2].set( rN,-tN,-_clipNear);
    P[3].set(-rN,-tN,-_clipNear);
    P[4].set(-rN, tN,-_clipNear);

    // init min & max points
    minV.set( FLT_MAX,  FLT_MAX,  FLT_MAX);
    maxV.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);

    // calc min and max point of all vertices
    for (SLuint i=0; i<5; ++i)
    {   if (P[i].x < minV.x) minV.x = P[i].x;
        if (P[i].x > maxV.x) maxV.x = P[i].x;
        if (P[i].y < minV.y) minV.y = P[i].y;
        if (P[i].y > maxV.y) maxV.y = P[i].y;
        if (P[i].z < minV.z) minV.z = P[i].z;
        if (P[i].z > maxV.z) maxV.z = P[i].z;
    }
}
Exemplo n.º 2
0
/*! 
SLMesh::calcMinMax calculates the axis alligned minimum and maximum point
*/
void SLMesh::calcMinMax(SLVec3f &minV, SLVec3f &maxV)
{  // init min & max points
   minV.set( FLT_MAX,  FLT_MAX,  FLT_MAX);
   maxV.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);

   // calc min and max point of all vertices
   for (SLuint i=0; i<numV; ++i)
   {  if (P[i].x < minV.x) minV.x = P[i].x;
      if (P[i].x > maxV.x) maxV.x = P[i].x;
      if (P[i].y < minV.y) minV.y = P[i].y;
      if (P[i].y > maxV.y) maxV.y = P[i].y;
      if (P[i].z < minV.z) minV.z = P[i].z;
      if (P[i].z > maxV.z) maxV.z = P[i].z;
   } 
}
Exemplo n.º 3
0
/*!
SLRay::diffuseMC scatters a ray around hit normal (cosine distribution).
This is only used for photonmapping(russian roulette).
The random direction lies around z-Axis and is then transformed by a rotation 
matrix to lie along the normal. The direction is calculated according to MCCABE
*/
void SLRay::diffuseMC(SLRay* scattered)
{
   SLVec3f randVec;
   SLfloat eta1,eta2,eta1sqrt;

   scattered->setDir(hitNormal);
   scattered->origin = hitPoint;
   scattered->depth = depth+1;
   depthReached = scattered->depth;
   
   // for reflectance the start material stays the same
   scattered->originMat = hitMat;
   scattered->originShape = hitShape;
   scattered->type = REFLECTED;

   //calculate rotation matrix
   SLMat3f rotMat;
   SLVec3f rotAxis((SLVec3f(0.0,0.0,1.0) ^ scattered->dir).normalize());
   SLfloat rotAngle=acos(scattered->dir.z); //z*scattered.dir()
   rotMat.rotation(rotAngle*180.0f/SL_PI, rotAxis);

   //cosine distribution
   eta1 = (SLfloat)random->Random(); 
   eta2 = SL_2PI*(SLfloat)random->Random();
   eta1sqrt = sqrt(1-eta1);
   //transform to cartesian
   randVec.set(eta1sqrt * cos(eta2),
               eta1sqrt * sin(eta2),
               sqrt(eta1));

   scattered->setDir(rotMat*randVec);
}
Exemplo n.º 4
0
/*!
SLRay::refractMC scatters a ray around perfect transmissive direction according 
to translucency (for higher translucency the ray is less scattered).
This is used for path tracing and distributed ray tracing as well as for photon 
scattering. The direction is calculated the same as with specular scattering
(see reflectMC). The created direction is along z-axis and then transformed to 
lie along transmissive direction with rotationMatrix rotMat. The rotation 
matrix must be precalculated (stays the same for each ray sample, needs to be 
be calculated only once)
*/
void SLRay::refractMC(SLRay* refracted,SLMat3f rotMat)
{  SLfloat eta1, eta2;
   SLVec3f randVec;
   SLfloat translucency = hitMat->translucency();

   //scatter within transmissive lobe
   eta1 = (SLfloat)random->Random(); 
   eta2 = SL_2PI*(SLfloat)random->Random();
   SLfloat f1=sqrt(1.0f-pow(eta1,2.0f/(translucency+1.0f)));

   //transform to cartesian
   randVec.set( f1*cos(eta2),
                f1*sin(eta2),
                pow(eta1,1.0f/(translucency+1.0f)));

   //ray needs to be reset if already hit a shape
   if(refracted->hitShape)
   {  refracted->length = SL_FLOAT_MAX;
      refracted->hitShape = 0;
      refracted->hitPoint = SLVec3f::ZERO;
      refracted->hitNormal = SLVec3f::ZERO;
   }
   
   refracted->setDir(rotMat*randVec);
}
Exemplo n.º 5
0
/*!
SLRay::reflectMC scatters a ray around perfect specular direction according to 
shininess (for higher shininess the ray is less scattered). This is used for 
path tracing and distributed ray tracing as well as for photon scattering. 
The direction is calculated according to MCCABE. The created direction is 
along z-axis and then transformed to lie along specular direction with 
rotationMatrix rotMat. The rotation matrix must be precalculated (stays the 
same for each ray sample, needs to be be calculated only once)
*/
bool SLRay::reflectMC(SLRay* reflected,SLMat3f rotMat)
{  SLfloat eta1, eta2;
   SLVec3f randVec;
   SLfloat shininess = hitMat->shininess();

   //scatter within specular lobe
   eta1 = (SLfloat)random->Random();
   eta2 = SL_2PI*(SLfloat)random->Random();
   SLfloat f1 = sqrt(1.0f-pow(eta1, 2.0f/(shininess+1.0f)));

   //tranform to cartesian
   randVec.set(f1 * cos(eta2),
               f1 * sin(eta2),
               pow(eta1, 1.0f/(shininess+1.0f)));

   //ray needs to be reset if already hit a shape
   if(reflected->hitShape)
   {  reflected->length = SL_FLOAT_MAX;
      reflected->hitShape = 0;
      reflected->hitPoint = SLVec3f::ZERO;
      reflected->hitNormal = SLVec3f::ZERO;
   }
   
   //apply rotation
   reflected->setDir(rotMat*randVec);
   
   //true if in direction of normal
   return (hitNormal * reflected->dir >= 0.0f);
}
Exemplo n.º 6
0
/*!Creates photons (ray with power) from a point light source and sends 
it into the scene. 
Note that a point light has no cosine distribution and no surface area
*/
void SLPhotonMapper::photonEmission(SLLight* light)
{
   SLfloat eta1,eta2,f1,f2;
   SLVec3f C,N;
   SLVec3f power;
      
   C = light->positionWS();

   //because point lights have no surface use only radiance for power of emitted photons
   power.set(light->diffuse().r,light->diffuse().g,light->diffuse().b);

   //progress
   SLlong maxPhotons=_mapCaustic->maxStoredPhotons()+_mapGlobal->maxStoredPhotons();
   SLlong curPhotons=_mapCaustic->storedPhotons()+_mapGlobal->storedPhotons();;
   
   SLlong emitted=0;

   //shoot the photons as long as maps are not full
   while(emitted<light->photons() && !(_mapCaustic->isFull()&&(_mapGlobal->isFull())))
   {
      //progress
      if(emitted%1000==0)
      {  curPhotons=_mapCaustic->storedPhotons()+_mapGlobal->storedPhotons();
         printf("\b\b\b\b%3.0f%%",(SLfloat)curPhotons/(SLfloat)maxPhotons*100.0f);
      }

      //create spherical random direction
      eta1=_random->Random();eta2=_random->Random();
      f1 = SL_2PI*eta2;
      f2 = 2.0f * sqrt(eta1 * (1-eta1));

      //direction in cartesian coordinates
      N.set(cos(f1)*f2, sin(f1)*f2, (1.0-2.0*eta1));
      
      //create and emit photon
      SLRay scattered(C,N,PRIMARY, (SLShape*)light, SL_FLOAT_MAX, 1);
      photonScatter(&scattered,power,LIGHT);

      emitted++;
      //scaling of stored photons is necessary if one of the maps was filled by this photon
      //(because emission of photons continues in order to fill the other map)
      if(_mapCaustic->isFull() && !_mapCausticGotFull)
      {  _mapCausticGotFull = true;
         _mapCaustic->scalePhotonPower(1.0f/SLfloat(emitted));
      }
      if(_mapGlobal->isFull() && !_mapGlobalGotFull)
      {  _mapGlobalGotFull = true;
         _mapGlobal->scalePhotonPower(1.0f/SLfloat(emitted));
      }

   }

   //scale all stored photons of this light source
   if(emitted)
   {  SLRay::emittedPhotons+=emitted;
      _mapCaustic->scalePhotonPower(1.0f/SLfloat(emitted));
      _mapGlobal->scalePhotonPower(1.0f/SLfloat(emitted));
   }
}
Exemplo n.º 7
0
SLfloat SLLightRect::shadowTestMC(SLRay* ray, // ray of hit point
                                  const SLVec3f& L, // vector from hit point to light
                                  const SLfloat lightDist) // distance to light
{
    SLVec3f SP; // vector hit point to sample point in world coords

    SLfloat randX = rnd01();
    SLfloat randY = rnd01();

    // choose random point on rect as sample
    SP.set(updateAndGetWM().multVec(SLVec3f((randX*_width)-(_width*0.5f), (randY*_height)-(_height*0.5f), 0)) - ray->hitPoint);
    SLfloat SPDist = SP.length();
    SP.normalize();
    SLRay shadowRay(SPDist, SP, ray);

    SLScene::current->root3D()->hitRec(&shadowRay);

    if (shadowRay.length >= SPDist - FLT_EPSILON)
        return 1.0f;
    else
        return 0.0f;
}
Exemplo n.º 8
0
//-----------------------------------------------------------------------------
//! Gets called whenever the mouse is moved.
SLbool SLCamera::onMouseMove(const SLMouseButton button, 
                             const SLint x, const SLint y, const SLKey mod)
{  
    if (button == ButtonLeft) //================================================
    {   
        // new vars needed
        SLVec3f position = this->translation();
        SLVec3f forward =  this->forward();
        SLVec3f right =    this->right();
        SLVec3f up =       this->up();

        // The lookAt point
        SLVec3f laP = position + _focalDist * forward;

         
        // Determine rotation point as the center of the AABB of the hitNode
        SLVec3f rtP;
        if (_lookAtRay.length < FLT_MAX && _lookAtRay.hitNode)
             rtP = _lookAtRay.hitNode->aabb()->centerWS();
        else rtP = laP;
              
        // Determine rot angles around x- & y-axis
        SLfloat dY = (y-_oldTouchPos1.y) * _rotFactor;
        SLfloat dX = (x-_oldTouchPos1.x) * _rotFactor;

        if (_camAnim==turntableYUp) //.......................................
        {
            SLMat4f rot;
            rot.translate(rtP);
            rot.rotate(-dX, SLVec3f(0,1,0));
            rot.rotate(-dY, right);
            rot.translate(-rtP);
			
            _om.setMatrix(rot * _om);
            needWMUpdate();
        }
        else if (_camAnim==turntableZUp) //..................................
        {
            SLMat4f rot;
            rot.translate(rtP);
            rot.rotate(dX, SLVec3f(0,0,1));
            rot.rotate(dY, right);
            rot.translate(-rtP);
         
            _om.setMatrix(rot * _om);
            needWMUpdate();
        }
        else if (_camAnim==walkingYUp) //....................................
        {
            dY *= 0.5f; 
            dX *= 0.5f; 
            
            SLMat4f rot;
            rot.rotate(-dX, SLVec3f(0, 1, 0));
            rot.rotate(-dY, right);

            forward.set(rot.multVec(forward));
            lookAt(position + forward);
        }
        else if (_camAnim==walkingZUp) //....................................
        {
            dY *= 0.5f; 
            dX *= 0.5f; 
            
            SLMat4f rot;
            rot.rotate(-dX, SLVec3f(0, 0, 1));
            rot.rotate(-dY, right);

            forward.set(rot.multVec(forward));
            lookAt(position + forward, SLVec3f(0, 0, 1));
        }
        
        _oldTouchPos1.set((SLfloat)x,(SLfloat)y);
    } 
    else
    if (button == ButtonMiddle) //==============================================
    {   if (_camAnim==turntableYUp || _camAnim==turntableZUp)
        {  
            // Calculate the fraction delta of the mouse movement
            SLVec2f dMouse(x-_oldTouchPos1.x, _oldTouchPos1.y-y);
            dMouse.x /= (SLfloat)_scrW;
            dMouse.y /= (SLfloat)_scrH;
         
            // Scale the mouse delta by the lookAt distance
            SLfloat lookAtDist;
            if (_lookAtRay.length < FLT_MAX)
                lookAtDist = _lookAtRay.length;
            else lookAtDist = _focalDist;

            // scale factor depending on the space sice at focal dist
            SLfloat spaceH = tan(SL_DEG2RAD*_fov/2) * lookAtDist * 2.0f;
            SLfloat spaceW = spaceH * _aspect;

            dMouse.x *= spaceW;
            dMouse.y *= spaceH;
         
            if (mod==KeyCtrl)
            {
                translate(SLVec3f(-dMouse.x, 0, dMouse.y), TS_Object);

            } else
            {
                translate(SLVec3f(-dMouse.x, -dMouse.y, 0), TS_Object);
            }
            _oldTouchPos1.set((SLfloat)x,(SLfloat)y);
        }
    } //========================================================================
    return true;
}
Exemplo n.º 9
0
/*!
onInit initializes the global variables and builds the shader program. It
should be called after a window with a valid OpenGL context is present.
*/
void onInit()
{  
    // Set light parameters
    _globalAmbi.set(0.0f, 0.0f, 0.0f);
    _lightPos.set( 0.0f, 0.0f, 100.0f);
    _lightDir.set( 0.0f, 0.0f,-1.0f);
    _lightAmbient.set( 0.1f, 0.1f, 0.1f);
    _lightDiffuse.set( 1.0f, 1.0f, 1.0f);
    _lightSpecular.set( 1.0f, 1.0f, 1.0f);
    _matAmbient.set( 1.0f, 1.0f, 1.0f);
    _matDiffuse.set( 1.0f, 1.0f, 1.0f);
    _matSpecular.set( 1.0f, 1.0f, 1.0f);
    _matEmissive.set( 0.0f, 0.0f, 0.0f);
    _matShininess = 100.0f;

    // backwards movement of the camera
    _camZ = -3.0f;

    // Mouse rotation parameters
    _rotX = 0;
    _rotY = 0;
    _deltaX = 0;
    _deltaY = 0;
    _mouseLeftDown = false;

    // Load textures
    _textureID = glUtils::buildTexture("../_data/images/textures/earth2048_C.jpg");

    // Load, compile & link shaders
    _shaderVertID = glUtils::buildShader("../_data/shaders/ADSTex.vert", GL_VERTEX_SHADER);
    _shaderFragID = glUtils::buildShader("../_data/shaders/ADSTex.frag", GL_FRAGMENT_SHADER);
    _shaderProgID = glUtils::buildProgram(_shaderVertID, _shaderFragID);

    // Activate the shader program
    glUseProgram(_shaderProgID);

    // Get the variable locations (identifiers) within the vertex & pixel shader programs
    _pLoc            = glGetAttribLocation (_shaderProgID, "a_position");
    _nLoc            = glGetAttribLocation (_shaderProgID, "a_normal");
    _tLoc            = glGetAttribLocation (_shaderProgID, "a_texCoord");
    _mvMatrixLoc     = glGetUniformLocation(_shaderProgID, "u_mvMatrix");
    _mvpMatrixLoc    = glGetUniformLocation(_shaderProgID, "u_mvpMatrix");
    _nMatrixLoc      = glGetUniformLocation(_shaderProgID, "u_nMatrix");
    _globalAmbiLoc   = glGetUniformLocation(_shaderProgID, "u_globalAmbi");
    _lightPosVSLoc   = glGetUniformLocation(_shaderProgID, "u_lightPosVS");
    _lightDirVSLoc   = glGetUniformLocation(_shaderProgID, "u_lightDirVS");
    _lightAmbientLoc = glGetUniformLocation(_shaderProgID, "u_lightAmbient");
    _lightDiffuseLoc = glGetUniformLocation(_shaderProgID, "u_lightDiffuse");
    _lightSpecularLoc= glGetUniformLocation(_shaderProgID, "u_lightSpecular");
    _matAmbientLoc   = glGetUniformLocation(_shaderProgID, "u_matAmbient");
    _matDiffuseLoc   = glGetUniformLocation(_shaderProgID, "u_matDiffuse");
    _matSpecularLoc  = glGetUniformLocation(_shaderProgID, "u_matSpecular");
    _matEmissiveLoc  = glGetUniformLocation(_shaderProgID, "u_matEmissive");
    _matShininessLoc = glGetUniformLocation(_shaderProgID, "u_matShininess");
    _texture0Loc     = glGetUniformLocation(_shaderProgID, "u_texture0");

    // Build object
    buildSquare();

    // Set some OpenGL states
    glClearColor(0.0f, 0.0f, 0.0f, 1);  // Set the background color
    glEnable(GL_DEPTH_TEST);            // Enables depth test
    glEnable(GL_CULL_FACE);             // Enables the culling of back faces
    GETGLERROR;                         // Check for OpenGL errors
}
Exemplo n.º 10
0
/*!
SLLightRect::shadowTest returns 0.0 if the hit point is completely shaded and 
1.0 if it is 100% lighted. A return value inbetween is calculate by the ratio 
of the shadow rays not blocked to the total number of casted shadow rays.
*/
SLfloat SLLightRect::shadowTest(SLRay* ray, // ray of hit point
                               const SLVec3f& L, // vector from hit point to light
                               const SLfloat lightDist) // distance to light
{  
    if (_samples.x==1 && _samples.y==1)
    {  
        // define shadow ray
        SLRay shadowRay(lightDist, L, ray);
            
        SLScene::current->root3D()->hitRec(&shadowRay);

        return (shadowRay.length < lightDist) ? 0.0f : 1.0f;
    } 
    else // do light sampling for soft shadows
    {   SLfloat dw = (SLfloat)_width/(SLfloat)_samples.x; // width of a sample cell
        SLfloat dl = (SLfloat)_height/(SLfloat)_samples.y;// length of a sample cell
        SLint   x, y, hx=_samples.x/2, hy=_samples.y/2;
        SLint   samples = _samples.x*_samples.y;
        SLbool* isSampled = new SLbool[samples];
        SLbool  importantPointsAreLighting = true;
        SLfloat lighted = 0.0f; // return value
        SLfloat invSamples = 1.0f/(SLfloat)(samples);
        SLVec3f SP; // vector hitpoint to samplepoint in world coords

        for (y=0; y<_samples.y; ++y)
        {   for (x=0; x<_samples.x; ++x)
            {  SLint iSP = y*_samples.x + x;
            isSampled[iSP]=false;
            }
        }

        /*
        Important sample points (X) on a 7 by 5 rectangular light.
        If all of them are lighting the hitpoint the sample points
        in between (O) are not tested anymore.

             0   1   2   3   4   5   6         
           +---+---+---+---+---+---+---+
        0  | X | . | . | X | . | . | X |
           +---+---+---+---+---+---+---+
        1  | . | . | . | . | . | . | . |
           +---+---+---+---+---+---+---+
        2  | X | . | . | X | . | . | X |
           +---+---+---+---+---+---+---+
        3  | . | . | . | . | . | . | . |
           +---+---+---+---+---+---+---+
        4  | X | . | . | X | . | . | X |
           +---+---+---+---+---+---+---+
        */

        // Double loop for the important sample points
        for (y=-hy; y<=hy; y+=hy)
        {   for (x=-hx; x<=hx; x+=hx)
            {  SLint iSP = (y+hy)*_samples.x + x+hx;
            isSampled[iSP]=true;
            
            SP.set(updateAndGetWM().multVec(SLVec3f(x*dw, y*dl, 0)) - ray->hitPoint);
            SLfloat SPDist = SP.length();
            SP.normalize();
            SLRay shadowRay(SPDist, SP, ray);

            SLScene::current->root3D()->hitRec(&shadowRay);
            
            if (shadowRay.length >= SPDist-FLT_EPSILON) 
                lighted += invSamples; // sum up the light
            else 
                importantPointsAreLighting = false;
            }
        }

        if (importantPointsAreLighting)
            lighted = 1.0f;
        else
        {  // Double loop for the samplepoints inbetween
            for (y=-hy; y<=hy; ++y)
            {   for (x=-hx; x<=hx; ++x)
                {  SLint iSP = (y+hy)*_samples.x + x+hx;
                    if (!isSampled[iSP])
                    {   SP.set(updateAndGetWM().multVec(SLVec3f(x*dw, y*dl, 0)) - ray->hitPoint);
                        SLfloat SPDist = SP.length();
                        SP.normalize();
                        SLRay shadowRay(SPDist, SP, ray);

                        SLScene::current->root3D()->hitRec(&shadowRay);
                  
                        // sum up the light
                        if (shadowRay.length >= SPDist-FLT_EPSILON) 
                            lighted += invSamples;
                    }
                }
            }
        }
        if (isSampled) delete [] isSampled;
        return lighted;
    }
}