Sign in to follow this  
Merowingian

OpenGL Texturing in OpenGL

Recommended Posts

Merowingian    120
Hey, I've got some problems displaying textures on a quadrangle in my program. But first I would like to make sure that I'm getting certain basics right. First, let's assume I have just called glGenTextures(3, textures), textures being an integer array of size 3. What will happen if I call glTexImage2D right after that? Will the texture data I use in this function be then associated with the first unoccupied texture name, in this case textures[0]? What if I don't use glGenTextures beforehand? Will texture names be generated automatically at each call of glTexImage3D? By which system will they be generated? Second: I want to use two functions, each one should draw a single textured object with its own texture. So the two functioned will be called in the display() function of OpenGL, followed by a flush command, since the two objects belong to the same scene. Let's look at one function: It will call glGenTextures, using a local int array as function input. Next, it will call glTexImage2D with a pointer to the texture data of course. Then the vertex data for the geometries will be specified together with the appropriate texture coordinates. At the end of the function the textures used for this object should be cleared using glDelTextures so they won't be placed more than once, since the drawing function will be called at every display call. I have a question here: texturing belongs to the rasterisation stage of the rendering pipeline. I would expect OpenGL not to perform any actual texturing before all vertex data prior to the flush command has been specified. And this won't happen before the second function has been executet also. But by then the textures for the first object will be cleared already, won't they? I know one could specify the textures in the initGL() function, but I would like everything concerning the drawing of a specific object to be in the drawing function for that object for a better structure and overview. This obviously requires creating and clearing textures at every call. Thanks in advance, cheers Marvin

Share this post


Link to post
Share on other sites
Sharlin    864
Before you can call glTexImage, you must bind some valid texture name with glBindTexture. It is not until the first time you bind a previously-unused texture name, the corresponding texture object is actually created. You can then initialize said object by calling glTexImage.

Share this post


Link to post
Share on other sites
Merowingian    120
Hey, that's good to know.

Just changed the order of commands accordingly.

Seem to be making real progress now.

But I'm now getting some access violation error with glTexImage2D. But I'm sure the data array passed on got the right size, can't be too big.

Here's the command sequence surrounding glTexImage2D:

const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
char* texture;
shelf.getSurface(texture); // stores the shelf's surface texture into texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);

Share this post


Link to post
Share on other sites
Merowingian    120
Well guys,

I've made a slight change to it:



const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
// shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);

As you can see I've now commented the line "shelf.getSurface(texture);".
This version works fine, but the shelf remains blank of course, since there is no texture loaded into texture. I have found out that in C++ you are still allowed to overstep the size of an array, which you shouldn't be:


unsigned int imagePixs = width * height;
unsigned int imageBytes = imagePixs * bytesPerPix;
char* image = new char[imageBytes];
cout << image[imageBytes + 5];

For some strange reason, this sequence doesn't give me an error. And that's exactly the problem. The function shelf.getSurface is supposed to write the char* of the shelf into the char* texture (call by reference).
And for some reason, glTexImage2D seems to think texture is too big. But texture, after the call of shelf.getSurface should be an array of exactly the proper size. I've "verbally" made sure of that with commands like those above, calculating the imageBytes and creating an array of the size imageBytes. But since you cannot rely on C++ to make it really an array of that restricted size, it seems like it practically could have any size bigger than expected, no matter what you put into "new char[imageBytes]".
I really don't get it. What should I do?

Share this post


Link to post
Share on other sites
Merowingian    120
Well guys,

I've made a slight change to it:



const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
// shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);

As you can see I've now commented the line "shelf.getSurface(texture);".
This version works fine, but the shelf remains blank of course, since there is no texture loaded into texture. I have found out that in C++ you are still allowed to overstep the size of an array, which you shouldn't be:


unsigned int imagePixs = width * height;
unsigned int imageBytes = imagePixs * bytesPerPix;
char* image = new char[imageBytes];
cout << image[imageBytes + 5];

