#java #android #opengl-es
Вопрос:
Сегодня я пытаюсь отобразить две текстуры на одной из граней 3d-куба. Я достиг своей цели. Проблема в том, что на других лицах также отображаются странные текстуры.
Я проверяю координаты текстуры, и отображается только основная грань.
private float textureCord[] = {
// Mapping coordinates for the vertices
// Front face
1.2f, 1.2f,
1.2f, -0.2f,
-0.2f, -0.2f,
-0.2f, 1.2f
};
Во — вторых, я добавляю эти строки, чтобы предотвратить повторения.
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
Это помогает, но все еще работает неправильно.
Любая помощь будет оценена по достоинству, спасибо
Класс Кубо:
public class Cubo {
private Context context;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;"
"attribute vec4 vPosition;"
"attribute vec4 aColor;"
"varying vec4 vColor;"
"attribute vec2 a_TexCoordinate0;"
"varying vec2 v_TexCoordinate0;"
"attribute vec2 a_TexCoordinate1;"
"varying vec2 v_TexCoordinate1;"
"void main() {"
" vColor=aColor;"
" gl_Position = uMVPMatrix * vPosition;"
" v_TexCoordinate0 = a_TexCoordinate0;"
" v_TexCoordinate1 = a_TexCoordinate1;"
"}";
private final String fragmentShaderCode =
"precision mediump float;"
"uniform sampler2D u_Texture0;"
"uniform sampler2D u_Texture1;"
"uniform vec4 aColor;"
"varying vec2 v_TexCoordinate0;"
"varying vec2 v_TexCoordinate1;"
"void main() {"
" vec4 base = texture2D(u_Texture0, v_TexCoordinate0);"
" vec4 overlay = texture2D(u_Texture1, v_TexCoordinate1);"
" mediump float ra = (overlay.a) * overlay.r (1.0 - overlay.a) * base.r;"
" mediump float ga = (overlay.a) * overlay.g (1.0 - overlay.a) * base.g;"
" mediump float ba = (overlay.a) * overlay.b (1.0 - overlay.a) * base.b;"
" vec3 textureColor = vec3(ra, ga, ba);"
" float textureAlpha = max(base.a, overlay.a);"
" gl_FragColor = vec4(mix(aColor.rgb, textureColor, textureAlpha), 1.0);"
"}";
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private FloatBuffer mTextureBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private final int mTextureCoordinateDataSize = 2;
static final int COORDS_PER_VERTEX = 3;
static float cubeCoords[] = {
-0.5f, 0.5f, 0.5f, // top left
-0.5f, -0.5f, 0.5f, // bottom left
0.5f, -0.5f, 0.5f, // bottom right
0.5f, 0.5f, 0.5f, // top right
-0.5f, 0.5f, -0.5f, // top left back
-0.5f, -0.5f, -0.5f, // bottom left back
0.5f, -0.5f, -0.5f, // bottom right back
0.5f, 0.5f, -0.5f // top right back
};
private final short drawOrder[] = {0, 1, 2, 0, 2, 3,
3, 2, 6, 3, 6, 7,
0, 3, 7, 0, 7, 4,
1, 5, 6, 1, 6, 2,
4, 5, 1, 4, 1, 0,
7, 6, 5, 7, 5, 4};
private final int vertexStride = COORDS_PER_VERTEX * 4;
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 0.0f};
private float textureCord[] = {
// Mapping coordinates for the vertices
// Front face
1.2f, 1.2f,
1.2f, -0.2f,
-0.2f, -0.2f,
-0.2f, 1.2f
};
private int[] textures = new int[2];
private int[] bitmapsId = {
R.drawable.horizontal,
R.drawable.casilla27
};
public Cubo(Context context) {
this.context = context;
ByteBuffer bb = ByteBuffer.allocateDirect(
cubeCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(cubeCoords);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCord.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mTextureBuffer = byteBuf.asFloatBuffer();
mTextureBuffer.put(textureCord);
mTextureBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
}
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//---------------textura-------------------
for (int i = 0; i < textures.length; i ) {
int mTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "u_Texture" i);
int mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate" i);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false,
0, mTextureBuffer);
GLES20.glActiveTexture(i == 0 ? GLES20.GL_TEXTURE0 : GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);
GLES20.glUniform1i(mTextureUniformHandle, i);
}
//------------------------------------------
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
public void loadTexture() {
GLES20.glGenTextures(2, textures, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
for (int i = 0; i < textures.length; i ) {
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), bitmapsId[i], options);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
}
Средство визуализации:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private Cubo cubo;
private Context context;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix_x = new float[16];
private final float[] mRotationMatrix_y = new float[16];
private final float[] mRotationMatrix = new float[16];
private float mXAngle;
private float mYAngle;
public MyGLRenderer(Context context) {
this.context = context;
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClearDepthf(1.0f);
GLES20.glEnable(GL10.GL_DEPTH_TEST);
cubo = new Cubo(context);
cubo.loadTexture();
}
@Override
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
GLES20.glViewport(0, 0, i, i1);
float ratio = (float) i / i1;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
@Override
public void onDrawFrame(GL10 gl10) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -4, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix_x, 0, mYAngle, 1.0f, 0, 0);
Matrix.setRotateM(mRotationMatrix_y, 0, mXAngle, 0, 1.0f, 0);
Matrix.multiplyMM(mRotationMatrix, 0, mRotationMatrix_y, 0, mRotationMatrix_x, 0);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
cubo.draw(scratch);
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public float getmXAngle() {
return mXAngle;
}
public void setmXAngle(float mXAngle) {
this.mXAngle = mXAngle;
}
public float getmYAngle() {
return mYAngle;
}
public void setmYAngle(float mYAngle) {
this.mYAngle = mYAngle;
}
Комментарии:
1. Когда вы создаете простой куб без текстур, вам может сойти с рук создание только 8 вершин, потому что каждая вершина имеет одинаковые данные (положение) для всех трех соседних граней. Это невозможно сделать, если вы отображаете текстуры на грани (если только текстура не должна обертываться непосредственно через вершину, что обычно не то, что вы хотели бы сделать с кубом). Поэтому вам нужно определить 24 вершины вместо 8. Некоторые вершины будут иметь идентичные данные о местоположении, но их координаты текстуры будут разными. Вам также понадобится 24 вершины, если вы добавите данные нормалей, чтобы они могли иметь освещение.
2. Привет, Tenfour04, спасибо! Я меняю свои кубики из 8 вершин на одну из 24. Теперь куб выглядит еще хуже. Мне кажется, я вас не понимаю, извините. Я меняю свои кубические области на вершины этого примера, который я нашел : ссылка
3. После того, как я потратил некоторое время на расследование, я понял, что необходимо также изменить де Драуордера. Теперь выглядит хорошо. Большое вам спасибо, Tenfour04!