I'm trying to add a texture to a simple square for more than 5h now but I still don't manage to do so.
Here's the code I'm using in paintGL():
glEnable(GL_TEXTURE_2D);
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
float pixels[] = {
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f
};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1,0,0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1,1,0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0,1,0);
glEnd();
if (glGetError() != 0)
{
qDebug() << glGetError();
}
There is no errors nor OpenGL's ones. I initialized the clear color to grey.
When I try to change color with glColor3f(...), it works.
I read about all tutorials that I could find with Google but no one helped.
SOLUTION:
I never put
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
at the right place: just after the glTexImage2D! Code above is edited and now work like a charm.
You HAVE to specify filtering for your texture:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
Because default filter uses mipmaps, but you don't generate them.
It looks to me like you're only using one quarter of your texture. It's only 4 pixels, and you've set the texture coordinates to be just the first pixel. If that pixel is white and your texture environment is set to multiply the quad's color by the texture, and you're set to use nearest neighbor sampling, then you'll get just the color. Try changing the texture coordinates to be (0,0) to (1,1) instead of (0,0) to (0.5,0.5) and see if that gives you the expected result. You can also try setting the various texture parameters and environments differently to see how that affects your drawing.
I am writing a rendering system in CUDA and want results to be quickly displayed via OpenGL, without touching main memory. I basically do the following:
Create and initialize OpenGL texture, and register it in CUDA as cudaGraphicsResource
GLuint viewGLTexture;
cudaGraphicsResource_t viewCudaResource;
void initialize() {
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &viewGLTexture);
glBindTexture(GL_TEXTURE_2D, viewGLTexture);
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.getWidth(), view.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
glBindTexture(GL_TEXTURE_2D, 0);
cudaGraphicsGLRegisterImage(&viewCudaResource, viewGLTexture, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard)
}
Whenever view is resized I resize viewport and texture image appropriately:
void resize() {
glViewport(0, 0, view.getWidth(), view.getHeight());
glBindTexture(GL_TEXTURE_2D, viewGLTexture);
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.getWidth(), view.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
glBindTexture(GL_TEXTURE_2D, 0);
}
And then each frame I map graphicsResource as a cudaSurfaceObject via cudaArray, call rendering kernel on it, unmap and synchronize to let OpenGL draw a fullscreen quad with this texture:
void renderFrame() {
cudaGraphicsMapResources(1, &viewCudaResource);
{
cudaArray_t viewCudaArray;
cudaGraphicsSubResourceGetMappedArray(&viewCudaArray, viewCudaResource, 0, 0);
cudaResourceDesc viewCudaArrayResourceDesc;
{
viewCudaArrayResourceDesc.resType = cudaResourceTypeArray;
viewCudaArrayResourceDesc.res.array.array = viewCudaArray;
}
cudaSurfaceObject_t viewCudaSurfaceObject;
cudaCreateSurfaceObject(&viewCudaSurfaceObject, &viewCudaArrayResourceDesc);
{
invokeRenderingKernel(viewCudaSurfaceObject);
}
cudaDestroySurfaceObject(viewCudaSurfaceObject));
}
cudaGraphicsUnmapResources(1, &viewCudaResource);
cudaStreamSynchronize(0);
glBindTexture(GL_TEXTURE_2D, viewGLTexture);
{
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(+1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(+1.0f, +1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, +1.0f);
}
glEnd();
}
glBindTexture(GL_TEXTURE_2D, 0);
glFinish();
}
The problem is: Whenever view is resized all CUDA calls start spewing out "unknown error"s and visually it looks like the texture is not in fact resized, just stretched across the whole view. Why is this happening and how do I fix it?
It seems interop requires to re-register textures upon resize. The following works:
void resize() {
glViewport(0, 0, view.getWidth(), view.getHeight());
// unregister
cudaGraphicsUnregisterResource(viewCudaResource);
// resize
glBindTexture(GL_TEXTURE_2D, viewGLTexture);
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.getWidth(), view.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
glBindTexture(GL_TEXTURE_2D, 0);
// register back
cudaGraphicsGLRegisterImage(&viewCudaResource, viewGLTexture, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard);
}
I created 4 textures and attach them to FBO, named fbo_texture0 - fbo_texture3. All of them are successfully created, as given by the following screenshot:
image 1
Now, i wanted to create the 5th texture which is obtained from the previous textures (fbo_texture0 - fbo_texture3) using GLSL. For now, i just want to copy the first texture into the fifth texture. Unfortunately, here is what i got:
image 2
The question is:
How can i access these fbo textures in GLSL?
How can i create the 5th texture? (or copy from the first texture to the fifth texture?)
Here's the complete code of the program (in case needed):
#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
}
Here is the vertex shader:
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
And here is the fragment shader:
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
void main(void)
{
gl_FragColor = texture2D(tex0, gl_TexCoord[0].st);
}
EDIT #1
After modifying the code as suggested by #Damon (the code has been edited as well) , here's the screenshot of the result:
image 3
Now, I don't really know what the problem actually is. I tried to change the fragment shader to access another texture e.g. gl_FragColor = texture2D(tex2, gl_TexCoord[0].st); but i still got the same display as above. So i think it is definitely not the modelview/projection problem.
EDIT #2
The problem still left unclear. However, I tried to give only one glActiveTexture(GL_TEXTUREn); command at the program, and comment out other glActiveTexture command (without shader modification), and got the following result:
image 4 Only glActiveTexture(GL_TEXTURE0);activated.
image 5 Only glActiveTexture(GL_TEXTURE1);activated.
image 6 Only glActiveTexture(GL_TEXTURE2);activated.
image 7 Only glActiveTexture(GL_TEXTURE3);activated.
When at least 2 glActiveTexture(GL_TEXTUREn); activated, i got the same result as image 5. That left me wondering what the problem actually is.
initShader compiles and links a shader. You seem to be binding the textures to texture units within renderTextures in an OK manner, too (after unbinding the FBO, which is important to sync). So far so good, but I can't find glUseProgram anywhere in the code. That would mean the rendering falls back to fixed function, which does not have any textures bound at that time.
The fragment shader reads only from tex0, so of course you wouldn't expect to see tex1-tex3 anyway (but I guess that's just the minimum working example code).
Other than that, it looks OK from what I can see by reading over the code in 5 mins.
(As a sidenote: init calls glEnable(GL_TEXTURE_2D), this is not strictly wrong, but useless as soon as you use a shader, see this.)
How about this:
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);
You just render into 4th attachment with binded texture from 0-th attachment.