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, ¤tDisplay);
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.