For some strange reason, this sequence doesn't give me an error. And that's exactly the problem. The function shelf.getSurface is supposed to write the char* of the shelf into the char* texture (call by reference).
And for some reason, glTexImage2D seems to think texture is too big. But texture, after the call of shelf.getSurface should be an array of exactly the proper size. I've "verbally" made sure of that with commands like those above, calculating the imageBytes and creating an array of the size imageBytes. But since you cannot rely on C++ to make it really an array of that restricted size, it seems like it practically could have any size bigger than expected, no matter what you put into "new char[imageBytes]".
I really don't get it. What should I do?

Share this post


Link to post
Share on other sites
Merowingian    120
Well guys,

I've made a slight change to it:



const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
// shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);

As you can see I've now commented the line "shelf.getSurface(texture);".
This version works fine, but the shelf remains blank of course, since there is no texture loaded into texture. I have found out that in C++ you are still allowed to overstep the size of an array, which you shouldn't be:


unsigned int imagePixs = width * height;
unsigned int imageBytes = imagePixs * bytesPerPix;
char* image = new char[imageBytes];
cout << image[imageBytes + 5];

For some strange reason, this sequence doesn't give me an error. And that's exactly the problem. The function shelf.getSurface is supposed to write the char* of the shelf into the char* texture (call by reference).
And for some reason, glTexImage2D seems to think texture is too big. But texture, after the call of shelf.getSurface should be an array of exactly the proper size. I've "verbally" made sure of that with commands like those above, calculating the imageBytes and creating an array of the size imageBytes. But since you cannot rely on C++ to make it really an array of that restricted size, it seems like it practically could have any size bigger than expected, no matter what you put into "new char[imageBytes]".
I really don't get it. What should I do?

Share this post


Link to post
Share on other sites
Naxos    306
Well I can't say for sure what the problem is... but I'm not sure what the method getSurface() does exactly. In the first example, you created the texture with just:

char *texture;

and then proceeded to call:

shelf.getSurface(texture)

Now what I'm wondering is, is whether or not the getSurface() method actually wants the pointer you pass in to already be pointing to valid memory, because if you don't call:

texture = new char[...]

then it doesn't point to anything, and the only way the getSurface function could do anything at all useful would be if its declaration was:

void getSurface(char *& ReferenceToPointer);

Otherwise the uninitialized pointer is useless to the function.

Share this post


Link to post
Share on other sites
Merowingian    120
OK, again:

I'm using an Object of the class Shelf. The class Shelf is supposed to describe all important properties of a shelf in an abstract way, independent of the rendering process. That is dimensions, position, thickness etc. and of course, the surface, represented by an array of characters representing the rgb-values of a each rectangle on the surface. In other words, the surface of the shelf is what the rendering pipeline will use as the shelf's texture.

So shelf being an object of the Shelf class, the function call getSurface(char* &dest) will take the "texture" argument "call by reference" and put the surface's pointer value into it, so after calling getSurface you should be able to use the shelf's surface via texture.

Now as I was saying, I made sure that the texture array has a fixed and unchangeable size, not to overstep the allowed number of characters.

But for some strange reason, after applying getSurface to texture and passing the new texture on to glTexImage2D for the texture data required, I get an access violation error, as if to say that "surface" (equals texture) is too big.

Well I don't get how texture could be "too big", since I extra made sure it doesn't.

You guys might wanna know how surface gets its content.
Well here's the code setting the shelf in the main.cpp file:


void setShelf() {

char* ppmFn = "holz.ppm";
PPMReader ppm = PPMReader(ppmFn);
char* surface;
ppm.getImage(surface);
shelf = Shelf(1.5, 1.5, 1.5, surface);

}

PPMReader's constructor loads the ppmFile specified by ppmFn into ppm's attributes height, width, bitdepth and image (the actual image data, i.e. an char*).
The last three commands place the ppm's image pointer into "surface", very much like getSurface would do, and then pass on surface to Shelf's constructor. Shelf's constructor will set the x-, y- and z-position (the first three arguments) and the surface pointer as passed on to it by the arguments.

I'll give you the functions to make sure you understand:


PPMReader::PPMReader(char * filename) {
loadPPMFile(filename);
}

