mardi 3 mars 2015

Cube in OpenGL ES 2.0 does not draw the given textures



Normally I would not bother you with my questions, but this time I'm rather desperate.


First of all, I'm fairly new to OpenGL so please don't shoot me if I've made some rookie mistakes. I've seen some examples already, but some of the example code is not understandable for me.


Secondly, I know this question is already been asked before on stack, but the answers that were given are no solutions for my case. They say one should resize the images so it becomes a power of 2, so I did, but no effect. They also say it could be the transparancy-element of a png, so I changed gl_FragColor in the fragmentShader (more than once), but no effect.


Here below you can find the code I'm using to draw the cube and rotate it. So everything works, beside the fact that it should show the textures as well but it doesn't. The one that could solve this problem for me is a god!


This is the activity that creates a surfaceview and sets the custom renderer



package --------------------;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class MyGLSurfaceView extends Activity {
private GLSurfaceView mGLSurfaceView;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mGLSurfaceView = new GLSurfaceView(this);

final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;

if (supportsEs2) {
mGLSurfaceView.setEGLContextClientVersion(2);
mGLSurfaceView.setRenderer(new MyOpenGLESRenderer(this));
} else {
return;
}

setContentView(mGLSurfaceView);
}

@Override
protected void onResume() {
super.onResume();
mGLSurfaceView.onResume();
}

@Override
protected void onPause() {
super.onPause();
mGLSurfaceView.onPause();
}
}


This is the renderer



package ----------------------;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.DisplayMetrics;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyOpenGLESRenderer implements GLSurfaceView.Renderer {
private final Context context;

private Cube cube;

private float[] viewMatrix = new float[16];
private float[] projectionMatrix = new float[16];

private int programHandle;
private int textureDataHandle1;
private int textureDataHandle2;
private int textureDataHandle3;
private int textureDataHandle4;
private int textureDataHandle5;
private int textureDataHandle6;

private int[] textureHandles = {
textureDataHandle1,
textureDataHandle2,
textureDataHandle3,
textureDataHandle4,
textureDataHandle5,
textureDataHandle6
};

int deviceWidth;
int deviceHeight;

public MyOpenGLESRenderer(final Context context) {
this.context = context;

DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
deviceWidth = displayMetrics.widthPixels;
deviceHeight = displayMetrics.heightPixels;
}

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
GLES20.glClearColor(0.3f, 1.0f, 0.3f, 0.0f);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);

final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = -0.5f;

final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;

final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;

Matrix.setLookAtM(viewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);

final String vertexShader =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.

+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
+ "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
+ "attribute vec2 a_TexCoordinate;\n"
+ "varying vec2 v_TexCoordinate; \n"
+ "varying vec4 v_Color; \n" // This will be passed into the fragment shader.

+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
+ " v_Color = a_Color; \n" // Pass the color through to the fragment shader.
+ "v_TexCoordinate = a_TexCoordinate;\n" // It will be interpolated across the triangle.
+ " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position.
+ " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in
+ "} \n"; // normalized screen coordinates.

final String fragmentShader =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
+ "uniform sampler2D u_Texture; \n"
+ "varying vec2 v_TexCoordinate; \n"// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate)); \n" // Pass the color directly through the pipeline.
+ "} \n";

final int vertexShaderHandle = loadShader(vertexShader, GLES20.GL_VERTEX_SHADER);
final int fragmentShaderHandle = loadShader(fragmentShader, GLES20.GL_FRAGMENT_SHADER);

programHandle = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
new String[]{"a_Position", "a_Color", "a_TexCoordinate"});

}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
GLES20.glViewport(0, 0, width, height);

final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;

Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far);
}

@Override
public void onDrawFrame(GL10 glUnused) {
cube = new Cube(deviceWidth, deviceHeight);
cube.onDraw(programHandle, textureHandles, viewMatrix, projectionMatrix);
}

