尝试在设备上绘制纹理三角形失败,但模拟器工作。为什么?

时间:2010-01-21 23:01:26

标签: android opengl-es

我有一系列OpenGL-ES调用,可以在模拟器(2.0.1)上使用alpha混合正确渲染三角形并对其进行纹理处理。当我在实际设备(Droid 2.0.1)上启动相同的代码时,我得到的只是白色方块。

这告诉我纹理没有加载,但我无法弄清楚它们为什么不加载。我的所有纹理都是具有alpha通道的32位PNG,在res / raw下,因此不会根据sdk docs进行优化。

以下是我加载纹理的方法:

private void loadGLTexture(GL10 gl, Context context, int reasource_id, int texture_id)
{
    //Get the texture from the Android resource directory
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), reasource_id, sBitmapOptions);

    //Generate one texture pointer...
    gl.glGenTextures(1, textures, texture_id);
    //...and bind it to our array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[texture_id]);

    //Create Nearest Filtered Texture
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

    //Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    //Clean up
    bitmap.recycle();
}

以下是我渲染纹理的方法:

        //Clear
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    //Enable vertex buffer
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
        //Push transformation matrix
        gl.glPushMatrix();
        //Transformation matrices
        gl.glTranslatef(x, y, 0.0f);
        gl.glScalef(scalefactor, scalefactor, 0.0f);
        gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
        //Bind the texture
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[textureid]);
        //Draw the vertices as triangles
        gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
        //Pop the matrix back to where we left it
        gl.glPopMatrix();
            //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

以下是我启用的选项:

        gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
        gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
        gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

编辑:我刚刚尝试向BitmapFactory.decodeResource()调用提供BitmapOptions,但这似乎无法解决问题,尽管手动设置了相同的preferredconfig,density和targetdensity。

Edit2:根据要求,这是模拟器工作的屏幕截图。底层三角形显示为圆形纹理,透明度正常,因为您可以看到黑色背景。

删除了死亡的ImageShack链接

以下是机器人使用完全相同的代码执行操作的镜头:

删除了死亡的ImageShack链接

EDIT3: 这是我的BitmapOptions,更新了上面的调用以及我现在调用BitmapFactory的方式,结果如下: sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;

sBitmapOptions.inDensity = 160;
sBitmapOptions.inTargetDensity = 160;
sBitmapOptions.inScreenDensity = 160;
sBitmapOptions.inDither = false;
sBitmapOptions.inSampleSize = 1;
sBitmapOptions.inScaled = false;

这是我的顶点,纹理坐标和索引:

    /** The initial vertex definition */
    private static final float vertices[] = { 
                                        -1.0f, -1.0f, 0.0f, 
                                        1.0f, -1.0f, 0.0f,
                                        -1.0f, 1.0f, 0.0f,
                                        1.0f, 1.0f, 0.0f
                                                        };
    /** The initial texture coordinates (u, v) */   
private static final float texture[] = {            
                                    //Mapping coordinates for the vertices
                                    0.0f, 1.0f,
                                    1.0f, 1.0f,
                                    0.0f, 0.0f,
                                    1.0f, 0.0f
                                    };
/** The initial indices definition */   
private static final byte indices[] = {
                                        //Faces definition
                                        0,1,3, 0,3,2
                                        };

一旦将纹理内容加载到OpenGL ES中,是否还要转储纹理的内容?也许我可以将模拟器的加载纹理与实际设备的加载纹理进行比较?

我尝试使用不同的纹理(默认的android图标),再次,它适用于模拟器,但无法在实际手机上呈现。

Edit4:当我进行纹理加载时尝试切换。没运气。尝试使用0到glGenTextures的常量偏移0,没有变化。

有没有我正在使用的模拟器支持实际的手机没有?

Edit5:下面的每个Ryan,我将纹理从200x200调整为256x256,问题未得到解决。

编辑:根据要求,在上面添加了对glVertexPointer和glTexCoordPointer的调用。另外,这里是vertexBuffer,textureBuffer和indexBuffer的初始化:

ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
loadGLTextures(gl, this.context);

7 个答案:

答案 0 :(得分:11)