void PPMReader::loadPPMFile(char * filename) {

const int readBufferSize = 20;
ifstream ifs;
char buffer[readBufferSize];
ifs.open(filename, ifstream::binary);

ifs.getline(buffer, readBufferSize);
ifs.getline(buffer, readBufferSize, ' ');
width = atoi(buffer);
ifs.getline(buffer, readBufferSize);
height = atoi(buffer);
ifs.getline(buffer, readBufferSize);
unsigned int bitDepth = atoi(buffer);
bytesPerPix = (bitDepth == 255) ? 3 : 6;

unsigned int imagePixs = width * height;
unsigned int imageBytes = imagePixs * bytesPerPix;
image = new char[imageBytes];
ifs.read(image, imageBytes);
ifs.close();

}


Shelf::Shelf(float x, float y, float z, char* surface) {
setPosition(x, y, z);
this->surface = surface;
}


The getSurface of Shelf is implemented as inline void in the header file:

inline void getSurface(const char* &dest) { dest = surface; }


...as is the getImage of PPMReader:

inline void getImage(char* &dest) { dest = image; };



Got it all? My problem is still the same. I can assure you, that my ppm-file's size IS 256x256 and that the failbit used in ifstream in PPMReader is 0 at the end of loadPPM.

So somewhere in my main.cpp I was having the following code:


const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
// shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);


Which is fine but without texture, unless I uncomment the line

shelf.getSurface(texture);

As I said, this would lead to an access violation error which I do not understand. How does texture get bigger than allowed despite my effords to declare its size?

Share this post


Link to post
Share on other sites
Naxos    306
Well this is more or less a shot in the dark but... have you tried calling:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

If, for some odd reason, this isn't what the system is defaulting to, you might have a problem... then again... that doesn't explain why the empty byte array works fine. So that, most likely, is not the problem. Sorry :/

Also, have you bound a texture object before calling glTexImage2D ? That shouldn't affect it either, as far as I know... worth a try I suppose.

Also, is there any particular reason you prefer
getSurface(surf) over surf = getSurface()
and
PPMReader ppm = PPMReader(ppmFn) over PPMReader ppm(ppmFn); ?

Just a matter of personal preference, I suppose. :)



Anyway, other than a problem with the image (which you said there wasn't) or a problem with the loading of the image (I'm not familiar with PPM, so I can't comment on the correctness of that code) then I'm not sure what the problem is, I'm sorry :(

Share this post


Link to post
Share on other sites
songho    268
Quote:
Original post by Merowingian
So somewhere in my main.cpp I was having the following code:

const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
// shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture);


I think that the above codes except glTexImage2D() should be done in your PPMReader::loadPPMFile(). I mean you better get the width/height of texture and the pointer to the texture data from your PPMReader object, for example, your main() would be:

GLint width = ppm.getWidth();
GLint height = ppm.getHeight();
const GLvoid* texture = (const GLvoid*)ppm.getImage();

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);






You don't need to re-allocate a memory for the texture data in main() again. If your Shelf class holds these properties, then use Self object instead of PPMReader object, for instance:

const GLvoid* texture = (const GLvoid*)shelf.getSurface();

[EDIT]
As Naxos pointed out, make sure your PPMReader is working properly, too. Here is my PPM reader/writer class. It reads both P3(Ascii) and P6(binary) formats. Check it out.

imagePpm.zip
[/EDIT]

[Edited by - songho on August 7, 2007 12:57:00 AM]

Share this post


Link to post
Share on other sites
Merowingian    120
@Naxos:

sorry, the alignment thing doesn't make a difference.

And it's not really that I PREFER getSurface(surf) over surf = getSurface() etc., it's just that C++ seems to be too stupid to return a char* from a function.



@songho:

I see your point, but I was going to write a Texture class holding the width and height information later on, so I can retrieve that information from there.
As you can see in my code, the PPMReader gets discarded after loading the texture infomation into the shelf's surface attribute. So I can't get width and height from there.
I'm thinking of replacing the surface attribute of the Shelf class with an object of the Texture class (still to be written). As said, the Texture class will then hold the image data PLUS width and height information.
For the time being, I have to resort to predefined width and height values.

