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);
Related
How i make camera in my lwjgl 3D java application?
I try use glRotate and glTranslatef, but this move only objects, and i need move scene.
Same i try use
glLoadMatrixf(new float[]{
50, 50, 50, 50,
50, 50, 50, 50,
-75, 50, 50, 50,
100, 100, 100, 100
});
But I don’t quite understand how it works, and i see white screen
What solotion i can use for my task?
In OpenGL there is no camera. To "move the camera", you have to move the objects in the opposite direction instead. For example, instead of moving the camera forward, you would move the objects backward.
If you want to make your first view matrix, then start with gluLookAt.
With this handy Legacy OpenGL utility function, you can define a view matrix by a position (eye), a target point (target) and an up vector (up):
(See also Java Code Examples for org.lwjgl.util.glu.GLU.gluLookAt())
GLU.gluLookAt(eye.x, eye.y, eye.z, target.x, target.y, target.z, up.x, up.y, up.z);
The view space is the local system which is defined by the point of view onto the scene.
The position of the view, the line of sight and the upwards direction of the view, define a coordinate system relative to the world coordinate system. The objects of a scene have to be drawn in relation to the view coordinate system, to be "seen" from the viewing position. The inverse matrix of the view coordinate system is named the view matrix. This matrix transforms from world coordinates to view coordinates.
Additionally you well need either an Orthographic or Perspective projection matrix.
The former matrix can be defined by glOrtho
(See also Java Code Examples for org.lwjgl.opengl.GL11.glOrtho())
GL11.glOrtho(0, width, height, 0, 1, -1);
and the later by gluPerspective
(See also Java Code Examples for org.lwjgl.util.glu.GLU.gluPerspective())
GLU.gluPerspective(45.0f, wRatio, (float) near, (float) far);
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space. The coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates.
In legacy OpenGL there exist different current matrices. The projection matrix should be set to the current GL_PROJECTION matrix and the view matrix to the current GL_MODELVIEW matrix. See glMatrixMode.
e.g.:
float width = ...; // width of the window
float height = ...; // height of the window
Vector3f eye = ...; // camera position
Vector3f target = ...; // camera target
Vector3f up = ...; // camera up vector
float ratio = 1.0f * width / height;
GL11.glViewport(0, 0, (int) w, (int) h);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f, ratio , 0.1f, 100.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GLU.gluLookAt(eye.x, eye.y, eye.z, target.x, target.y, target.z, up.x, up.y, up.z);
Instead of GLU.gluPerspective, a perspective projection matrix can be set as follows:
float width = ...; // width of the window
float height = ...; // height of the window
float fov_y = 45.0f; // filed of view in degrees (y axis)
float n = 0.1f; // near plane
float f = 100.0f; // far plane
float a = width / height;
float ta = Math.tan(Math.radians(fov_y) / 2.0f);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
glLoadMatrixf(new float[]{
1.0f/(ta*a), 0.0f, 0.0f, 0.0f,
0.0f, 1.0f/ta, 0.0f, 0.0f,
0.0f, 0.0f, -(f+n)/(f-n), -1.0f,
0.0f, 0.0f, -2.0f*f*n/(f-n), 0.0f
});
Instead of using a GLU.gluLookAt a view matrix can be set by glTranslate and glRoatate:
float distance = 10.0f; // distance to object
float pitch = 0.0f; // pitch in degrees
float yaw = 0.0f; // yaw in degrees
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
GL11.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
GL11.glTranslatef(0.0f, 0.0f, -distance);
just doing some tinkering with lwjgl and making some 2d shapes. Not sure what I'm doing wrong but I'm not able to show more than the first green square on screen. Here is the code for my window loop function:
private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glOrtho(0, vidmode.width(),0, vidmode.height(),-1,1);
// Set the clear color
glClearColor(.0f, 0.6f, 0.6f, 0.0f);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while (!glfwWindowShouldClose(window) && !dataH.isGameOver()) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glBegin(GL_QUADS);
{
glColor3f(0.1f, 1.0f, 0.1f); // Green
glVertex2d(xMapCentre - 100,yMapCentre - 100);
glVertex2d(xMapCentre - 100,yMapCentre + 100);
glVertex2d(xMapCentre + 100,yMapCentre + 100);
glVertex2d(xMapCentre + 100,yMapCentre - 100);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.9f, -0.7f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.5f, -0.7f);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.5f, -0.3f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.9f, -0.3f);
}
glEnd();
glBegin(GL_TRIANGLES); // Each set of 3 vertices form a triangle
{
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.1f, -0.6f);
glVertex2f(0.7f, -0.6f);
glVertex2f(0.4f, -0.1f);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(0.3f, -0.4f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(0.9f, -0.4f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.6f, -0.9f);
}
glEnd();
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
Any help would be appreciated, and let me know if I'm being too vague. Thanks.
Generally, when rendering 2D structures in 3D space, you should disable the back-face culling glDisable(GL_CULL_FACE). Otherwise you can only see them from one side. In your shaders you have to be aware of the normal direction.
In the 2D only case, check for your winding order of the triangles if you want to have back or front face culling, set glFontFace(GL_CCW) or glFrontFace(GL_CW) for counter-clockwise and clockwise winding order respectively. (I cant confirm if the winding order makes a difference in 2D when using glVertex2f)
Also try to diable the depth test and depth write glDisable(GL_DEPTH_TEST) and glDepthMask(GL_FALSE).
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.
I have some cube models and a lantern model in the "world" (with normals) and a light source which is placed in specific coordinates. The problem comes when I try move around the models, position of lightsource changes every frame to viewport position. Here is my initialization part of code, which contain lighting init:
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glClearDepth(1.0f);
GL11.glClearColor(0.0f, 0.75f, 1.0f, 1);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LESS);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
ByteBuffer temp = ByteBuffer.allocateDirect(16);
temp.order(ByteOrder.nativeOrder());
byf = temp;
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_AMBIENT, (FloatBuffer)temp.asFloatBuffer().put(lightAmbient).flip()); // Setup The Ambient Light
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_DIFFUSE, (FloatBuffer)temp.asFloatBuffer().put(lightDiffuse).flip()); // Setup The Diffuse Light
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_POSITION,(FloatBuffer)temp.asFloatBuffer().put(lightPosition).flip()); // Position The Light
GL11.glEnable(GL11.GL_LIGHT1);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glFogi(GL11.GL_FOG_MODE, fogMode[fogfilter]);
temp.asFloatBuffer().put(fogColor).flip();
GL11.glFog(GL11.GL_FOG_COLOR, temp.asFloatBuffer());
GL11.glFogf(GL11.GL_FOG_DENSITY, 0.35f);
GL11.glHint(GL11.GL_FOG_HINT, GL11.GL_DONT_CARE);
GL11.glFogf(GL11.GL_FOG_START, 1.0f);
GL11.glFogf(GL11.GL_FOG_END, 5.0f);
GL11.glEnable(GL11.GL_FOG);
I have seen some similar problems but their solutions didn't help me at all. I know that the problem is with irregular order of setting Matrixes, but I have no idea which one (Matrix) and where I should change.
I tried to place setting Modelview matrix before the init of lighting but it didn't work for me.
By the way, I don't want to set the correct light position every frame, it works for me but it can slow the render.
Your'e probably using a code similar to this or glulookat().
GL11.glTranslatef(Camera.x, Camera.y, Camera.z);
GL11.glRotatef(Camera.roatationz, 0.0f, 0.0f, 1.0f);
GL11.glRotatef(Camera.roatationx, 1.0f, 0.0f, 0.0f);
GL11.glRotatef(Camera.roatationy, 0.0f, 1.0f, 0.0f);
//Render stuff here
Your light has to move as well. :)
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).