当我从SDK 3移到4时,我确实遇到了这个问题。我的纹理将显示在模拟器上,但不会显示在真实设备上(Motorola Milestone / Droid)。

所有纹理必须是2的二进制幂。我的是256x256。然而,纹理不显示的原因是操作系统正在从二进制功率大小缩放它们以显示在Milestone的高密度屏幕上。

解决方案很简单 - 只需将纹理移动到drawable-nodpi目录,操作系统在加载时就不会缩放它们。

答案 1 :(得分:3)

我也是Android OpenGL ES dev的新手。我拥有里程碑(Droid的欧元版)。

从目前为止我所看到的,在我的里程碑上从不同的书籍/网站发布了几个教程应用程序,看起来这款手机以与目前为止发布的所有其他Android手机不同的方式处理OpenGL ES。

我认为它与设备支持的OpenGL扩展有关。

检查此链接以获取支持的扩展名列表,我非常确定代码大师会发现为什么droid正以这种奇怪的方式处理opengl。

http://www.rbgrn.net/content/345-hands-on-motorola-droid-opengl-es-specs

希望这有助于......一点


已编辑:

我调整了manifest.xml,并在使用

时注意到了
<uses-sdk android:minSdkVersion="6"/>

资源根本没有加载。

使用时

<uses-sdk android:minSdkVersion="3"/>

资源正在加载。

所以我转回

<uses-sdk android:minSdkVersion="6"/>

并更改了位图的加载方式。

尝试替换:

  //Get the texture from the Android resource directory 
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), reasource_id, sBitmapOptions); 

with:

InputStream is = context.getResources().openRawResource(your.resource.there);
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

纹理在我的里程碑上使用该代码正常加载,希望这对你有用!

答案 2 :(得分:1)

确保使用适当的BitmapConfig加载位图,而BitmapConfig不会在幕后缩放图像,因为这种情况会发生。

另外,是否有理由将png存储在/ raw /而不是/ drawable /?

答案 3 :(得分:1)

Dullahx编辑的答案解决了我在同一问题上的问题。非常感谢,这最近两天让我烦恼!

我试图在三星Galaxy选项卡上映射纹理,该选项卡已在模拟器上成功显示,但只有平面显示在设备上。

我替换了我的代码:

plane.loadBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.jay));

这一个:

InputStream is = context.getResources().openRawResource(R.drawable.jay);

// Load the texture.
plane.loadBitmap(BitmapFactory.decodeStream(is));

它也可以在设备上运行!

但是如果你还试图在像我这样的全屏尺寸矩形上映射纹理,请注意minSdkVersion。如果我使用

 <uses-sdk android:minSdkVersion="3"/>
在三星星系标签上,我的飞机没有全屏显示。它是根据使用sdk版本3的设备的全屏大小呈现的。我将其更改为

<uses-sdk android:minSdkVersion="8"/>

我的全屏矩形已经回来,其纹理已经打开。

希望这也有帮助。

答案 4 :(得分:0)

我不确定你的问题是什么,我对一般的开发都很陌生,但我的OpenGL android问题与模拟器和手机之间存在差异:

-Emulator可以支持非2 ^ x维度的位图,手机不能 -mmulator在NDK中翻转了用于openGL的屏幕,所以我不得不使用负坐标来定义模拟器中的视图,而我的G1使用的坐标是非否定的。

希望这能够在某种程度上帮助你。

答案 5 :(得分:0)

我认为您可能无法从APK加载纹理。尝试将纹理复制到SD卡,看看是否可以从那里加载它。

答案 6 :(得分:0)

你在某处使用GL11接口吗?并非所有设备都支持GL11。并删除glColor线,也许您的纹理显示但是被颜色覆盖? 这里有一些代码片段,我如何显示我的纹理网格:

void draw(GL10 gl) {

    // Enabled the vertices buffer for writing and to be used during
    // rendering.
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    // Specifies the location and data format of an array of vertex
    // coordinates to use when rendering.
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    gl.glEnable(GL10.GL_TEXTURE_2D);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
            GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
            GL10.GL_LINEAR);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, myTextureId);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    gl.glDrawArrays(drawMode, 0, verticesCount);

    gl.glDisable(GL10.GL_TEXTURE_2D);
    // Disable the vertices buffer.
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

}