【问题标题】:Creating texture atlas error (opengl ES 2.0, android)创建纹理图集错误(opengl ES 2.0,android)
【发布时间】:2013-08-01 14:28:59
【问题描述】:

我正在尝试使用 opengl ES 2.0 创建纹理图集。我想将许多小图像绑定在一个大图像中。它在模拟器中运行良好,但不适用于设备。 这是我的代码:

gl.glGenTextures(1, textureID, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.block);
ByteBuffer pixels   = ByteBuffer.allocate(bitmap.getWidth() * bitmap.getHeight() * 4);
bitmap.copyPixelsToBuffer(pixels);

gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, 0, 0, 0, bitmap.getWidth(), bitmap.getHeight(), GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixels);

第一个 Bitmap (bmp) 是 256x256 红色图像,第二个 Bitmap(bitmap) 是 16x16 白色图像。在模拟器中,我看到一个带有白色小图像的红色矩形,但在设备上我只能看到红色的大矩形。

【问题讨论】:

    标签: java android bitmap opengl-es-2.0 emulation


    【解决方案1】:

    您正在使用二次幂纹理,这很好,因为 OpenGL ES 2.0 的大多数实现不支持 npot 纹理。现在,因为您能够在模拟器上看到纹理,所以您似乎没有使用投影矩阵(MVP 矩阵)变换对象(要渲染)。这个例子展示了如何做到这一点 -

    public class GLES20Renderer implements Renderer {
    private int _planeProgram;
    private int _planeAPositionLocation;
    private int _planeACoordinateLocation;
    private int _planeUMVPLocation;
    private int _planeUSamplerLocation;
    private FloatBuffer _planeVFB;
    private FloatBuffer _planeTFB;
    private ShortBuffer _planeISB;
    
    private float[] _ViewMatrix         = new float[16];
    private float[] _ProjectionMatrix   = new float[16];
    private float[] _MVPMatrix          = new float[16];
    
    private int _textureId;
    public Context _context;
    
    public GLES20Renderer(Context context) {
        _context = context;
    }
    
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);
    }
    
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        initplane();
    
        float ratio = (float) width / height;
        float zNear = 0.1f;
        float zFar = 1000;
        float fov = 0.95f; // 0.2 to 1.0
        float size = (float) (zNear * Math.tan(fov / 2));
        Matrix.setLookAtM(_ViewMatrix, 0, 0, 0, 50, 0, 0, 0, 0, 1, 0);
        Matrix.frustumM(_ProjectionMatrix, 0, -size, size, -size / ratio, size / ratio, zNear, zFar);
    
        _planeProgram = loadProgram(_planeVertexShaderCode, _planeFragmentShaderCode);
    
        _planeAPositionLocation = GLES20.glGetAttribLocation(_planeProgram, "aPosition");
        _planeACoordinateLocation = GLES20.glGetAttribLocation(_planeProgram, "aCoord");
        _planeUMVPLocation = GLES20.glGetUniformLocation(_planeProgram, "uMVP");
        _planeUSamplerLocation = GLES20.glGetUniformLocation(_planeProgram, "uSampler");
    
        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);
        _textureId = textures[0];
    
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureId);
        InputStream is1 = _context.getResources().openRawResource(R.drawable.brick);
        Bitmap img1;
        try {
            img1 = BitmapFactory.decodeStream(is1);
        } finally {
            try {
                is1.close();
            } catch(IOException e) {
                //e.printStackTrace();
            }
        }
        GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); // GL_LINEAR
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img1, 0);
    }
    
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        Matrix.multiplyMM(_MVPMatrix, 0, _ProjectionMatrix, 0, _ViewMatrix, 0);
    
        GLES20.glUseProgram(_planeProgram);
    
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureId);
        GLES20.glUniform1i(_planeUSamplerLocation, 0);
    
        GLES20.glUniformMatrix4fv(_planeUMVPLocation, 1, false, _MVPMatrix, 0);
        GLES20.glVertexAttribPointer(_planeAPositionLocation, 3, GLES20.GL_FLOAT, false, 12, _planeVFB);
        GLES20.glEnableVertexAttribArray(_planeAPositionLocation);
        GLES20.glVertexAttribPointer(_planeACoordinateLocation, 2, GLES20.GL_FLOAT, false, 8, _planeTFB);
        GLES20.glEnableVertexAttribArray(_planeACoordinateLocation);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, _planeISB);
        System.gc();
    }
    
    public static void setZAngle(float angle) {
        GLES20Renderer._zAngle = angle;
    }
    
    public static float getZAngle() {
        return GLES20Renderer._zAngle;
    }
    
    private void initplane() {
        float[] planeVFA = {
                10.000000f,-10.000000f,0.000000f,
                -10.000000f,-10.000000f,0.000000f,
                10.000000f,10.000000f,0.000000f,
                -10.000000f,10.000000f,0.000000f,
        };
    
        float[] planeTFA = {
                // 1,0, 0,0, 1,1, 0,1
                1,1, 0,1, 1,0, 0,0
        };
    
        short[] planeISA = {
                2,3,1,
                0,2,1,
        };
    
        ByteBuffer planeVBB = ByteBuffer.allocateDirect(planeVFA.length * 4);
        planeVBB.order(ByteOrder.nativeOrder());
        _planeVFB = planeVBB.asFloatBuffer();
        _planeVFB.put(planeVFA);
        _planeVFB.position(0);
    
        ByteBuffer planeTBB = ByteBuffer.allocateDirect(planeTFA.length * 4);
        planeTBB.order(ByteOrder.nativeOrder());
        _planeTFB = planeTBB.asFloatBuffer();
        _planeTFB.put(planeTFA);
        _planeTFB.position(0);
    
        ByteBuffer planeIBB = ByteBuffer.allocateDirect(planeISA.length * 2);
        planeIBB.order(ByteOrder.nativeOrder());
        _planeISB = planeIBB.asShortBuffer();
        _planeISB.put(planeISA);
        _planeISB.position(0);
    }
    
    private int loadShader(int type, String source)  {
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, source);
        GLES20.glCompileShader(shader);
        return shader;
    }
    
    private int loadProgram(String vertexShaderCode, String fragmentShaderCode) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        int program = GLES20.glCreateProgram();
        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);
        GLES20.glLinkProgram(program);
        return program;
    }
    
    private final String _planeVertexShaderCode = 
            "attribute vec4 aPosition;          \n"
        +   "attribute vec2 aCoord;             \n"
        +   "varying vec2 vCoord;               \n"
        +   "uniform mat4 uMVP;                 \n"
        +   "void main() {                      \n"
        +   " gl_Position = uMVP * aPosition;   \n"
        +   " vCoord = aCoord;                  \n"
        +   "}                                  \n";
    
    private final String _planeFragmentShaderCode = 
            "#ifdef GL_FRAGMENT_PRECISION_HIGH              \n"
        +   "precision highp float;                         \n"
        +   "#else                                          \n"
        +   "precision mediump float;                       \n"
        +   "#endif                                         \n"
        +   "varying vec2 vCoord;                           \n"
        +   "uniform sampler2D uSampler;                    \n"
        +   "void main() {                                  \n"
        +   " gl_FragColor = texture2D(uSampler,vCoord);    \n"
        +   "}                                              \n";
    
    }
    

    更多内容请访问 - http://www.apress.com/9781430250531

    【讨论】:

      【解决方案2】:

      如果您的代码确实是 OpenGL ES 2.0,则不应使用 GL10 包装类。我认为 1.0 不支持非 2 纹理大小的幂,不使用扩展,但我想你已经处理了?您可能在您的设备的 OpenGL ES 驱动程序中发现了一个错误,因为它适用于 AVD 模拟器。尝试使用不同类型的 GPU 的不同设备。本文将有所帮助:

      http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1

      【讨论】:

        猜你喜欢
        • 2012-04-08
        • 1970-01-01
        • 1970-01-01
        • 2011-05-19
        • 2016-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多