Drawing graphics and OpenGL

Started by Wiggyboy, January 17, 2014, 16:45:22

Previous topic - Next topic

Wiggyboy

Hey, I'm currently developing a similiar game to minecraft to learn more about 3D graphics and OpenGL.

I've been looking around for some tutorials and some guides onto gettings started and so far I've got a a working camera that moves as I please and displays 2 objects. However I've got some questions and some things that I'm not 100% sure of. Since you're API is completely empty of actual information I'm posting here in hope to find my answers.

1. What does "GL11.glLoadIdentity();" actual do? from my understanding it just resets your position to the origin?.
But if you look at my code here:
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

public class Camera {
	public static void main(String[] args) {
		Camera cam = new Camera(0.0f, 0.0f, 0.0f);
		
		cam.createWindow();
		cam.initGL();
		
		float dx;
		float dy;
		float dt;
		float time;
		float lastTime = 0.0f;
		
		float mouseSensitivity = 0.15f;
		float movementSpeed = 10.0f;
		
		Mouse.setGrabbed(true);
		while(!closeRequest) {
			cam.renderGL();
			Display.update();
			
			time = Sys.getTime();
			dt = (time - lastTime)/1000.0f;
			lastTime = time;
			
			dx = Mouse.getDX();
			dy = Mouse.getDY();
			
			cam.yaw(dx * mouseSensitivity);
			cam.pitch(dy * mouseSensitivity);
			
			//Movement
			if(Keyboard.isKeyDown(Keyboard.KEY_W)) {
				cam.moveForward(dt * movementSpeed);
			}
			if(Keyboard.isKeyDown(Keyboard.KEY_D)) {
				cam.moveRight(dt * movementSpeed);
			}
			if(Keyboard.isKeyDown(Keyboard.KEY_A)) {
				cam.moveLeft(dt * movementSpeed);
			}
			if(Keyboard.isKeyDown(Keyboard.KEY_S)) {
				cam.moveBackwards(dt * movementSpeed);
			}
			if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
				cam.moveUp(dt * movementSpeed);
			}
			if(Keyboard.isKeyDown(Keyboard.KEY_X)) {
				cam.moveDown(dt * movementSpeed);
			}
			cam.pollInput();
			
			GL11.glLoadIdentity();
			cam.lookThrough();
		}
		