private int loadShader(final String shader, final int glShader) {
int shaderHandle = GLES20.glCreateShader(glShader);

if (shaderHandle != 0) {
GLES20.glShaderSource(shaderHandle, shader);
GLES20.glCompileShader(shaderHandle);

final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

if (compileStatus[0] == 0) {
GLES20.glDeleteShader(shaderHandle);
shaderHandle = 0;
}
}
if (shaderHandle == 0) {
throw new RuntimeException("Error creating shader.");
}
return shaderHandle;
}

private int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) {
programHandle = GLES20.glCreateProgram();

if (programHandle != 0) {
GLES20.glAttachShader(programHandle, vertexShaderHandle);
GLES20.glAttachShader(programHandle, fragmentShaderHandle);

if (attributes != null) {
final int size = attributes.length;
for (int i = 0; i < size; i++) {
GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
}
}

GLES20.glLinkProgram(programHandle);
textureDataHandle1 = loadTexture(R.drawable.diceface1);
textureDataHandle2 = loadTexture(R.drawable.diceface4);
textureDataHandle3 = loadTexture(R.drawable.diceface6);
textureDataHandle4 = loadTexture(R.drawable.diceface3);
textureDataHandle5 = loadTexture(R.drawable.diceface5);
textureDataHandle6 = loadTexture(R.drawable.diceface2);

final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);

if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0) {
throw new RuntimeException("Error creating program.");
}
return programHandle;
}

private int loadTexture(final int resourceId) {
final int[] textureHandle = new int[1];

GLES20.glGenTextures(1, textureHandle, 0);

if (textureHandle[0] != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling

final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

bitmap.recycle();
}

if (textureHandle[0] == 0) {
throw new RuntimeException("Error loading texture.");
}

return textureHandle[0];
}
}


And this is the object that needs to be rendered:



package ---------------;

import android.opengl.GLES20;
import android.opengl.Matrix;
import android.os.SystemClock;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class Cube {

private float X = 0, Y = 0;

private final FloatBuffer cubeVertices;
private final FloatBuffer cubeColors;
private final FloatBuffer cubeTextureCoordinates;

private float[] modelMatrix = new float[16];
private float[] viewMatrix = new float[16];
private float[] projectionMatrix = new float[16];

private float[] MVPMatrix = new float[16];

private int MVPMatrixHandle;
private int MVMatrixHandle;
private int textureUniformHandle;
private int positionHandle;
private int colorHandle;
private int textureCoordinateHandle;

private final int positionDataSize = 3;
private final int colorDataSize = 4;
private final int textureCoordinateDataSize = 2;

private final int bytesPerFloat = 4;

private boolean upX = true;
private boolean upY = true;
private float counterX = 0.0f;
private float counterY = 0.0f;

private int deviceWidth;
private int deviceHeight;

private final float[] verticesData = {
-0.6f, 0.6f, 0.6f,
-0.6f, -0.6f, 0.6f,
0.6f, 0.6f, 0.6f,
-0.6f, -0.6f, 0.6f,
0.6f, -0.6f, 0.6f,
0.6f, 0.6f, 0.6f,

0.6f, 0.6f, 0.6f,
0.6f, -0.6f, 0.6f,
0.6f, 0.6f, -0.6f,
0.6f, -0.6f, 0.6f,
0.6f, -0.6f, -0.6f,
0.6f, 0.6f, -0.6f,

0.6f, 0.6f, -0.6f,
0.6f, -0.6f, -0.6f,
-0.6f, 0.6f, -0.6f,
0.6f, -0.6f, -0.6f,
-0.6f, -0.6f, -0.6f,
-0.6f, 0.6f, -0.6f,

-0.6f, 0.6f, -0.6f,
-0.6f, -0.6f, -0.6f,
-0.6f, 0.6f, 0.6f,
-0.6f, -0.6f, -0.6f,
-0.6f, -0.6f, 0.6f,
-0.6f, 0.6f, 0.6f,

-0.6f, 0.6f, -0.6f,
-0.6f, 0.6f, 0.6f,
0.6f, 0.6f, -0.6f,
-0.6f, 0.6f, 0.6f,
0.6f, 0.6f, 0.6f,
0.6f, 0.6f, -0.6f,

0.6f, -0.6f, -0.6f,
0.6f, -0.6f, 0.6f,
-0.6f, -0.6f, -0.6f,
0.6f, -0.6f, 0.6f,
-0.6f, -0.6f, 0.6f,
-0.6f, -0.6f, -0.6f,
};

private final float[] cubeColorData = {
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,

1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,

1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,

1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,

1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,

1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};

private final float[] cubeTextureCoordinateData = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,

0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,

0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,

0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,

0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,

0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};

