2013-03-17 2 views
2

Я пытаюсь получить изображение 2D-фона. В fututre он будет реализован как автоматическое движение (похоже, камера следует за некоторым объектом). Типичный пример - игра сердитых птиц. Камера следит за птицей во время атаки.Фоновое изображение перемещение OpenGL ES2

В настоящее время я просто изменяю значения в setLookAtM(). Вот код:

public void onSurfaceCreated(GL10 unused, EGLConfig config) { 
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 

    GLES20.glDisable(GLES20.GL_DEPTH_TEST); 
    GLES20.glEnable(GLES20.GL_BLEND); 
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE_MINUS_SRC_ALPHA); 

    // background 
    bg = new BackGround(mActivityContext); 

} 

public void onDrawFrame(GL10 unused) { 
    // Redraw background color 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    Matrix.setLookAtM(mVMatrix, 0, -1f, 0f, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 
    Matrix.setIdentityM(mTrMatrix, 0); 

    bg.draw(mMVPMatrix); 
} 

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

    float ratio = (float) width/height; 
    Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 
} 


class BackGround { 

    private FloatBuffer vertexBuffer; 
    private ShortBuffer drawListBuffer; 

    static final int COORDS_PER_VERTEX = 3; 
    static float squareCoords[] = { -15.5f, 15.5f, 0.0f, // top left 
    -15.5f, -15.5f, 0.0f, // bottom left 
    15.5f, -15.5f, 0.0f, // bottom right 
    15.5f, 15.5f, 0.0f }; // top right 

    int mProgram; 
    int mPositionHandle; 

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices 
    private final String vertexShaderCode = "attribute vec2 a_TexCoordinate;" + 
    "varying vec2 v_TexCoordinate;" + 
    "uniform mat4 uMVPMatrix;" + 
    "attribute vec4 vPosition;" + 
    "void main() {" + 
    " gl_Position = uMVPMatrix * vPosition;" + 
    "v_TexCoordinate = a_TexCoordinate;" + 
    "}"; 

    private final String fragmentShaderCode = 
    "precision mediump float;" + 
    "uniform vec4 vColor;" + 
    "uniform sampler2D u_Texture;" + 
    "varying vec2 v_TexCoordinate;" + 
    "void main() {" + 
    "gl_FragColor = (texture2D(u_Texture, v_TexCoordinate));" + 
    "}"; 

    public BackGround(final Context context) { 
     // initialize vertex byte buffer for shape coordinates 
     ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); 
     bb.order(ByteOrder.nativeOrder()); 
     vertexBuffer = bb.asFloatBuffer(); 
     vertexBuffer.put(squareCoords); 
     vertexBuffer.position(0); 

     mActivityContext = context; 

     // initialize byte buffer for the draw list 
     ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); 
     dlb.order(ByteOrder.nativeOrder()); 
     drawListBuffer = dlb.asShortBuffer(); 
     drawListBuffer.put(drawOrder); 
     drawListBuffer.position(0); 

     int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); 
     int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 

     final float[] cubeTextureCoordinateData = { 
      -15.5f, 15.5f, 
      -15.5f, -15.5f, 
      15.5f, -15.5f, 
      15.5f, 15.5f 
     }; 

     mCubeTextureCoordinates = 
     ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * 
     4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0); 

     mProgram = GLES20.glCreateProgram();    
     GLES20.glAttachShader(mProgram, vertexShader); 
     GLES20.glAttachShader(mProgram, fragmentShader); 
     GLES20.glBindAttribLocation(mProgram, 0, "a_TexCoordinate"); 
     GLES20.glLinkProgram(mProgram); 

     // load background bitmap 256x256px    
     mTextureDataHandle = loadTexture(mActivityContext, R.drawable.mud); 
    } 

    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.glGetUniformLocation(mProgram, "vColor"); 
     GLES20.glUniform4fv(mColorHandle, 1, color, 0); 

     mTextureUniformHandle = GLES20.glGetAttribLocation(mProgram, "u_Texture"); 
     mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate"); 

     GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle); 
     GLES20.glUniform1i(mTextureUniformHandle, 0); 

     mCubeTextureCoordinates.position(0); 
     GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, 
     GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates); 
     GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 

     mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
     GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 
     GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, 
     GLES20.GL_UNSIGNED_SHORT, drawListBuffer); 
     GLES20.glDisableVertexAttribArray(mPositionHandle); 
    } 
} 

Проблема заключается в том, что я не знаю, как распространять свой фон (256x256) по большой площади (не ограниченного размера экрана). currenty, текстура повторяется только на краях экрана. И когда им пытаются переместить его (с помощью SetLookAtm()) она движется нормально, но оставляет пустую полосу позади:

Начальное фоновое изображение (BMP-обращенную):

ab 
cd 

Фоновое изображение на экране:

-------- 
|ababab| 
|cdcdcd| 
|ababab| 
|cdcdcd| 
|ababab| 
|cdcdcd| 
-------- 

Фоновое изображение после переезда (справа ->)

-------- 
| abab| 
| cdcd| 
| abab| 
| cdcd| 
| abab| 
| cdcd| 
-------- 

Направление (слева, RIGH t, вверх, вниз) не имеет значения. Она имеет только эффект на какой стороне полоса появляется

ответ

0

Либо:

A) Определить фоновый прямоугольник так, что он выходит за пределы края экрана (и «прокручивать» фон оживляющий свои позиции)

-------- 
|ababab|ababab 
|cdcdcd|cdcdcd 
|ababab|ababab 
|cdcdcd|cdcdcd 
|ababab|ababab 
|cdcdcd|cdcdcd 
-------- 

или:

B) Определить Б.Г. прямоугольник, заполняющий экран, как и раньше, но анимировать координаты текстуры, чтобы сделать его прокрутку. Например: Если ваши texcoords образуют прямоугольник (0.00,0.00)->(1.00,1.00), затем прокрутите bg слева, изменив texcoords на (0.05,0.00)->(1.05,1.00). Убедитесь, что вы установили glTexParameteri следующим образом:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
+0

Я действительно хочу сделать так, как вы описали в «A» «Но я не могу. Как вы можете видеть в моем коде, я пытаюсь определить прямоугольник фона в 15 раз больше размера экрана. Но он точно соответствует размеру экрана. Не могли бы вы предоставить некоторый код о том, как определить такой большой прямоугольник фона? –

+0

Ваш прямоугольник не соответствует размеру экрана точно. Ваши текстурные координаты, которые должны идти от (0,0) до (1,1), идут от (-15, -15) до (15,15), поэтому текстура повторяется 30 раз на экране, заставляя его казаться " точно соответствует ». Вы должны прочитать, как правильно использовать texcoords и сначала исправить cubeTextureCoordinateData. –

+0

Когда я меняю текстурные координаты, окончательное фоновое изображение просто масштабируется или вниз (повторите 30 раз, например, как вы сказали). Но он всегда обрезается по краям экрана. И когда я его перемещаю (setLookAt), он перемещается, оставляя пустую полосу позади. –

Смежные вопросы