OpenGL ES 2.0 中的立方体不绘制给定的纹理
Cube in OpenGL ES 2.0 does not draw the given textures
通常我不会用我的问题打扰你,但这次我很绝望。
首先,我是 OpenGL 的新手,所以如果我犯了一些新手错误,请不要批评我。我已经看过一些示例了,但是有些示例代码对我来说是无法理解的。
其次,我知道这个问题之前已经在堆栈中被问过,但是给出的答案不是我的案例的解决方案。他们说应该调整图像的大小,使其成为 2 的幂,所以我做了,但没有效果。他们还说它可能是png的透明元素,所以我在fragmentShader中更改了gl_FragColor(不止一次),但没有效果。
您可以在下面找到我用来绘制立方体并旋转它的代码。所以一切正常,除此之外它也应该显示纹理但它没有。能帮我解决这个问题的是大神!
这是创建表面视图并设置自定义渲染器的activity
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();
}
}
这是渲染器
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];
}
}
这是需要渲染的对象:
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);
}
}
我认为我不需要提供更多文件(如清单),但如果您确实需要,请询问。
备注:使用记录器会很困难,因为不知何故我无法运行 来自android.
的Trancer 程序
您的纹理句柄似乎也有一些可疑的变量设置。您将各个句柄声明为整数,然后还声明一个包含 6 个值的数组。这里的 6 个值是 "int" 基本类型,而不是对象,因此数组将采用值的副本而不是引用。在代码后面的一个地方,您通过非数组版本设置,并通过数组版本绑定,这将不起作用,因为您实际上正在查看两个完全不同的变量。我建议删除数组之外的版本,只使用数组作为 6 个纹理句柄的唯一存储。
更一般地说,某些东西看起来 "off" 在您的纹理设置中。您在着色器中只设置了一个纹理采样器,并且您正试图将 6 个不同的纹理绑定到它。着色器如何知道将哪个纹理应用于哪个三角形?它不能。如果您解决了上述关于如何管理手柄的问题,您当前的着色器将只显示所有 6 个面上的最后一个绑定纹理。
如果你想在立方体的每个面上显示像骰子这样的东西,有 6 个不同的图像,那么你通常需要将所有 6 个面的纹理数据打包到一个纹理图像中,然后给每个面的顶点不同的纹理坐标,以便它映射图像的正确子区域。
HTH,
皮特
通常我不会用我的问题打扰你,但这次我很绝望。
首先,我是 OpenGL 的新手,所以如果我犯了一些新手错误,请不要批评我。我已经看过一些示例了,但是有些示例代码对我来说是无法理解的。
其次,我知道这个问题之前已经在堆栈中被问过,但是给出的答案不是我的案例的解决方案。他们说应该调整图像的大小,使其成为 2 的幂,所以我做了,但没有效果。他们还说它可能是png的透明元素,所以我在fragmentShader中更改了gl_FragColor(不止一次),但没有效果。
您可以在下面找到我用来绘制立方体并旋转它的代码。所以一切正常,除此之外它也应该显示纹理但它没有。能帮我解决这个问题的是大神!
这是创建表面视图并设置自定义渲染器的activity
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();
}
}
这是渲染器
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];
}
}
这是需要渲染的对象:
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);
}
}
我认为我不需要提供更多文件(如清单),但如果您确实需要,请询问。
备注:使用记录器会很困难,因为不知何故我无法运行 来自android.
的Trancer 程序您的纹理句柄似乎也有一些可疑的变量设置。您将各个句柄声明为整数,然后还声明一个包含 6 个值的数组。这里的 6 个值是 "int" 基本类型,而不是对象,因此数组将采用值的副本而不是引用。在代码后面的一个地方,您通过非数组版本设置,并通过数组版本绑定,这将不起作用,因为您实际上正在查看两个完全不同的变量。我建议删除数组之外的版本,只使用数组作为 6 个纹理句柄的唯一存储。
更一般地说,某些东西看起来 "off" 在您的纹理设置中。您在着色器中只设置了一个纹理采样器,并且您正试图将 6 个不同的纹理绑定到它。着色器如何知道将哪个纹理应用于哪个三角形?它不能。如果您解决了上述关于如何管理手柄的问题,您当前的着色器将只显示所有 6 个面上的最后一个绑定纹理。
如果你想在立方体的每个面上显示像骰子这样的东西,有 6 个不同的图像,那么你通常需要将所有 6 个面的纹理数据打包到一个纹理图像中,然后给每个面的顶点不同的纹理坐标,以便它映射图像的正确子区域。
HTH, 皮特