IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

Probleme avec glReadPixels et glsl


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 17
    Par défaut Probleme avec glReadPixels et glsl
    Bonjour, j'ai un problème assez bizarre avec glReadPixels, je n'ai malheureusement pas mon code sous la main mais je vais essayer de décrire le problème de façon précise et si jamais ce n'est pas suffisant je pourrai poster mon code demain.

    Ça fait pas mal de temps que j'utilise cette fonction pour faire des captures d’écran et jusqu’à présent je n'ai jamais eu de soucis. Récemment j'ai commence a travailler sur les heightmap, j'ai fais un shader en glsl pour recuperer le z du vertex courant et lui assigner une couleur correspondant a sa position par rapport a la camera. J'obtiens donc une bonne heightmap (j'ai vérifié en l'affichant a l’écran, tout est correct) mais lorsque je fais ensuite un glreadpixels pour sauvegarder les pixels et les exporter dans une bitmap, le quart superieur de l'image est décalé vers la droite. J'ai essaye plein de possibilités et tant que je n'utilise pas le z du vertex en entrée (dans mon vertex shader) tout fonctionne normalement et j'obtiens une image normale. Mais des que j'utilise le z du vertex pour déterminer sa couleur j'ai de nouveau ce problème de décalage (je re-précise que l'image s'affiche normalement a l’écran, le problème ne se manifeste qu'au niveau de la capture des pixels).

    Voila un petit code d'exemple que j'ai fais de memoire :

    vertex shader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    varying vec4 couleur;
     
    void main()
    {
       float z = gl_Vertex.z;
     
       // traitements divers sur z, pour faire des tests j'ai simplifie au maximum 
       // en divisant simplement z par 3000 pour ne pas qu'il depasse 1
       // je me suis egalement assure qu'il ne soit pas negatif en le mettant a 0 le cas echeant
     
       couleur = vec4( z, z, z, 1 );
     
    }
    pixel shader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    varying vec4 couleur;
    void main()
    {
       gl_FragColor = couleur;
    }
    et mon code (j'ai simplifie pour les tests) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    vector< unsigned char > vPixels;
    vPixels.resize( 3 * 1280 * 1024 );
    glReadPixels(0, 0, 1280, 1024, GL_BGR, GL_UNSIGNED_BYTE, &vPixels[0] ); // j'utilise GL_BGR car j'exporte ensuite les donnees dans une bitmap et ca lit les couleurs a l'envers
    SaveBitmap("test.bmp", vPixels ); // fonction perso, ca m'etonnerais que le probleme vienne de la car je n'ai jamais eu de soucis avec
    Je precise que ma CG n'est pas toute recente, c'est une geforce 7950 GT au cas ou le probleme viendrait de la.

    Est-ce que quelqu'un a déjà rencontre ce type de problème ? Est-ce que ça pourrait venir d'un soucis avec glReadPixels qui ne se manifesterait que dans certaines conditions ? Merci.

    EDIT : j'ai oublié de préciser que j'utilise opengl 1.4

    EDIT 2 : Je précise également que j'appelle glPixelStorei(GL_PACK_ALIGNMENT, 1) avant de faire mon glReadPixel mais ça ne change rien.

  2. #2
    Membre averti
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 17
    Par défaut
    Re, au cas où ça pourrait aider j'ai fais un imprim écran avec la heightmap qui s'affiche normalement et j'ai également joint la texture telle qu'elle est quand je la capture moi-même avec glReadPixels (oui je sais c'est laid mais le terrain qu'elle représente l'est également) :


    Version imprim écran :



    (ce qui confirme que le problème ne vient pas de mon shader mais du readpixels)

    et voici la version glReadPixels :



    Voici la partie de mon code qui fait la capture :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    void CCollisionManager::CreateHeightMap( IMesh* pMesh, vector< unsigned char >& vPixels, IRenderer::TPixelFormat format )
    {
    	IShader* pOrgShader = pMesh->GetCurrentShader();
    	IShader* pHMShader = m_oRenderer.GetShader( "hm" );
    	pHMShader->Enable( true ); // appelle glUseProgram du shader heightmap
    	pMesh->SetShader( pHMShader ); // pour que le bon shader soit utilisé au moment du rendu, ça peut sembler redondant avec la ligne précédente mais si  je ne le faisais pas c'est le shader d'origine associé au mesh qui serait activé
     
    	CMatrix oModelView, oProj;  // les matrices sont initialisées à l'identité
    	int nWidth, nHeight;
    	m_oRenderer.GetResolution( nWidth, nHeight );
    	float fScreenRatio = (float)nWidth / (float)nHeight;
    	oProj.m_00 = 1.f / fScreenRatio;
    	CBox b;
    	pMesh->GetBbox( b );  // bounding box du terrain
    	float maxLenght = b.m_oDimension.m_x ;
    	if( maxLenght < b.m_oDimension.m_y )
    		maxLenght = b.m_oDimension.m_y;
    	float scale = ( maxLenght / 2.f );
     
    	pHMShader->SendUniformValues( "h", b.m_oDimension.m_z );
    	pHMShader->SendUniformValues( "zMin", b.m_oMinPoint.m_z );	
    	pHMShader->SendUniformValues( "scale", scale );
     
    	m_oRenderer.SetProjectionMatrix( oProj );
     
    	m_oRenderer.BeginRender();  // vidage du color buffer et du z-buffer 
    	pMesh->Update();  // rendu du terrain
    	m_oRenderer.ReadPixels( vPixels, format );  // correspond au glReadPixels(0, 0, 1280, 1024, GL_BGR, GL_UNSIGNED_BYTE, &vPixels[0] ) que j'avais mis dans le message précédent
    	m_oRenderer.EndRender();  // SwapBuffers
     
    	pHMShader->Enable( false );
    	pMesh->SetShader( pOrgShader );
    }
    J'envoie ensuite mon tableau de pixels à la fonction qui crée la bitmap :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    void CBMPLoader::Export( string sFileName, const ILoader::IRessourceInfos& ri )
    {
    	const ILoader::CTextureInfos* pInfos = static_cast< const ILoader::CTextureInfos* >( &ri );
    	int nWidth = pInfos->m_nWidth;
    	int nHeight = pInfos->m_nHeight;
    	if( nWidth < 0 || nHeight < 0 )
    	{
    		CEException e( "CBMPLoader::Export() : la taille de la texture doit être positive" );
    		throw e;
    	}
    	const vector< unsigned char >& vData = pInfos->m_vTexels;
    	int nBitPerPixel = 0;
    	switch( pInfos->m_ePixelFormat )
    	{
    	case TPixelFormat::eRGB:
    	case TPixelFormat::eBGR:
    		nBitPerPixel = 24;
    		break;
    	case TPixelFormat::eRGBA:
    	case TPixelFormat::eBGRA:
    		nBitPerPixel = 32;
    	}
     
    	// file header
    	FILE* pFile = fopen( sFileName.c_str(), "w" );
    	char* sMagic = "BM";
    	fwrite( sMagic, 1, 2, pFile );	
    	int nSize = 0;
    	fwrite( &nSize, 4, 1, pFile );
    	int id = 0;
    	fwrite( &id, 1, 2, pFile );
    	fwrite( &id, 1, 2, pFile );
    	int DataAdress = 0;
    	int nDataAdressOffset = ftell(pFile);
    	fwrite( &DataAdress, 4, 1, pFile );
     
    	// image header
    	int nHeaderSize = 40;
    	fwrite( &nHeaderSize, 4, 1, pFile );
    	fwrite( &nWidth, 4, 1, pFile );
    	fwrite( &nHeight, 4, 1, pFile );
    	int nPlanes = 1;
    	fwrite( &nPlanes, 2, 1, pFile );
    	fwrite( &nBitPerPixel, 2, 1, pFile );
    	int iData = 0;
    	fwrite( &iData, 4, 6, pFile );
     
    	int nDataAdress = ftell(pFile);
     
    	// Pixel data
    	fwrite( &vData[ 0 ], sizeof( unsigned char ), vData.size(), pFile );
    	nSize = ftell(pFile);
     
    	// complete infos
    	fseek( pFile, 2, SEEK_SET );
    	fwrite( &nSize, 4, 1, pFile );
    	fseek( pFile, nDataAdressOffset, SEEK_SET );
    	fwrite( &nDataAdress, 4, 1, pFile );
    	fclose( pFile );
    }
    Voici le code complet de mon shader :


    Vertex shader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    varying vec4 vColor;
    uniform float h; // hauteur de la bounding box du terrain
    uniform float zMin, scale;
     
    void main()
    {	
    	vec4 vVertex = gl_ProjectionMatrix * gl_Vertex;
    	gl_Position = vVertex / scale;
    	gl_Position.w = 1.;	
    	float color = ( vVertex.z - zMin ) / h;
    	vColor = vec4(color, color, color, 1);	
    }
    Pixel shader :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    varying vec4 vColor;
     
    void main()
    {
    	gl_FragColor = vColor;
    }
    La matrice de projection est la suivante (le 0.8 représente 1/ratio) :

    0.8 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 1


    J'espère que ça vous aidera mieux, merci d'avance !
    Images attachées Images attachées   

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 17
    Par défaut
    Bon finalement j'avais laisse ca de cote et en travaillant sur autre chose je suis tombe sur un autre probleme bizarre, toujours au niveau des textures, et en regardant le code plus en detail je me suis rendu compte que j'avais fais une petite erreur au niveau de l'ecriture du fichier (j'ouvrais un binaire en mode ASCII ). C'etait d'ailleurs visible dans le message que j'avais poste :

    Citation Envoyé par wperrad Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void CBMPLoader::Export( string sFileName, const ILoader::IRessourceInfos& ri )
    {
    	...
    	FILE* pFile = fopen( sFileName.c_str(), "w" );
            ...
    }

    Du coup j'ai corrige et ca m'a resolu mes 2 problemes en meme temps, ca n'avait donc rien a voir avec le glreadpixels. Je met ca en resolu.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec glReadPixels
    Par breton51 dans le forum OpenGL
    Réponses: 14
    Dernier message: 10/02/2006, 17h00
  2. Probleme avec la copie des surfaces
    Par Black_Daimond dans le forum DirectX
    Réponses: 3
    Dernier message: 09/01/2003, 10h33
  3. probleme avec la touche F10
    Par b.grellee dans le forum Langage
    Réponses: 2
    Dernier message: 15/09/2002, 22h04
  4. Probleme avec fseek
    Par Bjorn dans le forum C
    Réponses: 5
    Dernier message: 04/08/2002, 07h17
  5. [Kylix] probleme avec un imagelist
    Par NicoLinux dans le forum EDI
    Réponses: 4
    Dernier message: 08/06/2002, 23h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo