/////////////////////////////////////////////////////////////////////////////// /// public LancerRayons \n /// Description : Lancement des rayons (raytrace) dans la scène courante /// /// @return None /// /// @author Olivier Dionne /// @date 13/08/2008 /// /////////////////////////////////////////////////////////////////////////////// void CScene::LancerRayons( void ) { Initialiser(); // Distance entre la camera et la scene const float distanceCameraScene = CVecteur3::Distance(m_Camera.PointVise, m_Camera.Position); // Simple trigonometrie entre la distance entre la camera et la scene et l'angle de la camera const float hauteur = 2 * (tan(Deg2Rad(m_Camera.Angle)) * distanceCameraScene); // Regle de trois pour trouver la largeur a partir de la hauteur const float largeur = hauteur * m_ResLargeur / (float)m_ResHauteur; // On ne prend pas compte d'une rotation/orientation speciale de la camera ici, elle est prise en compte plus loin // La position Hauteur Min de la scene est la somme des vecteurs de distance en -Z et la moitie de la hauteur en -Y CVecteur3 positionHauteurMin = CVecteur3(0, -hauteur / 2, -distanceCameraScene); // Logique semblable pour la Largeur Min CVecteur3 positionLargeurMin = CVecteur3(-largeur / 2, 0, -distanceCameraScene); for (int y = 0; y < m_ResHauteur; ++y) { //Calculer la position pixelY dans la scene CVecteur3 pixelY = positionHauteurMin + CVecteur3(0, (y / (float)m_ResHauteur) * hauteur, 0); for (int x = 0; x < m_ResLargeur; ++x) { //Calculer la position pixelX dans la scene CVecteur3 pixelX = positionLargeurMin + CVecteur3((x / (float)m_ResLargeur) * largeur, 0, 0); CRayon rayon; //Ajuster l'origine du rayon rayon.AjusterOrigine(m_Camera.Position); //Ajuster la direction du rayon CVecteur3 direction = CVecteur3::Normaliser(pixelX + pixelY); //Ajuster la direction selon la matrice d'orientation de la camera rayon.AjusterDirection(direction * m_Camera.Orientation); //Initialiser les autres caracteristiques du rayon rayon.AjusterEnergie(Math3D::REAL(1)); rayon.AjusterNbRebonds(0); rayon.AjusterIndiceRefraction(Math3D::REAL(1)); //Lancer le rayon et obtenir la couleur CCouleur couleur = CScene::ObtenirCouleur(rayon); //Enregistrer les couleurs m_InfoPixel[(x + y * m_ResLargeur) * 3] = couleur.r; m_InfoPixel[(x + y * m_ResLargeur) * 3 + 1] = couleur.g; m_InfoPixel[(x + y * m_ResLargeur) * 3 + 2] = couleur.b; } } // Créer une texture openGL glGenTextures ( 1, &m_TextureScene ); glBindTexture ( GL_TEXTURE_2D, m_TextureScene ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA8, m_ResLargeur, m_ResHauteur, 0, GL_RGB, GL_FLOAT, m_InfoPixel ); }
/////////////////////////////////////////////////////////////////////////////// /// private constant ObtenirCouleurSurIntersection \n /// Description : Obtient la couleur à un point d'intersection en particulier /// Calcule les contributions colorées de toutes les lumières, avec /// les modèles de Phong et de Gouraud. Aussi, dépendemment des /// propriétés de la surface en intersection, on réfléchi ou in /// réfracte le rayon courant. /// current ray. /// /// @param [in] Rayon const CRayon & Le rayon à tester /// @param [in] Intersection const Scene::CIntersection & L'ntersection spécifiée /// /// @return const CCouleur La couleur à l'intersection donnée /// /// @author Olivier Dionne /// @date 13/08/2008 /// /////////////////////////////////////////////////////////////////////////////// const CCouleur CScene::ObtenirCouleurSurIntersection( const CRayon& Rayon, const CIntersection& Intersection ) const { CCouleur Result = Intersection.ObtenirSurface()->ObtenirCouleur() * Intersection.ObtenirSurface()->ObtenirCoeffAmbiant(); CVecteur3 IntersectionPoint = Rayon.ObtenirOrigine()+ Intersection.ObtenirDistance() * Rayon.ObtenirDirection(); // Calculer les contribution colorées des toutes les lumières dans la scène CCouleur LumiereContributions = CCouleur::NOIR; CRayon LumiereRayon; for( LumiereIterator uneLumiere = m_Lumieres.begin(); uneLumiere != m_Lumieres.end(); uneLumiere++ ) { // Initialise le rayon de lumière (ou rayon d'ombre) LumiereRayon.AjusterOrigine( IntersectionPoint ); LumiereRayon.AjusterDirection( ( *uneLumiere )->GetPosition() - IntersectionPoint ); LumiereRayon.AjusterEnergie( 1 ); LumiereRayon.AjusterIndiceRefraction( 1 ); if( CVecteur3::ProdScal( LumiereRayon.ObtenirDirection(), Intersection.ObtenirNormale() ) > 0 ) { // Obtenir la couleur à partir de la lumière CCouleur Filter = ObtenirFiltreDeSurface( LumiereRayon ); CCouleur LumiereCouleur = ( *uneLumiere )->ObtenirCouleur() * Filter; // Ajouter la contribution de Gouraud REAL GouraudFactor = ( *uneLumiere )->GetIntensity() * Intersection.ObtenirSurface()->ObtenirCoeffDiffus() * CVecteur3::ProdScal( Intersection.ObtenirNormale(), LumiereRayon.ObtenirDirection() ); Result += Intersection.ObtenirSurface()->ObtenirCouleur() * GouraudFactor * LumiereCouleur; // ... } } return Result; }
/////////////////////////////////////////////////////////////////////////////// /// public LancerRayons \n /// Description : Lancement des rayons (raytrace) dans la scène courante /// /// @return None /// /// @author Olivier Dionne /// @date 13/08/2008 /// /////////////////////////////////////////////////////////////////////////////// void CScene::LancerRayons( void ) { Initialiser(); REAL HalfH = tan( Deg2Rad<REAL>( m_Camera.Angle * RENDRE_REEL( 0.5 ) ) ); REAL HalfW = ( RENDRE_REEL( m_ResLargeur ) / m_ResHauteur ) * HalfH; REAL InvResWidth = RENDRE_REEL( 1.0 ) / m_ResLargeur; REAL InvResHeight = RENDRE_REEL( 1.0 ) / m_ResHauteur; CRayon Rayon; CCouleur PixelColor; int PixelIdx = 0; #pragma omp parallel for private(Rayon, PixelColor, PixelIdx) for( int PixY = 0; PixY < m_ResHauteur; PixY++ ) { for( int PixX = 0; PixX < m_ResLargeur; PixX++ ) { // Prépare le rayon Rayon.AjusterOrigine( m_Camera.Position ); Rayon.AjusterDirection( CVecteur3( ( 2 * PixX * InvResWidth - 1 ) * HalfW, ( 2 * PixY * InvResHeight - 1 ) * HalfH, -1 ) ); Rayon.AjusterDirection( CVecteur3::Normaliser( Rayon.ObtenirDirection() * m_Camera.Orientation ) ); Rayon.AjusterEnergie( 1 ); Rayon.AjusterNbRebonds( 0 ); Rayon.AjusterIndiceRefraction( 1 ); PixelColor = ObtenirCouleur( Rayon ); PixelIdx = ( PixX + ( PixY * m_ResLargeur ) ) * 3; m_InfoPixel[ PixelIdx + 0 ] = PixelColor.r; m_InfoPixel[ PixelIdx + 1 ] = PixelColor.g; m_InfoPixel[ PixelIdx + 2 ] = PixelColor.b; } } // Créer une texture openGL glGenTextures ( 1, &m_TextureScene ); glBindTexture ( GL_TEXTURE_2D, m_TextureScene ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA8, m_ResLargeur, m_ResHauteur, 0, GL_RGB, GL_FLOAT, m_InfoPixel ); }