		cam.cleanUp();
	}
	// STATIC Variables

	// STATIC Methods

	// Variables
	public static boolean closeRequest = false;
	
	private float x = 0;
	private float y = 0;
	private float z = 0;
	
	private float yaw = 0;
	private float pitch = 0;
	
	// Constructors
	public Camera(float x, float y, float z) {
		move(x, y, z);
	}
	private void initGL() {
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GLU.gluPerspective(45.0f,(1280.0f)/((float)720.0f),0.1f,100.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glLoadIdentity();
		
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glShadeModel(GL11.GL_SMOOTH);
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		GL11.glClearDepth(1.0f);
		GL11.glEnable(GL11.GL_DEPTH_TEST);
		GL11.glDepthFunc(GL11.GL_LEQUAL);
		GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
	}

	// Setters
	public void yaw(float amount) {
		yaw += amount;
	}
	public void pitch(float amount) {
		pitch -= amount;
	}
	
	public void move(float x, float y, float z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}
	public void moveForward(float distance) {
            x -= distance * (float) Math.sin(Math.toRadians(yaw));
            z += distance * (float) Math.cos(Math.toRadians(yaw));
	}
	public void moveRight(float distance) {
            x -= distance * (float) Math.sin(Math.toRadians(yaw+90));
            z += distance * (float) Math.cos(Math.toRadians(yaw+90));
	}
	public void moveLeft(float distance) {
            x -= distance * (float) Math.sin(Math.toRadians(yaw-90));
            z += distance * (float) Math.cos(Math.toRadians(yaw-90));
	}
	public void moveBackwards(float distance) {
            x += distance * (float) Math.sin(Math.toRadians(yaw));
            z -= distance * (float) Math.cos(Math.toRadians(yaw));
	}
	public void moveUp(float distance) {
		y -= distance;
	}
	public void moveDown(float distance) {
		y += distance;
	}

	// Getters

	// Adders

	// Removers

	// Others Methods
	public void lookThrough() {
        GL11.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
        GL11.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
        GL11.glTranslatef(x, y, z);
	}

	// Implementation Methods

	// Internal Classes
	
	public void pollInput() {
		while (Keyboard.next()) {
			if (Keyboard.getEventKeyState()) {
				if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
					
				}
			}
		}
	}
	
	public void renderGL() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		
		GL11.glTranslatef(-1.5f, 0.0f, -6.0f); // Move Left And Into The Screen
		GL11.glRotatef(0.0f, 0.0f, 1.0f, 0.0f); // Rotate The Pyramid On It's Y Axis

		GL11.glBegin(GL11.GL_TRIANGLES); // Start Drawing The Pyramid
		GL11.glColor3f(1.0f, 0.0f, 0.0f); // Red
		GL11.glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Green
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Left Of Triangle (Front)
		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Blue
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Right Of Triangle (Front)

		GL11.glColor3f(1.0f, 0.0f, 0.0f); // Red
		GL11.glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Blue
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Left Of Triangle (Right)
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Green
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Right Of Triangle (Right)

		GL11.glColor3f(1.0f, 0.0f, 0.0f); // Red
		GL11.glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Green
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Left Of Triangle (Back)
		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Blue
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Right Of Triangle (Back)

		GL11.glColor3f(1.0f, 0.0f, 0.0f); // Red
		GL11.glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Blue
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Left Of Triangle (Left)
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Green
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Right Of Triangle (Left)
		GL11.glEnd();
		
		GL11.glBegin(GL11.GL_QUADS);
		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Blue
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Top Right Of The Quad (Bottom)
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Green
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Top Left Of The Quad (Bottom)
		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Blue
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Bottom)
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Green
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Bottom)
		
		GL11.glEnd(); // Done Drawing The Pyramid
		
		//GL11.glLoadIdentity(); //If this is enabled the Cube is stays static to the camera.
		GL11.glTranslatef(1.5f, 0.0f, -6.0f); // Move Right And Into The Screen
		GL11.glRotatef(0.0f, 1.0f, 1.0f, 1.0f); // Rotate The Cube On X, Y & Z

		GL11.glBegin(GL11.GL_QUADS); // Start Drawing The Cube
		GL11.glColor3f(0.0f, 1.0f, 0.0f); // Set The Color To Green
		GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Top)
		GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Top)
		GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
		GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)

		GL11.glColor3f(1.0f, 0.5f, 0.0f); // Set The Color To Orange
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Top Right Of The Quad (Bottom)
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Top Left Of The Quad (Bottom)
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Bottom)
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Bottom)

		GL11.glColor3f(1.0f, 0.0f, 0.0f); // Set The Color To Red
		GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
		GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Front)
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Front)

		GL11.glColor3f(1.0f, 1.0f, 0.0f); // Set The Color To Yellow
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Back)
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Back)
		GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Back)
		GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Back)

		GL11.glColor3f(0.0f, 0.0f, 1.0f); // Set The Color To Blue
		GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
		GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Left)
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Left)
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Left)

		GL11.glColor3f(1.0f, 0.0f, 1.0f); // Set The Color To Violet
		GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Right)
		GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Right)
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Right)
		GL11.glEnd(); // Done Drawing The Quad
	}
	public void createWindow() {
		try {
			DisplayMode[] modes = Display.getAvailableDisplayModes();
			
			for (DisplayMode displayMode : modes) {
				if(displayMode.getWidth() == 1280 && displayMode.getHeight() == 720) {
					Display.setDisplayMode(displayMode);
					Display.setFullscreen(false);
					Display.setTitle("What's up!");
					Display.create();
					break;
				}
			}
		} catch (LWJGLException e) {
			Sys.alert("Error", "Initialization failed!\n\n" + e.getMessage());
			System.exit(0);
		}
	}
	public void cleanUp() {
		Display.destroy();
		System.exit(0);
	}

}


