I am in the process of updating our ancient OpenGL code. It is a Windows system and I am using GLEW. The OpenGL version is 4.4 (previously, the way the context was created limited us to 1.1). The code base is large and so I want to update it in stages (i.e. get everything working now on a version higher than 1.1 with minimal work). So far, I found only one break. Transparency no longer works. I suspect this may be due to glColor* or glTexEnv* being deprecated. I tried to request a specific version of OpenGL but was not successful. Can you tell me what I am doing wrong in context creation or what changes I can make to the draw code to get transparency to work? (Other help appreciated of course.)
Here is the context creation code (error checking removed for readability):
PIXELFORMATDESCRIPTOR pfd = {
/*WORD nSize*/ sizeof(PIXELFORMATDESCRIPTOR),
/*WORD nVersion*/ 1,
/*DWORD dwFlags*/ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
/*BYTE iPixelType*/ PFD_TYPE_RGBA,
/*BYTE cColorBits*/ 24,
/*BYTE cRedBits*/ 0,
/*BYTE cRedShift*/ 0,
/*BYTE cGreenBits*/ 0,
/*BYTE cGreenShift*/ 0,
/*BYTE cBlueBits*/ 0,
/*BYTE cBlueShift*/ 0,
/*BYTE cAlphaBits*/ 8,
/*BYTE cAlphaShift*/ 0,
/*BYTE cAccumBits*/ 0,
/*BYTE cAccumRedBits*/ 0,
/*BYTE cAccumGreenBits*/ 0,
/*BYTE cAccumBlueBits*/ 0,
/*BYTE cAccumAlphaBits*/ 0,
/*BYTE cDepthBits*/ 16,
/*BYTE cStencilBits*/ 0,
/*BYTE cAuxBuffers*/ 0,
/*BYTE iLayerType*/ PFD_MAIN_PLANE,
/*BYTE bReserved*/ 0,
/*DWORD dwLayerMask*/ 0,
/*DWORD dwVisibleMask*/ 0,
/*DWORD dwDamageMask*/ 0
};
int nPixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, nPixelFormat, &pfd);
hRC_ = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC_);
MsgUtil::TraceWin("version: %s", glGetString(GL_VERSION)); // Output: version: 4.4.0
glewInit();
GLint attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
HGLRC CompHRC = wglCreateContextAttribsARB(hDC, 0, attribs);
if (CompHRC && wglMakeCurrent(hDC, CompHRC)){
hRC_ = CompHRC;
}
MsgUtil::TraceWin("version: %s", glGetString(GL_VERSION)); // Output: version: 4.4.0
Even after requesting version 3.0, glGetString(GL_VERSION) returns 4.4.0. I draw to a framebuffer and then use glReadPixels() to write to a bitmap (though I don't think that is especially relevant here).
Here is the framebuffer code (stays bound for lifetime of context):
glGenFramebuffers(1, &defaultFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, framebufferWidth, framebufferHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, framebufferWidth, framebufferHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
Here is the draw code:
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0f, 1.0f, 1.0f, alpha);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
// Turn theImage (a CImage) into a texture
HBITMAP hbitmap = NewCreateDib24(*window_dc_, MAX_DELTA, MAX_DELTA);
CBitmap* bitmap = CBitmap::FromHandle(hbitmap);
CDC* memDC = new CDC();
memDC->CreateCompatibleDC(window_dc_);
CBitmap* pOldBitmap = memDC->SelectObject(bitmap);
theImage.StretchBlt(*memDC, 0, 0, MAX_DELTA, MAX_DELTA, SRCCOPY);
LPBYTE tempbitsMem = new BYTE[bm_info.bmiHeader.biSizeImage];
bitmap->GetBitmapBits(bm_info.bmiHeader.biSizeImage, (LPVOID)tempbitsMem);
glTexImage2D(GL_TEXTURE_2D, 0, 3, MAX_DELTA, MAX_DELTA, 0, GL_BGR, GL_UNSIGNED_BYTE, tempbitsMem);
// Draw texture
glBegin(GL_QUADS);
glTexCoord2d(tx.x_, 1.0 - tx.y_);
glVertex2d(px.x_, px.y_);
glTexCoord2d(t0.x_, 1.0 - t0.y_);
glVertex2d(p0.x_, p0.y_ );
glTexCoord2d(ty.x_, 1.0 - ty.y_);
glVertex2d(py.x_, py.y_);
glTexCoord2d(txy.x_, 1.0 - txy.y_);
glVertex2d(pxy.x_, pxy.y_);
glEnd();
The texture is now applied with full opacity, regardless of the alpha value sent to glColor4f(). However, if I change the RGB values, then that is still reflected in the output.
You should ask for a compatibility profile instead of a core profile.
Related
Let's say I have a texture that I need to mipmap but I want the mipmapping done hardware accelerated. I decided the best route to take would be something like this:
int read = glGenFramebuffers();
int draw = glGenFramebuffers();
int wh = 256;
int glObject = glGenTextures();
glBindTexture(GL_TEXTURE_2D, glObject);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wh, wh, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
for(int i = 0; i < mipLevels; ++i) {
glBindFramebuffer(GL_FRAMEBUFFER, read);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glObject, i);
glTexImage2D(GL_TEXTURE_2D, i + 1, GL_RGBA8, wh / 2, wh / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByeBuffer)null);
glBindFramebuffer(GL_FRAMEBUFFER, draw);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glObject, i + 1);
glBindFramebuffer(GL_READ_FRAMEBUFFER, read);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw);
glBlitFramebuffer(0, 0, wh, wh, 0, 0, wh / 2, wh / 2, GL_COLOR_BUFFER_BIT, GL_LINEAR);
wh /= 2;
}
Both framebuffers return INCOMPLETE_ATTACHMENT in this block of code when glCheckFramebufferStatus is called. What am I doing wrong? Am I allocating the blank mipmap levels correctly?
Answer: I was using glTexImage2D to allocate blank mip levels when I should have used glTexStorage2D to allocate the blank levels under these circumstances. Here is a link to the manual page for glTexStorage2D for more details: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage2D.xhtml
How can I specify the color of backside of a scene when I use CCTransitionPageTurn? In cocos2d-iphone 1.0, I did some modifications in blot() in CCGrid.m like this:
NSInteger n = gridSize_.x * gridSize_.y;
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: GL_COLOR_ARRAY
//enable culling, the default cull face is back
glEnable(GL_CULL_FACE);
//now only the front facing polygons are drawn
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, indices);
// This is very important, otherwise the backside of picture will be random color
glDisable(GL_TEXTURE_2D);
//change the winding of what OpenGl considers front facing
//only the back facing polygons will be drawn
//this works better then changing the cull face
glFrontFace(GL_CW);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4ub(255,255,255,255);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, indices);
//restore GL default states
glFrontFace(GL_CCW);
glDisable(GL_CULL_FACE);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
This is cpp code, I think I can use in cocos2d-x. But unfortunately, this code doesn't work for 2.0. Can anybody suggest how to translate this to 2.0 ? Or is there alternative way to set color in backside of a scene during CCTransitionPageTurn?
Basing on your snippet and other google searches I've managed to achieve this :
void CCGrid3D::blit(void)
{
CCLOG("CCGrid3D::blit()");
int n = m_sGridSize.width * m_sGridSize.height;
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
m_pShaderProgram->use();
m_pShaderProgram->setUniformsForBuiltins();;
//
// Attributes
//
#ifdef EMSCRIPTEN
// Size calculations from calculateVertexPoints().
unsigned int numOfPoints = (m_sGridSize.width+1) * (m_sGridSize.height+1);
// position
setGLBufferData(m_pVertices, numOfPoints * sizeof(ccVertex3F), 0);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, 0);
// texCoords
setGLBufferData(m_pTexCoordinates, numOfPoints * sizeof(ccVertex2F), 1);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, 0);
setGLIndexData(m_pIndices, n * 12, 0);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, 0);
#else
glEnable(GL_CULL_FACE);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, m_pVertices);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, m_pIndices);
glDisable(GL_TEXTURE_2D);
glFrontFace(GL_CW);
ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position);
glEnable(GL_BLEND);
glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, m_pIndices);
glFrontFace(GL_CCW);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
#endif // EMSCRIPTEN
CC_INCREMENT_GL_DRAWS(1);
}
It has only one drawback : it does not let you specify the back color, but rather it gets the color of the bottom-left pixel and uses it. I hope this is enough for you, or that you will be able to change this so that it will let us specify the color needed.
I changed code from ES 1.0 to ES 2.0 in cocos2d-x
Code in ES 1.0 version
const float DARK=30.0f;
int n = m_sGridSize.x * m_sGridSize.y;
glEnable(GL_CULL_FACE);
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
glTexCoordPointer(2, GL_FLOAT, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, m_pIndices);
glFrontFace(GL_CW);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4ub(255-(m_AnimationProgress*DARK), 255-(m_AnimationProgress*DARK), 255-(m_AnimationProgress*DARK), 255);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, m_pIndices);
glColor4f(255, 255, 255, 255);
glFrontFace(GL_CCW);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
Code in ES 2.0 version
const float DARK=30.0f;
m_pShaderProgram->use();
m_pShaderProgram->setUniformForModelViewProjectionMatrix();
int n = m_sGridSize.x * m_sGridSize.y;
glEnable(GL_CULL_FACE);
glDisableVertexAttribArray(kCCVertexAttrib_Color);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, m_pVertices);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, m_pTexCoordinates);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, m_pIndices);
glFrontFace(GL_CW);
glDisable(GL_TEXTURE_2D);
glDisableVertexAttribArray(kCCVertexAttrib_TexCoords);
ccDrawColor4B(255-(m_AnimationProgress*DARK), 255-(m_AnimationProgress*DARK), 255-(m_AnimationProgress*DARK), 255);
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, m_pIndices);
ccDrawColor4B(255, 255, 255, 255);
glFrontFace(GL_CCW);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glEnableVertexAttribArray(kCCVertexAttrib_TexCoords);
glEnableVertexAttribArray(kCCVertexAttrib_Color);
Results in the following output (XCode)
Cocos2d: OpenGL error 0x0500 in /cocos2dx/sprite_nodes/CCSprite.cpp draw 616
what did I do wrong? I think all is well, a few times tested.
In OpenGL ES 1.1, texture mapping for fragments (there's no vertex texture mapping in ES 1.1) is turned on and off, using glEnable, and glDisable, respectively.
In OpenGL ES 2.0, fragment texture mapping is only done if it's coded into the fragment shader, so there's no need to enable or disable it. I suspect the GL_INVALID_ENUM is from the leftover glEnable(GL_TEXTURE_2D); and glDisable(GL_TEXTURE_2D);. I'm guessing you're seeing that error more than once.
0x0500 is an "illegal enum" error. Check the error codes here.
This most likely refers to the enums like GL_CULL_FACE or GL_TRIANGLES. Refer to the DL ES reference which ones might not be available in 2.0, or which of those can't be used under certain circumstances.
I'm decoding video with ffmpeg libraries and store decoded frames in array. Now i want to draw these frames on the screen with OpenGL. I googled and found that apple offers to use GL_APPLE_ycbcr_422 format for effective drawing. So i switched decoding frames in ffmpeg to PIX_FMT_YUYV422 format (packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr) which seems to be an equivalent of GL_APPLE_ycbcr_422 in OpenGL. Now i'm trying to draw frames on surface with this code:
GLsizei width = 2, height = 2;
uint8_t data[8] = {128,200,123,10,5,13,54,180};
GLuint texture_name;
glEnable(GL_TEXTURE_RECTANGLE_ARB);
assert(glGetError() == GL_NO_ERROR);
glGenTextures (1,&texture_name);
assert(glGetError() == GL_NO_ERROR);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_name);
assert(glGetError() == GL_NO_ERROR);
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, width * height * 2, (void*)data);
assert(glGetError() == GL_NO_ERROR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE);
assert(glGetError() == GL_NO_ERROR);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
assert(glGetError() == GL_NO_ERROR);
// not sure about code above
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
assert(glGetError() == GL_NO_ERROR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
assert(glGetError() == GL_NO_ERROR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
assert(glGetError() == GL_NO_ERROR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
assert(glGetError() == GL_NO_ERROR);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
assert(glGetError() == GL_NO_ERROR);
// end
glViewport(0, 0, width,height);
assert(glGetError() == GL_NO_ERROR);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
assert(glGetError() == GL_NO_ERROR);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, width, height, 0,
GL_YCBCR_422_APPLE,GL_UNSIGNED_SHORT_8_8_APPLE,
(void*)data);
assert(glGetError() == GL_NO_ERROR);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_YCBCR_422_APPLE,GL_UNSIGNED_SHORT_8_8_APPLE,
(void*)data);
assert(glGetError() == GL_NO_ERROR);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glScalef(1.0f, -1.0f, 1.0f);
glOrtho(0, width, 0, height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glVertex3f(0, 0, -1.0f);
glVertex3f(width, 0, -1.0f);
glVertex3f(width, height, -1.0f);
glVertex3f(0, height, -1.0f);
glEnd();
But i don't see correct frames. Instead i see corrupted pictures of my display. So i understand that my using of OpenGL is not correct and maybe i don't understand some fundamental things.
Please, help to correct and to understand my mistakes. If i should RTFM please give me a link that will help me, because i didn't find any useful info.
Here's what I use in one of my applications to set up a YUV 4:2:2 texture target for uploaded data from YUV frames pulled off of a CCD camera:
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_RECTANGLE_EXT);
glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, videoImageSize.width * videoImageSize.height * 2, videoTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, videoImageSize.width, videoImageSize.height, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
The actual upload to the texture is accomplished using the following:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, videoImageSize.width, videoImageSize.height, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);
In the above, videoTexture is the memory location of the raw bytes from a captured YUV frame off of the camera. I'm also using Apple's storage hints in the above to accelerate the upload, although I never could get the GL_UNPACK_CLIENT_STORAGE_APPLE optimization to speed things up further.
This was copied and pasted out of a working application, and the only real differences I see is my use of GL_RGBA instead of GL_RGB in the getTexImage2D() and the use of GL_UNSIGNED_SHORT_8_8_REV_APPLE instead of GL_UNSIGNED_SHORT_8_8_APPLE. Both the ARB and EXT rectangle extensions resolve to the same thing on the Mac.
It's a really stupid, basic question, but: Can someone please tell me the difference between:
glBegin(GL_QUADS);
glTexCoord3f(0, 0, 0); glVertex3f(0, 1, 0);
glTexCoord3f(1, 0, 0); glVertex3f(1, 1, 0);
glTexCoord3f(1, 1, 0); glVertex3f(1, 0, 0);
glTexCoord3f(0, 1, 0); glVertex3f(0, 0, 0);
glEnd();
and
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat vertexData[] = {
0, 0, 0,
width, 0, 0,
0, height, 0,
width, height, 0
};
const GLfloat texCoords[] = {
0, 0,
1, 0,
0, 1,
1, 1
};
glVertexPointer(3, GL_FLOAT, 0, &vertexData);
glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
(width & height is the texture size in pixel)
I can't really understand why, but if I use the second code (because OpenGL ES compatible) my texture is on the y-axis inverted. What I'm doing wrong?
Edit:
I dont know, if its relevant - maybe i made a mistake at init the viewport for 2D drawing?
GLint iViewport[4];
glGetIntegerv( GL_VIEWPORT, iViewport );
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho( iViewport[0], iViewport[0]+iViewport[2], iViewport[1]+iViewport[3], iViewport[1], -1, 1 );
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
Sticking to the simplest, you have 4 vertices with texcoords. Here they are put in parallel:
texcoord/vert
0, 0, / 0, 1
1, 0, / 1, 1
1, 1, / 1, 0
0, 1, / 0, 0
0, 0 / 0, 0
1, 0 / width, 0
0, 1 / 0, height
1, 1 / width, height
Now, if we reorder them by verts, you can see that the texcoords do not correspond
// sorted verts by "alphabetical" position.
0, 1, / 0, 0
0, 0, / 0, 1
1, 1, / 1, 0
1, 0, / 1, 1
0, 0 / 0, 0
0, 1 / 0, height
1, 0 / width, 0
1, 1 / width, height
As you can see, for each equivalent position, the second texture coordinate is inverted between the 2. That explains why the textures are y-flipped.
So if you want to fix it, simply flip them back on the second method:
const GLfloat texCoords[] = {
0, 1,
1, 1,
0, 0,
1, 0
};
Try using the same geometry in each case:
Immediate mode:
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(1, 0, 0); glVertex3f(1, 0, 0);
glTexCoord2f(1, 1, 0); glVertex3f(1, 1, 0);
glTexCoord2f(1, 1, 0); glVertex3f(1, 1, 0);
glTexCoord2f(0, 1, 0); glVertex3f(0, 1, 0);
glTexCoord2f(0, 0, 0); glVertex3f(0, 0, 0);
glEnd();
Vertex arrays:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat vertexData[] = {
0, 0, 0,
width, 0, 0,
width, height, 0
width, height, 0
0, height, 0,
0, 0, 0,
};
const GLfloat texCoords[] = {
0, 0,
1, 0,
1, 1
1, 1
0, 1,
0, 0,
};
glVertexPointer(3, GL_FLOAT, 0, &vertexData);
glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
Ok, try this complete GLUT program. I actually tested it this time around :)
#include <vector>
#include <GL/glut.h>
using namespace std;
size_t win_w = 0;
size_t win_h = 0;
double aspect_ratio = 0;
GLuint tex_obj;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10*aspect_ratio, 10*aspect_ratio, -10, 10, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex_obj);
glPushMatrix();
glScalef(5,5,0);
/*
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(1, 0); glVertex3f(1, 0, 0);
glTexCoord2f(1, 1); glVertex3f(1, 1, 0);
glTexCoord2f(1, 1); glVertex3f(1, 1, 0);
glTexCoord2f(0, 1); glVertex3f(0, 1, 0);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glEnd();
*/
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat vertexData[] = {
0, 0, 0,
1, 0, 0,
1, 1, 0,
1, 1, 0,
0, 1, 0,
0, 0, 0,
};
const GLfloat texCoords[] = {
0, 0,
1, 0,
1, 1,
1, 1,
0, 1,
0, 0,
};
glVertexPointer(3, GL_FLOAT, 0, &vertexData);
glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
win_w = w;
win_h = h;
aspect_ratio = (double)win_w / (double)win_h;
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800,600);
glutCreateWindow("Aspect Ratio");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex_obj);
glBindTexture(GL_TEXTURE_2D, tex_obj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
vector< unsigned char > pixels(4 * 3);
pixels[3*0+0] = 255;
pixels[3*0+1] = 0;
pixels[3*0+2] = 0;
pixels[3*1+0] = 0;
pixels[3*1+1] = 255;
pixels[3*1+2] = 0;
pixels[3*2+0] = 0;
pixels[3*2+1] = 0;
pixels[3*2+2] = 255;
pixels[3*3+0] = 255;
pixels[3*3+1] = 255;
pixels[3*3+2] = 255;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}