I am working with LWJGL to make a game. It's very basic. Before even implementing any sort of gpu rendering, or fancy model loaders, I wanted to make sure I could at least render 2D and 3D at the same time; My game has a gui while you walk around. Or at least, it is supposed to. Here is my initialization code; The flickering does not happen when I only render 3D.
public void clearGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
}
public void init3D() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective((float) 68, Engine.size[0] / Engine.size[1], 0.3f, 1000);
glMatrixMode(GL_MODELVIEW);
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);
}
public void render3D(Camera c) {
init3D();
clearGL();
//Do translations here
glTranslatef(0f, -5f, 0f);
glColor3f(0, 1, 0);
glBegin(GL_QUADS);
glVertex3f(-50f, 0f, -50f);
glColor3f(0, 0, 1);
glVertex3f(50f, 0f, -50f);
glColor3f(1, 0, 0);
glVertex3f(50f, 0f, 50f);
glColor3f(0, 1, 1);
glVertex3f(-50f, 0f, 50f);
glEnd();
}
public void init2D() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Engine.size[0], 0, Engine.size[1], -1, 1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
}
public void render2D() {
init2D();
glBegin(GL_QUADS);
glVertex2f(0f, 50f);
glVertex2f(50f, 50f);
glVertex2f(50f, 0f);
glVertex2f(0f, 0f);
glPopMatrix();
}
I can tell its rendering at all because I am drawing a quad to represent the floor in JBullet. For some reason it is above the cameras head, but when I translate the camera up towards it it get's further away, which is why I translated the Camera to -5. That's another problem, for another day.
You should really consider disabling the depth test when you "switch" from 3D to 2D if you are going to draw at Z=0 (middle of your depth range). Half of the visible space in your 3D scene will potentially obstruct your 2D drawing if you do not do this. Alternatively, you could replace your glVertex2f (...) calls with glVertex3f (x,y, -1.0) to bring everything in 2D to the very front of the depth range.
But the really weird thing about all of this is the end of your render2D (...) function: You never call glEnd (...) and you pop a matrix that you appear never to have pushed. That is two sources of mismatched weirdness, either one of them could be causing your problem.
Related
Looking through googles cardboard example I am wondering, where the head movement transformation takes place, so that the scene or the view is adopted to reflect the head movement.
The interesting methods should be public void onNewFrame(HeadTransform headTransform) and public void onDrawEye(Eye eye) in the MainActivity class.
Here is a snippet:
#Override
public void onNewFrame(HeadTransform headTransform) {
// Build the Model part of the ModelView matrix.
Matrix.rotateM(modelCube, 0, TIME_DELTA, 0.5f, 0.5f, 1.0f);
// Build the camera matrix and apply it to the ModelView.
Matrix.setLookAtM(camera, 0, 0.0f, 0.0f, CAMERA_Z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
headTransform.getHeadView(headView, 0);
// Update the 3d audio engine with the most recent head rotation.
headTransform.getQuaternion(headRotation, 0);
cardboardAudioEngine.setHeadRotation(
headRotation[0], headRotation[1], headRotation[2], headRotation[3]);
checkGLError("onReadyToDraw");
}
#Override
public void onDrawEye(Eye eye) {
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
checkGLError("colorParam");
// Apply the eye transformation to the camera.
Matrix.multiplyMM(view, 0, eye.getEyeView(), 0, camera, 0);
// Set the position of the light
Matrix.multiplyMV(lightPosInEyeSpace, 0, view, 0, LIGHT_POS_IN_WORLD_SPACE, 0);
// Build the ModelView and ModelViewProjection matrices
// for calculating cube position and light.
float[] perspective = eye.getPerspective(Z_NEAR, Z_FAR);
Matrix.multiplyMM(modelView, 0, view, 0, modelCube, 0);
Matrix.multiplyMM(modelViewProjection, 0, perspective, 0, modelView, 0);
drawCube();
// Set modelView for the floor, so we draw floor in the correct location
Matrix.multiplyMM(modelView, 0, view, 0, modelFloor, 0);
Matrix.multiplyMM(modelViewProjection, 0, perspective, 0, modelView, 0);
drawFloor();
}
My first assumption was that the model (or camera) is modified in onNewFrame() depending on data from headTransform. But this seems not to be the case as there are only two accesses to it. One to identify at which cube we are looking (headTransform.getHeadView(headView, 0);) and another for the audio engine.
So my next assumption, and only possibility I see, is that it is handled by the eye passed to onDrawEye(). But on the other hand after having a short look inside the disassembly I could not find the relation between headTransform and eye (Which doesn't mean there is no relation, because I haven't invested much time in that).
So my question:
Is my assumption right? Does the rendering take the head movement in account by multiplying the camera with the eyeView?
Well, I spend some more time with browsing the disassembly and it seems as if my assumption was correct.
The private class RendererHelper within CardboardView implements the following method (it is quite large, so I removed what seems not to be important to me):
public void onDrawFrame(GL10 gl)
{
// ...
if (mVRMode)
{
Matrix.setIdentityM(mLeftEyeTranslate, 0);
Matrix.setIdentityM(mRightEyeTranslate, 0);
Matrix.translateM(mLeftEyeTranslate, 0, halfInterpupillaryDistance, 0.0F, 0.0F);
Matrix.translateM(mRightEyeTranslate, 0, -halfInterpupillaryDistance, 0.0F, 0.0F);
Matrix.multiplyMM(mLeftEye.getTransform().getEyeView(), 0, mLeftEyeTranslate, 0, mHeadTransform.getHeadView(), 0);
Matrix.multiplyMM(mRightEye.getTransform().getEyeView(), 0, mRightEyeTranslate, 0, mHeadTransform.getHeadView(), 0);
}
// ...
}
The last two matrix multiplications seem to be the place, where the relation between headTransform and the eye is made.
I am attempting to create a 2D overlay over a 3D scene! I have tried all the solutions I can find on GameDev and StackOverflow, however they have not seemed to work!
My current code:
static void ready3D()
{
glViewport(0, 0, Display.getWidth(),Display.getHeight());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluPerspective(45, (float) Display.getWidth()/Display.getHeight(), 0.1f, 5000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
}
static void ready2D()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluOrtho2D(0.0f, Display.getWidth(), Display.getHeight(), 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375f, 0.375f, 0.0f);
glDisable(GL_DEPTH_TEST);
}
And,
glPushMatrix();
//Overlay start - This is in my render method BTW.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ready2D();
glBegin(GL_QUADS);
glColor3f(1, 1, 1);
glVertex2f(0, 0); // bottom-left
glVertex2f(0, 1); // top-left
glVertex2f(1, 1); // top-right
glVertex2f(1, 0); // bottom-right
glEnd();
glPopMatrix();
ready3D();
However the 2D box thing that I am trying to draw does not draw! Obviously I eventually hope to have complicated objects/icons on an overlay, but first things first.
The 3D world still draws totally fine.
Is anyone able to tell me what I am doing wrong?
The order of the vertices in the 2D quad look a bit suspicious to me, if I'm reading that rightly it's going: bottom-left, top-right, bottom-right, top-left, which results in a sort of cross rather than a quad.
Try this:
glVertex2f(0, 0); // bottom-left
glVertex2f(0, 1); // top-left
glVertex2f(1, 1); // top-right
glVertex2f(1, 0); // bottom-right
Note the clockwise ordering which I believe OpenGL is expecting by default for front-facing quads.
I am trying to render a group of textured quads.
I can get colored quads to render, but not textured ones (screen comes up empty.)
I am using LWJGL and PNGDecoder.
Code for initializing my OGL:
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
Code for decoding my image:
ByteBuffer buffer = null;
InputStream in = ClassLoader.getSystemResourceAsStream(filename);
try {
buffer = decodeStreamToBuffer(in);
} finally {
in.close();
}
return buffer;
My decodeStreamToBuffer(InputStream in):
PNGDecoder decoder;
ByteBuffer buf = null;
try {
decoder = new PNGDecoder(in);
buf = ByteBuffer.allocateDirect(4*decoder.getWidth()*decoder.getHeight());
decoder.decode(buf, decoder.getWidth()*4, Format.RGBA);
buf.flip();
} catch (Exception e) {
e.printStackTrace();
}
return buf;
My rendering code:
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(0.5f, 0.5f, 1.0f); //Still there to test color quads.
// draw quad
GL11.glPushMatrix();
GL11.glTranslatef(screencenter.getX(), screencenter.getY(), 0);
GL11.glScalef(1f, 0.5f, 1f);
GL11.glRotatef(camRotation, 0f, 0f, 1f);
GL11.glTranslatef(-screencenter.getX(), -screencenter.getY(), 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
GL11.glBegin(GL11.GL_TEXTURE_2D);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex2f(32, 0);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(32, 32);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(0, 32);
GL11.glEnd();
GL11.glPopMatrix();
When I leave the texture binding out and change the GL_TEXTURE_2D to GL_MODELVIEW it all works... but with color instead of a texture. Am I making a noob mistake here?
This is wrong GL11.glBegin(GL11.GL_TEXTURE_2D);
The glBegin method an primitive mode GLenum.
Thereby you either use:
GL_POINTS
GL_LINES
GL_LINE_STRIP
GL_LINE_LOOP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
GL_QUADS
GL_QUAD_STRIP
GL_POLYGON
The mode you use specify what you are rendering. In your case you would code GL_QUADS So to fix your code you need to replace GL11.glBegin(GL11.GL_TEXTURE_2D); with GL11.glBegin(GL11.GL_QUADS);.
Extra
Also take in mind that the glVertex, glNormal, glTexCoord, etc. Methods are deprecated and should not be used. You are suppose to use VBOs and Shaders. Though if you are learning OpenGL then keep using the deprecated methods since they are good and easy to use when learning!
I'm trying to rotate one of two objects on the screen. How should I do this? I can only get it to rotate all the objects on the screen.
Code:
glColor3f(1, 0, 0);
glBegin(GL_QUADS);
glVertex3f(0f, 0f, 0f);
glVertex3f(0f, .5f, 0f);
glVertex3f(.5f, .5f, 0f);
glVertex3f(.5f, 0f, 0f);
glEnd();
glRotated(.1, 0f, 1f, 0f);
glRotated(.1, 1f, 0f, 0f);
glRotated(.1, 0f, 0f, 1f);
glBegin(GL_QUADS);
glVertex3f(2f, 0f, 0f);
glVertex3f(2f, .5f, 0f);
glVertex3f(2.5f, .5f, 0f);
glVertex3f(2.5f, 0f, 0f);
glEnd();
code I have so far.
Calling glRotated endlessly without resetting the matrices is a bad idea. Rounding errors will accumulate. You currently don't call glIdentity each frame. Render each frame the following way:
Call glIdentity
Draw the first quad
Rotate
Draw the second quad
The way you render things the rotation difference of the two quads is only 1/10th of a degree on the three axis - which is not noticeable.
Be sure to read up on OpenGL, to learn the current way of OpenGL programming and try to improve your code. It looks as if you don't quite understand what you're doing, no offence.
use glPushMatrix(); before your rotation transforms and glPopMatrix(); after the second quad is rendered then only the second quad will be affected by the rotation transforms.
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?