public Cube(int deviceWidth, int deviceHeight) {
this.deviceWidth = deviceWidth;
this.deviceHeight = deviceHeight;

cubeVertices = ByteBuffer.allocateDirect(verticesData.length * bytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
cubeVertices.put(verticesData).position(0);

cubeColors = ByteBuffer.allocateDirect(cubeColorData.length * bytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
cubeColors.put(cubeColorData).position(0);

cubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * bytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
cubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);
}

public void onDraw(int programHandle, int[] textureDataHandles, float[] viewMatrix, float[] projectionMatrix) {
this.viewMatrix = viewMatrix;
this.projectionMatrix = projectionMatrix;

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

long time = SystemClock.uptimeMillis() % 10000L;
float angleInDegrees = (360.0f / 10000.0f) * ((int) time);

GLES20.glUseProgram(programHandle);

MVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
MVMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVMatrix");
textureUniformHandle = GLES20.glGetUniformLocation(programHandle, "u_Texture");
positionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
colorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");
textureCoordinateHandle = GLES20.glGetAttribLocation(programHandle, "a_TexCoordinate");

Matrix.setIdentityM(modelMatrix, 0);

//Matrix.translateM(modelMatrix, 0, 3.0f, 5.5f, -7.0f);

//zie kladblok!!!!!!!!!!
Matrix.translateM(modelMatrix, 0, X, Y, -7.0f);

Matrix.rotateM(modelMatrix, 0, angleInDegrees, 1.0f, 0.0f, 0.0f);

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandles[0]);
GLES20.glUniform1i(textureUniformHandle, 0);
drawCube(0);

GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandles[1]);
GLES20.glUniform1i(textureUniformHandle, 1);
drawCube(1);

GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandles[2]);
GLES20.glUniform1i(textureUniformHandle, 2);
drawCube(2);

GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandles[3]);
GLES20.glUniform1i(textureUniformHandle, 3);
drawCube(3);

GLES20.glActiveTexture(GLES20.GL_TEXTURE4);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandles[4]);
GLES20.glUniform1i(textureUniformHandle, 4);
drawCube(4);

GLES20.glActiveTexture(GLES20.GL_TEXTURE5);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandles[5]);
GLES20.glUniform1i(textureUniformHandle, 5);
drawCube(5);
}

private void drawCube(final int i) {
cubeVertices.position(18 * i);
GLES20.glVertexAttribPointer(positionHandle, positionDataSize, GLES20.GL_FLOAT, false,
0, cubeVertices);
GLES20.glEnableVertexAttribArray(positionHandle);

cubeColors.position(24 * i);
GLES20.glVertexAttribPointer(colorHandle, colorDataSize, GLES20.GL_FLOAT, false,
0, cubeColors);
GLES20.glEnableVertexAttribArray(colorHandle);

cubeTextureCoordinates.position(12 * i);
GLES20.glVertexAttribPointer(textureCoordinateHandle, textureCoordinateDataSize, GLES20.GL_FLOAT, false,
0, cubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(textureCoordinateHandle);

Matrix.multiplyMM(MVPMatrix, 0, viewMatrix, 0, modelMatrix, 0);
GLES20.glUniformMatrix4fv(MVMatrixHandle, 1, false, MVPMatrix, 0);
Matrix.multiplyMM(MVPMatrix, 0, projectionMatrix, 0, MVPMatrix, 0);
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, MVPMatrix, 0);

GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
}


I don't think I need to provide more files (like the manifest), but if you do need it please ask.


Remark: Working with a logger would be difficult because somehow I can't run the Trancer program from android.




Aucun commentaire:

Enregistrer un commentaire