At line 213 where I run this command. However when I run it, the cube gets stuck to the camera, in front of me weather how I move. If I don't have that line of code, everything is good. So I'm abit confused?

2. Since I'm developing something similiar to minecraft I'm going to draw ALOT of cubes, now that would require alot of proccessing so I'd like to only draw the ones that are actually visible right?. So I don't wanna draw cubes behind me, or to far away from me, or if they're just simply out of my view. I thought OpenGL handled all those things itself, but from my experience I've been losing FPS when drawing alot of cubes weather I'm looking at them or not, weather I'm a mile away or not. Suggesting OpenGL does NOT handle this, is this correct or have I got it wrong?.

Thanks in advance, and please use a fairly simple and not to complex english. Thank you.

quew8

1) The reason the javadocs have no descriptions of those functions is that they are simply bindings to OpenGL functions. Putting in the documentation for all of those functions would be a lot of work (although that is exactly what is happening when LWJGL 3.0 is finished). You can read up on the individual OpenGL functions here: http://www.opengl.org/sdk/docs/man4/. Bookmark that, you will find it hugely useful.

What glLoadIdentity() actually does: you are essentially right. It's a little more complicated in reality but the outcome should be just that. The code sections here don't have line numbers and I'm afraid I'm not going to count 200 lines into it so I can't say specifically why it isn't doing what you expected at line 213.

2) OpenGL does handle this in the sense that you can't see the cubes that are behind you or too far away. But the act of testing whether or not to draw these cubes still takes up time. If OpenGL was to actually draw them then it would take even longer but it must still process the information to work out whether or not it should. To implement this test yourself (and you should see performance increases) look into "frustum culling."

Hope I've helped. Also hope I haven't used too complex English but as a native speaker I'm not entirely sure what a non-native speaker would consider more complex. But I tried.

Wiggyboy

Thank you,

I'll sum it up, I make a display, I initGL etc, then I renderGL, I lookThrough the camera and I Display.update();
During this time I only run GL11.glLoadIdentity(); once, and that's inside the lookThrough method, If I run this anywhere in the renderGL(); everything rendered after taht will be stuck to my screen/camera.

2. If openGL does this themselves, should I bother trying to figure out myself which cubes are displaying and which are not or should I just let openGL do it?.
3. Does openGL also handle things like, Backface culling? or do I have to do that myself too?.

Thank you again, and no you're english is just fine :)

Cornix

1) LoadIdentity loads a matrix with only 1's into the matrix that is currently active. If you use that matrix to represent your camera then it will "reset" your camera if you want to call it that.
But the matrix can be used for almost anything; its completely up to you how to use it.
In modern openGL the loadIdentity function is deprecated as it still assumes fixed functionality pipeline. Nowadays you are supposed to define your own matrices and change their data on your own.

2) OpenGL has some functionality to discard rendering data. First of all you can define face culling and cull the back faces of your geometry. This would cut down rasterization by a good portion.
Then you can define scissor / stencil tests to not draw certain fragments on screen. If used correctly this could also cut down the performance needed for rendering.
And lastly you can always try to clip some of the blocks yourself and put some more work on the CPU instead of on the GPU. Whether this is worth it or not is to be decided by you.


The bad performance probably comes from drawing everything with immediate mode. That is glBegin(...); glEnd();
This is a very old technique that is a real performance killer and not supported on almost any hardware anymore. If you want to improve performance greatly (about 500 times on my computer) you should learn how to use VBO's, especially for static data that changes only rarely.