Android OpenGL 纹理未渲染

发布于 2024-11-25 15:25:46 字数 2918 浏览 1 评论 0原文

这是我的 GL 初始化代码:

    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glShadeModel(GL10.GL_SMOOTH);

    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();

    gl.glViewport(0, 0, width, height);

    float left = 0;
    float right = width;
    float top = height;
    float bottom = 0;
    gl.glOrthof(left, right, top, bottom, -1, 1);

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    textures.put("ball", new Texture(gl, BitmapFactory.decodeResource(context.getResources(), R.drawable.ball)));

这是我的纹理类

public class Texture
{
int[] texture = new int[1];

static int real_width = 0;
static int real_height = 0;

Texture(GL10 gl, Bitmap bmp)
{
    real_width = bmp.getWidth();
    real_height = bmp.getHeight();

    gl.glGenTextures(1, texture, 0);

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

    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
    bmp.recycle();

    int error = gl.glGetError();
    if (error != GL10.GL_NO_ERROR)
    { 
        Log.e("ROLL", "GL Texture Load Error: " + GLU.gluErrorString(error));
    }
}

public void draw(GL10 gl, float x, float y)
{
    draw(gl, x, y, real_width, real_height);
}

public void draw(GL10 gl, float x, float y, float w, float h)
{
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    float[] vertices = { x + w, y + h, x, y + h, x, y, x + w, y };
    float[] textureCoords = { 1, 1, 0, 1, 0, 0, 1, 0 };

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    FloatBuffer vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    FloatBuffer textureBuffer = byteBuf.asFloatBuffer();
    textureBuffer.put(textureCoords);
    textureBuffer.position(0);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);

    gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

}
}

我遇到的问题是,除了纹理应在的正确形状和位置的白框之外,什么都没有绘制。

图像大小为 50x50,我认为这是由于 2 的幂造成的,但这个问题也出现在模拟器上。

另外,我确实在日志中收到错误,它显示:“GL 纹理加载错误:无效值”,但我不知道这意味着什么。

最后,我画出这样的纹理:

gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

textures.get("ball").draw(gl, 10, 10);

Here is my GL init code:

    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glShadeModel(GL10.GL_SMOOTH);

    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();

    gl.glViewport(0, 0, width, height);

    float left = 0;
    float right = width;
    float top = height;
    float bottom = 0;
    gl.glOrthof(left, right, top, bottom, -1, 1);

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    textures.put("ball", new Texture(gl, BitmapFactory.decodeResource(context.getResources(), R.drawable.ball)));

And here is my Texture class

public class Texture
{
int[] texture = new int[1];

static int real_width = 0;
static int real_height = 0;

Texture(GL10 gl, Bitmap bmp)
{
    real_width = bmp.getWidth();
    real_height = bmp.getHeight();

    gl.glGenTextures(1, texture, 0);

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

    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
    bmp.recycle();

    int error = gl.glGetError();
    if (error != GL10.GL_NO_ERROR)
    { 
        Log.e("ROLL", "GL Texture Load Error: " + GLU.gluErrorString(error));
    }
}

public void draw(GL10 gl, float x, float y)
{
    draw(gl, x, y, real_width, real_height);
}

public void draw(GL10 gl, float x, float y, float w, float h)
{
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    float[] vertices = { x + w, y + h, x, y + h, x, y, x + w, y };
    float[] textureCoords = { 1, 1, 0, 1, 0, 0, 1, 0 };

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    FloatBuffer vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    FloatBuffer textureBuffer = byteBuf.asFloatBuffer();
    textureBuffer.put(textureCoords);
    textureBuffer.position(0);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);

    gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

}
}

The problem I get is where nothing is drawn but a white box in the correct shape and position of where the texture should be.

The image is size 50x50 and I thought it would be due to the power of 2 thing, but this problem also occurs on the emulator.

Also, I do get an error in the log and it says: "GL Texture Load Error: invalid value", but I do not know what that means.

Finally, I draw the texture like this:

gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

textures.get("ball").draw(gl, 10, 10);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

长伴 2024-12-02 15:25:46

