I am porting some code from OpenGL to the ES version. I am using glDrawArrays() to draw a triangle in conjuction with glVertexPointer(). However, it doesn't draw on the screen. The complete code is:
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glEnableClientState (GL_COLOR_ARRAY);
glClear (GL_COLOR_BUFFER_BIT);
glColor4f (0.0, 0.0, 1.0, 1.0);
glLoadIdentity ();
glTranslatef(0, 0, -20);
const GLfloat triVertices[] = {
0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
glVertexPointer(3, GL_FLOAT, 0, triVertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
glFlush ();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode (GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
GLUT opens up the window, it clears with black, but doesn't draw anything.
Can someone please spot what I am doing wrong? Thanks.
I see no call to glEnableClientState(GL_VERTEX_ARRAY);. I also see glEnableClientState (GL_COLOR_ARRAY); but no call to glColorPointer(). Perhaps you wrote one when you meant the other?
Related
I tried a lot of examples for loading and displaying images in openGL using SOIL.
while running the source code below, it displays just a wite quad without an image.
I tried to open an image called: foto.
I placed the image-file in the folder of the program.
bool* keyStates = new bool[256];
GLuint texture[0];
void resize(int height, int width) {
const float ar = (float) width / (float) height;
glViewport(0, 10, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 90.0);
//gluLookAt(0, 2, 0, -1, 1, -3, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
void keyOperations (void) {
if (!keyStates['a']) {}
}
static void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
texture[0] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
"foto.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
// allocate a texture name
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glutSwapBuffers();
}
void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = false;
}
void keyUp (unsigned char key, int x, int y) {
keyStates[key] = true;
}
int main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutCreateWindow("ugh fml");
glutReshapeFunc(resize);
glutDisplayFunc(Draw);
glutKeyboardFunc(keyPressed);
glutKeyboardUpFunc(keyUp);
/////////////////////////////////////
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glutMainLoop();
}
You're using a relative path to access foto.png.
Make sure your working directory is where you expect.
Some IDEs like to change the working directory to someplace other than where the executable is.
I am writing a small program to simulate animation. I use QGLWidget to display a dynamic image to mimic picture animation. The basic idea is to use texture and update it through QGLFamebufferOject::blitFramebuffer. Each time, the image array will be changed and then frame buffer will be changed.
The code can run and the image can be moved forward, but image has chopping problem, or flicking, not smooth.
Following is the code for a class:
GLWidget::GLWidget(QWidget *parent) : QGLWidget(QGLFormat(), parent)
{
makeCurrent();
if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) {
QGLFramebufferObjectFormat format;
render_fbo = new QGLFramebufferObject(640, 480, format);
texture_fbo = new QGLFramebufferObject(640, 480);
} else {
render_fbo = new QGLFramebufferObject(640, 480);
texture_fbo = render_fbo;
}
tile_list = glGenLists(1);
glNewList(tile_list, GL_COMPILE);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
}
glEnd();
glEndList();
backbufferImg = new unsigned char[640 * 480 * sizeof(unsigned char) * 3];
}
GLWidget::~GLWidget()
{
}
void GLWidget::initializeGL()
{
}
void GLWidget::resizeGL(int width, int height)
{
}
void GLWidget::paintGL()
{
}
void GLWidget::saveGLState()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void GLWidget::restoreGLState()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
void GLWidget::changeTextureImage(int nextColumn, int direction)
{
// code about chaning backbufferImg
// ...
// call draw
draw();
}
void GLWidget::draw()
{
makeCurrent();
QPainter p(this); // used for text overlay
// save the GL state set for QPainter
saveGLState();
QPainter fbo_painter(render_fbo);
QImage renderImg(backbufferImg, 640, 480, QImage::Format_RGB888);
fbo_painter.begin(render_fbo);
QRect rect(640, 480);
fbo_painter.drawImage(rect, renderImg, rect);
fbo_painter.end();
if (render_fbo != texture_fbo) {
QGLFramebufferObject::blitFramebuffer(texture_fbo, rect, render_fbo, rect);
} else {
// qDebug() << "render_fbo == texture_fbo";
}
// draw into the GL widget
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, width(), height());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, texture_fbo->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glScalef(1.0f, 1.0f, 1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glCallList(tile_list);
glPopMatrix();
// restore the GL state that QPainter expects
restoreGLState();
glFinish();
}
Qt's QGLWidget expects that you perform all drawing operations from its overloaded paintGL function so that it iteracts nicely with Qt's double buffer management.
Also why are you taking that detour over a FBO to update a texture? This is highly inefficient and introduces a lot of synchronization points. Use a Pixel Buffer Object and update the texture with glTexSubImage2D.
Thank you very much! I have changed the code and put the drawing code inside paintGL and didn't use FBO's blit method. MUch better, but still need to improve the code. The following is the code:
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(QGLFormat(), parent)
{
makeCurrent();
fbo = new QGLFramebufferObject(WIDTH, HEIGHT);
tile_list = glGenLists(1);
glNewList(tile_list, GL_COMPILE);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
}
glEnd();
glEndList();
backbufferImg = new unsigned char[WIDTH * HEIGHT * sizeof(unsigned char) * 3];
}
GLWidget::~GLWidget()
{
glDeleteLists(tile_list, 1);
delete fbo;
delete backbufferImg;
}
void GLWidget::initializeGL()
{
}
void GLWidget::resizeGL(int width, int height)
{
}
void GLWidget::paintGL()
{
glViewport(0, 0, fbo->size().width(), fbo->size().height());
glMatrixMode(GL_MODELVIEW);
// render to the framebuffer object
fbo->bind();
glBindTexture(GL_TEXTURE_2D, refreshTexture);
glCallList(tile_list);
fbo->release();
//////////////////////////////////////////////////////////////////////
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, width(), height());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glScalef(1.0f, 1.0f, 1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glCallList(tile_list);
glPopMatrix();
// restore the GL state that QPainter expects
restoreGLState();
glFinish();
}
void GLWidget::saveGLState()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void GLWidget::restoreGLState()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
void GLWidget::refreshTextureImage(int nextColumn, int direction)
{
// upadte backbufferImg
// add code...
QImage renderImg(backbufferImg, WIDTH, HEIGHT, QImage::Format_RGB888);
refreshTexture = bindTexture(renderImg);
updateGL();
}
I will try the method you suggested. But I think framebuffer and pixel buffer in the same level. It means there is no much performance difference. For glTexSubImage2D, I am not quite sure, I need to check it.
Thank you so much.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Image loading using openGL, SOIL
while running the source code below, it displays just a wite quad without an image.
I tried to open an image called: foto.
I placed the image-file in the folder of the program.
bool* keyStates = new bool[256];
GLuint texture[0];
void resize(int height, int width) {
const float ar = (float) width / (float) height;
glViewport(0, 10, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 90.0);
//gluLookAt(0, 2, 0, -1, 1, -3, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
void keyOperations (void) {
if (!keyStates['a']) {}
}
static void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
texture[0] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
"foto.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
// allocate a texture name
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glutSwapBuffers();
}
void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = false;
}
void keyUp (unsigned char key, int x, int y) {
keyStates[key] = true;
}
int main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutCreateWindow("ugh fml");
glutReshapeFunc(resize);
glutDisplayFunc(Draw);
glutKeyboardFunc(keyPressed);
glutKeyboardUpFunc(keyUp);
/////////////////////////////////////
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glutMainLoop();
}
I get the same behavior if the image file (foto.png) is not located in the program's working directory. But when I add the image to the program's working directory, the quad is textured properly. Try either 1) adding the texture image to the program's working directory or 2) changing the program's working directory to the directory where the texture file is located.
I'm trying to rotate a triangle around the the Y axis. When I rotate it about the Z axis, everything is fine. But when I try rotating about the Y axis, all I get is a half triangle, rotating about the Y axis. I'm using PowerVRs OpenGL ES 2.0 SDK. My Init and Draw functions are below.
int Init(ESContext* esContext)
{
UserData* userData = (UserData *)esContext->userData;
const char *vShaderStr =
"attribute vec4 vPosition; \n"
"uniform mat4 MVPMatrix;"
"void main() \n"
"{ \n"
" gl_Position = MVPMatrix * vPosition;\n"
"} \n";
const char *fShaderStr =
"precision mediump float; \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
GLfloat ratio = 320.0f/240.0f;
vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);
programObject = glCreateProgram();
if (programObject == 0)
return 0;
glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);
glBindAttribLocation(programObject, 0, "vPosition");
glLinkProgram(programObject);
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &linked);
if (!linked)
{
GLint infoLen = 0;
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1)
{
char* infoLog = (char *)malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
free(infoLog);
}
glDeleteProgram(programObject);
return FALSE;
}
userData->programObject = programObject;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, esContext->width, esContext->height);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(userData->programObject);
userData->angle = 0.0f;
userData->start = time(NULL);
userData->ProjMatrix = PVRTMat4::Perspective(ratio*2.0f, 2.0f, 3.0f, 7.0f, PVRTMat4::eClipspace::OGL, false, false);
userData->ViewMatrix = PVRTMat4::LookAtLH(PVRTVec3(0.0f, 0.0f, -3.0f), PVRTVec3(0.0f, 0.0f, 0.0f), PVRTVec3(0.0f, 1.0f, 0.0f));
return TRUE;
}
void Draw(ESContext *esContext)
{
GLfloat vVertices[] = {0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f};
GLint MVPHandle;
double timelapse;
PVRTMat4 MVPMatrix = PVRTMat4::Identity();
UserData* userData = (UserData *)esContext->userData;
timelapse = difftime(time(NULL), userData->start) * 1000;
if(timelapse > 16.0f) //Maintain approx 60FPS
{
if (userData->angle > 360.0f)
{
userData->angle = 0.0f;
}
else
{
userData->angle += 0.1f;
}
}
userData->ModelMatrix = PVRTMat4::RotationY(userData->angle);
MVPMatrix = userData->ViewMatrix * userData->ModelMatrix;
MVPMatrix = userData->ProjMatrix * MVPMatrix;
MVPHandle = glGetUniformLocation(userData->programObject, "MVPMatrix");
glUniformMatrix4fv(MVPHandle, 1, FALSE, MVPMatrix.ptr());
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}
PVRTMat4::Perspective(ratio*2.0f, 2.0f, 3.0f, 7.0f, PVRTMat4::eClipspace::OGL, false, false); puts the near clipping plane at 3.0f units away from the camera (via the third argument).
PVRTMat4::LookAtLH(PVRTVec3(0.0f, 0.0f, -3.0f), PVRTVec3(0.0f, 0.0f, 0.0f), PVRTVec3(0.0f, 1.0f, 0.0f)); places the camera at (0, 0, -3), looking back at (0, 0, 0).
You generate a model matrix directly using PVRTMat4::RotationY(userData->angle); so that matrix does no translation. The triangle you're drawing remains positioned on (0, 0, 0) as per its geometry.
So what's happening is that the parts of the triangle that get closer to the camera than 3 units are being clipped by the near clipping plane. The purpose of the near clipping plane is effectively to place the lens of the camera relative to where the image will be perceived. Or it's like specifying the distance from user to screen, if you prefer.
You therefore want either to bring the near clip plane closer to the camera or to move the camera further away from the triangle.
This is my code:
- (void)drawView {
// Define square for flowers head (vertecies)
const GLfloat flowerHead[] = {
-1.0, 1.0, 1.0, // top left
-1.0, -1.0, 1.0, // bottom left
1.0, -1.0, 1.0, // bottom right
1.0, 1.0, 1.0
};
// Define the texture coordinates --> as the flowerHead vertecies
const GLshort flowerHeadTextureCoord[] = {
0, 1, // top left
0, 0, // bottom left
1, 0, // bottom right
1, 1 // top right
};
rota = 1.0;
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glTexCoordPointer(2, GL_SHORT, 0, flowerHeadTextureCoord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// flower #1
glPushMatrix();
{
glEnable(GL_ALPHA_TEST); // enable alpha -> transparency state
glTranslatef(0.0, 0.0, -6.0); // positioning the flower
glRotatef(55.0, 1.0, 0.0, 0.0); // rotate flower on (x) axis
glVertexPointer(3, GL_FLOAT, 0, flowerHead); // pointer to the flowerHead vertecies array
glEnableClientState(GL_VERTEX_ARRAY); // enable the vertex array state
// Draw the front face
// Bind texture
glBindTexture(GL_TEXTURE_2D, textures[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glPopMatrix();
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
[self checkGLError:NO];
}
Now this is my drawing code...all I need now is to rotate the camera around the object (and not the object itself)...
My setupView function:
const GLfloat zNear = 0.1, zFar = 1000.0, fieldOfView = 60.0;
GLfloat size;
// Set the general polygon properties - for transparency!!!
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GREATER,0.1f);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
// This give us the size of the iPhone display
CGRect rect = self.bounds;
glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size / (rect.size.width / rect.size.height), zNear, zFar);
glViewport(0, 0, rect.size.width, rect.size.height);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);