Я пытаюсь получить изображение 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, вверх, вниз) не имеет значения. Она имеет только эффект на какой стороне полоса появляется
Я действительно хочу сделать так, как вы описали в «A» «Но я не могу. Как вы можете видеть в моем коде, я пытаюсь определить прямоугольник фона в 15 раз больше размера экрана. Но он точно соответствует размеру экрана. Не могли бы вы предоставить некоторый код о том, как определить такой большой прямоугольник фона? –
Ваш прямоугольник не соответствует размеру экрана точно. Ваши текстурные координаты, которые должны идти от (0,0) до (1,1), идут от (-15, -15) до (15,15), поэтому текстура повторяется 30 раз на экране, заставляя его казаться " точно соответствует ». Вы должны прочитать, как правильно использовать texcoords и сначала исправить cubeTextureCoordinateData. –
Когда я меняю текстурные координаты, окончательное фоновое изображение просто масштабируется или вниз (повторите 30 раз, например, как вы сказали). Но он всегда обрезается по краям экрана. И когда я его перемещаю (setLookAt), он перемещается, оставляя пустую полосу позади. –