In JOGL, there is the addGLEventListener; I added a listener to it.
When the display() "callback on gl" is called, the screen is printed in black, but after four frames the display() prints something.
How to make display() print something on the first callback display()?
If you application implements an interface GLEventListener, there is always a next sequence:
—init();
—reshape();
—display().
In my opinion, you have a wrong drawing sequence in the function display().
Try do it in this way:
public void display(GLAutoDrawable drawable) {
gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glColor3f(1.0f, 1.0f, 1.0f);
gl.glBegin(GL.GL_POLYGON);
gl.glVertex2f(-0.5f, -0.5f);
gl.glVertex2f(-0.5f, 0.5f);
gl.glVertex2f(0.5f, 0.5f);
gl.glVertex2f(0.5f, -0.5f);
gl.glEnd();
drawable.swapBuffers(); // — it's for double buffering
}
Related
I am trying to create an interactive openGL program which takes user input and displays a shape. Everything seems to be working once the user inputs something...but on first execution, the glClear in the display function isn't actually clearing the screen...am I missing something somewhere?
Thanks!!
#include <stdlib.h>
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
void exit(int);
void myInit(void){
glClearColor(0.0, 0.0, 0.0, 1.0);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(4.0);
}
//SET WINDOW
void setWindow(double left, double right, double bottom, double top){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left, right, bottom, top, -1.0, 1.0); //viewing volume at origin, edge length 2
}
//SET VIEWPORT
void setViewport(int x, int y, int width, int height){
glViewport(x, y, width, height);
}
//DISPLAY FUNCTION
void myDisplay(void){
glClear(GL_COLOR_BUFFER_BIT);
}
void myKeyboard(unsigned char key, int mouseX, int mouseY){
switch(key)
{
case 'Q':
case'q':
exit(-1);
case 't':
//displayTriangle();
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(0.0, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char** argv){
glutInit(&argc, argv); //initialize toolkit
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640,480);
glutInitWindowPosition(100, 150);
glutCreateWindow("Interactive Shape Display!");
myInit();
glutDisplayFunc(myDisplay);
glutKeyboardFunc(myKeyboard);
glutMainLoop();
return 0;
}
glClear(GL_COLOR_BUFFER_BIT)
will clear the screen to the glClearColor() value. I'll run your code when I get a chance, but the glColor3f(1.0f, 0.0f, 0.0f) will set the color to red for your vertices (glVertex2f(-0.5, -0.5)...) until you change the glColor3f(). After you set the glClearColor() (black), you should be able to clear the screen again, anytime you call glClear(). You call it with myDisplay(). When you enter myKeyboard(), glClear () is called again, but the red glVertex2f()s are called immediately, which will draw over it.
When you say that the screen is not cleared on first execution, are you not seeing black initially? Will run the code and edit this if any results change for me.
Edit:
It's a good idea to move the drawing code to the display function. If you still want keyboard interaction, you could have a glutTimerFunc() in your main method:
glutTimerFunc(1, timerLoopCallback, 0);
The timer's callback would perform any logic based on the keyboard callbacks. So myKeyboard() registers the 't' key and the timer callback determines a triangle must be drawn (maybe setting a variable).
glutPostRedisplay();
should come next in the timer callback, then another call to the timer func (exactly as above). In the display func, the triangle is called if the timer callback determined it should.
This describes the relation between drawing and its separation from other logic. You might also want glutSwapBuffers(); at the end of your draw code.
I'm trying to understand how to use glClearBuffer* to change the background color in a (either single or double buffered) NSOpenGLView in Cocoa for OS X.
The following code fragment as suggested by the OpenGL Superbible fails with GL_INVALID_OPERATION:
GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, red);
What do I need to supply for the second parameter?
I'm using a double buffered View extending OpenGLView.
#import "MyOpenGLView.h"
#include <OpenGL/gl3.h>
#implementation MyOpenGLView
-(void) drawRect: (NSRect) bounds
{
GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, red);
GLenum e = glGetError();
// e == GL_INVALID_OPERATION after this call
// and the view is drawn in black
// The following two lines work as intended:
//glClearColor(1.0, 0.f, 0.f, 1.f);
//glClear(GL_COLOR_BUFFER_BIT);
[[self openGLContext] flushBuffer];
}
#end
Really? It is giving you GL_INVALID_OPEARATION?
This function is not supposed to generate that error... are you sure something earlier in your program did not create the error and you are mistaking the source?
The bigger problem however, is that using GL_COLOR as the buffer in this API call expects the second parameter to be an index into your set of draw buffers. It is unclear how your draw buffers are setup in this code, it is possible that you have GL_NONE. As there is no defined error behavior if you try to clear a draw buffer when GL_NONE is used, I suppose an implementation might choose to raise GL_INVALID_OPERATION.
In order for your current usage of glClearBufferfv (...) to make sense, I would expect to see something like this:
GLenum buffers [] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
GLfloat red [] = { 1.0f, 0.0f, 0.0f, 1.0f };
glDrawBuffers (2, buffers);
glClearBufferfv (GL_COLOR, 0, red);
Now this call will clear GL_COLOR_ATTACHMENT0, if you wanted to clear GL_COLOR_ATTACHMENT1, you could replace 0 with 1.
I'm working on a program which will calculate the centroids of some polygons. I have the centroid calculations in place. I would like to display the polygons with OpenGL. I have an OpenGL window up and running already.
In the OpenGL class there is a method, drawRect where you 'draw' the vertices to screen. I have however got the vertices I want to draw in a separate polygon class. Ideally I would like to call a draw method on a polygon, e.g.
firstPolygon.draw();
But I don't know how I would do that as the drawRect method is in the OpenGL class and thats the only way I know to draw. Can I somehow send data to the draw method from within the Polygon class? or draw directly to the screen within the polygon class?
Currently 'OpenGLView.m' contains:
#import "OpenGL/gl.h"
#import "OpenGLView.h"
#import "Poly.h"
#implementation OpenGLView
-(id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
if(self){
// initialise things here
}
return self;
}
-(void)drawRect:(NSRect)Rect
{
glClearColor(1.0f,1.0f,1.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_LINE_LOOP);
{
glVertex3f( 0.0, 0.6, 0.0);
glVertex3f( -0.2, -0.3, 0.0);
glVertex3f( 0.2, -0.3 ,0.0);
}
glEnd();
// finish drawing
glFlush();
}
#end
And the 'Polygon' class I would like to draw in this method so I can refer to the stored vertices easily..
-(void)drawPolygon
{
// draw vertices
}
If you call your draw() function from the context of the screen draw in opengl you should be okay. That means your draw() will have to still call the opengl appropriate draw calls of course.
I'm unfamiliar with opengl on objective-c but you can probably just pass the drawing context to the draw() function and have it call drawRect that way.
I have two arrays that I declared on the stack in a function, and verified that they both contain the exact same data:
/// Rasters the textured quad using the specified parameters.
- (void)privateConfigureRasterWithTexture:(GLuint)theTexture
bottomLeftX:(GLfloat)bottomLeftX
bottomLeftY:(GLfloat)bottomLeftY
topRightX:(GLfloat)topRightX
topRightY:(GLfloat)topRightY
{
const GLfloat texices[] =
{ bottomLeftX, bottomLeftY, // bottom left corner
bottomLeftX, topRightY, // top left corner
topRightX, topRightY, // top right corner
topRightX, bottomLeftY }; // bottom right corner
const GLfloat texices2[] =
{ 0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f };
for(int x=0;x<8;x++)
if(texices[x] != texices2[x])
{
NSLog(#"Mismatch!");
abort();
}
When I execute the following line of code in (the bottom of) that function
glVertexAttribPointer(_attributeTexturedTexCoords, 2, GL_FLOAT, GL_FALSE,
2*sizeof(GLfloat), texices2);
I get the expected result, however if I instead execute
glVertexAttribPointer(_attributeTexturedTexCoords, 2, GL_FLOAT, GL_FALSE,
2*sizeof(GLfloat), texices);
I get a bad result. I don't get what the difference is.
Edit: Here is how I'm invoking this function.
[self privateConfigureRasterWithTexture:_atlasTexture1
bottomLeftX:0.0f
bottomLeftY:0.0f
topRightX:1.0f
topRightY:1.0f];
Nevermind, I think I've found it (probably at around the exact same time Martins did). It looks like glVertexAttribPointer doesn't make a copy of the data until the call to glDrawElements. Since my glDrawElements is outside of that function, the stack memory was being released (yet for some reason texices2 remained valid).
I've rewritten the code a bit so that texices is heap allocated once when that class is allocated, and just reused over and over again and free'd when the application deallocs.
I want to draw cubes using textures.
void OperateWithMainMatrix(ESContext* esContext, GLfloat offsetX, GLfloat offsetY, GLfloat offsetZ) {
UserData *userData = (UserData*) esContext->userData;
ESMatrix modelview;
ESMatrix perspective;
//Manipulation with matrix
...
glVertexAttribPointer(userData->positionLoc, 3, GL_FLOAT, GL_FALSE, 0, cubeFaces);
//in cubeFaces coordinates verticles cube
glVertexAttribPointer(userData->normalLoc, 3, GL_FLOAT, GL_FALSE, 0, cubeFaces);
//for normals (use in fragment shaider for textures)
glEnableVertexAttribArray(userData->positionLoc);
glEnableVertexAttribArray(userData->normalLoc);
// Load the MVP matrix
glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE,
(GLfloat*)&userData->mvpMatrix.m[0][0]);
//Bind base map
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, userData->baseMapTexId);
//Set the base map sampler to texture unit to 0
glUniform1i(userData->baseMapLoc, 0);
// Draw the cube
glDrawArrays(GL_TRIANGLES, 0, 36);
}
(coordinates transformation is in OperateWithMainMatrix() )
Then Draw() function is called:
void Draw(ESContext *esContext)
{
UserData *userData = esContext->userData;
// Set the viewport
glViewport(0, 0, esContext->width, esContext->height);
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(userData->programObject);
OperateWithMainMatrix(esContext, 0.0f, 0.0f, 0.0f);
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}
This work fine, but if I try to draw multiple cubes (next code for example):
void Draw(ESContext *esContext)
{ ...
// Use the program object
glUseProgram(userData->programObject);
OperateWithMainMatrix(esContext, 2.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, 1.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, 0.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, -1.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, -2.0f, 0.0f, 0.0f);
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}
A side faces overlapes frontal face. This process is illustrated on image:
Alternate picture (with colours and clean image):
The side face of the right cube overlaps frontal face of the center cube.
How can i remove this effect and display miltiple cubes without it?
To fix this you need to utilize what's known as the depth buffer. This is what's responsible for making sure that surfaces don't get drawn overtop of surfaces that are nearer (like the side of a cube showing over the front of a cube).
Luckily it's not much work involved to do so:
Enable depth testing at initialization with glEnable(GL_DEPTH_TEST)
Clear depth buffer on each frame by adding it's bit to the glClear call:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
After this you should no longer see your surfaces popping on top of nearer surfaces.