我是OpenGL的新手,我正在通过使用ES 2.0为
Android制作2D游戏来自学.我首先创建一个“Sprite”类,创建一个平面并为其渲染纹理.为了练习,我有两个Sprite对象在同一个地方交替绘制.我用ES 1.0很好地工作了,但是现在我已经切换到2.0,我得到了一个没有错误的黑屏.我已经筋疲力尽地想弄清楚我做错了什么,但我有一种强烈的感觉,它与我的着色器有关.我将把所有相关的代码转储到这里,希望有人可以给我一个答案,或者告诉我我做错了什么.如果不能立即明白我做错了什么,或许就如何解决这个问题提出一些建议?提前感谢您浏览我即将发布的所有代码.
我发布的三个课程是:
GameRenderer – 我的GLSurfaceView的渲染器
着色器 – 创建着色器程序对象
精灵 – 创建一个正方形并在其上绘制纹理
此外,我将发布我的顶点和片段着色器源.
我认为没有足够相关的相关课程发布:
GameActivity
GameView – 一个GLSurfaceView
GameLoopThread – 我的主要游戏循环
FPSCounter – 每100帧将平均FPS输出到logcat.
GameRender类:
package com.detour.raw; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.opengl.GLES20; import android.opengl.GLU; import android.opengl.Matrix; import android.opengl.GLSurfaceView; public class GameRenderer implements GLSurfaceView.Renderer{ private static final String LOG_TAG = GameRenderer.class.getSimpleName(); Context mContext; Bitmap bitmap; private float red = 0.0f; private float green = 0.0f; private float blue = 0.0f; Shader shader; FPSCounter fps; Sprite sprite; Sprite sprite2; int x = 0; private float[] mProjMatrix = new float[16]; private float[] mVMatrix = new float[16]; //int[] vertexShader; //int[] fragmentShader; //int program; //String vShaderSource = ""; //String fShaderSource = ""; public GameRenderer(Context context){ mContext = context; //create objects/sprites sprite = new Sprite(mContext); sprite2 = new Sprite(mContext); fps = new FPSCounter(); } @Override public void onDrawFrame(GL10 gl) { GLES20.glClearColor(red,green,blue,1.0f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); if(x>3){ x=0; } if(x%2==0){ sprite.draw(gl); }else{ sprite2.draw(gl); } x++; fps.calculate(); //fps.draw(gl); } @Override public void onSurfaceChanged(GL10 gl,int width,int height) { GLES20.glViewport(0,width,height); float ratio = (float)(width/height); Matrix.frustumM(mProjMatrix,-ratio,ratio,-1,1,0.5f,10); } @Override public void onSurfaceCreated(GL10 gl,EGLConfig config) { // TODO Auto-generated method stub GLES20.glEnable(GLES20.GL_TEXTURE_2D); GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glClearDepthf(1.0f); GLES20.glDepthFunc(GLES20.GL_LEQUAL); GLES20.glDepthMask(true); GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glCullFace(GLES20.GL_BACK); GLES20.glClearColor(red,1.0f); //load sprite/object textures (preferably loop through an array of all sprites). sprite.loadGLTexture(gl,mContext,R.drawable.raw1); sprite2.loadGLTexture(gl,R.drawable.raw2); Matrix.setLookAtM(mVMatrix,-5.0f,0.0f,0f,0.0f); System.gc(); } }
着色器类:
package com.detour.raw; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import android.content.Context; import android.opengl.GLES20; import android.util.Log; public class Shader { public static final String TAG = Shader.class.getSimpleName(); int program; int vertexShader; int fragmentShader; String vShaderSource; String fShaderSource; public Shader(){ //blank constructor //createProgram(); } public Shader(String vs_source,String fs_source){ this.vShaderSource = vs_source; this.fShaderSource = fs_source; createProgram(); } public Shader(int vs_source_id,int fs_source_id,Context context) { StringBuffer vs = new StringBuffer(); StringBuffer fs = new StringBuffer(); try{ InputStream inputStream = context.getResources().openRawResource(vs_source_id); BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); String read = in.readLine(); while (read != null) { vs.append(read + "\n"); read = in.readLine(); } vs.deleteCharAt(vs.length() - 1); inputStream = context.getResources().openRawResource(fs_source_id); in = new BufferedReader(new InputStreamReader(inputStream)); read = in.readLine(); while (read != null) { fs.append(read + "\n"); read = in.readLine(); } fs.deleteCharAt(fs.length() - 1); }catch (Exception e){ Log.d("ERROR-readingShader","Could not read shader: " + e.getLocalizedMessage()); } this.vShaderSource = vs.toString(); this.fShaderSource = fs.toString(); createProgram(); } private void createProgram(){ program = GLES20.glCreateProgram(); if(program!=0){ vertexShader = createShader(GLES20.GL_VERTEX_SHADER,vShaderSource); fragmentShader = createShader(GLES20.GL_FRAGMENT_SHADER,fShaderSource); GLES20.glAttachShader(program,vertexShader); GLES20.glAttachShader(program,fragmentShader); GLES20.glLinkProgram(program); }else{ Log.e(TAG,"Couldn't create program."); } } private int createShader(int type,String source){ int shader = GLES20.glCreateShader(type); if(shader!=0){ GLES20.glShaderSource(shader,source); GLES20.glCompileShader(shader); } return shader; } public int getProgram(){ return program; }
精灵类:
package com.detour.raw; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLES20; import android.opengl.GLUtils; public class Sprite { //public static final int FRAME_WIDTH = 64; //public static final int FRAME_HEIGHT = 64; private static final String LOG_TAG = Sprite.class.getSimpleName(); Context mContext; Bitmap bitmap; private int textureLoc; private int vertexLoc; private int[] textures = new int[1]; //private int[] pixels; /*private float textureCoordinates[] = { 0.0f,1.0f,0.0f};*/ private float vertices[] = { -1.0f,// 0.0f,-1.0f,1.0f// 0.0f }; private short[] indices = { 0,2,3}; private FloatBuffer vertexBuffer; //private IntBuffer textureBuffer; private ShortBuffer indexBuffer; Shader shader; int program; String vShaderSource = ""; String fShaderSource = ""; public Sprite(Context context){ mContext = context; ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); ibb.order(ByteOrder.nativeOrder()); indexBuffer = ibb.asShortBuffer(); indexBuffer.put(indices); indexBuffer.position(0); } public void draw(GL10 gl) { GLES20.glDrawElements(GLES20.GL_TRIANGLES,indices.length,GLES20.GL_FLOAT,indexBuffer); } public void loadGLTexture(GL10 gl,Context context,int id){ shader = new Shader(R.raw.sprite_vs,R.raw.sprite_fs,mContext); program = shader.getProgram(); GLES20.glUseProgram(program); vertexLoc = GLES20.glGetAttribLocation(program,"a_position"); textureLoc = GLES20.glGetUniformLocation(program,"u_texture"); //texture InputStream is = context.getResources().openRawResource(id); try { bitmap = BitmapFactory.decodeStream(is); } finally { try { is.close(); is = null; } catch (IOException e) { } } //pixels = new int[(bitmap.getWidth()*bitmap.getHeight())]; //bitmap.getPixels(pixels,bitmap.getWidth(),bitmap.getHeight()); /*ByteBuffer byteBuf = ByteBuffer.allocateDirect(pixels.length * 4); byteBuf.order(ByteOrder.nativeOrder()); textureBuffer = byteBuf.asIntBuffer(); textureBuffer.put(pixels); textureBuffer.position(0);*/ GLES20.glDeleteTextures(1,textures,0); GLES20.glGenTextures(1,0); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0]); GLES20.glUniform1i(textureLoc,0); GLES20.glEnableVertexAttribArray(vertexLoc); GLES20.glVertexAttribPointer(vertexLoc,false,vertexBuffer); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT); //GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,GLES20.GL_RGBA,FRAME_WIDTH,FRAME_HEIGHT,GLES20.GL_UNSIGNED_BYTE,byteBuf);//(GLES20.GL_TEXTURE_2D,bitmap,0); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0); bitmap.recycle(); } }
顶点着色器(sprite_vs.txt):
#version 110 attribute vec2 a_position; varying vec2 v_texcoord; void main() { gl_Position = vec4(a_position,0.0,1.0); v_texcoord = a_position * vec2(0.5) + vec2(0.5); }
片段(像素)着色器(sprite_fs.txt):
#version 110 uniform sampler2D u_texture; varying vec2 v_texcoord; void main() { gl_FragColor = texture2D(u_texture,v_texcoord); }
非常感谢你,如果你真的花时间仔细研究这个!希望其他人也可以在将来使用它作为自己的资源.