java – 适用于Android的OpenGL ES 2.0中的纹理

前端之家收集整理的这篇文章主要介绍了java – 适用于Android的OpenGL ES 2.0中的纹理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我是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);
}

非常感谢你,如果你真的花时间仔细研究这个!希望其他人也可以在将来使用它作为自己的资源.

解决方法

一些意见/问题:

>我不知道您是如何更改片段着色器的,但当前发布的版本需要精度说明符.只需添加

precision mediump float;

到顶部,它应该工作.现在关于黑屏这里有一些问题:>当你将glClearColor更改为非黑色并注释掉所有绘图命令时,它是否仍然看起来是黑色的?如果是这样,那么你有一个比纹理更大的问题.>其次,如果忽略纹理输出并尝试将每个精灵绘制为一个没有纹理数据的平面彩色矩形,你会得到什么?您应该能够在屏幕上看到一些彩色矩形.>最后,您需要在调用glDrawElements之前绑定纹理. (虽然这个例子无关紧要,因为你还没有改变状态.)

猜你在找的Android相关文章