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; } } }