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
- android studio 使用opengl es布置游戏背景
- Android studio中使用opengl es绘图
- android游戏开发-OPENGL ES
- android中使用OpenGL ES
- Android Training - 使用OpenGL ES(1) - 构建OpenGL ES环境
- Android开发:用OpenGL ES实现GLSurfaceView背景透明
- android openGL使用透明背景
- Android 如何使用NDK开发OPenGL ES
- Android OpenGL ES 开发中的Buffer使用
- Android 如何使用NDK开发OPenGL ES
- Android OpenGL ES 开发中的Buffer使用
- android使用OpenGL ES显示图形
- android使用OpenGL ES定义图片形状
- Android OpenGL ES拾取(使用Java)
- Android中的OpenGL ES使用案例
- android游戏开发(OpenGL ES绘制矩形平面)
- android studio上第一个opengl es程序
- android opengl es 源码
- Swift 开源库
- ECS Windows服务器之DFS文件同步
- Python数据采集之BeautifulSoup
- 微信小程序教程:文字跑马灯效果
- 每天定时备份数据库
- android studio 使用opengl es布置游戏背景
- 徐汉彬:Web系统大规模并发——电商秒杀与抢购
- warning: -D_SCL_SECURE_NO_WARNINGS
- jsessionid传送对session实现机制的影响 jsessionid传送对session实现机制的影响
- 5月4日青年节
- js中的回调函数的理解和使用方法
- 音频二--音乐
- anaconda下面安装opencv
- android 自定义ImageView控件实现圆形图片-适用于用户头像