在 GLSL 中访问多个 FBO 纹理以创建另一个纹理
Posted
技术标签:
【中文标题】在 GLSL 中访问多个 FBO 纹理以创建另一个纹理【英文标题】:Accessing Multiple FBO Textures in GLSL to create another texture 【发布时间】:2011-04-28 12:41:03 【问题描述】:我创建了 4 个纹理并将它们附加到 FBO,命名为 fbo_texture0 - fbo_texture3。全部成功创建,如下图所示:
图片 1
现在,我想使用 GLSL 创建从先前纹理 (fbo_texture0 - fbo_texture3) 获得的第 5 个纹理。现在,我只想将第一个纹理复制到第五个纹理中。不幸的是,这是我得到的:
图片 2
问题是:
-
如何在 GLSL 中访问这些 fbo 纹理?
如何创建第 5 个纹理? (或者从第一个纹理复制到第五个纹理?)
这是程序的完整代码(以备不时之需):
#include <windows.h>
#include <GL/glew.h> // Include the GLEW header file
#include <GL/glut.h> // Include the GLUT header file
#include <iostream> // Allow us to print to the console
using namespace std;
bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255)
unsigned int fbo; // The frame buffer object
unsigned int fbo_depth; // The depth buffer for the frame buffer object
unsigned int fbo_texture0; // The texture object to write our frame buffer object to
unsigned int fbo_texture1;
unsigned int fbo_texture2;
unsigned int fbo_texture3;
unsigned int fbo_texture4;
GLhandleARB shaderProgram;
GLhandleARB vertexShader;
GLhandleARB fragmentShader;
int window_width = 500; // The width of our window
int window_height = 500; // The height of our window
void initFrameBufferDepthBuffer(void)
glGenRenderbuffers(1, &fbo_depth); // Generate one render buffer and store the ID in fbo_depth
glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth); // Bind the fbo_depth render buffer
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, window_width, window_height); // Set the render buffer storage to be a depth component, with a width and height of the window
glBindRenderbuffer(GL_RENDERBUFFER, 0); // Unbind the render buffer
void initFrameBufferTextures(void)
glGenTextures(1, &fbo_texture0); // Generate one ture
glBindTexture(GL_TEXTURE_2D, fbo_texture0); // Bind the ture fbo_texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard ture with the width and height of our window
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &fbo_texture1); // Generate one ture
glBindTexture(GL_TEXTURE_2D, fbo_texture1); // Bind the ture fbo_texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard ture with the width and height of our window
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &fbo_texture2); // Generate one ture
glBindTexture(GL_TEXTURE_2D, fbo_texture2); // Bind the ture fbo_texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard ture with the width and height of our window
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &fbo_texture3); // Generate one ture
glBindTexture(GL_TEXTURE_2D, fbo_texture3); // Bind the ture fbo_texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard ture with the width and height of our window
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &fbo_texture4); // Generate one ture
glBindTexture(GL_TEXTURE_2D, fbo_texture4); // Bind the ture fbo_texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard ture with the width and height of our window
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
void printInfoLog(GLhandleARB obj)
int infologLength = 0;
int charsWritten = 0;
char* infoLog;
glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
if (infologLength > 0)
infoLog = (char*)malloc(infologLength);
glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
void initFrameBuffer(void)
initFrameBufferDepthBuffer(); // Initialize our frame buffer depth buffer
initFrameBufferTextures(); // Initialize our frame buffer ture
glGenFramebuffers(1, &fbo); // Generate one frame buffer and store the ID in fbo
glBindFramebuffer(GL_FRAMEBUFFER, fbo); // Bind our frame buffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture0, 0);// Attach the ture fbo_texturen to the color buffer in our frame buffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, fbo_texture1, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, fbo_texture2, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, fbo_texture3, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, fbo_texture4, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth); // Attach the depth buffer fbo_depth to our frame buffer
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // Check that status of our generated frame buffer
if (status != GL_FRAMEBUFFER_COMPLETE) // If the frame buffer does not report back as complete
cout << "Couldn't create frame buffer" << endl; // Output an error to the console
exit(0); // Exit the application
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind our frame buffer
void init(void)
//glEnable(GL_TEXTURE_2D); // Enable turing so we can bind our frame buffer ture
glEnable(GL_DEPTH_TEST); // Enable depth testing
initFrameBuffer(); // Create our frame buffer object
void keyOperations (void)
if (keyStates['a']) // If the a key has been pressed
// Perform 'a' key operations
void renderTextures(void)
glBindFramebuffer(GL_FRAMEBUFFER, fbo); // Bind our frame buffer for rendering
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
glViewport(0, 0, window_width, window_height); // Set the size of the frame buffer view port
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set the clear colour
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear the depth and colour buffers
glLoadIdentity();// Reset the modelview matrix
glTranslatef(0.0f, 0.0f, -5.0f);
//Add ambient light
GLfloat ambientColor[] = 0.2f, 0.2f, 0.2f, 1.0f; //Color(0.2, 0.2, 0.2)
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
//Add positioned light
GLfloat lightColor0[] = 0.5f, 0.5f, 0.5f, 1.0f; //Color (0.5, 0.5, 0.5)
GLfloat lightPos0[] = 4.0f, 0.0f, 8.0f, 1.0f; //Positioned at (4, 0, 8)
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
//Add directed light
GLfloat lightColor1[] = 0.5f, 0.2f, 0.2f, 1.0f; //Color (0.5, 0.2, 0.2)
//Coming from the direction (-1, 0.5, 0.5)
GLfloat lightPos1[] = -1.0f, 0.5f, 0.5f, 0.0f;
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_DEPTH_TEST);
glutSolidTeapot(2.0);
glColor3f(0.1,0.2,0.7);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glClearColor(0.5f, 0.5f, 0.0f, 1.0f); // Set the clear colour
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear the depth and colour buffers
glLoadIdentity();// Reset the modelview matrix
glTranslatef(0.0f, 0.0f, -5.0f);
glutSolidTorus(0.80, 1.6, 50, 100);
glColorMaterial ( GL_FRONT_AND_BACK, GL_EMISSION ) ;
glEnable ( GL_COLOR_MATERIAL ) ;
glDrawBuffer(GL_COLOR_ATTACHMENT2);
glClearColor(0.5f, 0.0f, 0.0f, 1.0f); // Set the clear colour
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear the depth and colour buffers
glLoadIdentity();// Reset the modelview matrix
glTranslatef(0.0f, 0.0f, -2.0f);
glutSolidTetrahedron();
glColorMaterial ( GL_FRONT_AND_BACK, GL_EMISSION ) ;
glEnable ( GL_COLOR_MATERIAL ) ;
glDrawBuffer(GL_COLOR_ATTACHMENT3);
glClearColor(0.5f, 0.0f, 0.3f, 1.0f); // Set the clear colour
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear the depth and colour buffers
glLoadIdentity();// Reset the modelview matrix
glTranslatef(0.0f, 0.0f, -2.0f);
glutSolidOctahedron();
glColorMaterial ( GL_FRONT_AND_BACK, GL_EMISSION ) ;
glEnable ( GL_COLOR_MATERIAL ) ;
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind our ture
glActiveTexture(GL_TEXTURE0);
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fbo_texture0);
glUniform1i(glGetUniformLocation(shaderProgram, "tex0"), 0);
glActiveTexture(GL_TEXTURE1);
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fbo_texture1);
glUniform1i(glGetUniformLocation(shaderProgram, "tex1"), 1);
glActiveTexture(GL_TEXTURE2);
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fbo_texture2);
glUniform1i(glGetUniformLocation(shaderProgram, "tex2"), 2);
glActiveTexture(GL_TEXTURE3);
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fbo_texture3);
glUniform1i(glGetUniformLocation(shaderProgram, "tex3"), 3);
glPopAttrib(); // Restore our glEnable and glViewport states
glutSwapBuffers();
static char* textFileRead(const char *fileName)
char* text;
if (fileName != NULL)
FILE *file = fopen(fileName, "rt");
if (file != NULL)
fseek(file, 0, SEEK_END);
int count = ftell(file);
rewind(file);
if (count > 0)
text = (char*)malloc(sizeof(char) * (count + 1));
count = fread(text, sizeof(char), count, file);
text[count] = '\0';
fclose(file);
return text;
void initShader()
char* vsSource = textFileRead("./shader/multitexture.vs");
char* fsSource = textFileRead("./shader/multitexture.fs");
printf("%s\n",fsSource);
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const GLchar **)(&vsSource), NULL);
glCompileShader(vertexShader);
printInfoLog(vertexShader);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, (const GLchar **)(&fsSource), NULL);
glCompileShader(fragmentShader);
printInfoLog(fragmentShader);
delete [] vsSource;
delete [] fsSource;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
void display (void)
keyOperations(); // Perform any key presses
glUseProgram(0);
renderTextures(); // Render our teapot scene into our frame buffer
GLsync s = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glUseProgram(shaderProgram);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // Clear the background of our window to red
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
glTranslatef(-4.7f, 1.0f, -4.0f);
glWaitSync(s, 0, GL_TIMEOUT_IGNORED);
glDeleteSync(s);
glBindTexture(GL_TEXTURE_2D, fbo_texture0); // Bind our frame buffer ture
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
glBindTexture(GL_TEXTURE_2D, 0); // Unbind any tures
glLoadIdentity();
glTranslatef(-2.5f, 1.0f, -4.0f);
glBindTexture(GL_TEXTURE_2D, fbo_texture1); // Bind our frame buffer ture
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
glBindTexture(GL_TEXTURE_2D, 0); // Unbind any tures
glLoadIdentity();
glTranslatef(-0.3f, 1.0f, -4.0f);
glBindTexture(GL_TEXTURE_2D, fbo_texture2); // Bind our frame buffer ture
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
glBindTexture(GL_TEXTURE_2D, 0); // Unbind any tures
glLoadIdentity();
glTranslatef(1.9f, 1.0f, -4.0f);
glBindTexture(GL_TEXTURE_2D, fbo_texture3); // Bind our frame buffer ture
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
glBindTexture(GL_TEXTURE_2D, 0); // Unbind any tures
glLoadIdentity();
glTranslatef(4.1f, 1.0f, -4.0f);
glBindTexture(GL_TEXTURE_2D, fbo_texture4); // Bind our frame buffer ture
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
glBindTexture(GL_TEXTURE_2D, 0); // Unbind any tures
glutSwapBuffers();
void reshape (int width, int height)
glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed
glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly
void keyPressed (unsigned char key, int x, int y)
keyStates[key] = true; // Set the state of the current key to pressed
void keyUp (unsigned char key, int x, int y)
keyStates[key] = false; // Set the state of the current key to not pressed
int main (int argc, char **argv)
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA); // Set up a basic display buffer (only single buffered for now)
glutInitWindowSize (1280, 500); // Set the width and height of the window
glutInitWindowPosition (100, 100); // Set the position of the window
glutCreateWindow ("OpenGL FBO"); // Set the title for the window
if (GLEW_OK != glewInit())
std::cout << "Couldn't initialize GLEW" << std::endl;
exit(0);
initShader();
init();
glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering
glutIdleFunc(display); // Tell GLUT to use the method "display" for rendering
glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping
glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses
glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events
glutMainLoop(); // Enter GLUT's main loop
这是顶点着色器:
void main(void)
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
这里是片段着色器:
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
void main(void)
gl_FragColor = texture2D(tex0, gl_TexCoord[0].st);
编辑#1
按照@Damon的建议修改代码后(代码也已编辑),结果截图如下:
图片 3
现在,我真的不知道问题究竟是什么。我试图更改片段着色器以访问另一个纹理,例如gl_FragColor = texture2D(tex2, gl_TexCoord[0].st);
但我仍然得到与上面相同的显示。所以我认为这绝对不是模型视图/投影问题。
编辑#2
问题仍然不清楚。但是,我尝试在程序中只给出一个glActiveTexture(GL_TEXTUREn);
命令,并注释掉其他glActiveTexture
命令(不修改shader),得到如下结果:
image 4 仅限glActiveTexture(GL_TEXTURE0);
activated。
image 5 仅限glActiveTexture(GL_TEXTURE1);
activated。
图片 6 仅限 glActiveTexture(GL_TEXTURE2);
activated。
图片 7 仅限 glActiveTexture(GL_TEXTURE3);
activated。
当至少 2 个glActiveTexture(GL_TEXTUREn);
被激活时,我得到了与 image 5 相同的结果。这让我想知道问题到底是什么。
【问题讨论】:
您找到问题的原因了吗?我有同样的问题,我真的变得疯狂了.. 不幸的是没有。很抱歉我的回复晚了。 【参考方案1】:initShader
编译和链接着色器。您似乎也以正常的方式将纹理绑定到 renderTextures
内的纹理单元(在取消绑定 FBO 之后,这对于同步很重要)。到目前为止一切顺利,但我在代码中的任何地方都找不到glUseProgram
。这意味着渲染会退回到固定函数,该函数当时没有绑定任何纹理。
片段着色器只从 tex0 读取,所以当然你不会期望看到 tex1-tex3(但我想这只是最小的工作示例代码)。
除此之外,从我在 5 分钟内阅读代码所看到的情况来看,它看起来还不错。
(作为旁注:init
调用 glEnable(GL_TEXTURE_2D)
,这并没有完全错误,但是一旦使用着色器就没有用,请参阅 this。)
【讨论】:
谢谢,非常感谢您的宝贵时间。顺便说一句,不使用 glUseProgram 是一个愚蠢的错误。所以我通过评论 glEnable(GL_TEXTURE_2D) 并在 display() 方法上使用 glUseProgram(shaderProgram) 对代码进行了修改。但是,我得到了相同的结果(纹理全黑),并得到了一些警告:“警告 gl_TexCoord 仅在兼容性配置文件中可用”和“警告 gl_MultiTexCoord0 仅在兼容性配置文件中可用”。有什么办法可以修复着色器脚本? 在您编辑的代码中,您激活了着色器程序 (glUseProgram
)之前 renderTextures()
。只有在之后激活它才有意义(事实上,应该是glUseProgram(0)
),因为它使用的纹理作为输入,当时既没有定义也没有绑定。关于兼容性警告,“正确”的方法是使用通用顶点属性,但既然你肯定有一个兼容性上下文(到处使用固定函数!),应该没问题。尽管如此,你还是应该在你的着色器代码中放置一个#version 150 compatibility
以消除任何疑虑。
当我删除 #version 150
行时,警告不再存在。谢谢你。但是,当我移动glUseProgram(shaderProgram)
after renderTextures() 方法时,结果仍然与显示的所有黑色纹理相同。当我使用glUseProgram(0)
时,纹理变为白色。可能,错误在于我如何访问着色器中的纹理?
除了没有正确启用/禁用着色器之外,我看到的唯一其他可能的原因是同步问题,即在 GPU 完成绘制之前读取纹理。但我真的不相信会发生这种情况。首先,您在绑定纹理之前确实取消绑定 FBO,它应该正确同步(并且正在读取的也是第一个渲染的),其次,如果存在同步问题,人们会期望有时至少会出现一些半画框,而不仅仅是始终黑屏。
现在这个确实看起来像一个同步问题,虽然我不明白为什么。哦,好吧...由于您使用的是 GLSL 1.5,因此您有 OpenGL 3.2,因此必须存在 ARB_sync,值得一试:在第 266 行之后插入 GLsync s = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
(您调用 renderTextures()
)和在第 274 行之前插入 glWaitSync(s, 0, GL_TIMEOUT_IGNORED); glDeleteSync(s);
. 这将在使用纹理之前强制阻塞,直到实现glFenceSync
调用之前的所有渲染命令。希望能解决它(不过,也应该有一种更清洁的方法)。【参考方案2】:
这个怎么样:
glBindFramebuffer(GL_FRAMEBUFFER, fbo); // Bind our frame buffer for rendering
glDrawBuffer(GL_COLOR_ATTACHMENT4);
glBindTexture(GL_TEXTURE_2D, fbo_texture0); // bind texture that is rendered in 0-th attachment
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
您只需使用来自第 0 个附件的绑定纹理渲染到第 4 个附件。
【讨论】:
以上是关于在 GLSL 中访问多个 FBO 纹理以创建另一个纹理的主要内容,如果未能解决你的问题,请参考以下文章