2017-06-09 8 views
2

J'ai 2 programmes - 3.x OpenGL:OpenGL + SDL + ne peut pas tirer à Offscreen OIR

  • un est un programme Win32 (un tutoriel NeHe modifié) qui crée une fenêtre et le contexte GL via wglCreateContext () et wlgMakeCurrent()
  • un est un progamme de SDL2

Les deux programmes appellent cette fonction:

int DrawGLScene(GLvoid)        
{ 
    static int nFirstTime = 1; 

    if(nFirstTime) 
    { 
    glewInit(); 

    nFirstTime = 0; 
    glGenTextures(1, &g_OffscreenTexture); 
    glGenFramebuffers(1, &g_OffscreenFBO); 
    } 

    GLuint nScreenFBO = 0; 

    glBindTexture(GL_TEXTURE_2D, 0); 

    SelectColor(COLOR_YELLOW); 
    DrawFilledRectangle(50, 50, 200, 200); 

    // Now draw to offscreen FBO.. 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &nScreenFBO); 

    glBindFramebuffer(GL_FRAMEBUFFER, g_OffscreenFBO); 
    glBindTexture(GL_TEXTURE_2D, g_OffscreenTexture); 

    //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_ScreenWidth, g_ScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // WORKS 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // DOESN'T WORK 

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_OffscreenTexture, 0); 

    SelectColor(COLOR_GREEN); 
    DrawFilledRectangle(0, 0, 200, 200); 

    SelectColor(COLOR_RED); 
    DrawFilledRectangle(0, 50, 200, 200); 

    // Go test the colours 
    TestRGB(); 

    // Put screen FBO back.. 
    glBindTexture(GL_TEXTURE_2D, 0); 
    glBindFramebuffer(GL_FRAMEBUFFER, nScreenFBO); 

    return TRUE; 
} 

La fonction dessine un rectangle jaune sur l'écran visible et doit dessiner quelques rectangles verts et rouges dans un FBO hors écran.

J'utilise alors une fonction (TestRGB() qui appelle glReadPixels() pour renvoyer les valeurs RVB aux points dans les rectangles rouges et verts dans le OIR offscreen.

glReadPixels() fonctionne très bien dans le non-SDL programme. pour le programme SDL, elle renvoie toujours des valeurs RVB de 0 (noir).

Quand je change les dimensions glTexImage2D() du offscreen OIR pour correspondre à l'écran réel, la version SDL fonctionne!

Remarque : Je veux que la texture de l'écran soit plus petite que l'écran

Qu'est-ce que je fais de mal? Ai-je manqué une étape d'initialisation de la texture?

est ici la fonction que j'utiliser pour obtenir les valeurs RVB:

void GetRGBAt(GLuint nFBO, int x, int y, GLfloat *pfR, GLfloat *pfG, GLfloat *pfB) 
{ 
    GLuint nScreenFBO = 0; 

    // Remember the screen FBO.. 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &nScreenFBO); 

    // Now bind to given FBO where we'll pull the colours from.. 
    glBindFramebuffer(GL_FRAMEBUFFER, nFBO); 

    // windowHeight - y - 1 
    BYTE abRGBA[ 4 ] = { 0 }; 
    glReadPixels(x, g_ScreenHeight - y - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, abRGBA); 

    (*pfR) = (float) abRGBA[ 0 ]/255.0f; 
    (*pfG) = (float) abRGBA[ 1 ]/255.0f; 
    (*pfB) = (float) abRGBA[ 2 ]/255.0f; 

    // Put screen FBO back.. 
    glBindFramebuffer(GL_FRAMEBUFFER, nScreenFBO); 
} 

Et voici mon initialisation de la fenêtre SDL - pas sûr si la double mise en mémoire tampon est une cause de cela.

if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) 
    { 
    LogDebugf("FATAL - SDL_Init"); 
    exit(-1); 
    } 

    atexit(SDL_Quit); 

    // Use OpenGL 3.1 core 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); 
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE,  8); 
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); 
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 

    SDL_DisplayMode currentDisplay; 

    SDL_GetCurrentDisplayMode(0, &currentDisplay); 

    g_ScreenWidth = 960; 
    g_ScreenHeight = 640; 

    int nWindowPosY = SDL_WINDOWPOS_UNDEFINED; 

    SDL_DisplayMode displayMode; 
    SDL_GetDesktopDisplayMode(0, &displayMode); 

    g_SDLWindow = SDL_CreateWindow("OffscreenFBO", 
           SDL_WINDOWPOS_UNDEFINED, 
           nWindowPosY, 
           g_ScreenWidth, 
           g_ScreenHeight, 
           /* SDL_WINDOW_FULLSCFREEN | */ SDL_WINDOW_OPENGL); 
    if(g_SDLWindow == NULL) 
    { 
    LogDebugf("SDL_CreateWindow.. FAILED"); 
    exit(-1); 
    } 

    g_SDLWindowID = SDL_GetWindowID(g_SDLWindow); 

    SDL_GL_CreateContext(g_SDLWindow); 

    GLenum glewRC = glewInit(); 

    if(glewRC != GLEW_OK) 
    exit(1); 

    glViewport(0, 0, g_ScreenWidth, g_ScreenHeight);     // Reset The Current Viewport 
    glClearColor(0.9f, 0.9f, 0.9f, 1.0f); 

    g_Ortho = glm::ortho(0.0f, (GLfloat) g_ScreenWidth, (GLfloat) g_ScreenHeight, 0.0f, 0.0f, 1000.0f); 

    g_SolidProgram   = BuildProgram(vsSolid, fsSolid); 

    glClearColor(0.215f, 0.2f, 0.176f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    SDL_Event  event; 

    while(g_Running) 
    { 
    DrawGLScene(); 
    ... 
    } 

MISE À JOUR: J'ai trouvé que la taille de la texture semble être lié à mon problème.

//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_ScreenWidth, g_ScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // WORKS 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // WORKS 
    //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // DOESN'T WORK 

Khronos indiquent ce qui suit:

width 
    Specifies the width of the texture image. All implementations support texture images that are at least 1024 texels wide. 
height 
    Specifies the height of the texture image, or the number of layers in a texture array, in the case of the GL_TEXTURE_1D_ARRAY and GL_PROXY_TEXTURE_1D_ARRAY targets. All implementations support 2D texture images that are at least 1024 texels high, and texture arrays that are at least 256 layers deep. 

Il me semble que si une mise en œuvre de SDL2 ne soutiendra pas des textures plus de 1024 pixels de large/haut - au moins dans le but de tirer dans un FBO de toute façon.

Répondre

1

La principale raison pour laquelle cela ne fonctionnait pas était parce que j'ai oublié d'appliquer la matrice de projection ortho correcte sur le FBO hors écran. J'utilisais la même projection que l'écran (1024x640) où la matrice de texture aurait dû utiliser 512x512. Suite à cela, le code GetRGBAt() utilisait g_ScreenHeight au lieu de la hauteur de la texture. Il fonctionne maintenant avec un certain nombre de hauteurs de texture tant que je définis la projection. En d'autres termes, le dessin n'était pas exécuté correctement sur le FBO hors écran.