来自glTexImage2D

  • 如果internalFormat不是1、2,则会生成GL_INVALID_VALUE 、 3、 4 或
    可接受的分辨率和格式符号常量之一。
  • 如果宽度或高度小于 0 或则生成 GL_INVALID_VALUE
    大于 2 + GL_MAX_TEXTURE_SIZE。
  • 如果不是非二的幂纹理,则生成 GL_INVALID_VALUE
    支持,且宽度或高度不能表示为2k + 2
    k 的某个整数值的边界。
  • 如果 border 不是 0 或 1,则会生成 GL_INVALID_VALUE。

我认为内部格式是错误的。尝试为您自己指定它怎么样?有关 GLUtils 的更多文档,您可以在那里找到。

但首先我发现在将纹理加载到 GL 之前您还没有绑定纹理。

gl.glGenTextures(1, texture, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); 

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

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
bmp.recycle();

From glTexImage2D:

  • GL_INVALID_VALUE is generated if internalFormat is not 1, 2, 3, 4, or
    one of the accepted resolution and format symbolic constants.
  • GL_INVALID_VALUE is generated if width or height is less than 0 or
    greater than 2 + GL_MAX_TEXTURE_SIZE.
  • GL_INVALID_VALUE is generated if non-power-of-two textures are not
    supported and the width or height cannot be represented as 2k + 2
    border for some integer value of k.
  • GL_INVALID_VALUE is generated if border is not 0 or 1.

I assume that internal format would be wrong. What about trying to specify it for your own. More documentation about GLUtils you can find there.

But as first i see you haven't bind texture before loading it to GL.

gl.glGenTextures(1, texture, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); 

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

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
bmp.recycle();
很酷不放纵 2024-12-02 15:25:46

我解决了这样做:

  1. 将所有图像移动到 res/drawable-nodpi
  2. 缩放到 2 的幂,在 Linux 中,

如果您从外部加载纹理, mogrify 将完成这项工作(find . -exec mogrify -scale '512x512!' {} \;)源代码将转换为最接近的 2 的幂调整大小的位图

public class ScalePowerof2 { // some devices require to scale texture bitmaps to power of 2 size 'ScalePower2.scalePowerof2(Bitmpap)' does the job
private static boolean isPowerof2(int v) { // is v a 2^n ?
    for (int i=1; i!=0; i<<=1) if (v==i) return true;
    return false;
}
private static int closestPowerof2(int v) { // n | 2^n <= v
    for (int i=1; i!=0; i<<=1) if (i>=v) return i;
    return 0;
}
public static Bitmap scalePowerof2(Bitmap bmp) {
    Bitmap b=null;
    if (bmp!=null) {
        int w=bmp.getWidth(), h=bmp.getHeight();
        if (isPowerof2(w) & isPowerof2(h)) return bmp; // ok, both 2^n nothing to do
        w=closestPowerof2(w); h=closestPowerof2(h); // new 2^n values
        b=Bitmap.createScaledBitmap(bmp, w, h, false);
    }
    return b;
}

}

i solved doing:

  1. move all images to res/drawable-nodpi
  2. scale to a power of 2, in linux mogrify will do the job (find . -exec mogrify -scale '512x512!' {} \;)

if you load textures from exteral souces this code will do the conversion to closest power of 2 resized bitmap

public class ScalePowerof2 { // some devices require to scale texture bitmaps to power of 2 size 'ScalePower2.scalePowerof2(Bitmpap)' does the job
private static boolean isPowerof2(int v) { // is v a 2^n ?
    for (int i=1; i!=0; i<<=1) if (v==i) return true;
    return false;
}
private static int closestPowerof2(int v) { // n | 2^n <= v
    for (int i=1; i!=0; i<<=1) if (i>=v) return i;
    return 0;
}
public static Bitmap scalePowerof2(Bitmap bmp) {
    Bitmap b=null;
    if (bmp!=null) {
        int w=bmp.getWidth(), h=bmp.getHeight();
        if (isPowerof2(w) & isPowerof2(h)) return bmp; // ok, both 2^n nothing to do
        w=closestPowerof2(w); h=closestPowerof2(h); // new 2^n values
        b=Bitmap.createScaledBitmap(bmp, w, h, false);
    }
    return b;
}

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文