Omitting the memory allocation line unfortunately doesn't change anything. Actually, I already thought it might be totally unneccesary, but I thought that this way I could make C++ understand that whatever gets assigned to texture should BY NO MEANS be bigger than the array size defined in that statement. But obviously C++ doesn't work that way.
How can I tell C++ NEVER to allow an assignement bigger than x characters to the texture variable, or let's say to the surface variable? Obviously it's surface that is too big, causing the problem.
Look at my void PPMReader::loadPPMFile(char * filename) again, you'll see that image gets its predefined size at image = new char[imageBytes];.
But perhaps that line is unneccessary too, then, maybe the follwing read command is still allowed to place ANY number of characters into image.

Share this post


Link to post
Share on other sites
Kalidor    1087
Quote:
Original post by Sharlin
Before you can call glTexImage, you must bind some valid texture name with glBindTexture. It is not until the first time you bind a previously-unused texture name, the corresponding texture object is actually created. You can then initialize said object by calling glTexImage.
That's true except for the first sentence. Texture object 0 (the default texture) is initially bound so any texture operations will operate on that unless you bind a different texture.
Quote:
Original post by Merowingian
void setShelf()
{
char* ppmFn = "holz.ppm";
PPMReader ppm = PPMReader(ppmFn);
char* surface;
ppm.getImage(surface);
shelf = Shelf(1.5, 1.5, 1.5, surface);
}
So what happens with ppm goes out of scope? Does its destructor delete [] PPMReader::image?
Quote:
Original post by Merowingian
Which is fine but without texture, unless I uncomment the line
shelf.getSurface(texture);
As I said, this would lead to an access violation error which I do not understand.
Since all PPMReader::getImage() and Shelf::getSurface() do is set some pointer to point to the same data as PPMReader::image, if PPMReader's destructor delete[]s that data, than trying to access it should cause an access violation.
Quote:
Original post by Merowingian
And it's not really that I PREFER getSurface(surf) over surf = getSurface() etc., it's just that C++ seems to be too stupid to return a char* from a function.
C++'s stupidity is a subject of much debate/argument, but it has no trouble returning a char*.

And although I didn't notice anything wrong with this (I didn't really look though), since you're using C++, why not use std::string for strings instead of a char pointer?.

Share this post


Link to post
Share on other sites
Merowingian    120
You're so right, Kalidor!!!

I haven't defined any destructor for PPMReader, so it will DESTROY the image!
Passing on the image pointer to the shelf therefore will cause "structure" to point to inaccessible memory when used outside the scope of setShelf().
Well I've tried to solve this problem by modifying the setShelf() function in my main.cpp like this:

void setShelf() {

char* ppmFn = "holz.ppm";
PPMReader ppm = PPMReader(ppmFn);
char* surface = new char[256 * 256 * 3];
char* image;
ppm.getImage(image);
memcpy(surface, image, 256 * 256 * 3);
shelf = Shelf(1.5, 1.5, 1.5, surface);

}


You see, I'm copying the whole image byte by byte into a new array, to be independent of ppm's existence.

The access violation error is now GONE, but the shelf remains WHITE. I'm trying to figure out how this is possible. Any hints?

Share this post


Link to post
Share on other sites
Kalidor    1087
Did you change the texture's minification filter? The default is GL_NEAREST_MIPMAP_LINEAR, which is a mipmapping minification filter. If the texture uses a mipmapping filter but doesn't have all mipmap levels specified than it's as if texturing were disabled for the texture unit that texture is bound to. It looks like you're only specifying level 0 of the texture so I would try setting GL_TEXTURE_MIN_FILTER to GL_NEAREST or GL_LINEAR. You can do that with glTexParameter*.

Share this post


Link to post
Share on other sites
Merowingian    120
yeah, but i want to start without using mipmaps first.

mipmapping is just an optional improvement, you should be able to use texturing with just linear filtering. these are my opengl texturing settings:


glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


meanwhile, I have also applied changes to the Shelf constructor:

Shelf::Shelf(float x, float y, float z, char* surface) {
setPosition(x, y, z);
this->surface = new char[256 * 256 * 3];
memcpy((char*)(this->surface), surface, 256 * 256 * 3);
}


All this hasn't helped yet, sorry :





