我有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。