I'm trying to have the contents of my display resize when the window is resized. Here's my code:
if (Display.wasResized()) {
this.width = Display.getWidth();
this.height = Display.getHeight();
GL11.glViewport(0, 0, this.width, this.height);
GL11.glLoadIdentity();
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0.0f, this.width, 0.0f, this.height, 1.0f, -1.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
}
When I use this, the window's content don't resize, it just moves towards the origin. Is there any way to make the contents actually resize?
Redraw the scene. OpenGL is not a scene graph. It's "merely" the pencil with which you draw on the paper provided by the OS. Once you've drawn something, OpenGL doesn't remember it.
BTW: You should neither set the viewport size nor the projection matrix in the window resize handler. You do that as preparations in the drawing function, just like clearing the framebuffer.
Related
I have made a simple application in lwjgl and created simple gui. For now I have frame and panel. But there is a problem.
Because (Display 800x600) when I make panel on Panel(x,y,w,h) (0,0,64,64) everything works fine, but when I create it on other position (x,y where point 0,0 is in left upeper corner) it render moved panel.
The white space is my panel which should change color when I drag mouse on it. It is created on (417,417,64,64), but it's rendered on somethink like (90,90).
I have rendered fonts to show all of itss positions. The blue box I draw on this image is where it should be and it looks like there the panel is, because the white space is changing color when I drag mouse there, but this white space should be there.
My code looks like that:
I am adding all components to HashMap like Panels.
glColor3f(backgroundColor.getRed(), backgroundColor.getGreen(),
backgroundColor.getBlue());
if (hasFocus()) {
glColor3f(1f, 0f, 0f);
}
glPushMatrix();
glRecti(getX(), getY(), getWidth(), getHeight());
glPopMatrix();
And initGL method:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glScalef(1.0f, 1.0f, 1.0f);
glOrtho(0, 800, 600, 0, 1, -1);
glFrustum(-1, 1, -1, 1, 0.0, 40.0);
glViewport(0, 0, Display.getWidth(), Display.getHeight());
glMatrixMode(GL_MODELVIEW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
glRecti doesn't work that way it expects the coordinates of the corners
so instead you should do:
glRecti(getX(), getY(), getX()+getWidth(), getY()+getHeight());
I'm quite new to OpenGL ES and I'm trying to draw some textured quads. I want to keep it 2D so I decided to use orthographic projection. What I really want is to draw a plane that takes the same relative amount of screen space on every device regardless the screen resolution.
The problem I encounter is the setup of the orthographic projection. The aspect ratio just isn't correct. A square is drawn as a rectangle in the height. This is my code so far:
The Renderer:
// automatically looped by android
public void onDrawFrame(GL10 gl) {
// clear screen and buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Draw elements
for (GameObject object : level.getGameObjects()) {
gl.glScalef(0.2f, 0.2f, 0.0f);
object.draw(gl);
gl.glLoadIdentity();
}
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glOrthof(0f, 480f, 0f, 800f, -1f, 1f);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Load all textures
for (GameObject object : level.getGameObjects()) {
object.bindTexture(gl);
}
// Initialize game canvas
gl.glEnable(GL10.GL_TEXTURE_2D); // Enable Texture Mapping
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black background
// enable texture transparency
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
}
The draw method is exactly the same as in this tutorial: http://obviam.net/index.php/texture-mapping-opengl-android-displaying-images-using-opengl-and-squares/
Kind regards,
Daan
Why are you hardcoding the width and height to glOrthof? Shouldn't you use the passed in width and height?
gl.glOrthof(0f, width, 0f, height, -1f, 1f);
I have found the answer to my problem. First of all I was hardcoding the width and height wich wasn't a good option. To have a fixed with on all screen resolutions i now calculate the aspect ratio and for the height I use the with multiplied by the aspect ratio.
Another problem was the fact that I hadn't reset the projection matrix prior to setting the glortho. I have changed all this and it solved the problem:
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0f, 320, 0f, 320*aspect, -1f, 1f);
}
I hope this will be helpfull for somebody.
Kind regards,
Daan
Looks like you've solved it. Can you provide details on how you calculated the aspect variable (a division of height and width perhaps?) Just as an FYI, the height and width values passed in to the onSurfaceChanged() event are indeed dynamic. For instance, they are reversed when you flip the screen orientation.
I'm relatively new to this as well, but in my desktop gl experience, it's important to factor these in when a window size changes.
I'm trying to make a copy of MineCraft in Java using OpenGL (LWJGL). The problem I'm facing is that everything of my 2D overlay (aiming cross in the middle, menus, etc...) are all white. The 3D part of the game works great: every cube has a texture on each side.
But when I try to draw the overlay, as I said, every texture is white, but I can see the shape of it (because it has transparent areas). I'll add a picture of it.
(This is supposed to be the inventory)
As you can see, the overlay is completely white. And it should look like this:
I'm already searching the web for hours. Can't seem to find a solution.
This drives my crazy... I already searched for instructions of how to create a 2D overlay on a 3D scene, but they don't help either. So I though, I'll give StackOverflow a try.
Hopefully someone can help me?
Thanks for reading my question and for the (hopefully coming) answers!
Martijn
Here is the code:
Initialising OpenGL
public void initOpenGL() throws IOException
{
// init OpenGL
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 600, 0, 1, 300);
glMatrixMode(GL_MODELVIEW);
float color = 0.9f;
glClearColor(color, color, color, color);
glEnable(GL_TEXTURE_2D);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_CULL_FACE);
glEnable(GL_FOG);
glFog(GL_FOG_COLOR, MineCraft.wrapDirect(color, color, color, 1.0f));
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, _configuration.getViewingDistance() * 0.8f);
glFogf(GL_FOG_END, _configuration.getViewingDistance());
glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
glHint(GL_FOG_HINT, GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Configuring the matrixes for drawing the overlay (Out of inspiration, I literally copied all the OpenGL calls for this method from BlockMania (another open-source MineCraft copy), which works great)
public void renderOverlay()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
GLU.gluOrtho2D(0, conf.getWidth(), conf.getHeight(), 0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_COLOR_MATERIAL);
glPushMatrix();
glLoadIdentity();
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/** RENDER **/
if (_activatedInventory != null)
{
_activatedInventory.renderInventory();
}
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
Drawing the texture itself:
public void renderInventory()
{
Configuration conf = Game.getInstance().getConfiguration();
glTranslatef(conf.getWidth() / 2.0f, conf.getHeight() / 2.0f, 0.0f);
glEnable(GL_TEXTURE_2D);
Texture tex = TextureStorage.getTexture("gui.inventory");
tex.bind(); // newdawn.slick (same library for my whole program, so this works)
float hw = 170; // half width
float hh = 163; // half height
Vector2f _texPosUpLeft = new Vector2f(3, 0);
Vector2f _texPosDownRight = new Vector2f(_texPosUpLeft.x + hw, _texPosUpLeft.y + hh);
_texPosUpLeft.x /= tex.getTextureWidth();
_texPosUpLeft.y /= tex.getTextureHeight();
_texPosDownRight.x /= tex.getTextureWidth();
_texPosDownRight.y /= tex.getTextureHeight();
glColor3f(1, 1, 1); // Changes this doesn't make any effect
glBegin(GL_QUADS);
glTexCoord2f(_texPosUpLeft.x, _texPosUpLeft.y);
glVertex2f(-hw, -hh);
glTexCoord2f(_texPosDownRight.x, _texPosUpLeft.y);
glVertex2f(hw, -hh);
glTexCoord2f(_texPosDownRight.x, _texPosDownRight.y);
glVertex2f(hw, hh);
glTexCoord2f(_texPosUpLeft.x, _texPosDownRight.y);
glVertex2f(-hw, hh);
glEnd();
}
(The texture pack I'm using is CUBISM1.00)
I found it!!
It was the fog. For one or another reason it looks like it thinks the overlay is out of sight and gives it the color of the fog. So, disabling the fog before rendering the overlay solved it.
glDisable(GL_FOG);
/* Render overlay here */
glEnable(GL_FOG);
If there are still people who read this, is this caused by matrix abuse or is this behaviour normal?
The following code produces the image that follows. The image I am using for the background is 640 x 480, as is the displayMode. The texture background is a .bmp and is loaded with the Slick texture loader. I am confuse to why it is not filling the Quad and why it is reflected.
EDIT: The background of my OpenGL scene is pink, the black you see is from the Quad created. The background image is the green block with a 2px light blue border with "test" plastered on it.
private void renderBackground(){
float w = displayMode.getHeight()/2;
float h = displayMode.getWidth()/2;
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix();
GL11.glLoadIdentity();
GLU.gluOrtho2D(-w, w, -h, h);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPushMatrix();
GL11.glLoadIdentity();
GL11.glDisable(GL11.GL_DEPTH_TEST);
if(useTextures)background.bind();
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f(-w,-h);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex2f(w,-h);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(w, h);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(-w, h);
GL11.glEnd();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPopMatrix();
}
Now when I add GL11.glTranslatef(20.0f, 20.0f, 0.0f); you will notice that the pink appears, which is the colour created int my "initGL" method:
GL11.glClearColor(1.0f, 0.75f, 0.796f, 0.0f);
My GL_PROJECTION contains the following before pushing it, my GL_MODELVIEW is unmodified when renderBackground() is called.
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 25.0f);
//position camera
GLU.gluLookAt(5.0f, 3.0f, -5.0f, 0.0f, 0.0f, -10.0f, 0.0f, 1.0f, 0.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
I need more information to determine the problem, but here is a list with some possibilities.
1) You are using an older video card, which does not support texture non-power of 2, since you are using a library to load the texture, maybe it is detecting it, creating a power of two image, and filling it with black.
2) You (or some library you are using) changed the matrix of the texture matrix stack, and it is changing the texture coordinates.
3) You are doing something wrong when you load the texture (or call the library to do so).
The first thing I would check is if your video card supports texture non-power of 2 extension. You can check it at runtime, see how to detect if openGL/card supports non power of 2?
What I see first, is that you compute
float w = displayMode.getHeight()/2;
float h = displayMode.getWidth()/2;
switched?
Second, the texture could be flipped because the loader flipped it (when I remember right this happened to me, too especially with BMPs).
I am started to deal with OpenGL. My application is written in Java using SWT as windowing system.
Using http://lwjgl.org/ and SWT, I am able to use OpenGL in my SWT canvas. I wrote the following simple OpenGL code in my canvas paint listener:
// clear to background color
GL11.glClearColor(.3f, .5f, .8f, 1.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
// draw rectangle
GL11.glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glBegin(GL11.GL_POLYGON);
GL11.glVertex3f(0.1f, 0.1f, 0.0f);
GL11.glVertex3f(0.1f, 0.9f, 0.0f);
GL11.glVertex3f(0.9f, 0.9f, 0.0f);
GL11.glVertex3f(0.9f, 0.1f, 0.0f);
GL11.glEnd();
GL11.glFlush();
I want know to add a resize listener on my canvas in order to always have my rectangle in the center of the window. How should I do that?
You need to manually set your viewport size by calling glViewport() every time canvas size changes. After that your screen will have dimensions specified by glOrtho().
Also, your matrices are a mess. Projection matrix is used for projection only and modelview for other transformations (rotation, scaling, moving, etc.).
// Viewport (needs to be done on canvas resize only)
GL11.glViewport(0.0, 0.0, // Set viewport size
canvas.getBounds().width,
canvas.getBounds().height);
// Projection (only needs to be set once in most cases)
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select projection matrix
GL11.glLoadIdentity(); // Clear it
GL11.glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); // Set your projection
// model/view transforms
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select modelview matrix
GL11.glLoadIdentity(); // Clear it
// Draw (shortcut)
GL11.glRectf(0.1f, 0.1f, 0.9f, 0.9f);