Can't add a texture to GL_QUAD - c++

I have a series of rectangles and I am trying to add a texture to just one of them. Here is my current code:
glEnable (GL_TEXTURE_2D);
QBitmap image;
GLuint texture;
float pixels[] = {
42, 0, 1, 0, 42, 1,
-42 , 0, 1, 0, -42, 1,
};
image.load("texture.bmp");
GLuint m_TextureID;
glGenTextures(1, &m_TextureID);
glBindTexture ( GL_TEXTURE_2D, m_TextureID);
glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_MODULATE);
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 84, 84, 0, GL_RGB, GL_FLOAT, pixels);
glEnable(GL_TEXTURE_2D);
glBindTexture ( GL_TEXTURE_2D, m_TextureID);
glBegin(GL_QUADS);
glBegin(GL_QUADS);
glVertex3f(42, 0, 42);
glVertex3f(42, 0, -42);
glVertex3f(-42, 0, -42);
glVertex3f(-42, 0, 42);
glEnd();
Where am I going wrong?

Where's your call to glTexImage2D? The data in the image variable isn't going to "magically" jump into the OpenGL texture. Oh, and you should not reload the image/texture upon every redraw.

Related

Texture Mapping bug in opengl (with multiple textures)

i'm having trouble in using more then one texture in Opengl. I've written a test program that draws two squares, one bigger then other. When i texturize just one of then, everything works fine, but when i texture both, thats the result:
Thats the code i use to initialize the textures:
unsigned int grass_height, grass_width, wall_height, wall_width;
unsigned char *grass = loadBMP("./minegrama.bmp", &grass_height, &grass_width);
unsigned char *wall = loadBMP("./mineleaves.bmp", &wall_height, &wall_width);
glShadeModel(GL_SMOOTH);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glGenTextures(2, tex);
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, grass_width, grass_height, 0, GL_BGR, GL_UNSIGNED_BYTE, grass);
gluBuild2DMipmaps(tex[0], GL_RGB, grass_width, grass_height, GL_RGB, GL_UNSIGNED_BYTE, grass);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, tex[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, wall_width, wall_height, 0, GL_BGR, GL_UNSIGNED_BYTE, wall);
gluBuild2DMipmaps(tex[1], GL_RGB, grass_width, grass_height, GL_RGB, GL_UNSIGNED_BYTE, wall);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Thats the code of the drawing:
//Seta o MatrixMode pra usar texturas
glMatrixMode(GL_TEXTURE);
//INICIO DO CHAO
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex[0]);
//Desenhar o chao;
glColor3f(0, 0.39, 0);
glBegin(GL_QUADS);
glVertex3f(-30, -30, -0.001);
glTexCoord3f(-30, -30, -0.001);
glVertex3f(30, -30, -0.001);
glTexCoord3f(30, -30, -0.001);
glVertex3f(30, 30, -0.001);
glTexCoord3f(30, 30, -0.001);
glVertex3f(-30, 30, -0.001);
glTexCoord3f(-30, 30, -0.001);
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
//FIM DO CHAO
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex[1]);
glTranslatef(0, 0, 10);
glBegin(GL_QUADS);
glVertex3f(-1, -1, 0); glTexCoord3f(-1, -1, 0); //Especifica cada vértice
glVertex3f(1, -1, 0); glTexCoord3f(1, -1, 0);
glVertex3f(1, 1, 0); glTexCoord3f(1, 1, 0);
glVertex3f(-1, 1, 0); glTexCoord3f(-1, 1, 0);
glDisable(GL_TEXTURE_2D);
glEnd();
glPopMatrix();
The first parameter of gluBuild2DMipmaps is wrong. The documentation for the target paramter states:
Specifies the target texture. Must be GLU_TEXTURE_2D.
In addition, your texture coordinates don't look good. With the current values, the texture on the large rectangle will be repeated 60 times. In addition, the z-value of the texture coordinates should be 0, not 0.01. Even better: Use glTexCoord2f for 2-dimensional textures.

I'm trying to update a texture with glTexSubImage2D

I started learning OpenGL recently and I've been messing with texture. I updated my texture using glTexImage2D but I've learned that it's better to use glTexSubImage2D, so I tried to change my code but i doesn't work.
Working code
void GLWidget::updateTextures(){
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
glBindTexture( GL_TEXTURE_2D, 0);
}
Not working code
void GLWidget::updateTextures(){
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t.width(), t.height(), GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
glBindTexture( GL_TEXTURE_2D, 0);
}
All I have is a black screen.
Thanks.
EDIT :
Here is the initialization of my texture :
void GLWidget::initializeGL(){
...
LoadGLTextures();
...
}
void GLWidget::LoadGLTextures(){
QImage t = img.mirrored();
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture( GL_TEXTURE_2D, 0);
}
img is a QImage variable containing the pixel data.
glGetError() Returns code 1281.
glTexSubImage2D updates the content of a previously allocated texture. glTexImage2D has to be called at least once to trigger the allocation:
void GLWidget::initializeGL(){
//...
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(
GL_TEXTURE_2D,
0,
3,
t.width(),
t.height(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
t.bits()
);
glBindTexture( GL_TEXTURE_2D, 0);
// ...
}
Update with glTexSubImage2D:
void GLWidget::updateTextures(){
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexSubImage2D(
GL_TEXTURE_2D,
0,
0,
0,
t.width(),
t.height(),
GL_RGBA,
GL_UNSIGNED_BYTE,
t.bits()
);
glBindTexture( GL_TEXTURE_2D, 0);
}
EDIT: the problem was glTexImage2D and glTexSubImage2D were called with different image sizes, generating the error GL_INVALID_VALUE (1281, 0x501) on glTexSubImage2D call.

C++ Adding a texture to a GL_QUAD and it's coming out black

I have a series of rectangles of different colours and I'm trying to add a texture to one of them. However when I apply the texture to the given rectangle, it just turns black. Below is the function I use to load the texture.
GLuint GLWidget:: LoadTexture(const char * pic, int width, int height){
GLuint Texture;
BYTE * data;
FILE * picfile;
picfile = fopen(pic, "rb");
if (picfile == NULL)
return 0;
data = (BYTE *)malloc(width * height * 3);
fread(data, width * height, 3, picfile);
fclose(picfile);
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
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_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB8, GL_UNSIGNED_BYTE, data);
return Texture;
}
In another function where the GL_QUADS are drawn, I then have...
GLuint myTex = LoadTexture("texture.bmp", 500, 500);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, myTex);
glBegin(GL_QUADS);
glTexCoord2f(1, 1); glVertex3f(42, 10, 42);
glTexCoord2f(1, 0); glVertex3f(42, 10, -42);
glTexCoord2f(0, 0); glVertex3f(-42,10,-42);
glTexCoord2f(0, 1); glVertex3f(-42,10, 42);
glEnd();
If anyone could let me know where I am going wrong that would be great, thanks!
This call
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB8, GL_UNSIGNED_BYTE, data);
is invalid. GL_RGB8 is a valid internalFormat, but it is not a valid enum for format. Use GL_RGB, GL_UNSIGNED_BYTE as format and type if your client-side data is 3 channels with 8 but unsigned int data per channel.
Another thing is
LoadTexture("texture.bmp", 500, 500);
This suggests that you are dealing with BMP files, but your loader only deals with completely raw image data.

