Related
I am trying to render a simple 2d Image with the QOpenGLWidget using a quad as a texture. But no matter what I am trying, I always get a black box.
I have read many tutorials, I have a simple pixelbuffer like this
uchar* m_pData;
which stores my RGB values. This is valid, since I have it tested with glDrawPixles(). I will post the three most important functions considering the OpenGLWidget.
initializeGL() first:
void QGLImageviewer::initializeGL()
{
initializeOpenGLFunctions();
// Clear the color
float r = ((float)m_backColor.darker().red())/255.0f;
float g = ((float)m_backColor.darker().green())/255.0f;
float b = ((float)m_backColor.darker().blue())/255.0f;
glClearColor(r,g,b,1.0f);
// Set shading model.
glShadeModel(GL_SMOOTH);
// Set the viewport
glViewport(0.f, 0.f, m_origW, m_origH);
// Init. Projection Matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, m_origW, m_origH,0.0,1.0,-1.0);
// Init Modelview Matrix
glClearColor(0.f, 0.f, 0.f, 1.f);
// Enable texturing
glEnable(GL_TEXTURE_2D);
// Generate texture ID
glGenTextures(1, &m_textureID);
// Bind texture ID
glBindTexture(GL_TEXTURE_2D, m_textureID);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Generate Texture, and assign pixles to our texture ID
if (m_pData != nullptr)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_origW, m_origH, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)m_pData);
}
else
{
qCritical("Buffer is empty!!");
}
// Unbind texture
glBindTexture(GL_TEXTURE_2D, NULL);
// Check for Error
GLenum error_ = glGetError();
if (error_ != GL_NO_ERROR)
{
qCritical("Error Loading Texture!");
}
}
Then paintGL():
void QGLImageviewer::paintGL()
{
makeCurrent();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// Clear Screen And Depth Buffer
glClear(GL_COLOR_BUFFER_BIT);
if (!(m_renderQtImg->isNull()))
{
//QImage image;
int imWidth = m_renderQtImg->width();
int imHeight = m_renderQtImg->height();
// The image has to be resized to fit the widget
if (imWidth != this->size().width() &&
imHeight != this->size().height())
{
imWidth = this->size().width();
imHeight = this->size().height();
}
else
{
//image = *m_renderQtImg;
imWidth = m_origW;
imHeight = m_origH;
}
if (m_textureID != 0)
{
glMatrixMode(GL_MODELVIEW);
// Remove any previous transformations
glLoadIdentity();
glPushMatrix();
// Move to rendering point
glTranslatef(0.f, 0.f, 0.f);
glColor3f(0.0f, 0.0f, 0.5f);
// Set texture ID
glBindTexture(GL_TEXTURE_2D, m_textureID);
glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f); glVertex2f(0.f, 0.f);
glTexCoord2f(1.f, 0.f); glVertex2f(imWidth, 0.f);
glTexCoord2f(1.f, 1.f); glVertex2f(imWidth, imHeight);
glTexCoord2f(0.f, 1.f); glVertex2f(0.f, imHeight);
glEnd();
//glDisable(GL_TEXTURE_2D);
glPopMatrix();
glFlush();
}
}
}
And last but not least resizeGL():
void QGLImageviewer::resizeGL(int width, int height)
{
makeCurrent();
glViewport(0,0,(GLint)width,(GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluOrtho2D(0.0, width, 0.0, height);
glOrtho(0.0, width, 0.0, height, 0.0, 1.0);
}
I am using Qt5.6 and the Microsoft Visual Studio 2015 compiler.
Damn, the problem was on
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_origW , m_origH, 0, GL_RGB, GL_UNSIGNED_BYTE, (float*)m_pData);
My member variables m_orgiW and m_orgiH were initialized to 0. So quite unsurprising that my code did not work.
For the record I will post my running code, the three most important functions of the QOpenGLWidget, hope that it will be useful to somebody with the same issue.
void QGLImageviewer::initializeGL()
{
initializeOpenGLFunctions();
float r = ((float)m_backColor.darker().red())/255.0f;
float g = ((float)m_backColor.darker().green())/255.0f;
float b = ((float)m_backColor.darker().blue())/255.0f;
glClearColor(r,g,b,1.0f);
// Generate texture ID
glGenTextures(1, &m_textureID);
// Bind texture ID
glBindTexture(GL_TEXTURE_2D, m_textureID);
if (m_pData != nullptr)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_origW , m_origH, 0, GL_RGB, GL_UNSIGNED_BYTE, (float*)m_pData);
}
else
{
qCritical("Buffer is empty!!");
}
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //IMPORTANT FOR NON POWER OF 2 TEXTURES
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Enable texturing Mapping
glEnable(GL_TEXTURE_2D);
// Enable Smooth Shading
glShadeModel(GL_SMOOTH);
// Black Background
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
// Depth Buffer Setup
glClearDepth(1.0f);
// Enables Depth Testing
glEnable(GL_DEPTH_TEST);
// Type of depth testing to do
glDepthFunc(GL_LEQUAL);
// Really Nice Perspective Calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// Unbind Texture
glBindTexture(GL_TEXTURE_2D, NULL);
}
Now paintGL()
void QGLImageviewer::paintGL()
{
makeCurrent();
// Clear Screen And Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glBegin(GL_QUADS);
// Drawing the quad with the texture mapped on it
//
// OpenGL 2D Coordinates
// Sticking with the Coordinate Convention mentioned here
glTexCoord2f(1.0f, 0.0f); glVertex2f(m_width, 0.0f); // vertex 1
glTexCoord2f(1.0f, 1.0f); glVertex2f(m_width, m_height); // vertex 2
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, m_height); // vertex 3
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // vertex 4
glEnd();
}
And resizeGL()
void QGLImageviewer::resizeGL(int width, int height)
{
makeCurrent();
m_width = width;
m_height = height;
// Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
// Set the viewport to cover the new window
glViewport(0, 0, width, height);
// Set the aspect ratio of the clipping area to match the viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset the projection matrix
glOrtho(0, m_width/ m_zoomFactor, m_height/ m_zoomFactor,0, -1, 1);
}
I'm trying to collate several native PNG images into Opengl & I'm having some roadblocks. I'm already using a Cximage library, so would prefer to stick to this if I can help it.
3 related issues;
PNGs are showing as black & white in OpenGL. The image isn't the issue as Other image types work but I'd rather not convert unless it's easy & doesn't require disk saving or another library.
PNG having black background which are suppose to be transparent.
OpenGL view/Orientation issue. Image is skewed in OpenGL ie not orientated properly. The PNGs contain isometric views, which I'm trying to display.
Sample of code I am currently using;
*And Yes I realise I'm using depreciated Opengl. I need to due to legacy code I am working with.
int MyScene::LoadTexture
{
m_pImgCol = new CxImage((BYTE *)pdatabuffer, (DWORD)filesize, CXIMAGE_FORMAT_PNG);
DWORD iDest(0), iSrc(0);
DWORD dwSize = m_pImgCol->GetWidth()*m_pImgCol->GetHeight();
BYTE *pSrc = m_pImgCol->GetBits();
BYTE *pDest = new BYTE[dwSize * 4];
BYTE *pSrcA = m_pImgAlpha ? m_pImgAlpha->GetBits() : NULL;
BYTE alpha;
for (DWORD iX = 0; iX<dwSize; iX++)
{
alpha = 255;
if (pSrcA)
alpha = pSrcA[iX];
else
{
if (pSrc[iSrc] == 0 && pSrc[iSrc + 1] == 0 && pSrc[iSrc + 2] == 0)
alpha = 0;
}
pDest[iDest++] = pSrc[iSrc++];
pDest[iDest++] = pSrc[iSrc++];
pDest[iDest++] = pSrc[iSrc++];
pDest[iDest++] = alpha;
}
GLuint iTexture=0;
glGenTextures(1, &iTexture);
glBindTexture(GL_TEXTURE_2D, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 4, m_pImgCol->GetWidth(), m_pImgCol->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pDest);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
}
int MyScene::DrawGLScene()
{
CRect rWnd;
GetClientRect(&rWnd);
glViewport(0,0,rWnd.Width(),rWnd.Height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-20 * m_Zoom, 20 * m_Zoom, -15 * m_Zoom, 25 * m_Zoom, 20000, -20000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glTranslatef(0, -0.5f, 0.0f);
glRotatef(m_rx, 1.0f, 0.0f, 0.0f);
glRotatef(m_rz, 0.0f, 0.0f, 1.0f);
glRotatef(m_ry, 0.0f, 1.0f, 0.0f);
DrawScene();
SwapBuffers(m_pView->m_hDC);
return TRUE;
}
int MyScene::DrawScene
{
float dL = -8;
float dR = 8;
float dT = -8;
float dB = 8;
glBindTexture(GL_TEXTURE_2D, 0);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(dL, dT, 0);
glTexCoord2f(0, 0);
glVertex3f(dL, dB, 0);
glTexCoord2f(0, 1);
glVertex3f(dR, dB, 0);
glTexCoord2f(1, 1);
glVertex3f(dR, dT, 0);
glTexCoord2f(1, 0);
glEnd();
}
If necessary I can provide more code, but this is as basic as I can break it down to.
Found http://ysflight.in.coocan.jp/programming/pngdecoder/pngdecodere.html & modified it to read existing buffer. Minimal fuss, no disk saving or library.
got PNG transparency working by adding;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Imaging tearing; seems I had following in wrong order;
glTexCoord2f(0, 0);
glVertex3f(dL, dT, 0);
I tried to load the six pictures as texture and draw a skybox, but the result is weird, each picture is mapped three times on its corresponding rectangle in grey. What is the problem?
#include <stdlib.h>
#include <stdio.h>
#include <glut.h>
#include <gl.h>
#include <glu.h>
#include <math.h>
#include <windows.h>
GLuint texture [6]; //the array for our texture
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glShadeModel (GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
}
GLuint LoadTexture( const char * filename, int width, int height) {
GLuint texture;
unsigned char * data;
FILE* file;
file = fopen( filename, "r" );
if ( file == NULL ) return 0;
data = (unsigned char *)malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
void FreeTexture( GLuint texture )
{
glDeleteTextures( 1, &texture );
}
void skybox (void) {
float x = 0;
float y = 0;
float z = 0;
float width = 100;
float height = 100;
float length = 100;
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
// Bind the BACK texture of the sky map to the BACK side of the cube
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Center the skybox
x = x - width / 2;
y = y - height / 2;
z = z - length / 2;
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z + length);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[5]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z + length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z + length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y, z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y, z + length);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
glEnd();
//glBindTexture( GL_TEXTURE_CUBE_MAP, texture[0] ); //bind the texture
//glRotatef( angle, 1.0f, 1.0f, 1.0f );
//glutSolidSphere(2, 40, 40);
}
void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat light_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0.0, 0.0, 30.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLoadIdentity();
glPushMatrix();
gluLookAt (20.0, 20.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
texture[1] = LoadTexture( "front.bmp", 256, 256 ); //load the texture
texture[2] = LoadTexture( "left.bmp", 256, 256 ); //load the texture
texture[3] = LoadTexture( "right.bmp", 256, 256 ); //load the texture
texture[4] = LoadTexture( "bottom.bmp", 256, 256 ); //load the texture
texture[5] = LoadTexture( "top.bmp", 256, 256 ); //load the texture
glPopMatrix();
glPopMatrix();
//glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
//glEnable(GL_TEXTURE_GEN_T);
skybox();
for (int i = 0; i < 6; i++) {
FreeTexture( texture[i] );
}
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0,-100.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main (int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("A basic OpenGL Window");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
So, you're trying to load DIB/BMP image files:
> texture[0] = LoadTexture( "back.bmp", 256, 256 ); //load the texture
> ^^^^
>
Reading the contents of the file
> GLuint LoadTexture( const char * filename, int width, int height) {
> GLuint texture; unsigned char * data; FILE* file;
>
> file = fopen( filename, "r" );
> if ( file == NULL ) return 0;
> data = (unsigned char *)malloc( width * height * 3 );
> fread( data, width * height * 3, 1, file );
This is too short for a BMP, BTW.
> fclose( file );
So where's your DIB parser code?
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
free(data);
return texture;
}
You just pass the unparsed DIB/BMP file contents to OpenGL. What do you expect OpenGL to do with this? OpenGL has no idea about file format, less how process a DIB file. You need a DIB parser there.
Since you're loading RGB data make sure GL_UNPACK_ALIGNMENT is set to 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1).
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data);
I use the ImageMagick open library to easily load any image for use with OpenGL.
I am trying to learn about using OpenGL with the 4th edition of OpenGL Super Bible, but whenever I try to copy one of the example codes in Visual Studio 2010, I get a "Open_GL.exe -System Error: The program can't start because libGLESv2.dll is missing from your computer".
I do have this .dll somewhere on my computer, but don't know how to make it available towards VS. The pre-built binaries on the site do work however.
The code I used, for reference:
// Block.cpp
// OpenGL SuperBible, Chapter 1
// Demonstrates an assortment of basic 3D concepts
// Program by Richard S. Wright Jr.
#include "../../shared/gltools.h" // OpenGL toolkit
#include "../../shared/math3d.h"
#include <math.h>
// Keep track of effects step
int nStep = 0;
// Lighting data
GLfloat lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat lightDiffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat lightSpecular[] = { 0.9f, 0.9f, 0.9f };
GLfloat materialColor[] = { 0.8f, 0.0f, 0.0f };
GLfloat vLightPos[] = { -80.0f, 120.0f, 100.0f, 0.0f };
GLfloat ground[3][3] = { { 0.0f, -25.0f, 0.0f },
{ 10.0f, -25.0f, 0.0f },
{ 10.0f, -25.0f, -10.0f } };
GLuint textures[4];
// Called to draw scene
void RenderScene(void)
{
M3DMatrix44f mCubeTransform;
M3DVector4f pPlane;
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glPushMatrix();
// Draw plane that the cube rests on
glDisable(GL_LIGHTING);
if(nStep == 5)
{
glColor3ub(255,255,255);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-100.0f, -25.3f, -100.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-100.0f, -25.3f, 100.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(100.0f, -25.3f, 100.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(100.0f, -25.3f, -100.0f);
glEnd();
}
else
{
glColor3f(0.0f, 0.0f, 0.90f); // Blue
glBegin(GL_QUADS);
glVertex3f(-100.0f, -25.3f, -100.0f);
glVertex3f(-100.0f, -25.3f, 100.0f);
glVertex3f(100.0f, -25.3f, 100.0f);
glVertex3f(100.0f, -25.3f, -100.0f);
glEnd();
}
// Set drawing color to Red
glColor3f(1.0f, 0.0f, 0.0f);
// Enable, disable lighting
if(nStep > 2)
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_COLOR_MATERIAL);
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glMaterialfv(GL_FRONT, GL_SPECULAR,lightSpecular);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, materialColor);
glMateriali(GL_FRONT, GL_SHININESS,128);
}
// Move the cube slightly forward and to the left
glTranslatef(-10.0f, 0.0f, 10.0f);
switch(nStep)
{
// Just draw the wire framed cube
case 0:
glutWireCube(50.0f);
break;
// Same wire cube with hidden line removal simulated
case 1:
// Front Face (before rotation)
glBegin(GL_LINES);
glVertex3f(25.0f,25.0f,25.0f);
glVertex3f(25.0f,-25.0f,25.0f);
glVertex3f(25.0f,-25.0f,25.0f);
glVertex3f(-25.0f,-25.0f,25.0f);
glVertex3f(-25.0f,-25.0f,25.0f);
glVertex3f(-25.0f,25.0f,25.0f);
glVertex3f(-25.0f,25.0f,25.0f);
glVertex3f(25.0f,25.0f,25.0f);
glEnd();
// Top of cube
glBegin(GL_LINES);
// Front Face
glVertex3f(25.0f,25.0f,25.0f);
glVertex3f(25.0f,25.0f,-25.0f);
glVertex3f(25.0f,25.0f,-25.0f);
glVertex3f(-25.0f,25.0f,-25.0f);
glVertex3f(-25.0f,25.0f,-25.0f);
glVertex3f(-25.0f,25.0f,25.0f);
glVertex3f(-25.0f,25.0f,25.0f);
glVertex3f(25.0f,25.0f,25.0f);
glEnd();
// Last two segments for effect
glBegin(GL_LINES);
glVertex3f(25.0f,25.0f,-25.0f);
glVertex3f(25.0f,-25.0f,-25.0f);
glVertex3f(25.0f,-25.0f,-25.0f);
glVertex3f(25.0f,-25.0f,25.0f);
glEnd();
break;
// Uniform colored surface, looks 2D and goofey
case 2:
glutSolidCube(50.0f);
break;
case 3:
glutSolidCube(50.0f);
break;
// Draw a shadow with some lighting
case 4:
glGetFloatv(GL_MODELVIEW_MATRIX, mCubeTransform);
glutSolidCube(50.0f);
glPopMatrix();
// Disable lighting, we'll just draw the shadow as black
glDisable(GL_LIGHTING);
glPushMatrix();
m3dGetPlaneEquation(pPlane, ground[0], ground[1], ground[2]);
m3dMakePlanarShadowMatrix(mCubeTransform, pPlane, vLightPos);
//MakeShadowMatrix(ground, lightpos, cubeXform);
glMultMatrixf(mCubeTransform);
glTranslatef(-10.0f, 0.0f, 10.0f);
// Set drawing color to Black
glColor3f(0.0f, 0.0f, 0.0f);
glutSolidCube(50.0f);
break;
case 5:
glColor3ub(255,255,255);
glGetFloatv(GL_MODELVIEW_MATRIX, mCubeTransform);
// Front Face (before rotation)
glBindTexture(GL_TEXTURE_2D, textures[1]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(25.0f,25.0f,25.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(25.0f,-25.0f,25.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-25.0f,-25.0f,25.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-25.0f,25.0f,25.0f);
glEnd();
// Top of cube
glBindTexture(GL_TEXTURE_2D, textures[2]);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f);
glVertex3f(25.0f,25.0f,25.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(25.0f,25.0f,-25.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-25.0f,25.0f,-25.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-25.0f,25.0f,25.0f);
glEnd();
// Last two segments for effect
glBindTexture(GL_TEXTURE_2D, textures[3]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(25.0f,25.0f,-25.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(25.0f,-25.0f,-25.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(25.0f,-25.0f,25.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(25.0f,25.0f,25.0f);
glEnd();
glPopMatrix();
// Disable lighting, we'll just draw the shadow as black
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glPushMatrix();
m3dGetPlaneEquation(pPlane, ground[0], ground[1], ground[2]);
m3dMakePlanarShadowMatrix(mCubeTransform, pPlane, vLightPos);
glMultMatrixf(mCubeTransform);
glTranslatef(-10.0f, 0.0f, 10.0f);
// Set drawing color to Black
glColor3f(0.0f, 0.0f, 0.0f);
glutSolidCube(50.0f);
break;
}
glPopMatrix();
// Flush drawing commands
glutSwapBuffers();
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
GLbyte *pBytes;
GLint nWidth, nHeight, nComponents;
GLenum format;
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_MODULATE);
glGenTextures(4, textures);
// Load the texture objects
pBytes = gltLoadTGA("floor.tga", &nWidth, &nHeight, &nComponents, &format);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
format, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);
pBytes = gltLoadTGA("Block4.tga", &nWidth, &nHeight, &nComponents, &format);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
format, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);
pBytes = gltLoadTGA("block5.tga", &nWidth, &nHeight, &nComponents, &format);
glBindTexture(GL_TEXTURE_2D, textures[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
format, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);
pBytes = gltLoadTGA("block6.tga", &nWidth, &nHeight, &nComponents, &format);
glBindTexture(GL_TEXTURE_2D, textures[3]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
format, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);
}
void KeyPressFunc(unsigned char key, int x, int y)
{
if(key == 32)
{
nStep++;
if(nStep > 5)
nStep = 0;
}
// Refresh the Window
glutPostRedisplay();
}
void ChangeSize(int w, int h)
{
// Calculate new clipping volume
GLfloat windowWidth;
GLfloat windowHeight;
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
// Keep the square square
if (w <= h)
{
windowHeight = 100.0f*(GLfloat)h/(GLfloat)w;
windowWidth = 100.0f;
}
else
{
windowWidth = 100.0f*(GLfloat)w/(GLfloat)h;
windowHeight = 100.0f;
}
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the clipping volume
glOrtho(-100.0f, windowWidth, -100.0f, windowHeight, -200.0f, 200.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightfv(GL_LIGHT0,GL_POSITION, vLightPos);
glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
glRotatef(330.0f, 0.0f, 1.0f, 0.0f);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("3D Effects Demo");
glutReshapeFunc(ChangeSize);
glutKeyboardFunc(KeyPressFunc);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
glDeleteTextures(4,textures);
return 0;
}
I do have this .dll somewhere on my computer
libGLESv2.dll sounds suspiciously like an implementation of OpenGL ES 2.0. Which will not execute your code, since your code is written for desktop OpenGL.
In short, you are linking to the wrong library. On Windows, you should be linking to OpenGL32.lib.
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.