I use OpenGL ES 2.0 in order to draw Square objects like from this tutorial:
developer.android.com/training/graphics/opengl/draw.html
and to draw text like from this tutorial:
fractiousg.blogspot.com/2012/04/rendering-text-in-opengl-on-android.html
d1.draw(mMVPMatrix);
d2.draw(mMVPMatrix);
d3.draw(mMVPMatrix);
d4.draw(mMVPMatrix);
p1.draw(mMVPMatrix);
if(punkty>0)
p2.draw(mMVPMatrix);
koala.draw(mMVPMatrix);
punktyString = String.valueOf(punkty);
glText.begin( 1.0f, 1.0f, 1.0f, 1.0f, mVPMatrix );
glText.drawC(punktyString, width/2, height/2);
glText.end(); <i>
To draw square object I use mMVPMatrix. To draw text I use mVPMatrix.
onSurfaceChanged:
float ratio = (float) width / height;
Matrix.frustumM(mProjMatrix, 0, -1, 1, -1 / ratio, 1 / ratio, 1, 10);
int useForOrtho = Math.min(width, height);
//TODO: Is this wrong?
Matrix.orthoM(mVMatrix, 0,
-useForOrtho / 2,
useForOrtho / 2,
-useForOrtho / 2,
useForOrtho / 2, 0.1f, 100f);
Matrix.frustumM(mProjectionMatrix, 0, 1, -1, -1, 1, 3, 7); </i>
onDrawFrame:
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
On most devices app works well:
http://prntscr.com/75ucsf
But on some devices app works like this:
http://prntscr.com/75ucle
Only text is rendered, Square objects aren't rendered.
What should I do to render both Square objects and text on all devices?
Ask me if you need more informations.
Related
I have, a problem with the setLookAtM function. My goal is to create a cube within a cube something like this (yep, it's paint :P ):
So basically everything works... almoust... I have the smaller cube and I have the bigger one.
However, there is a problem. I created the bigger one with coords from -1 to 1 and now I want to upscale it. With scale 1.0f i have something like this (the inner cube is rotating):
And thats good, but now... when I try to scale the bigger cube (so that it looks like in the paint drawing) the image goes black or white (i guess it's because the "camera" looks at the white cube but still i dont know why does my inner cube disappear :/ I don't understand what I'm doing wrong. Here is my code:
public void onDrawFrame(GL10 unused) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5.0f, 0f, 0f, -1.0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
mRoom.mScale = 1.0f;
Matrix.setIdentityM(mScaleMatrix, 0);
Matrix.scaleM(mScaleMatrix, 0, mRoom.mScale, mRoom.mScale, mRoom.mScale);
float[] scaleTempMatrix = new float[16];
Matrix.multiplyMM(scaleTempMatrix, 0, mMVPMatrix, 0, mScaleMatrix, 0);
mRoom.draw(scaleTempMatrix);
When I set for example:
mRoom.mScale = 3.0f;
And
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -2.0f, 0f, 0f, 0.0f, 1.0f, 1.0f, 0.0f);
My camera should be at (0, 0, -2) looking at (0,0, -1) and it should be inside the white cube (since scale is 3.0 so the coords should be from -3 to 3 right?) But all I get is a white screen without the smaller cube rotating inside :/
If your scale is 3x in this code, then your visible coordinate range is actually going to be [-1/3,1/3].
You are thinking about things backwards, it might help if you considered the order in which the scale operation is applied. Right now you are scaling the object-space coordinates, then applying the view matrix and then projection. It may not look that way, but that is how matrix multiplication in GL works; GL effectively flips the operands when it does matrix multiplication and matrix multiplication is not commutative.
I believe this is what you actually want:
public void onDrawFrame(GL10 unused) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5.0f, 0f, 0f, -1.0f, 0f, 1.0f, 0.0f);
mRoom.mScale = 3.0f;
Matrix.setIdentityM(mScaleMatrix, 0);
Matrix.scaleM(mScaleMatrix, 0, mRoom.mScale, mRoom.mScale, mRoom.mScale);
Matrix.multiplyMM(mMVPMatrix, 0, mScaleMatrix, 0, mProjectionMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mMVPMatrix, 0, mViewMatrix, 0);
mRoom.draw(mMVPMatrix);
I tried to map my texture to a square made in opengl es 2.0, and when i do, the texture appears upside down, is my mapping wrong? or the way im drawing it? here is a picture of what it looks like:
here is my code for the onDrawFrame()
public void onDrawFrame(GL10 glUnused) {
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
GLES20.glEnableVertexAttribArray(maTextureHandle);
Matrix.orthoM(mProjMatrix, 0, 0, 200, 0, 100, -5, 5);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mProjMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
}
the coordination for the square and mapping UV are:
private final float[] mTriangleVerticesData = {
// X, Y, Z, U, V
0f, 0f, 0, 0.0f, 0.0f,
50f, 0f, 0, 1.0f, 0.0f,
50f, 50f, 0, 1.0f, 1.0f,
0f, 50f, 0.0f, 0.0f, 1.0f };
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 };
how could i achieve a right-side up view?
This looks like a common mistake. You need to account for the fact that OpenGL's origin for textures is in the lower left corner (and not the upper-left corner).
There's a couple of things you can do to compensate:
read the pixels lines from bottom to top;
swap the pixel lines;
or swap the texture Y coordinates;
You could try swapping the texture coordinates in a shader (source: http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_06)
void main(void) {
vec2 flipped_texcoord = vec2(f_texcoord.x, 1.0 - f_texcoord.y);
gl_FragColor = texture2D(mytexture, flipped_texcoord);
}
I am trying to write code that will cycle between rendering an animation and rendering a heads up display. The animation works, however I am having difficulty switching between the animation's projection matrix and another orthographic projection matrix for the HUD.
The main loop runs as follows:
init();
while (isAnimationRunning) {
drawAnimation();
drawHUD();
}
And the initialization of the surface is:
void init(){
glEnableClientState(GL10.GL_VERTEX_ARRAY);
glClearColor(1, 1, 1, 1);
glMatrixMode(GL11.GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, windowWidth, windowHeight);
GLU.gluPerspective(gl11, 45.0f, windowWidth / windowHeight, 0.1f, 100.0f);
}
And the code for the animation rendering
void drawAnimation() {
glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL10.GL_MODELVIEW);
glLoadIdentity();
GLU.gluLookAt(gl11, x, y, zoom, x, y, 0, 0, 1, 0);
drawAnimationTextures();
}
And the code for the HUD rendering
void drawHUD(){
glMatrixMode(GL10.GL_MODELVIEW);
glPushMatrix();
// IF THIS LINE IS REMOVED THE ANIMATION DISPLAYS BUT NOT THE HUD
glLoadIdentity();
glClear(GL10.GL_COLOR_BUFFER_BIT);
GLU.gluLookAt(gl11, 0, 0, 2, 0, 0, 0, 0, 1, 0);
glMatrixMode(GL10.GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
GLU.gluPerspective(gl11, 45, aspectRatio, 0.1f, 100.0f);
glOrthof(-aspectRatio, aspectRatio, -1, 1, -4, 4);
drawHUDTexture();
glPopMatrix();
glMatrixMode(GL10.GL_MODELVIEW);
glPopMatrix();
}
The screen is blank when this code is implemented. Any ideas what the problem might be?
////////////////////////
void drawTexture(float x, float y, float z, float sizeX, float sizeY,...){
glEnable(GL10.GL_TEXTURE_2D);
glPushMatrix();
bindTexture(texture);
glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
glFrontFace(GL10.GL_CW);
glColor4f(RGB[0], RGB[1], RGB[2], alpha);
glTranslatef(x, y, z);
glScalef(sizeX, sizeY, sizeZ);
glVertexPointer(3, GL10.GL_FLOAT, 0, squareVertexBuffer);
glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
glPopMatrix();
}
Why are you clearing the framebuffer in both routines? You should call it once only in your top level loop. If the animation appears when you comment out the loadidentity but still have the glclear there I am puzzled.
It looks like the hud overwrites the whole screen, make it semi transparent to check this, it may be so large you're just seeing a small part of it.
plus your hud code is setting up a perspective view, then an ortho view - which one do you want?
in this posting http://www.badlogicgames.com/wordpress/?p=504 Mr. libgdx Mario writes:
OpenGL from the ground up: an extremely well written tutorial series on OpenGL ES 1.x. Covers all the basics you need to get started with OpenGL. Note that the tutorial is written for the IPhone and uses Objective C/C++. This shouldn’t be a big problem though as the API is the same.
To my shame, I wasn't able to get a libgdx aequivalent of the very first example in that tutorial running, which is this:
- (void)drawView:(GLView*)view;
{
Vertex3D vertex1 = Vertex3DMake(0.0, 1.0, -3.0);
Vertex3D vertex2 = Vertex3DMake(1.0, 0.0, -3.0);
Vertex3D vertex3 = Vertex3DMake(-1.0, 0.0, -3.0);
Triangle3D triangle = Triangle3DMake(vertex1, vertex2, vertex3);
glLoadIdentity();
glClearColor(0.7, 0.7, 0.7, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0, 0.0, 0.0, 1.0);
glVertexPointer(3, GL_FLOAT, 0, &triangle);
glDrawArrays(GL_TRIANGLES, 0, 9);
glDisableClientState(GL_VERTEX_ARRAY);
}
my code...
public void render () {
Gdx.gl11.glLoadIdentity();
Gdx.gl11.glRotatef(rotation, 0.0f, 0.0f, 1.0f);
Gdx.gl11.glClearColor((float)0.7, (float)0.7, (float)0.7, (float)1.0);
Gdx.gl11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
Gdx.gl11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
Gdx.gl11.glColor4f((float)1.0, (float)0.0, (float)0.0, (float)1.0);
Gdx.gl11.glVertexPointer(3, GL11.GL_FLOAT, BYTES_PER_VERTEX, vertices);
Gdx.gl11.glDrawArrays(GL11.GL_TRIANGLES, 0, 9);
Gdx.gl11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
}
The problem here is 'vertices'. I have no idea what that should be. After lots of googling I came up with:
final int BYTES_PER_VERTEX = (3 + 4) * 4;
public void create () {
ByteBuffer buffer = ByteBuffer.allocateDirect(BYTES_PER_VERTEX * 3);
buffer.order(ByteOrder.nativeOrder());
vertices = buffer.asFloatBuffer();
float[] verts = {
0.0f, 1.0f, 0.0f, 1, 0, 0, 0,
1.0f, 0.0f, 0.0f, 0, 1, 0, 0,
-1.0f, 0.0f, 0.0f, 0, 0, 1, 0};
vertices.put(verts);
vertices.flip();
}
. and that seems to be displaying a triangle, but the values for the vertices are not the same as in the original example (z value is 0 instead of -3, in which case I wouldn't see anything).
Can anyone shed any light on vertices?
Here's what I have. I create a square instead of a triangle but you get the jist. A lot of the random code that is in the iphone tutorial is taken care internally. You can actually dissect the source of libgdx if you are curious how (in java) it's going about the calls internally (camera management, mesh management, etc).
in create() :
mesh = new Mesh(true, 4, 4,
new VertexAttribute(Usage.Position, 3, "a_position"),
new VertexAttribute(Usage.ColorPacked, 4, "a_color"));
mesh.setVertices(new float[] {
-1.0f, -1.0f, -3.0f, Color.toFloatBits(255, 0, 0, 255),
1.0f, -1.0f, -3.0f, Color.toFloatBits(255, 0, 0, 255),
-1.0f, 1.0f, -3.0f, Color.toFloatBits(255, 0, 0, 255),
1.0f, 1.0f, -3.0f, Color.toFloatBits(255, 0, 0, 255)});
mesh.setIndices(new short[] { 0, 1, 2, 3 });
in resize()
float aspectRatio = (float) width / (float) height;
camera = new PerspectiveCamera(67, 2f * aspectRatio, 2f);
camera.near = 0.1f;
camera.translate(0, 0, 0);
in render()
Gdx.gl11.glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
mesh.render(GL10.GL_TRIANGLE_STRIP, 0, 4);
Hope that helps.
Resources:
http://dpk.net/2011/03/07/libgdx-cubes-handling-inputs-in-applicationlistener-render/
http://www.badlogicgames.com/wordpress/?p=2032
I need to position sky sphere in 3D space right where camera is.
I set up camera as follows:
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
// Ignore the passed-in GL10 interface, and use the GLES20
// class's static methods instead.
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 2, 1000);
}
...
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
...
Sphere has a diameter of 100 units and it's center is in (0;0;0).
The method to draw a sphere:
private void drawSphere() {
//Matrix.setLookAtM(mVMatrix, 0, 0, 0, 0, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
mTriangleVerticesSphere.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVerticesSphere);
mTriangleVerticesSphere.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVerticesSphere);
GLES20.glEnableVertexAttribArray(maTextureHandle);
Matrix.setRotateM(mMMatrix, 0, jitterX, 1.0f, 0, 0);
Matrix.rotateM(mMMatrix, 0, angleYaw + jitterY, 0, 1.0f, 0);
Matrix.scaleM(mMMatrix, 0, 0.01f, 0.01f, 0.01f);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, numPolysSphere);
}
This code displays a sphere. Backface culling is disabled, and I can see both sides of sphere (texture has transparent parts).
In order to display sphere right in the camera position I try to move camera. But if I uncomment Matrix.setLookAtM(mVMatrix, 0, 0, 0, 0, 0f, 0f, 0f, 0f, 1.0f, 0.0f) in the beginning of drawSphere() it doesn't display anything. May be it has something to do with clipping planes?
Please give an example how to position the sphere correctly.
I think your more looking to do something like
Matrix.setLookAtM(mvMatrix, 0, 0, 0, 10, 0, 0, 0, 0, 1, 0);
if I'm not wrong opengl doesn't know which way its looking at
your asking too look for (0,0,0) towards (0,0,0) while oriented towards (0,1.0,0)
OK, so I figured out how to do it.
1. Look at correct angle.
3. Draw sky sphere.
2. Clear Z-buffer.
3. Reposition camera.
4. Draw the rest.