Текстура OpenGL не соответствует геометрии

Я борюсь с прыжком сложности от OpenGL ES 1.x до 2.0. Я пытаюсь применить текстуру к прямоугольной плоскости, а затем смогу масштабировать и переводить эту плоскость, сохраняя при этом правильную карту текстуры.

Мой вопрос: что я делаю неправильно и как я смогу текстурировать свои самолеты во время перевода и масштабирования?

Я выведу свой класс рендерера, класс, который объекты будут использовать для рисования, и мои шейдеры вершин и фрагментов:

GL Renderer:

package com.detour.raw; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; public class GameRenderer implements GLSurfaceView.Renderer{ private static final String TAG = "GameRenderer"; Context mContext; Bitmap bitmap; private float red = 0.5f; private float green = 0.5f; private float blue = 0.5f; Shader shader; int program; FPSCounter fps; Sprite sprite; Sprite sprite2; int x = 0; private int muMVPMatrixHandle; private float[] mMVPMatrix = new float[16]; private float[] mProjMatrix = new float[16]; private float[] mMVMatrix = new float[16]; //private float[] mVMatrix = new float[16]; //private float[] mMMatrix = new float[16]; //private float[] mVPMatrix = new float[16]; //private float[] mIMatrix = new float[16]; public GameRenderer(Context context){ mContext = context; //create objects/sprites sprite = new Sprite(mContext); sprite2 = new Sprite(mContext); fps = new FPSCounter(); } @Override public void onDrawFrame(GL10 gl) { GLES20.glClearColor(red, green, blue, 1.0f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glUseProgram(program); //Matrix.setIdentityM(mIMatrix, 0); //Matrix.multiplyMM(mMVMatrix, 0, mVMatrix, 0, mMMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVMatrix , 0); GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); sprite.draw(); /*if(x>3){ x=0; } if(x%2==0){ sprite.draw(); }else{ sprite2.draw(); } x++;*/ //fps.calculate(); //fps.draw(gl); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = ((float)(width))/((float)(height)); Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 0.5f, 10); Matrix.setLookAtM(mMVMatrix, 0, 0, 0, 1.0f, 0.0f, 0f, 0f, 0f, 1.0f, 0.0f); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO Auto-generated method stub /*int error = GLES20.glGetError(); Log.d(LOG_TAG, ""+error);*/ shader = new Shader(R.raw.sprite_vs, R.raw.sprite_fs, mContext); program = shader.getProgram(); muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "u_MVPMatrix"); GLES20.glEnable(GLES20.GL_TEXTURE_2D); GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glClearDepthf(1.0f); GLES20.glDepthFunc(GLES20.GL_LEQUAL); GLES20.glDepthMask(true); GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glCullFace(GLES20.GL_BACK); GLES20.glClearColor(red, green, blue, 1.0f); sprite.loadGLTexture(R.drawable.raw1a, program); sprite2.loadGLTexture(R.drawable.raw2, program); System.gc(); } } 

Класс рисования:

 package com.detour.raw; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLES20; import android.opengl.GLUtils; public class RenderVisible implements Renderable{ Context mContext; Bitmap bitmap; private int vertexHandle; private int texCoordHandle; private int textureHandle; private int[] textures = new int[1]; private float textureCoordinates[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }; private float vertices[] = { -1.0f, 1.0f,// 0.0f, -1.0f, -1.0f,// 0.0f, 1.0f, -1.0f,// 0.0f, 1.0f, 1.0f// 0.0f, }; private short[] indices = { 0, 1, 2, 0, 2, 3}; private FloatBuffer vertexBuffer; private FloatBuffer textureBuffer; private ShortBuffer indexBuffer; public RenderVisible(Context context){ mContext = context; ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoordinates.length * 4); byteBuf.order(ByteOrder.nativeOrder()); textureBuffer = byteBuf.asFloatBuffer(); textureBuffer.put(textureCoordinates); textureBuffer.position(0); ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); ibb.order(ByteOrder.nativeOrder()); indexBuffer = ibb.asShortBuffer(); indexBuffer.put(indices); indexBuffer.position(0); } @Override public void draw() { GLES20.glEnableVertexAttribArray(vertexHandle); GLES20.glVertexAttribPointer(vertexHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer); } @Override public void loadGLTexture(int id, int program) { vertexHandle = GLES20.glGetAttribLocation(program, "a_position"); texCoordHandle = GLES20.glGetAttribLocation(program, "a_texcoord"); textureHandle = GLES20.glGetUniformLocation(program, "u_texture"); bitmap = BitmapFactory.decodeResource(mContext.getResources(), id); /*InputStream is = mContext.getResources().openRawResource(id); try { bitmap = BitmapFactory.decodeStream(is); } finally { try { is.close(); is = null; } catch (IOException e) { } }*/ GLES20.glGenTextures(1, textures, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); GLES20.glUniform1i(textureHandle, 0); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); //GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, FRAME_WIDTH, FRAME_HEIGHT, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);//(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); } } 

Фрагментный шейдер:

 precision mediump float; uniform sampler2D u_texture; varying vec2 v_texcoord; void main() { gl_FragColor = texture2D(u_texture, v_texcoord); } 

Vertex Shader:

 attribute vec2 a_position; attribute vec2 a_texcoord; uniform mat4 u_MVPMatrix; varying vec2 v_texcoord; void main() { gl_Position = vec4(a_position, 0.0, 1.0) * u_MVPMatrix; v_texcoord = a_position * vec2(0.5, -0.5) + vec2(0.5); } 

Когда я запускаю эту программу, я получаю ожидаемый результат:

Введите описание изображения здесь

Когда я изменяю вершины своего рендерируемого (в этом случае все разделяют каждое значение на 2), форма моей плоскости изменяется, но текстура не движется с ней так, как я ожидал. Я не уверен, почему (объяснение было бы неплохо).

Введите описание изображения здесь

Когда я исправляю вершины своего плана и меняю вершинный шейдер, чтобы принять координаты текстуры, я даю его ( v_texcoord = a_texcoord; ), я получаю правильный квадрат размера, но текстура не видна / квадрат полностью белый.

Я также пытаюсь создать методы для рендерируемого класса (RenderVisible), который упростит перемещение и масштабирование моих спрайтов. Как я могу это сделать?

Ваши координаты текстуры являются функцией координат вершин, вот почему это поведение, чтобы исправить это, просто измените шейдерный вершин:

 v_texcoord = a_texcoord; 

Таким образом, вы используете свои постоянные координаты текстуры. Также не забудьте включить атрибут вершин текстуры:

 GLES20.glEnableVertexAttribArray(texCoordHandle);