How can I correctly figure out what values I must use for gl.glTranslatef(x,y,z), and similar methods. Example: I've got an square, and want to display it in the upper left corner, at about 1/4th of the screen. I figured it would be glTranslate() with values -0.5 and 0.5, but this doens't display where I expected it.
So basically I wan't to know how to find the right coordinates for objects in OpenGL-ES.
Unfortunately haven't developed opengl-es content for android yet, but AFAIK you need to convert screen coordinates (e.g. upper left corner on your screen) to world coordinates(coordinates in your 3D world in OpenGL).
For 3D you could do this would be through ray projection. You will find plenty of examples through google search and maybe a OpenGL implementation too.
For 2D you can get away bit using an orthogonal projection matrix(with no perspective distortion basically) and rotating it as needed (e.g. for lanscape mode):
// Initialize your projection matrix - current number are half the dimensions for the G1 I borrowed(320x480)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-240.0f, 240.0f, -160.0f, 160.0f, -1.0f, 1.0f);
// Rotate everything by 90 degrees
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
HTH
Related
I am currently working on implementing lighting to my project with OpenGL. Still working on the basic implementation (getting lights to display correctly) and I encountered a weird problem. When trying to create a spotlight with a cutoff (limited angle affected by the light) I get very hard edges, almost like stairs, as seen in this picture:
There is no ambient light (using glLightModel(GL_LIGHT_MODEL_AMBIENT, colorToFloatBuffer(new Color(0.0f, 0.0f, 0.0f, 1.0f)))) and I also disabled spot exponent (specifies how the light is distributed in the cone) and all attenuations to make the effect clearer and the background is a big white image (made black by the lack of ambient light; I am also wondering why I even need ot use an image at all in order to see the light).
Here is how I set up the light:
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glLight(glLightID, GL_AMBIENT, colorToFloatBuffer(Color.blue));
glLight(glLightID, GL_DIFFUSE, colorToFloatBuffer(Color.black));
glLight(glLightID, GL_SPECULAR, colorToFloatBuffer(Color.black));
glLight(glLightID, GL_POSITION, floatBuffer.put(position.x).put(position.y).put(0.0f).put(1.0f));
glLight(glLightID, GL_SPOT_DIRECTION, otherFloatBuffer.put(1.0f, 0.0f, 0.0f));
glLightf(glLightID, GL_SPOT_EXPONENT, 0);
glLightf(glLightID, GL_SPOT_CUTOFF, 22.5f);
glLightf(glLightID, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf(glLightID, GL_LINEAR_ATTENUATION, 0.0f);
glLightf(glLightID, GL_QUADRATIC_ATTENUATION, 0.0f);
On a different note, I also scale the context before applying any of these effects (I use perspective view for some visual effects and yet want to maintain orthographic coordinates), if that is any help.
There are to ways you can achieve that:
Continue using per-vertex lighting. You, however, should increase the resolution of your scene - put more polygons inside!
Change to per-pixel lighting. You will need to learn shader programs. Here are some tutorials on the topic.
I'm rendering a simple rectangle mesh using libgdx, and other geometric elements that are similar in simplicity. Therse are going to interact with the sprites I have setup in my game. The sprites' position and other properties are setup in world units and before each sprite draw session I setup the camera like this:
camera.update();
batch.setProjectionMatrix(camera.combined);
It all works well but I need to draw meshes using world units. How can I feed the shader program world coordinates(12.5f, 30f, etc, based on my game world data) instead of (0f, 1f) ranges? I want to draw several textured meshes so I need coordinates that are in relation with the other elements in the game.
Here is how I draw a simple rectangle mesh :
mesh = new Mesh(true, 4, 6,
new VertexAttribute(Usage.Position, 3, "a_position"),
new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"));
mesh.setVertices(new float[] {
-1.0f, -1.0f, 0, 0,1,
0.0f, -1.0f, 0,1,1,
0.0f, 0.0f, 0, 1,0,
-1.0f, 0.0f, 0, 0,0 });
mesh.setIndices(new short[] { 0, 1, 2, 2, 3, 0});
Gdx.graphics.getGL20().glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE);
createShader();
shader.begin();
mesh.render(shader, GL20.GL_TRIANGLES);
shader.end();
Is there any way I can feed world units to the mesh vertices array ?
You can transform the vertices in the vertex shader. This allows you to project world coordinates onto the -1 to 1 range required for rendering. This is typically done by multiplying the position vertex attribute with a (projection) matrix. Have a look at the default spritebatch shader, for an example of how to implement this.
You can use the camera.combined matrix to multiply these vertices in vertex shader. Just like you did when specifying the projection matrix for the spritebatch. You'll have to assign this matrix to the uniform you've used in your vertex shader. An example of how to do this can also be found in default spritebatch implementation.
However, you might want to reconsider your approach. Since you're using a spritebatch, you can profit from a performance gain by using the spritebatch instead of manually rendering. This will also simplify the rendering for you, because you dont have to mess with the shader and matrices yourself. Spritebatch contains a method (javadoc) which allows you to specify a manually created mesh (or vertices actually). Each vertex is expected to be 5 floats (x, y, u, v, color) in size and a multiple of four vertices (doesn't have to be a rectangle shape though) must provided (you can use Color.WHITE.toFloatBits() for the color).
But, since you're trying to render a simple rectangle, you might as well use one of the more convenient methods that allows you to render a rectangle without having to create a mesh all together (javadocs). Or, even easier, use it how it is designed by creating a Sprite for your rectangle (wiki page).
Now, if you're still certain that you do want to create a mesh and shader manually, then I'd suggest learning that using e.g. a tutorial, instead of just diving into it. E.g. these tutorials might help you get started. The wiki also contains an article describing how to do this, including transforming vertices in the vertex shader.
I am writing a voxel engine and at the moment
I am working on the Chunk-Rendering-System but I have a problem.
It seems that the textures were repeated on the quads.
There is this green line at the bottom of the grass blocks and I don't know why.
This is the OpenGL-Render-Code:
Texture texture = TextureManager.getTexture(block.getTextureNameForSide(Direction.UP));
texture.bind();
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2d(0, 0); GL11.glVertex3f(0, 1, 0);
GL11.glTexCoord2d(1, 0); GL11.glVertex3f(0, 1, 1);
GL11.glTexCoord2d(1, 1); GL11.glVertex3f(1, 1, 1);
GL11.glTexCoord2d(0, 1); GL11.glVertex3f(1, 1, 0);
GL11.glEnd();
And here is the OpenGL-Setup:
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glClearColor(0.1F, 0.4F, 0.6F, 0F);
GL11.glClearDepth(1F);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
GL11.glCullFace(GL11.GL_BACK);
GL11.glEnable(GL11.GL_CULL_FACE);
Make sure GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T are set to GL_CLAMP_TO_EDGE.
genpfault's answer should do the trick for you, I just wanted to give you some insight into why you need this particular wrap state.
To be clear, the green line in your screenshot corresponds to the edges of one of your voxels?
It looks like you are using GL_LINEAR filtering (default) together with an inappropriate texture wrap state (e.g. GL_REPEAT or GL_CLAMP). I will explain why GL_CLAMP is a bad idea later.
You may think that the texture coordinate 0.0 and 1.0 are perfectly within the normalized texture coordinate range and therefore not subject to wrapping, but you would be wrong.
This particular combination of states will pickup texels from the other side of your texture at either extreme of the [0,1] texture coordinate range. The texture coordinate 1.0 is actually slightly beyond the center of the last texel in your texture, so when GL fetches the 4 nearest texels for linear filtering, it wraps around to the other side of the texture for at least 2 of them.
GL_CLAMP_TO_EDGE modifies this behavior, it clamps the texture coordinates to a range that is actually more restrictive than [0,1] so that no coordinate goes beyond the center of any edge texels in your texture. Linear filtering will not pickup texels from the other side of your texture with this set. You could also (mostly) fix this by using GL_NEAREST filtering, but that will result in a lot of texture aliasing.
It is also possible that you are using GL_CLAMP, which, by the way was removed in OpenGL 3.1. In older versions of GL it was designed to clamp the coordinates into the range [0,1] and then if linear filtering tried to fetch a texel beyond the edge it would use a special set of border texels rather than wrapping around. Border texels are no longer supported, and thus that wrap mode is gone.
The bottom line is do not use GL_CLAMP, it does not do what most people think. GL_CLAMP_TO_EDGE is almost always what you really want when you think of clamping textures.
EDIT:
genpfault brings up a good point; this would be a lot easier to understand with a diagram...
The following diagram illustrates the problem in 1 dimension:
http://i.msdn.microsoft.com/dynimg/IC83860.gif
I have a more thorough explanation of this diagram in an answer I wrote to a similar issue.
In JOGL im trying to create a few 3D shapes using GL_QUADS (i.e. different components of a whole object) and so far its been fine to do this but I cant figure out how to translate the shape, there must be a way to do this but im not very familiar with GL_QUADS so im not entirely sure how to go about this. Editing gl.glVertex3f just results in the shape being a different size which seems to be the only thing I can edit, is it possible to give a GL_QUAD a variable name?
You can use the glTranslatef function:
// render the shape
gl.glTranslatef(5.0f, 0.0f, 0.0f); // translate along x, y, z
// render the shape - you will now have two shapes next to each other
Calling gl.glTranslatef(1.0f, 0.0f, 0.0f); will apply to the current matrix in the stack, effectively meaning that whatever you draw from then on will appear 1 unit along on the x axis from whatever the matrix was on before (probably the origin in your case).
I can see why it might seem confusing, rather than creating the shape then moving it (can't be done, it's already been drawn), you'll want to translate then draw your shape.
For example:
gl.glPushMatrix();
gl.glTranslatef(1.0f, 0.0f, 0.0f);
gl.glBegin(GL2.GL_QUADS);
// draw some vertices here
gl.glEnd();
gl.glPopMatrix();
I've already checked the other questions on this topic and their solutions haven't worked for me. I'm at a bit of a loss. I have the following functions in my GLEventListener implementation.
public void init(GLAutoDrawable gl) {
GL2 gl2 = gl.getGL().getGL2();
gl2.glMatrixMode(GL2.GL_PROJECTION);
gl2.glLoadIdentity();
GLU glu = GLU.createGLU(gl2);
glu.gluPerspective(45.0f, 1, 0.1f,100.0f);
gl2.glMatrixMode(GL2.GL_MODELVIEW);
gl2.glLoadIdentity();
gl2.glViewport(0, 0, width, height);
gl2.glEnable(GL.GL_DEPTH_TEST);
}
private void render(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
GLU glu = GLU.createGLU(gl);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(5, 0, 20,
0, 30, 0,
0, 1, 0);
gl2.glPushMatrix();
gl2.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
gl2.glLoadIdentity();
gl2.glTranslatef(x, y, z);
gl2.glBegin( GL2.GL_QUADS );
gl2.glColor3f( 1, 0, 0 );
//24 glVertex3f calls & some colour changes go here.
gl2.glVertex3f(...)
gl2.glEnd();
gl2.glPopMatrix();
gl.glFlush();
}
It doesn't matter what values I put into the gluLookAt() matrix, the view doesn't change. I still end up looking at the same face of a cube.
Any ideas?
Thanks
EDIT: Responding to the edit in the original question. Leaving the original text below because people seem to find it to be useful.
I think your problem is in your cube drawing code. Check the commentary below: the glLoadIdentity call is doing exactly what you would expect - forcing the cube to be there in front of you:
gl2.glPushMatrix();
gl2.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
/** Try removing the following glLoadIdentity call below.
* That call was blowing out the MODELVIEW matrix - it's removing your
* gluLookAt call and returning to the identity.
* As a result, the cube will always be right there in front of you.
*/
// gl2.glLoadIdentity();
gl2.glTranslatef(x, y, z);
gl2.glBegin( GL2.GL_QUADS );
gl2.glColor3f( 1, 0, 0 ); //24 glVertex3f calls & some colour changes go here.
gl2.glVertex3f(...)
gl2.glEnd();
gl2.glPopMatrix();
Here's a very quick explanation about what the related calls will do. See the documentation for more information:
gl2.glPushMatrix(); // This preserves current MODEL_VIEW matrix so you can get back here.
// Think of it as a checkpoint save in a game.
// Most of your objects will be wrapped in push and pop.
gl2.glLoadIdentity(); // This erases the MODEL_VIEW and replaces it with an identity.
// This un-does your previous gluLookAt call. You will rarely use
// this inside an object (but it's not impossible).
// Does not apply here so don't use.
gl2.glTranslatef(x, y, z); // This is what puts your object out in space for you to find
// as opposed to putting it at the origin. Most objects will
// have a translate (and likely a rotate as well).
// Note that the order of operations matters:
// translate and then rotate != rotate and then translate.
// QUAD strip code with vertices and colors - you're okay with these.
gl2.glPopMatrix(); // This brings back the MODEL_VIEW that you originally saved by pushing
// it.
The great thing about the matrix code in OpenGL is that once you get a portfolio of example code that you understand, you'll always have it as a reference. When I switched from IrisGL to OpenGL back in the day, it took me a little while to port my utilities over and then I never looked back.
ORIGINAL: You need to add your cube drawing code - if you are putting the cube in the vicinity of (0, 30, 0), it's highly likely that the code is doing what you asked it to.
Checking the OpenGL FAQ, there's a specific question and answer that is likely relevant to what you're doing: 8.080 Why doesn't gluLookAt work? I'm going to quote the whole answer as there really isn't a good break but please visit the OpenGL FAQ, the answer is likely there:
This is usually caused by incorrect
transformations.
Assuming you are using
gluPerspective() on the Projection
matrix stack with zNear and zFar as
the third and fourth parameters, you
need to set gluLookAt on the ModelView
matrix stack, and pass parameters so
your geometry falls between zNear and
zFar.
It's usually best to experiment with a
simple piece of code when you're
trying to understand viewing
transformations. Let's say you are
trying to look at a unit sphere
centered on the origin. You'll want to
set up your transformations as
follows:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.0, 1.0, 3.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
It's important to note how the Projection
and ModelView transforms work
together.
In this example, the Projection
transform sets up a 50.0-degree field
of view, with an aspect ratio of 1.0.
The zNear clipping plane is 3.0 units
in front of the eye, and the zFar
clipping plane is 7.0 units in front
of the eye. This leaves a Z volume
distance of 4.0 units, ample room for
a unit sphere.
The ModelView transform sets the eye
position at (0.0, 0.0, 5.0), and the
look-at point is the origin in the
center of our unit sphere. Note that
the eye position is 5.0 units away
from the look at point. This is
important, because a distance of 5.0
units in front of the eye is in the
middle of the Z volume that the
Projection transform defines. If the
gluLookAt() call had placed the eye at
(0.0, 0.0, 1.0), it would produce a
distance of 1.0 to the origin. This
isn't long enough to include the
sphere in the view volume, and it
would be clipped by the zNear clipping
plane.
Similarly, if you place the eye at
(0.0, 0.0, 10.0), the distance of 10.0
to the look at point will result in
the unit sphere being 10.0 units away
from the eye and far behind the zFar
clipping plane placed at 7.0 units.
If this has confused you, read up on
transformations in the OpenGL red book
or OpenGL Specification. After you
understand object coordinate space,
eye coordinate space, and clip
coordinate space, the above should
become clear. Also, experiment with
small test programs. If you're having
trouble getting the correct transforms
in your main application project, it
can be educational to write a small
piece of code that tries to reproduce
the problem with simpler geometry.