android studio 使用opengl es布置游戏背景

来源:互联网 发布:淘宝投诉服务态度 编辑:程序博客网 时间:2024/05/29 17:26

首先新建一个activity用于屏幕的view

package com.example.wang.airhockey3d;import android.opengl.GLSurfaceView;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;public class AirHockeyActivity extends AppCompatActivity {    private GLSurfaceView glSurfaceView;    private boolean rendererSet = false;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        glSurfaceView = new GLSurfaceView(this);        glSurfaceView.setEGLContextClientVersion(2);        glSurfaceView.setRenderer(new AirHockeyRenderer(this));        setContentView(glSurfaceView);    }    @Override    protected void onPause() {        super.onPause();        if (rendererSet) {            glSurfaceView.onPause();        }    }    @Override    protected void onResume() {        super.onResume();        if (rendererSet) {            glSurfaceView.onResume();        }    }}

最重要的是有一个新渲染类, new AirHockeyRenderer(this)

package com.example.wang.airhockey3d;import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;import static android.opengl.GLES20.GL_FLOAT;import static android.opengl.GLES20.GL_LINES;import static android.opengl.GLES20.GL_POINTS;import static android.opengl.GLES20.GL_TRIANGLE_FAN;import static android.opengl.GLES20.glClear;import static android.opengl.GLES20.glClearColor;import static android.opengl.GLES20.glDrawArrays;import static android.opengl.GLES20.glEnableVertexAttribArray;import static android.opengl.GLES20.glGetAttribLocation;import static android.opengl.GLES20.glGetUniformLocation;import static android.opengl.GLES20.glUniformMatrix4fv;import static android.opengl.GLES20.glUseProgram;import static android.opengl.GLES20.glVertexAttribPointer;import static android.opengl.GLES20.glViewport;import static android.opengl.Matrix.multiplyMM;import static android.opengl.Matrix.rotateM;import static android.opengl.Matrix.setIdentityM;import static android.opengl.Matrix.translateM;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.content.Context;import android.opengl.GLSurfaceView.Renderer;public class AirHockeyRenderer implements Renderer {    private static final String U_MATRIX = "u_Matrix";    private static final String A_POSITION = "a_Position";    private static final String A_COLOR = "a_Color";    /*    private static final int POSITION_COMPONENT_COUNT = 4;    */    private static final int POSITION_COMPONENT_COUNT = 2;    private static final int COLOR_COMPONENT_COUNT = 3;    private static final int BYTES_PER_FLOAT = 4;    private static final int STRIDE =            (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;    private final FloatBuffer vertexData;    private final Context context;    private final float[] projectionMatrix = new float[16];    private final float[] modelMatrix = new float[16];    private int program;    private int uMatrixLocation;    private int aPositionLocation;    private int aColorLocation;    public AirHockeyRenderer(Context context) {        this.context = context;        /*        float[] tableVerticesWithTriangles = {            // Order of coordinates: X, Y, Z, W, R, G, B            // Triangle Fan               0f,    0f, 0f, 1.5f,   1f,   1f,   1f,            -0.5f, -0.8f, 0f,   1f, 0.7f, 0.7f, 0.7f,             0.5f, -0.8f, 0f,   1f, 0.7f, 0.7f, 0.7f,             0.5f,  0.8f, 0f,   2f, 0.7f, 0.7f, 0.7f,            -0.5f,  0.8f, 0f,   2f, 0.7f, 0.7f, 0.7f,            -0.5f, -0.8f, 0f,   1f, 0.7f, 0.7f, 0.7f,            // Line 1            -0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,             0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,            // Mallets            0f, -0.4f, 0f, 1.25f, 0f, 0f, 1f,            0f,  0.4f, 0f, 1.75f, 1f, 0f, 0f        };        */        float[] tableVerticesWithTriangles = {                // Order of coordinates: X, Y, R, G, B                // Triangle Fan                0f,     0f,    1f,    1f,    1f,                -0.5f, -0.8f, 0.7f, 0.7f, 0.7f,                0.5f, -0.8f, 0.7f, 0.7f, 0.7f,                0.5f,  0.8f, 0.7f, 0.7f, 0.7f,                -0.5f,  0.8f, 0.7f, 0.7f, 0.7f,                -0.5f, -0.8f, 0.7f, 0.7f, 0.7f,                // Line 1                -0.5f, 0f, 1f, 0f, 0f,                0.5f, 0f, 1f, 0f, 0f,                // Mallets                0f, -0.4f, 0f, 0f, 1f,                0f,  0.4f, 1f, 0f, 0f        };        vertexData = ByteBuffer                .allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)                .order(ByteOrder.nativeOrder()).asFloatBuffer();        vertexData.put(tableVerticesWithTriangles);    }    @Override    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);        String vertexShaderSource = TextResourceReader                .readTextFileFromResource(context, R.raw.simple_vertex_shader);        String fragmentShaderSource = TextResourceReader                .readTextFileFromResource(context, R.raw.simple_fragment_shader);        int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);        int fragmentShader = ShaderHelper                .compileFragmentShader(fragmentShaderSource);        program = ShaderHelper.linkProgram(vertexShader, fragmentShader);        if (LoggerConfig.ON) {            ShaderHelper.validateProgram(program);        }        glUseProgram(program);        uMatrixLocation = glGetUniformLocation(program, U_MATRIX);        aPositionLocation = glGetAttribLocation(program, A_POSITION);        aColorLocation = glGetAttribLocation(program, A_COLOR);        // Bind our data, specified by the variable vertexData, to the vertex        // attribute at location A_POSITION_LOCATION.        vertexData.position(0);        glVertexAttribPointer(aPositionLocation,                POSITION_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, vertexData);        glEnableVertexAttribArray(aPositionLocation);        // Bind our data, specified by the variable vertexData, to the vertex        // attribute at location A_COLOR_LOCATION.        vertexData.position(POSITION_COMPONENT_COUNT);        glVertexAttribPointer(aColorLocation,                COLOR_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, vertexData);        glEnableVertexAttribArray(aColorLocation);    }    /**     * onSurfaceChanged is called whenever the surface has changed. This is     * called at least once when the surface is initialized. Keep in mind that     * Android normally restarts an Activity on rotation, and in that case, the     * renderer will be destroyed and a new one created.     *     * @param width     *            The new width, in pixels.     * @param height     *            The new height, in pixels.     */    @Override    public void onSurfaceChanged(GL10 glUnused, int width, int height) {        // Set the OpenGL viewport to fill the entire surface.        glViewport(0, 0, width, height);        /*        final float aspectRatio = width > height ?            (float) width / (float) height :            (float) height / (float) width;        if (width > height) {            // Landscape            orthoM(projectionMatrix, 0,                -aspectRatio, aspectRatio,                -1f, 1f,                -1f, 1f);        } else {            // Portrait or square            orthoM(projectionMatrix, 0,                -1f, 1f,                -aspectRatio, aspectRatio,                -1f, 1f);        }        */        MatrixHelper.perspectiveM(projectionMatrix, 45, (float) width                / (float) height, 1f, 10f);        /*        setIdentityM(modelMatrix, 0);        translateM(modelMatrix, 0, 0f, 0f, -2f);        */        setIdentityM(modelMatrix, 0);        translateM(modelMatrix, 0, 0f, 0f, -2.5f);        rotateM(modelMatrix, 0, -60f, 1f, 0f, 0f);        final float[] temp = new float[16];        multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);        System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);    }    /**     * OnDrawFrame is called whenever a new frame needs to be drawn. Normally,     * this is done at the refresh rate of the screen.     */    @Override    public void onDrawFrame(GL10 glUnused) {        // Clear the rendering surface.        glClear(GL_COLOR_BUFFER_BIT);        // Assign the matrix        glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);        // Draw the table.        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);        // Draw the center dividing line.        glDrawArrays(GL_LINES, 6, 2);        // Draw the first mallet.        glDrawArrays(GL_POINTS, 8, 1);        // Draw the second mallet.        glDrawArrays(GL_POINTS, 9, 1);    }}

剩下的是一些辅助类,这个编译,链接shader时用的。

package com.example.wang.airhockey3d;/** * Created by wang on 17-5-4. */import static android.opengl.GLES20.GL_COMPILE_STATUS;import static android.opengl.GLES20.GL_FRAGMENT_SHADER;import static android.opengl.GLES20.GL_LINK_STATUS;import static android.opengl.GLES20.GL_VALIDATE_STATUS;import static android.opengl.GLES20.GL_VERTEX_SHADER;import static android.opengl.GLES20.glAttachShader;import static android.opengl.GLES20.glCompileShader;import static android.opengl.GLES20.glCreateProgram;import static android.opengl.GLES20.glCreateShader;import static android.opengl.GLES20.glDeleteProgram;import static android.opengl.GLES20.glDeleteShader;import static android.opengl.GLES20.glGetProgramInfoLog;import static android.opengl.GLES20.glGetProgramiv;import static android.opengl.GLES20.glGetShaderInfoLog;import static android.opengl.GLES20.glGetShaderiv;import static android.opengl.GLES20.glLinkProgram;import static android.opengl.GLES20.glShaderSource;import static android.opengl.GLES20.glValidateProgram;import android.util.Log;public class ShaderHelper {    private static final String TAG = "ShaderHelper";    /**     * Loads and compiles a vertex shader, returning the OpenGL object ID.     */    public static int compileVertexShader(String shaderCode) {        return compileShader(GL_VERTEX_SHADER, shaderCode);    }    /**     * Loads and compiles a fragment shader, returning the OpenGL object ID.     */    public static int compileFragmentShader(String shaderCode) {        return compileShader(GL_FRAGMENT_SHADER, shaderCode);    }    /**     * Compiles a shader, returning the OpenGL object ID.     */    private static int compileShader(int type, String shaderCode) {        // Create a new shader object.        final int shaderObjectId = glCreateShader(type);        if (shaderObjectId == 0) {            if (LoggerConfig.ON) {                Log.w(TAG, "Could not create new shader.");            }            return 0;        }        // Pass in the shader source.        glShaderSource(shaderObjectId, shaderCode);        // Compile the shader.        glCompileShader(shaderObjectId);        // Get the compilation status.        final int[] compileStatus = new int[1];        glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS,                compileStatus, 0);        if (LoggerConfig.ON) {            // Print the shader info log to the Android log output.            Log.v(TAG, "Results of compiling source:"                    + "\n" + shaderCode + "\n:"                    + glGetShaderInfoLog(shaderObjectId));        }        // Verify the compile status.        if (compileStatus[0] == 0) {            // If it failed, delete the shader object.            glDeleteShader(shaderObjectId);            if (LoggerConfig.ON) {                Log.w(TAG, "Compilation of shader failed.");            }            return 0;        }        // Return the shader object ID.        return shaderObjectId;    }    /**     * Links a vertex shader and a fragment shader together into an OpenGL     * program. Returns the OpenGL program object ID, or 0 if linking failed.     */    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {        // Create a new program object.        final int programObjectId = glCreateProgram();        if (programObjectId == 0) {            if (LoggerConfig.ON) {                Log.w(TAG, "Could not create new program");            }            return 0;        }        // Attach the vertex shader to the program.        glAttachShader(programObjectId, vertexShaderId);        // Attach the fragment shader to the program.        glAttachShader(programObjectId, fragmentShaderId);        // Link the two shaders together into a program.        glLinkProgram(programObjectId);        // Get the link status.        final int[] linkStatus = new int[1];        glGetProgramiv(programObjectId, GL_LINK_STATUS,                linkStatus, 0);        if (LoggerConfig.ON) {            // Print the program info log to the Android log output.            Log.v(TAG, "Results of linking program:\n"                    + glGetProgramInfoLog(programObjectId));        }        // Verify the link status.        if (linkStatus[0] == 0) {            // If it failed, delete the program object.            glDeleteProgram(programObjectId);            if (LoggerConfig.ON) {                Log.w(TAG, "Linking of program failed.");            }            return 0;        }        // Return the program object ID.        return programObjectId;    }    /**     * Validates an OpenGL program. Should only be called when developing the     * application.     */    public static boolean validateProgram(int programObjectId) {        glValidateProgram(programObjectId);        final int[] validateStatus = new int[1];        glGetProgramiv(programObjectId, GL_VALIDATE_STATUS,                validateStatus, 0);        Log.v(TAG, "Results of validating program: " + validateStatus[0]                + "\nLog:" + glGetProgramInfoLog(programObjectId));        return validateStatus[0] != 0;    }}

package com.example.wang.airhockey3d;/** * Created by wang on 17-5-4. */public class MatrixHelper {    public static void perspectiveM(float[] m, float yFovInDegrees, float aspect,                                    float n, float f) {        final float angleInRadians = (float) (yFovInDegrees * Math.PI / 180.0);        final float a = (float) (1.0 / Math.tan(angleInRadians / 2.0));        m[0] = a / aspect;        m[1] = 0f;        m[2] = 0f;        m[3] = 0f;        m[4] = 0f;        m[5] = a;        m[6] = 0f;        m[7] = 0f;        m[8] = 0f;        m[9] = 0f;        m[10] = -((f + n) / (f - n));        m[11] = -1f;        m[12] = 0f;        m[13] = 0f;        m[14] = -((2f * f * n) / (f - n));        m[15] = 0f;    }}

这个应该是在读取shader程序

package com.example.wang.airhockey3d;/** * Created by wang on 17-5-4. */import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import android.content.Context;import android.content.res.Resources;public class TextResourceReader {    /**     * Reads in text from a resource file and returns a String containing the     * text.     */    public static String readTextFileFromResource(Context context,                                                  int resourceId) {        StringBuilder body = new StringBuilder();        try {            InputStream inputStream = context.getResources()                    .openRawResource(resourceId);            InputStreamReader inputStreamReader = new InputStreamReader(                    inputStream);            BufferedReader bufferedReader = new BufferedReader(                    inputStreamReader);            String nextLine;            while ((nextLine = bufferedReader.readLine()) != null) {                body.append(nextLine);                body.append('\n');            }        } catch (IOException e) {            throw new RuntimeException(                    "Could not open resource: " + resourceId, e);        } catch (Resources.NotFoundException nfe) {            throw new RuntimeException("Resource not found: "                    + resourceId, nfe);        }        return body.toString();    }}

package com.example.wang.airhockey3d;/** * Created by wang on 17-5-4. */public class LoggerConfig {    public static final boolean ON = true;}

资源文件

precision mediump float;        varying vec4 v_Color;           void main()                    {                                  gl_FragColor = v_Color;                                  }

uniform mat4 u_Matrix;attribute vec4 a_Position;  attribute vec4 a_Color;varying vec4 v_Color;void main()                    {                                v_Color = a_Color;        gl_Position = u_Matrix * a_Position;    gl_PointSize = 10.0;          }

生成的效果


0 0
原创粉丝点击