Share this post


Link to post
Share on other sites
Merowingian    120
Hhmmm...

well, just to remind you, this isn't about memory access violation any more.

It's just that the textures are not seen on my objects at all, they just remain plain white.

Any new hints at where the problem could be?

Share this post


Link to post
Share on other sites
Merowingian    120
Yeah, here it is:



void drawShelf() {

Dimensions dims = Shelf::getDimensions();
float innerWidth = dims.width - 2 * Shelf::getThickness();
float innerHeight = dims.height - 2 * Shelf::getThickness();

glPushMatrix();
Position position = shelf.getPosition();
glTranslatef(position.x, position.y, position.z);
bool textFlags[6] = { true, true, true, true, true, true };
GLuint* textures = (GLuint*)(malloc(sizeof(GLuint)));
glGenTextures(1, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
const unsigned int textWidth = 256;
const unsigned int textHeight = 256;
const unsigned int bytesPerPix = 3;
const unsigned int textBytes = textWidth * textHeight * bytesPerPix;
char* texture = new char[textBytes];
shelf.getSurface(texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textWidth, textHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);

// zeichne linkes Seitenbrett
drawTextQuad(Shelf::getThickness(), dims.height, dims.length, textFlags);

// zeichne rechtes Seitenbrett
glPushMatrix();
glTranslatef(Shelf::getThickness() + innerWidth, 0.0f, 0.0f);
drawTextQuad(Shelf::getThickness(), dims.height, dims.length, textFlags);
glPopMatrix();

// zeichne unteres Brett
glPushMatrix();
glTranslatef(Shelf::getThickness(), 0.0f, 0.0f);
drawTextQuad(innerWidth, Shelf::getThickness(), dims.length, textFlags);

// zeichne oberes Brett
glTranslatef(0.0f, Shelf::getThickness() + innerHeight, 0.0f);
drawTextQuad(innerWidth, Shelf::getThickness(), dims.length, textFlags);
glPopMatrix();

glPopMatrix();
glDeleteTextures(1, textures);

}



void drawQuad(float width, float height, float length) {

drawLRQuadWall(height, length);

glPushMatrix();
glTranslatef(width, 0.0f, 0.0f);
drawLRQuadWall(height, length);
glPopMatrix();

drawBTQuadWall(width, length);

glPushMatrix();
glTranslatef(0.0f, height, 0.0f);
drawBTQuadWall(width, length);
glPopMatrix();

drawBFQuadWall(width, height);

glPushMatrix();
glTranslatef(0.0f, 0.0f, length);
drawBFQuadWall(width, height);
glPopMatrix();

}




void drawTextQuad(float width, float height, float length, textFlagAr textFlags) {

if (textFlags[0]) drawTextLRQuadWall(height, length); else drawLRQuadWall(height, length);

glPushMatrix();
glTranslatef(width, 0.0f, 0.0f);
if (textFlags[1]) drawTextLRQuadWall(height, length); else drawLRQuadWall(height, length);
glPopMatrix();

if (textFlags[2]) drawTextBTQuadWall(width, length); else drawBTQuadWall(width, length);

glPushMatrix();
glTranslatef(0.0f, height, 0.0f);
if (textFlags[3]) drawTextBTQuadWall(width, length); else drawBTQuadWall(width, length);
glPopMatrix();

if (textFlags[4]) drawTextBFQuadWall(width, height); else drawBFQuadWall(width, height);

glPushMatrix();
glTranslatef(0.0f, 0.0f, length);
if (textFlags[5]) drawTextBFQuadWall(width, height); else drawBFQuadWall(width, height);
glPopMatrix();

}

void drawLRQuadWall(float height, float length) {
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, height, 0.0f);
glVertex3f(0.0f, height, length);
glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawBTQuadWall(float width, float length) {
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(width, 0.0f, 0.0f);
glVertex3f(width, 0.0f, length);
glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawBFQuadWall(float width, float height) {
glBegin(GL_POLYGON);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, height, 0.0f);
glVertex3f(width, height, 0.0f);
glVertex3f(width, 0.0f, 0.0f);
glEnd();
}

void drawTextLRQuadWall(float height, float length) {
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, height, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.0f, height, length);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawTextBTQuadWall(float width, float length) {
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width, 0.0f, length);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, length);
glEnd();
}

