我有2種方案 - 無論是OpenGL的3.x的:的OpenGL + SDL +不能畫到畫外FBO
- 一個是Win32程序(修改訥河教程),它通過創建一個wglCreateContext窗口和GL上下文( )和wlgMakeCurrent()
- 一個是SDL2編程'
兩個程序調用該函數:
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;
}
該函數在可見屏幕上繪製一個黃色矩形,並應在屏幕外FBO中繪製幾個綠色和紅色矩形。
然後我用一個函數(TestRGB()的調用glReadPixels()以點紅色和綠色的矩形內的屏幕外FBO返回RGB值。
glReadPixels()在非SDL工作正常程序。對於SDL程序,它總是返回RGB值0(黑色)。
當我改變glTexImage2D()的屏幕外FBO的尺寸,以符合實際的屏幕,SDL版本的作品!
注:我想讓屏幕外的紋理比屏幕更小。
我做錯了什麼?我錯過了紋理初始化步驟嗎?
下面是我用得到的RGB值的功能:
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);
}
這裏是我的SDL窗口初始化 - 不知道雙緩衝就是一個原因。
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();
...
}
UPDATE: 我發現紋理的大小似乎與我的問題。
//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的聲明如下:
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.
在我看來,就好像一個SDL2實施,將不寬/高支持紋理小於1024個像素 - 至少繪製成的目的無論如何FBO。