i have animation project which requires multiple textures ,i intend to see all of them yet only 1 texture covers on my model.i cant see all tga files on the object.
GLuint LoadTexture(char *TexName)
{
TGAImg Img; // Image loader
// Load our Texture
if(Img.Load(TexName)!=IMG_OK)
return -1;
glGenTextures(1,textures); // Allocate space for texture
glBindTexture(GL_TEXTURE_2D,textures[0]); // Set our Tex handle as current
// Create the texture
if(Img.GetBPP()==24)
glTexImage2D(GL_TEXTURE_2D,0,3,Img.GetWidth(),Img.GetHeight(),0,GL_RGB,GL_UNSIGNED_BYTE,Img.GetImg());
else if(Img.GetBPP()==32)
glTexImage2D(GL_TEXTURE_2D,0,4,Img.GetWidth(),Img.GetHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,Img.GetImg());
else
return -1;
// Specify filtering and edge actions
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_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
return textures[0];
}
void Draw()
{
glEnable(GL_TEXTURE_2D);
glGenTextures(17,textures);
for (int i = 0; i<17; i++){
textures[i] = LoadTexture(textureNames[i
glBindTexture(GL_TEXTURE_2D, textures[i]);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3,GL_FLOAT,0,triangleArr);
glNormalPointer(GL_FLOAT, 0, normals);
glDrawArrays(GL_TRIANGLES, 0, TotalConnectedTriangles);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
void initialize ()
{
glViewport(0, 0, 500, 500);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, 1, 0.1, 1000.0);
glMatrixMode(GL_MODELVIEW);
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glShadeModel( GL_SMOOTH );
glEnable( GL_DEPTH_TEST );
glEnable(GL_TEXTURE_2D);
textures[textureIndex] = LoadTexture(textureNames[textureIndex]);
glBindTexture(GL_TEXTURE_2D, textures[textureIndex]);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, textureArr);
}
</code>`enter code here`
i am not sure if i need to post my obj file?
Look at the docs of glActiveTexture. Calling glBindTexture in a loop doesn't do what you think it does.
Your code is wrong for many reasons :
if the draw() function is your rendering callback, then you are going to create a set of textures and load data into them. It is wrong, since you need to do it only once.
LoadTexture() is going to create a new texture, and load it with data from a file. This is wrong, since you already created 17 textures i function
Then you are binding each texture in a loop, and only the last is going to be active
Then you dump all vertexes from a VBO to be rendered. I do not see where you initialized them, but they are going to use only the last binded texture.
You have another call to LoadTexture() in the initialize(). Actually all textures should be generated and loaded there
Related
I making an OpenGL video game using GLFW version 2. I am getting an error I do not understand
The following code is:
//
// GameWindow.cpp
// RocketGame
//
// Created by Vaibhav Malhotra on 12/5/17.
// Copyright © 2017 Vaibhav Malhotra. All rights reserved.
//
#include "GameWindow.hpp"
typedef struct
{
GLfloat positionCoordinates[3];
GLfloat textureCoordinates[2];
} vertexData;
#define Square_Size 100
vertexData vertices[] = {
{{0.0f,0.0f,0.0f}, {0.0f,0.0f}},
{{Square_Size,0.0f,0.0f},{1.0f,0.0f}},
{{Square_Size,Square_Size,0.0f},{1.0f,1.0f}},
{{0.0f,Square_Size,0.0f},{0.0f,1.0f}}
};
void GameWindow::setRunning(bool newRunning)
{
_running = newRunning;
}
bool GameWindow::getRunning()
{
return _running;
}
GLuint GameWindow::loadAndBufferImage(const char *filename)
{
GLFWimage imageData;
glfwReadImage(filename, &imageData, NULL);
GLuint textureBufferID;
glGenTextures(1, &textureBufferID);
glBindTexture(GL_TEXTURE_2D, textureBufferID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageData.Width, imageData.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData.Data);
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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glfwFreeImage(&imageData);
return textureBufferID;
}
GameWindow::GameWindow(bool running):_running(running),_height(800),_width(800*16/9),_vertexBufferID(0)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glViewport(0.0f, 0.0f, _width, _height);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, _width, 0, _height);
glMatrixMode(GL_MODELVIEW);
glGenBuffers(1, &_vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, positionCoordinates));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, textureCoordinates));
_textureBufferID = loadAndBufferImage("rocket.tga");
}
void GameWindow::render()
{
glClear(GL_COLOR_BUFFER_BIT);
//glColor3f(1.0f, 0.0f, 0.0f);
glDrawArrays(GL_QUADS, 0, 4);
glfwSwapBuffers();
}
void GameWindow::update()
{
}
Under the render function the code glDrawArrays(GL_QUADS, 0, 4); is returning a runtime error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
For output I am just getting a black screen.
Why is this error is coming for me?
Under the render function the code glDrawArrays(GL_QUADS, 0, 4); is returning a runtime error Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
A memory access violation on glDrawArrays generally hints at some sort of problem with VBOs or similar storage objects.
From what I can tell, there are three issues with your code:
You are only calling glEnableClientState and its corresponding gl*Pointer calls once, when they need to be called every frame before glDrawArrays. If you'd like to only call them once, look into Vertex Array Objects (VAOs), although these are only available since OpenGL 3. Bear in mind, that when you move the glEnableClientState calls, you will have to ensure that your buffer is bound again with glBindBuffer.
Each client state has a corresponding gl*Pointer call. You correctly use glVertexPointer for GL_VERTEX_ARRAY, but for GL_TEXTURE_COORD_ARRAY, you need glTexCoordPointer.
Your glEnableClientState calls are missing their corresponding glDisableClientState calls, which need to be called in reverse order of the enabling calls, after your glDrawArrays call.
Just as a side note, the GLU library is deprecated. Your gluOrtho2D call appears to be the only instance where you depend on it, and it can be easily replaced with:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, _width, 0, _height, -1.0f, 1.0f);
You are getting an exception in glDrawArrays because it tries to read memory at address 0, which is what your code actually specifies.
GL's texture coordinate array pointer is initializez to NULL and no VBO. Since you use legacy GL, this will be interpreted as a client memory address. Now you enable GL_TEXCOORD_ARRAY but never actually set glTexCoordPointer, so it stays NULL:
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, textureCoordinates));
The quick solution is of course to not overwrite your vertex array pointer state by having it point to the the texture coords, but to specify the texcoord array pointer via glTexCoordPointer.
The real solution is to give up on legacy GL which is deprecated0 since a decade by now, and switch to "modern" OpenGL using a GL 3.2 core profile or above.
I'm implementing a HUD for FreeCAD (i.e. some graphics on top of the CAD view).
My code works nicely but if there is any content in display other than my HUD i.e. the CAD document contains some objects, then all my HUD elements that are rendered with textures appear black. If for debugging purposes I render them with color then the color works so I suspect this related to the textures.
Below is the code that does the rendering (this is the fixed pippelin OpenGL 1.1).
So what can cause this code to render the textures as black when run after some other rendering code but let it work correctly when there is no other (or very little) other rendering going on before this?
And how should I debug this?
The FreeCAD code base is huge and it uses the Coin3D library which is also huge so looking into that seems daunting to trace what is causing this.
Probably my fault but I can't spot it.
glPushAttrib(GL_ALL_ATTRIB_BITS);
GLfloat depthrange[2];
glGetFloatv(GL_DEPTH_RANGE, depthrange);
GLdouble projectionmatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix);
glDepthMask(GL_TRUE);
glDepthRange(0.0, 1.0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const float NEARVAL = 0.1f;
const float FARVAL = 10.0f;
const float dim = NEARVAL * float(tan(M_PI / 8.0));
glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL);
SbMatrix mx;
SoCamera* cam = this->getSoRenderManager()->getCamera();
mx = cam->orientation.getValue();
mx = mx.inverse();
mx[3][2] = -7.0; // Translate away from the projection point (along z axis).
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf((float*)mx);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glClear(GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer( 3, GL_FLOAT, 0,(void*) g_VertexArray.data() );
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer( 2, GL_FLOAT, 0, g_TextureCoordArray.data() );
glEnableClientState(GL_INDEX_ARRAY);
glIndexPointer( 2, GL_UNSIGNED_BYTE,(void*) g_IndexArray.data() );
int b=0;
int tc = (int) g_TriangleFans.size();
for (int i = 0; i < tc; i++) {
glBindTexture(GL_TEXTURE_2D, g_Textures[g_TriangleTextures[i]]);
int n = g_TriangleFans[i];
glDrawArrays( GL_TRIANGLE_FAN, b, n);
b += n;
}
glPopMatrix();
glDepthRange(depthrange[0], depthrange[1]);
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(projectionmatrix);
glPopAttrib();
Found out what the problem was, I had some code that was used to initialise some static data structures and I did the texture generation there in the first OpenGL context, thus the textures I generated were not valid for any subsequent contexts.
I'm trying to render to a texture, then copy that texture and run it through post processing, then combine the filtered image with the original. I've got it so I can render to a a texture, then process it and display it, but I can only process it once. I'm really not sure what's going wrong.
Here is my FBO setup code:
for (int i = 0; i < 3; i++) {
glGenFramebuffers(1, &postfboId[i]);
glGenTextures(1, &postTextureId[i]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, postTextureId[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//float color[4] = {0.0, 0.0, 0.0, 1.0};
//glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, screenSize.x, screenSize.y, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
// create a framebuffer object
glBindFramebuffer(GL_FRAMEBUFFER, postfboId[i]);
glGenRenderbuffers(1, &depthrenderbuffer[i]);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer[i]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screenSize.x, screenSize.y);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer[i]);
// attach the texture to FBO depth attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, postTextureId[i], 0);
}
GLenum DrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(1, DrawBuffers);
// check FBO status
FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(FBOstatus != GL_FRAMEBUFFER_COMPLETE)
printf("hey man, you might want to sit down a minute, i didn't want to have to say this to you, but the FBO failed.\n");
I thought maybe I need glDrawBuffers to make 3 instead of 1, but this just causes the FBO to be incomplete.
Here is my render code:
glBindFramebuffer(GL_FRAMEBUFFER,postfboId[0]);
sf::Vector2u size = screenSize;
changeSize(size.x, size.y);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
//clear viewport
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(prog);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
setLookat();
glCullFace(GL_BACK);
setLights();
drawObjs();
glPopMatrix();
//first round post process
glClearColor(0, 0, 0, 1);
glUseProgram(postProg);
glBindFramebuffer(GL_FRAMEBUFFER,postfboId[1]);
glUniform1i(postProcessMode, 1);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPushMatrix();
glLoadIdentity();
glOrtho(0,screenSize.x,0,screenSize.y,-1,20);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
glLoadIdentity();
glColor4f(1,1,1,1);
glUniform1i(texUniform3, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,postTextureId[0]);
glEnable(GL_TEXTURE_2D);
glTranslated(0,0,-19.5);
glBegin(GL_QUADS);
glTexCoord2d(0,0);glVertex3f(0,0,0);
glTexCoord2d(1,0);glVertex3f(screenSize.x,0,0);
glTexCoord2d(1,1);glVertex3f(screenSize.x,screenSize.y,0);
glTexCoord2d(0,1);glVertex3f(0,screenSize.y,0);
glEnd();
// round 2 post
glUniform1i(postProcessMode, 2);
glBindFramebuffer(GL_FRAMEBUFFER,0);
glUniform1i(texUniform3, 3);
glActiveTexture(GL_TEXTURE3);
// bind postTextureId[0] to draw real screen.
glBindTexture(GL_TEXTURE_2D,postTextureId[1]);
glEnable(GL_TEXTURE_2D);
glTranslated(0,0,0.5);
glBegin(GL_QUADS);
glTexCoord2d(0,0);glVertex3f(0,0,0);
glTexCoord2d(1,0);glVertex3f(screenSize.x,0,0);
glTexCoord2d(1,1);glVertex3f(screenSize.x,screenSize.y,0);
glTexCoord2d(0,1);glVertex3f(0,screenSize.y,0);
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
For whatever reason, drawing an FBOs texture to another FBO results in nonsense, but drawing that FBO texture to the screen is fine. Also, all 3 FBOs work, just not at the same time, which is odd since I have another FBO with just a depth buffer for shadowmapping which displays correctly.
One immediately apparent problem is that you're missing glClear() calls for all but the first render target. You call it once after binding fbo 0:
glBindFramebuffer(GL_FRAMEBUFFER,postfboId[0]);
...
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
But you'll also need to clear after binding fbo 1:
glBindFramebuffer(GL_FRAMEBUFFER,postfboId[1]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
and after binding the default framebuffer:
glBindFramebuffer(GL_FRAMEBUFFER,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Some of your glPushMatrix() and glPopMatrix() calls also look somewhat suspicious. But it's hard to tell if they are incorrect without seeing the whole code. You may want to double check that they all balance, and that you're in the right matrix mode when calling them. For example in this sequence:
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPushMatrix();
glLoadIdentity();
the glPopMatrix() and glPushMatrix() calls are redundant. If anything, they could be harmful because there would be an error if you did not previously call glPushMatrix(). Otherwise, it will first copy the previous matrix to the top entry, but then immediately overwrite it with the identity matrix. Which is the same as just calling glLoadIdentity() by itself.
I have a test program that programmatically renders a texture and then renders a simple quad that is skinned with the previously drawn texture. The program is extremely simple and everything is done in 2D. This program works great under linux and everything looks like it should:
However when I run the program on my mac running 10.7 nothing shows up:
I'm at a complete loss as to why this program isn't working on my mac.
Here are the relevant bits of the program.
Creating the texture:
void createTextureObject(){
cout<<"Creating a new texture of size:"<<textureSize<<endl;
//glDeleteTextures(1, &textureId);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
isTextureValid = true;
createFBObject();
}
Creating the Frame Buffer Object:
void createFBObject(){
cout<<"Creating a new frame buffer object"<<endl;
glDeleteFramebuffers(1, &fboId);
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, textureSize, textureSize);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);
bool status = checkFramebufferStatus();
if(!status){
cout<<"FrameBufferObject not created! Quitting!"<<endl;
exit(1);
fboUsed = false;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
Rendering to the texture:
void drawToTexture(){
if (!isTextureValid)
createTextureObject();
glViewport(0, 0, textureSize, textureSize);
glLoadIdentity();
// set the rendering destination to FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
// clear buffer
glClearColor(0, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw to the texture
glColor3f(0.0, 1.0, 0.0);
for (int i=1; i<=5; i++){
glBegin(GL_LINE_LOOP);
glVertex2f(-1 * i/5.0f, -1 * i/5.0f);
glVertex2f( 1 * i/5.0f, -1 * i/5.0f);
glVertex2f( 1 * i/5.0f, 1 * i/5.0f);
glVertex2f(-1 * i/5.0f, 1 * i/5.0f);
glEnd();
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
Rendering the textured quad:
void drawTexturedQuad(){
glViewport(50, 50, textureSize, textureSize);
glLoadIdentity();
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, textureId);
int size = 1;
int texS = 1;
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);
glTexCoord2f(texS, texS); glVertex3f(size, size,0);
glTexCoord2f(0, texS); glVertex3f(-1 * size , size,0);
glTexCoord2f(0, 0); glVertex3f(-1 * size, -1 * size,0);
glTexCoord2f(texS, 0); glVertex3f(size, -1 * size,0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
I'm using GLUT and my display call back is simply:
void displayCB(){
drawToTexture();
drawTexturedQuad();
glutSwapBuffers();
}
Additionally I have other methods check to see if FrameBufferObjects are supported by OpenGL and if they are not the program quits. Additionally I have other logic that sets textureSize whenever the window is resized.
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4
This might be a problem. The GL specification doesn't say exactly at what point mipmaps should be generated, and of course, this generates problems with render to texture. So the GL_EXT_framebuffer_object (and core versions too) introduced glGenerateMipmapEXT, which you call exactly in the point where you want mipmaps generated (usually after rendering to the texture).
So, remove the GL_GENERATE_MIPMAP stuff and use glGenerateMipmap manually when needed. You can read more about this problem in the GL_EXT_framebuffer_object specification.
Are you sure that your buffer id is 0 and not 1?
Maybe another FBO was already created before.
Also check texture dimensions try make them power of 2
I'll begin by apologizing for the length of the question. I believe I've committed some small, dumb error, but since I'm entirely unable to find it, I decided to post all relevant code just in case.
I finally got texture loading working using QImage, and am able to render textures in immediate mode.
However, vertex arrays don't work, and I'm at a loss as to why.
The most obvious things like "Have you enabled vertex arrays and texture coordinate arrays?" are probably not the answer. I'll post the initialization code.
Here's the init function:
/* general OpenGL initialization function */
int initGL()
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0, 0, 0, 1); // Black Background
glEnable ( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glDisable(GL_DEPTH_TEST);
//ENABLED VERTEX ARRAYS AND TEXTURE COORDINATE ARRAYS
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
//ENABLED 2D TEXTURING
glEnable ( GL_TEXTURE_2D );
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//seed random
srand(time(NULL));
return( TRUE );
}
I have initialization, resize and draw functions that are called by a QGLWidget (which is itself just a skeleton that calls the real work functions)
The texture loading function:
GLuint LoadGLTextures( const char * name )
{
//unformatted QImage
QImage img;
//load the image from a .qrc resource
if(!img.load(":/star.bmp"))
{
qWarning("ERROR LOADING IMAGE");
}
//an OpenGL formatted QImage
QImage GL_formatted_image;
GL_formatted_image = QGLWidget::convertToGLFormat(img);
//error check
if(GL_formatted_image.isNull())
qWarning("IMAGE IS NULL");
else
qWarning("IMAGE NOT NULL");
//texture ID
GLuint _textures[1];
//enable texturing
glEnable(GL_TEXTURE_2D);
//generate textures
glGenTextures(1,&_textures[0]);
//bind the texture
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//generate texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_formatted_image.width(),
GL_formatted_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
GL_formatted_image.bits());
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//return the texture ID
return _textures[0];
}
Here's the draw code:
//this does draw
//get the texture ID
GLuint tex_id = LoadGLTextures(":/star.png");
glBindTexture(GL_TEXTURE_2D, tex_id); // Actually have an array of images
glColor3f(1.0f, 0.0f, 0.5f);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f);glVertex2f(1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);glVertex2f(0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);glVertex2f(0.0f, 0.0f);
glEnd();
//this does not draw
//translations code
glLoadIdentity();
glTranslatef(-1.0f, 0.0f, 0.0f);
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
//set color state
glColor4f(0.0f, 1.0f, 0.0f, 0.5);
//vertices to be rendered
static GLfloat vertices[] =
{
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
static GLshort coord_Data[] =
{
1, 0,
1, 1,
0, 1,
0, 0
};
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
//pointer to the vertex array
glVertexPointer(2, GL_FLOAT, 0, vertices);
//texture coordinate pointer
glTexCoordPointer(2, GL_SHORT, 0, coord_Data);
//draw the arrays
glDrawArrays(GL_QUADS, 0, 4);
Thanks for all help,
Dragonwrenn
One possibility is that the problem stems from calling glVertexCoordPointer before calling glTexCoordPointer. Weird things happen when you specify the texture coordinate after the vertex coordinate. I know this is true for drawing a single vertex with a texture coordinate. I'm not sure if it's true with arrays.
A few other things...
Have you tried using QPixMap instead of QImage? I doubt this is the answer to your problem since it sounds like the texture is applied to the first quad properly.
There are two calls to bindTexture.
Have you tried just drawing the vertices (without the texture) in the second part of the code?
Finally, do you get any compiler warnings?
The way you place your OpenGL state manipulations, it is difficult to keep track of things. It's a good idea to set OpenGL state on demand. So
Move this
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_CORRD_ARRAY);
right before
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_SHORT, 0, coord_Data);
//draw the arrays
glDrawArrays(GL_QUADS, 0, 4);
also you should move the other code from initGL.
Belonging into the texture loader, before supplying the data to glTexImage:
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
Belonging to the beginning of the drawing function:
glShadeModel(GL_SMOOTH);
glClearColor(0, 0, 0, 1);
glEnable( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glDisable(GL_DEPTH_TEST);
Following the scheme you should set viewport and projection matrices in the drawing function, too. I'm just telling this, because most of the tutorials do it differently, which tricks people into thinking this was the right way. Technically projection and viewport and on-demand-states as well.
You should not re-load the texture with every draw call. Note that initializing the texture on demand through the drawing handler is a good idea, you should just add some flag to the texture encapsulating class telling, if the referenced texture is already available to OpenGL.
Just for debugging purposes try changing the type of the texture coordinates to floats.