void drawTextBFQuadWall(float width, float height) {
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width, height, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, height, 0.0f);
glEnd();
}

Share this post


Link to post
Share on other sites
Merowingian    120
Sorry, forgot the definitions:


const unsigned int numOfQuadSides = 6;

typedef bool textFlagAr[numOfQuadSides];

void drawQuad(float width, float height, float length);

void drawTextQuad(float width, float height, float length, textFlagAr textFlags);

void drawLRQuadWall(float height, float length);

void drawBTQuadWall(float width, float length);

void drawBFQuadWall(float width, float height);

void drawTextLRQuadWall(float height, float length);

void drawTextBTQuadWall(float width, float length);

void drawTextBFQuadWall(float width, float height);

Share this post


Link to post
Share on other sites
Naxos    306
I think you need to set these each time you create and bind a new texture:

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

Also, make doubly sure that texturing is enabled before you draw. I didn't see a glEnable(GL_TEXTURE_2D) call, so I wasn't sure.


Also, every time you draw the object you are creating the texture, using it, and deleting it. This is not the ideal solution. It will get slow really fast, because that means that the texture data has to be sent to gpu memory for every texture, every single frame! If you don't know, these transfers are not quick.

Instead, you should create the textures outside of the drawing code, and only call glTexImage2D(...) once for each texture created. Then, when you want to use a texture, just call glBindTexture(GL_TEXTURE_2D, texID). Once you no longer need the textures (most likely when the program ends, or when you load a different level, for example), then you call glDeleteTextures.

For example:

const unsigned int TexCount = 4;
GLuint TextureIDs[TexCount];

std::string texFiles[] =
{ "tex1.bmp", "shelf.bmp", "sky.bmp", "dirt.bmp" };

void initGL()
{
//initialize viewport, perspective, anything else you need

//Load textures
glGenTextures(TexCount, TextureIDs);

for(int i=0;i<TexCount;++i)
{
unsigned int width, height;
glBindTexture(GL_TEXTURE_2D, TextureIDs[i]);
char* texData = MyTextureLoadingFunction(texFiles[i].c_str(), width, height);

glTexEnvi(...);
glTexParameteri(...);
glTexParameteri(...);
glTexParameteri(...);
glTexParameteri(...);

glTexImage2D(..., width, height, ..., texData);
}
glEnable(GL_TEXTURE_2D);
}


void drawStuff()
{
//.. drawing code, transforms, whatever
glBindTexture(GL_TEXTURE_2D, TextureIDs[0]);
drawMyObject();

//more transforms and whatnot
glBindTexture(GL_TEXTURE_2D, TextureIDs[1]);
drawMyShelf();

//more transforms and whatnot
glBindTexture(GL_TEXTURE_2D, TextureIDs[2]);
drawMySkyPlane();

// etc, etc...

}

//Then when you don't need the textures anymore

void cleanupTextures()
{
glDeleteTextures(TexCount, TextureIDs);
}





Anyway... make sure texturing is enabled, and make sure you set the parameters you want for each texture (Even if they are the same! You must!). Also, don't forget to call glTexEnvi() and setup that properly for each texture.

Share this post


Link to post
Share on other sites
Kalidor    1087
Quote:
Original post by NaxosAnyway... make sure texturing is enabled, and make sure you set the parameters you want for each texture (Even if they are the same! You must!). Also, don't forget to call glTexEnvi() and setup that properly for each texture.
Most of Naxos' post was spot-on but that last sentence is just slightly wrong. Texture parameters are per-texture-object state so you need to set them for each texture you create (and just to reiterate, don't recreate a texture every frame). Texture environment settings, however, are per-texture-unit state. So if the current texture unit is GL_TEXTURE0 and you bind texture object 1, then change texture environment settings, then bind texture object 2, the texture environment settings you just set are still in effect on texture unit GL_TEXTURE0. You change the current texture unit with glActiveTexture, but this gets into using multiple textures at once (multitexturing) so if you don't need that then just stick with using texture unit GL_TEXTURE0 for now.

