256 lines
8.9 KiB
Java
256 lines
8.9 KiB
Java
package com.ea.ironmonkey;
|
|
|
|
import android.app.Activity;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.opengl.GLES20;
|
|
import android.opengl.GLUtils;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.Buffer;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteOrder;
|
|
import java.nio.FloatBuffer;
|
|
import javax.microedition.khronos.opengles.GL10;
|
|
|
|
|
|
public class SplashScreen {
|
|
private static final String TAG = "SplashScreen";
|
|
private Activity _activity;
|
|
private int _attPosition;
|
|
private int _attSampler;
|
|
private int _attTexCoord;
|
|
private int _fragmentShader;
|
|
private int _program;
|
|
private int _vertexShader;
|
|
private FloatBuffer vBuffer;
|
|
|
|
// Вершинный шейдер
|
|
private final String vShaderStr =
|
|
"attribute vec4 a_position; \n" +
|
|
"attribute vec2 a_texCoord; \n" +
|
|
"varying vec2 v_texCoord; \n" +
|
|
"void main() { \n" +
|
|
" gl_Position = a_position; \n" +
|
|
" v_texCoord = a_texCoord; \n" +
|
|
"} \n";
|
|
|
|
// Фрагментный шейдер
|
|
private final String fShaderStr =
|
|
"precision mediump float; \n" +
|
|
"varying vec2 v_texCoord; \n" +
|
|
"uniform sampler2D s_texture; \n" +
|
|
"void main() { \n" +
|
|
" gl_FragColor = texture2D(s_texture, v_texCoord); \n" +
|
|
"} \n";
|
|
|
|
private int[] _textureId = new int[1];
|
|
|
|
public SplashScreen(Activity activity) {
|
|
this._activity = activity;
|
|
}
|
|
|
|
public void init(GL10 gl10, int width, int height) {
|
|
if (!initRenderer()) {
|
|
destroy(gl10);
|
|
return;
|
|
}
|
|
|
|
// Загрузка текстуры
|
|
GLES20.glGenTextures(1, _textureId, 0);
|
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureId[0]);
|
|
|
|
// Установка параметров текстуры
|
|
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);
|
|
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);
|
|
|
|
// Загрузка изображения
|
|
Bitmap bitmap = null;
|
|
try {
|
|
InputStream is = _activity.getAssets().open("splash.png");
|
|
bitmap = BitmapFactory.decodeStream(is);
|
|
} catch (IOException e) {
|
|
Log.e(TAG, "Could not load bitmap", e);
|
|
}
|
|
|
|
if (bitmap != null) {
|
|
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
|
|
bitmap.recycle();
|
|
} else {
|
|
Log.e(TAG, "Failed to load bitmap");
|
|
destroy(gl10);
|
|
return;
|
|
}
|
|
|
|
// Проверка ошибок
|
|
int error = GLES20.glGetError();
|
|
if (error != GLES20.GL_NO_ERROR) {
|
|
Log.e(TAG, "Texture Load GLError: " + error);
|
|
destroy(gl10);
|
|
}
|
|
}
|
|
|
|
private boolean initRenderer() {
|
|
// Загрузка шейдеров
|
|
_vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vShaderStr);
|
|
_fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fShaderStr);
|
|
|
|
// Создание программы
|
|
_program = GLES20.glCreateProgram();
|
|
if (_program == 0) {
|
|
Log.e(TAG, "Failed to create program");
|
|
return false;
|
|
}
|
|
|
|
// Прикрепление шейдеров
|
|
GLES20.glAttachShader(_program, _vertexShader);
|
|
GLES20.glAttachShader(_program, _fragmentShader);
|
|
|
|
// Линковка программы
|
|
GLES20.glLinkProgram(_program);
|
|
|
|
// Проверка статуса линковки
|
|
int[] linkStatus = new int[1];
|
|
GLES20.glGetProgramiv(_program, GLES20.GL_LINK_STATUS, linkStatus, 0);
|
|
if (linkStatus[0] != GLES20.GL_TRUE) {
|
|
Log.e(TAG, "Could not link program: " + GLES20.glGetProgramInfoLog(_program));
|
|
GLES20.glDeleteProgram(_program);
|
|
_program = 0;
|
|
return false;
|
|
}
|
|
|
|
// Получение атрибутов
|
|
_attPosition = GLES20.glGetAttribLocation(_program, "a_position");
|
|
_attTexCoord = GLES20.glGetAttribLocation(_program, "a_texCoord");
|
|
_attSampler = GLES20.glGetUniformLocation(_program, "s_texture");
|
|
|
|
return true;
|
|
}
|
|
|
|
private int loadShader(int type, String shaderCode) {
|
|
int shader = GLES20.glCreateShader(type);
|
|
if (shader == 0) {
|
|
Log.e(TAG, "Failed to create shader");
|
|
return 0;
|
|
}
|
|
|
|
GLES20.glShaderSource(shader, shaderCode);
|
|
GLES20.glCompileShader(shader);
|
|
|
|
// Проверка статуса компиляции
|
|
int[] compiled = new int[1];
|
|
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
|
|
if (compiled[0] == 0) {
|
|
Log.e(TAG, "Could not compile shader: " + GLES20.glGetShaderInfoLog(shader));
|
|
GLES20.glDeleteShader(shader);
|
|
return 0;
|
|
}
|
|
|
|
return shader;
|
|
}
|
|
|
|
public boolean draw(GL10 gl10, int width, int height) {
|
|
if (_textureId[0] == 0 || _program == 0) {
|
|
return false;
|
|
}
|
|
|
|
// Расчет координат с уменьшением на 20%
|
|
float ratio = (float) width / height;
|
|
float imageRatio = 1.0f; // Предполагаем квадратное изображение
|
|
|
|
float scaleX, scaleY;
|
|
if (ratio > imageRatio) {
|
|
// Шире, чем изображение
|
|
scaleY = 0.8f; // Уменьшаем на 20%
|
|
scaleX = imageRatio / ratio * 0.8f;
|
|
} else {
|
|
// Уже, чем изображение
|
|
scaleX = 0.8f; // Уменьшаем на 20%
|
|
scaleY = ratio / imageRatio * 0.8f;
|
|
}
|
|
|
|
// Координаты вершин и текстур
|
|
float[] vertices = {
|
|
-scaleX, -scaleY, 0.0f, // нижний левый
|
|
scaleX, -scaleY, 0.0f, // нижний правый
|
|
-scaleX, scaleY, 0.0f, // верхний левый
|
|
scaleX, scaleY, 0.0f // верхний правый
|
|
};
|
|
|
|
float[] texCoords = {
|
|
0.0f, 1.0f, // нижний левый
|
|
1.0f, 1.0f, // нижний правый
|
|
0.0f, 0.0f, // верхний левый
|
|
1.0f, 0.0f // верхний правый
|
|
};
|
|
|
|
// Создание буферов
|
|
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
|
|
bb.order(ByteOrder.nativeOrder());
|
|
FloatBuffer vertexBuffer = bb.asFloatBuffer();
|
|
vertexBuffer.put(vertices);
|
|
vertexBuffer.position(0);
|
|
|
|
bb = ByteBuffer.allocateDirect(texCoords.length * 4);
|
|
bb.order(ByteOrder.nativeOrder());
|
|
FloatBuffer texBuffer = bb.asFloatBuffer();
|
|
texBuffer.put(texCoords);
|
|
texBuffer.position(0);
|
|
|
|
// Отрисовка с белым фоном
|
|
GLES20.glViewport(0, 0, width, height);
|
|
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Белый цвет
|
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
|
|
|
GLES20.glUseProgram(_program);
|
|
|
|
// Передача вершин
|
|
GLES20.glVertexAttribPointer(_attPosition, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
|
|
GLES20.glEnableVertexAttribArray(_attPosition);
|
|
|
|
// Передача текстурных координат
|
|
GLES20.glVertexAttribPointer(_attTexCoord, 2, GLES20.GL_FLOAT, false, 0, texBuffer);
|
|
GLES20.glEnableVertexAttribArray(_attTexCoord);
|
|
|
|
// Активация текстуры
|
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureId[0]);
|
|
GLES20.glUniform1i(_attSampler, 0);
|
|
|
|
// Отрисовка
|
|
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
// Отключение атрибутов
|
|
GLES20.glDisableVertexAttribArray(_attPosition);
|
|
GLES20.glDisableVertexAttribArray(_attTexCoord);
|
|
|
|
return true;
|
|
}
|
|
|
|
public void destroy(GL10 gl10) {
|
|
if (_textureId[0] != 0) {
|
|
GLES20.glDeleteTextures(1, _textureId, 0);
|
|
_textureId[0] = 0;
|
|
}
|
|
if (_program != 0) {
|
|
GLES20.glDeleteProgram(_program);
|
|
_program = 0;
|
|
}
|
|
if (_vertexShader != 0) {
|
|
GLES20.glDeleteShader(_vertexShader);
|
|
_vertexShader = 0;
|
|
}
|
|
if (_fragmentShader != 0) {
|
|
GLES20.glDeleteShader(_fragmentShader);
|
|
_fragmentShader = 0;
|
|
}
|
|
if (vBuffer != null) {
|
|
vBuffer.clear();
|
|
vBuffer = null;
|
|
}
|
|
}
|
|
}
|