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 :

OpenGL : Offscreen texture rendering to bitmap


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 10
    Par défaut OpenGL : Offscreen texture rendering to bitmap
    Bonjour,

    J'essaie de créer un rendu hors écran au sein de mon application OpenGL. Pour ce faire, je stock mon rendu offscreen dans une texture que je désire ensuite exporter dans un fichier image. Après une journée de recherche/lecture de tutorial au sujet des FBO, DIB, Offscreen rendering et Render to texture, je suis bloqué à l'étape "texture => image".

    S'il vous plait pourriez vous m'aider à sauver ma texture dans un 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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    ///////////////////////////////////////////////////////////////////////////////
    // Define static variable
    static unsigned char texture[3 * SIZE * SIZE];
    static unsigned int texture_id;
    static int window_width = 512;
    static int window_height = 512;
     
    // OpenGL settings
    glEnable(GL_DEPTH_TEST);
     
    // Texture setting
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &texture_id);
    glBindTexture(GL_TEXTURE_2D, texture_id);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RGB,
    GL_UNSIGNED_BYTE, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
     
    glLoadIdentity();
    glTranslatef(0, 0, -10);
    glRotatef(30, 1, 0, 0);
     
    /* Define a view-port adapted to the texture */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(20, 1, 5, 15);
    glViewport(0, 0, SIZE, SIZE);
    glMatrixMode(GL_MODELVIEW);
     
    /* Render to buffer */
    glClearColor(1, 1, 1, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    //DrawCube
    glBegin(GL_LINE_LOOP);
     
    glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1, -1, 1);
    glTexCoord2i(1, 1); glVertex3f(-1, 1, 1);
    glTexCoord2i(1, 0); glVertex3f(-1, 1, -1);
     
    glTexCoord2i(0, 0); glVertex3f( 1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f( 1, -1, 1);
    glTexCoord2i(1, 1); glVertex3f( 1, 1, 1);
    glTexCoord2i(1, 0); glVertex3f( 1, 1, -1);
     
    glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1, -1, 1);
    glTexCoord2i(1, 1); glVertex3f( 1, -1, 1);
    glTexCoord2i(1, 0); glVertex3f( 1, -1, -1);
     
    glTexCoord2i(0, 0); glVertex3f(-1, 1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1, 1, 1);
    glTexCoord2i(1, 1); glVertex3f( 1, 1, 1);
    glTexCoord2i(1, 0); glVertex3f( 1, 1, -1);
     
    glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
    glTexCoord2i(0, 1); glVertex3f(-1, 1, -1);
    glTexCoord2i(1, 1); glVertex3f( 1, 1, -1);
    glTexCoord2i(1, 0); glVertex3f( 1, -1, -1);
     
    glTexCoord2i(0, 0); glVertex3f(-1, -1, 1);
    glTexCoord2i(0, 1); glVertex3f(-1, 1, 1);
    glTexCoord2i(1, 1); glVertex3f( 1, 1, 1);
    glTexCoord2i(1, 0); glVertex3f( 1, -1, 1);
     
    glEnd();
    //Ending texture
    glFlush();
     
    /* Copy buffer to texture */
    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, SIZE - 10, SIZE - 10);
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////
    Ce code créé une texture que vous pouvez voir dans le lien ci-dessous projeté sur les faces d'un cube :



    Comment puis je exporter cette texture dans un bitmap ?

    ++Tyra =)

  2. #2
    Membre chevronné
    Inscrit en
    Février 2008
    Messages
    413
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Février 2008
    Messages : 413
    Par défaut
    Salut,

    si j'ai bien compris ton rendu offscreen est OK et tu veux juste sauver ca dans un fichier BMP, exact?

    si c'est ca voilà le code que j'utilise (je saute les parties spécifiques aux buffers offscreen puisqu'apparement ca marche)

    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
    62
     
    short GLScene::RenderToFile(char* fileName, short width, short height)
    {
    	// Create the offscreen pBuffer / FBO / DIB
    	// ---------------------------------------
    	CreateOffscreenBuffers(m_offscreen_SizeX, m_offscreen_SizeY);
     
    	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
     
    	// Render the scene
    	// ----------------
    	RenderScene();	
     
    	// Save result of rendering to destination file
    	// --------------------------------------------
    	// Create a BMP buffer to save the scene to
    	byte* bmpBuffer = (byte*) malloc(m_offscreen_SizeX * m_offscreen_SizeY * 3);
    	if (!bmpBuffer)	return 0;
     
    	// Read the frame buffer pixels into the bmp buffer	
    	glReadPixels(0, 0, m_offscreen_SizeX - 1, m_offscreen_SizeY - 1, GL_BGR, GL_UNSIGNED_BYTE, bmpBuffer);
     
    	// Open destination File
    	FILE *file = NULL;
    	fopen_s(&file, fileName, "wb");
    	if (!file) return 0;
     
    	// Create & configure Bitmap and File info headers
    	BITMAPFILEHEADER bitmapFileHeader;
    	BITMAPINFOHEADER bitmapInfoHeader;
     
    	bitmapFileHeader.bfType			= 0x4D42; //"BM"
    	bitmapFileHeader.bfSize			= m_offscreen_SizeX * m_offscreen_SizeY * 3;
    	bitmapFileHeader.bfReserved1	= 0;
    	bitmapFileHeader.bfReserved2	= 0;
    	bitmapFileHeader.bfOffBits		= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
     
    	bitmapInfoHeader.biSize			= sizeof(BITMAPINFOHEADER);
    	bitmapInfoHeader.biWidth		= m_offscreen_SizeX - 1;
    	bitmapInfoHeader.biHeight		= m_offscreen_SizeY - 1;
    	bitmapInfoHeader.biPlanes		= 1;
    	bitmapInfoHeader.biBitCount		= 24;
    	bitmapInfoHeader.biCompression	= BI_RGB;
    	bitmapInfoHeader.biSizeImage	= 0;
    	bitmapInfoHeader.biXPelsPerMeter= 0; // ?
    	bitmapInfoHeader.biYPelsPerMeter= 0; // ?
    	bitmapInfoHeader.biClrUsed		= 0;
    	bitmapInfoHeader.biClrImportant = 0;
     
    	fwrite(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, file);
    	fwrite(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, file);
    	fwrite(bmpBuffer, m_offscreen_SizeX*m_offscreen_SizeY*3, 1, file);
    	fclose(file);
    	free(bmpBuffer);
     
    	// Unbind and Delete offscreen Buffers
    	// ----------------------------------
    	ReleaseOffscreenBuffers();
     
    	return 1;
    }
    L'étape important est le glReadPixels, qui va lire dans le buffer actif, en l'occurence, ton buffer offscreen.

    Bonne chance!

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 10
    Par défaut
    Un immense merci pour ce code. Je l'ai implémenté et il est fonctionnel. J'arrive bien à lire mes textures directement dans le buffer et à les sauvegarder dans un fichier BMP.

    Le problème auquel je suis confronté désormais est celui de la résolution. Je n'arrive pas a faire un rendu offscreen dans une texture avec une définition supérieure à celle de mon écran (1280px.1024px), le tout en conservant l'accélération graphique.

    Après prise de renseignement j'ai retenu les potentiels techniques suivantes :

    - Utiliser un HDC sur-dimensionné et switcher au moment du rendu
    - Utiliser les pbuffer
    - Utiliser les FBO
    - Faire le rendu en quatre passes et recomposer l'image globale dans le fichier de sortie.

    Avez-vous des idées/commentaires/sources personnelles sur le sujet ?

    ++Tyra

  4. #4
    Membre chevronné
    Inscrit en
    Février 2008
    Messages
    413
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Février 2008
    Messages : 413
    Par défaut
    Re,

    tu as peut-être un problème avec ton implémentation des FBO / pBuffers / DIB Section, car normalement:

    1) Tu crées le FBO / pBuffer / DIB en lui donnant la taille que tu veux (il y a les limitations de ta carte graphique, mais normalement tu peux monter en 4096 x 4096 sur à peut près toute config récente)

    2) Au moment de "binder" ton FBO / pBuffer / DIB, tu fais un glViewport et un glOrtho (ou gluPerspective, ca ca dépend de ton application) aux dimensions correspondantes

    3) tu fais le rendu

    4) Tu sauvegardes le tout dans un .bmp aux dimensions correspondantes

    Je n'ai pas mis les détails de création / binding des buffers offscreen, mais en gros, du début à la fin, j'utilise les paramètres m_offscreen_SizeX et m_offscreen_SizeY que tu vois dans mon bout de code.

    Peut-être as-tu sauté l'étape 2?
    Tu utilises quoi? pBuffer, FBO, DIB?

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 10
    Par défaut
    Un grand grand merci ShevchenKik, le code est désormais opérationnel et j'arrive a faire des rendus en 4096x4096 !

    Par contre, je suis maintenant confronté à un autre problème. j'aimerais utiliser ces images HD pour les injecter dans un AVI. ma fonction d'ajout de frame dans mon AVI prend en entrée un HBITMAP

    J'ai donc essayé d'utiliser CreateCompatibleBitmap() qui prend en paramètres un HDC (Handle to Device Context). Si je comprends bien, ce device context peut se voir attribuer des paramètres de complexité (hauteur, largeur, etc...)
    mais je n'arrive pas à obtenir un HBITMAP correct.

    Si quelqu'un parmis vous sait comment obtenir un HBITMAP avec un HDC custom et un buffer de pixel en byte* , je suis preneur !

    ++Tyra=)

Discussions similaires

  1. Réponses: 3
    Dernier message: 29/07/2009, 14h32
  2. opengl et texture 2D
    Par Rniamo dans le forum OpenGL
    Réponses: 4
    Dernier message: 20/06/2008, 17h03
  3. Rendu OpenGl Offscreen
    Par mrshadow dans le forum OpenGL
    Réponses: 10
    Dernier message: 19/06/2007, 12h39
  4. Texture and Saving Bitmap or Video
    Par capriolo dans le forum DirectX
    Réponses: 1
    Dernier message: 22/04/2007, 14h54
  5. Rendu OpenGL offscreen sous Windows
    Par rincevent_123 dans le forum OpenGL
    Réponses: 3
    Dernier message: 28/11/2003, 09h23

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