2011-11-25 115 views
0

我已经跟随了关于如何在OpenGL中显示图像的教程,我首先必须制作一个正方形然后纹理它。我已经尝试gl.glColor4f(0f,0f,0f,1f);,这工作,我可以看到广场。但是当我试图纹理它时,屏幕保持白色。我做错了什么?OpenGL ES纹理不会绘制

这里是与gl.glColor4f(0f,0f,0f,1f);屏幕:

image description

如果我申请纹理(使用定制纹理类的教程建议),屏幕完全是白色。

这里是我的代码:

Square.java:

package com.chrypthic.android.reference; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.opengles.GL10; 

import android.content.Context; 

public class Square 
{ 
final int VERTEX_SIZE = (2+2) *4; 
FloatBuffer vertices; 
ShortBuffer indices; 

Texture texture; 

GL10 gl; 
Context c; 

public Square(GL10 gl, Context context) 
{ 
    this.gl = gl; 
    this.c = context; 

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    vertices = byteBuffer.asFloatBuffer(); 
    vertices.put(new float[]{ 
     10.0f, 10.0f, 0.0f, 0.0f, //bl 
     160.0f, 10.0f, 1.0f, 0.0f, //br 
     160.0f, 160.0f, 1.0f, 1.0f, //tr  
     10.0f, 160.0f, 1.0f, 0.0f, //tl 
    }); 
    vertices.flip(); 

    byteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    indices = byteBuffer.asShortBuffer(); 
    indices.put(new short[]{ 
     0, 1, 2, 2, 3, 0 
    }); 
    indices.flip(); 

    texture = new Texture("image/picture.png", c, gl); 
} 

public void draw() 
{ 
    gl.glEnable(GL10.GL_TEXTURE_2D); 
    texture.bind(); 
    //gl.glColor4f(0f, 0f, 0f, 1f); 

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

    vertices.position(0); 
    gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); 
    vertices.position(2); 
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); 

    gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_SHORT, indices); 
} 
} 

Texture.java

package com.chrypthic.android.reference; 

import java.io.InputStream; 

import javax.microedition.khronos.opengles.GL10; 

import android.content.Context; 
import android.content.res.AssetManager; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.opengl.GLUtils; 

public class Texture { 

String texturePath; 
Context context; 
GL10 gl; 

int textureId; 
int minFilter; 
int magFilter; 
Bitmap texture; 

public Texture(String texturePath, Context context, GL10 gl) 
{ 
    this.gl = gl; 
    this.texturePath = texturePath; 
    this.context = context; 
} 

public void load() 
{ 
    try{ 
     AssetManager assetManager = context.getAssets(); 
     InputStream is = assetManager.open(texturePath); 
     texture = BitmapFactory.decodeStream(is); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0); 
     setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); 
    }catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

public void reload() 
{ 
    load(); 
    bind(); 
    setFilters(minFilter, magFilter); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); 
} 

public void setFilters(int minFilter, int magFilter) 
{ 
    this.minFilter = minFilter; 
    this.magFilter = magFilter; 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter); 
} 

public void bind() 
{ 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); 
} 

public void dispose() 
{ 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); 
    int[] textureIds = {textureId}; 
    gl.glDeleteTextures(1, textureIds, 0); 
} 

} 

OpenGLRenderer.java

package com.chrypthic.android.reference; 

import java.util.Random; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.content.Context; 
import android.opengl.GLSurfaceView.Renderer; 

public class OpenGLRenderer implements Renderer 
{ 
Random rand = new Random(); 
int mWidth = 0; 
int mHeight = 0; 

Context c; 

Square square; 

public OpenGLRenderer(Context c) 
{ 
    this.c = c; 
} 

@Override 
public void onDrawFrame(GL10 gl) 
{ 
    gl.glClearColor(1, 1, 1, 1); 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 
    gl.glViewport(0, 0, mWidth, mHeight); 
    gl.glMatrixMode(GL10.GL_PROJECTION); 
    gl.glLoadIdentity(); 
    gl.glOrthof(0, mWidth, 0, mHeight, -1, 1); 

    if(square != null)square.draw(); 
} 

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) 
{ 
    mWidth = width; 
    mHeight = height; 
} 

@Override 
public void onSurfaceCreated(GL10 gl, EGLConfig config) 
{ 
    square = new Square(gl, c); 
} 

} 

我希望你能帮助我,如果你需要更多的信息mation只是告诉我。 在此先感谢。我没有把白色屏幕作为屏幕截图发布,因为它似乎与stackoverflow具有的白色背景毫无意义。

+0

为什么使用glVertexPointer两次而不是glVertexPointer然后glTexCoordPointer?此外,似乎在该行中有一个拼写错误,表示GL_FLAT而不是GL_FLOAT。你确定你给我们你的实际代码吗? –

+0

哎呀,这是一个错字,我会修复它。抱歉。 – chrypthic

+0

请参阅我的文章的编辑2,忽略其余。 –

回答

1

你永远不会创建纹理!

public void load() 
{ 
    try{ 
     int []texture = new int[1]; 
     gl.glGenTextures(1, texture,0);//the missing method 
     textureId = texture[0]; 
     //now you can call 
     AssetManager assetManager = context.getAssets(); 
     InputStream is = assetManager.open(texturePath); 
     texture = BitmapFactory.decodeStream(is); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);/*this fails 
      if textureId is a 'random' number. You must/should generate a valid id. */ 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0); 
     setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); 

这与您的dispose()方法完全相反。

+1

在2个论坛上发帖并研究了我的年龄代码之后,我意识到我忘记调用load()方法。 GOSH IM SO STUPID。我需要更专心。无论如何,感谢您指出。顺便说一句,我使用GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,纹理,0);而不是你认为错过的东西。 – chrypthic

+0

@chrypthic - 更新了我的答案。你仍然需要glGenTextures ... – Ishtar

+0

但它工作得很好,因为它是。另外一个问题,我如何将原点移动到左上角而不是左下角? – chrypthic

1

从评论转到答案。

(评论):为什么你使用glVertexPointer两次,而不是glVertexPointer,然后glTexCoordPointer?此外,似乎在该行中有一个拼写错误,表示GL_FLAT而不是GL_FLOAT。你确定你给我们你的实际代码吗?

-Answer开始这里 -

看起来你没有使用纹理坐标的。您必须指定要分配给三角形/四角形的哪个角的纹理的哪个角。例如,我看到在左上角顶点旁边有一个“tl”注释。您同样需要提供一个纹理坐标,指出“使用此顶点的图像左上角”,然后OpenGL会计算出其余部分。

然后,当您要传递顶点指针时,还必须传递一个纹理坐标指针,该指针包含我刚刚在前一段中讨论的纹理坐标。您可以用glVeexexPointer完全相同的方式使用glTexCoordPointer。您还可以将纹理坐标加载到VBO中(实际上,将其与顶点相同的VBO加载到该VBO中,然后可以将带有偏移量的glTexCoordPointer调用到VBO到tex坐标开始的位置)。

让我知道(通过评论)如果你需要更详细的阐述/代码示例或更多解释任何地方。

编辑1:

查看关于纹理映射这些链接的信息: gamedev, nehe

编辑2:

好吧,我笨。我没有注意到你实际上已经获得了顶点数据中的纹理坐标数据。尝试改变你的第二次调用glVeexexPointer到glTexCoordPointer。这可能会完全解决您的问题。

+0

我会尽快告诉你,因为我的电脑只是过热,而我正在使用手机。 – chrypthic

+0

我已经尝试过,但没有运气。我更新了OP中的代码。 – chrypthic