What might be the issue with my pipeline to rendering the depth buffer to a texture?

The main steps for depth testing from my understanding:
1) enable depth testing and how we want to depth test
2) create the frame buffer object and make sure it has a depth attached to it
3) bind our frame buffer object ( make sure to clear it before rendering )
4) draw stuff
And that should be it no? our frame buffer depth attachment should have depth data? But I always get straight 1's default depth clear color
step 1:
glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LEQUAL );
step 2:
//create the frame buffer object
glGenFramebuffers(1, &m_uifboHandle);
// Initialize FBO
glBindFramebuffer(GL_FRAMEBUFFER, m_uifboHandle);
//create 2 texture handles 1 for diffuse, 1 for depth
unsigned int m_uiTextureHandle[2];
glGenTextures( 2, m_uiTextureHandle );
//create the diffuse texture
glBindTexture( GL_TEXTURE_2D, m_uiTextureHandle[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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, uiWidth, uiHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uiTextureHandle[0], 0);
.
//create the depth buffer
glBindTexture(GL_TEXTURE_2D, m_uiTextureHandle[1]);
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 );
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, uiWidth, uiHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_uiTextureHandle[1], 0);
//go back to default binding
glBindFramebuffer(GL_FRAMEBUFFER, 0);
step 3:
//bind the frame buffer object
glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle );
//clear it
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
step 4:
//draw things
Are these not the steps?
Am i missing something?
I've tried a few different tutorials.
I can't get any depth to render to a texture
I keep getting straight 1's over and over.
The framebuffer probably is not complete. Try checking for completeness. Moreover your code was:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, uiWidth, uiHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
However, it should be (watch the RGB-RGBA):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, uiWidth, uiHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

How Can I Render To One Face Of An OpenGL Cubemap texture

I'm making a Cube map render target class.
I already have a 2D one that works fine. But for this cube map render target class I want to be able to render to a specific face as i wish. Maybe I want to render circles on the "X+" face but triangles in the "Y+" face.
This is what my class looks like
class CRenderTarget
{
private:
//frame buffer to render on
unsigned m_uifboHandle;
//depth stencil
unsigned m_uiDepthStencilHandle;
//the texture we will render on
unsigned m_uiTextureHandle;
public:
CCubeRenderTarget( void );
~CCubeRenderTarget( void );
void Create( unsigned uiHeightWidth = 512,
int iInternalFormat = 0x1908 ); //GL_RGBA
void Bind( void );
void UnBind( void );
}
This is how my create function looks like
void Create( unsigned uiHeightWidth, int iInternalFormat )
{
//generate our variables
glGenFramebuffers(1, &m_uifboHandle);
glGenRenderbuffers(1, &m_uiDepthStencilHandle);
glGenTextures(1, &m_uiTextureHandle);
// Initialize FBO
glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle);
glBindTexture( GL_TEXTURE_CUBE_MAP, m_uiTextureHandle);
// Pre-allocate the correct sized cube map
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, iInternalFormat, uiHeightWidth, uiHeightWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, iInternalFormat, uiHeightWidth, uiHeightWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, iInternalFormat, uiHeightWidth, uiHeightWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, iInternalFormat, uiHeightWidth, uiHeightWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, iInternalFormat, uiHeightWidth, uiHeightWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, iInternalFormat, uiHeightWidth, uiHeightWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Must attach texture to framebuffer. Has Stencil and depth
glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthStencilHandle);
glRenderbufferStorage(GL_RENDERBUFFER, /*GL_DEPTH_STENCIL*/GL_DEPTH24_STENCIL8, uiHeightWidth, uiHeightWidth );
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthStencilHandle);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthStencilHandle);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
this is what my bind function looks like
void Bind( void )
{
glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle );
}
//this is what my unbind function looks like
void Unbind( void )
{
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
I done tons of research for the past week. I can't seem to find a way that i can just some how instead of binding my entire cube map just bind maybe 1 face of my cube map. which is my overall goal. I know that in DirectX you can by just grabbing the 6 faces and manually handling them but how can i manually handle each face on an openGL cube map?
Having bound the framebuffer, you need to specify what level of the texture should be targetted. It should be something like this:
glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_uiTextureHandle, 0);