Share this post


Link to post
Share on other sites
Merowingian    120
Hey guys,

thanks for your help so far, I just got a new Macbook and I need to transfer all my data to that new notebook before I can continue programming.

I'll get back to ya'll later.

Cheers
Marvin

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By ZeldaFan555
      Hello, My name is Matt. I am a programmer. I mostly use Java, but can use C++ and various other languages. I'm looking for someone to partner up with for random projects, preferably using OpenGL, though I'd be open to just about anything. If you're interested you can contact me on Skype or on here, thank you!
      Skype: Mangodoor408
    • By tyhender
      Hello, my name is Mark. I'm hobby programmer. 
      So recently,I thought that it's good idea to find people to create a full 3D engine. I'm looking for people experienced in scripting 3D shaders and implementing physics into engine(game)(we are going to use the React physics engine). 
      And,ye,no money =D I'm just looking for hobbyists that will be proud of their work. If engine(or game) will have financial succes,well,then maybe =D
      Sorry for late replies.
      I mostly give more information when people PM me,but this post is REALLY short,even for me =D
      So here's few more points:
      Engine will use openGL and SDL for graphics. It will use React3D physics library for physics simulation. Engine(most probably,atleast for the first part) won't have graphical fron-end,it will be a framework . I think final engine should be enough to set up an FPS in a couple of minutes. A bit about my self:
      I've been programming for 7 years total. I learned very slowly it as "secondary interesting thing" for like 3 years, but then began to script more seriously.  My primary language is C++,which we are going to use for the engine. Yes,I did 3D graphics with physics simulation before. No, my portfolio isn't very impressive. I'm working on that No,I wasn't employed officially. If anybody need to know more PM me. 
       
    • By Zaphyk
      I am developing my engine using the OpenGL 3.3 compatibility profile. It runs as expected on my NVIDIA card and on my Intel Card however when I tried it on an AMD setup it ran 3 times worse than on the other setups. Could this be a AMD driver thing or is this probably a problem with my OGL code? Could a different code standard create such bad performance?
    • By Kjell Andersson
      I'm trying to get some legacy OpenGL code to run with a shader pipeline,
      The legacy code uses glVertexPointer(), glColorPointer(), glNormalPointer() and glTexCoordPointer() to supply the vertex information.
      I know that it should be using setVertexAttribPointer() etc to clearly define the layout but that is not an option right now since the legacy code can't be modified to that extent.
      I've got a version 330 vertex shader to somewhat work:
      #version 330 uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; layout(location = 0) in vec4 Vertex; layout(location = 2) in vec4 Normal; // Velocity layout(location = 3) in vec3 TexCoord; // TODO: is this the right layout location? out VertexData { vec4 color; vec3 velocity; float size; } VertexOut; void main(void) { vec4 p0 = Vertex; vec4 p1 = Vertex + vec4(Normal.x, Normal.y, Normal.z, 0.0f); vec3 velocity = (osg_ModelViewProjectionMatrix * p1 - osg_ModelViewProjectionMatrix * p0).xyz; VertexOut.velocity = velocity; VertexOut.size = TexCoord.y; gl_Position = osg_ModelViewMatrix * Vertex; } What works is the Vertex and Normal information that the legacy C++ OpenGL code seem to provide in layout location 0 and 2. This is fine.
      What I'm not getting to work is the TexCoord information that is supplied by a glTexCoordPointer() call in C++.
      Question:
      What layout location is the old standard pipeline using for glTexCoordPointer()? Or is this undefined?
       
      Side note: I'm trying to get an OpenSceneGraph 3.4.0 particle system to use custom vertex, geometry and fragment shaders for rendering the particles.
    • By markshaw001
      Hi i am new to this forum  i wanted to ask for help from all of you i want to generate real time terrain using a 32 bit heightmap i am good at c++ and have started learning Opengl as i am very interested in making landscapes in opengl i have looked around the internet for help about this topic but i am not getting the hang of the concepts and what they are doing can some here suggests me some good resources for making terrain engine please for example like tutorials,books etc so that i can understand the whole concept of terrain generation.
       
  • Popular Now