Useage of Textures collides with drawing Triangles, Only one is displayed

huangapple go评论147阅读模式
英文:

Useage of Textures collides with drawing Triangles, Only one is displayed

问题

我目前正在学习OpenGL(使用Java/Android),直到现在,每个问题都可以通过一个名为stackoverflow或google的网站来解决(你可能都知道)。

直到现在,我只画了三角形(使用顶点和索引),类似于以下内容:

// 一些数学运算以计算顶点和索引
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, vertex_stride, vertex_buffer);
gl.glColor4f(color.r, color.g, color.b, color.a);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, index_buffer_size, GL10.GL_UNSIGNED_SHORT, index_buffer);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

其中vertex_buffer保存顶点,index_buffer保存索引。这可以用来绘制矩形、圆形、箭头和其他简单的形状。

现在,我想添加一个纹理。我按照这个链接的方法进行操作:https://examples.javacodegeeks.com/android/games/opengl-es/opengl-es-texture-mapping/

单独使用它也可以:

// 一次性:将位图转换为纹理
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
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);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// 对顶点和映射进行一些数学运算

// 始终使用:绘制
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, vertex_stride, vertex_buffer);
gl.glTexCoordPointer(COORDS_PER_TEXTURE_COORD, GL10.GL_FLOAT, 0, texture_buffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, NUM_VERTICES);

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

其中**textures[0]**保存纹理的指针,vertex_buffer再次保存顶点,texture_buffer保存纹理与顶点的映射,bitmap保存位图。

现在,如果我同时使用它们,我发现OpenGL只绘制纹理。所有“简单形状”都不显示。如果我将应用程序置于后台,然后再次切换到前台,突然所有“简单形状”都会显示出来,但纹理变成了填充有随机颜色的矩形(可能是最后一个“简单形状”绘制的颜色)。无论是首先绘制“简单形状”然后再绘制纹理,还是反之,结果都不会改变。

我猜测只调用gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);用于“简单形状”,然后对于纹理同时调用gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);可能会发生冲突。

是否有办法在同一个“帧”中同时使用两者?

也许我需要在Render类中配置一些OpenGL设置?

以下是OpenGLRenderer类的一部分:

class OpenGLRenderer implements GLSurfaceView.Renderer {

    public OpenGLRenderer(Context c, int screen_width_px, int screen_height_px){
        context = c;
        this.screen_width_px = screen_width_px;
        this.screen_height_px = screen_height_px;
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig egl_config){
        gl10.glEnable(GL10.GL_TEXTURE_2D);
        gl10.glShadeModel(GL10.GL_SMOOTH);

        gl10.glClearColor(0.5f, 0.5f, 0.0f, 0.5f);
        gl10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
        gl10.glEnable(GL10.GL_DEPTH_TEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height){
        //...
    }

    @Override
    public void onDrawFrame(GL10 gl10){
        //...
    }

    void prepareFrame(GL10 gl10){
        //...
    }  
}

我认为这是所有相关的代码。如果需要,我不知道是否适合在这里发布(Github)项目的链接,但如果有要求,我可以创建一个分支并提供链接。


问题已解决:简而言之,我需要在绘制纹理之前启用2D纹理gl10.glEnable(GL10.GL_TEXTURE_2D),然后在绘制之后禁用它gl10.glDisable(GL10.GL_TEXTURE_2D)。(我只启用了它。)关于这个问题的详细答案请参见被接受的回答。

在将应用程序移至后台并再次切换到前台后,纹理消失的问题与此无关。通过再次调用下面的部分**// 一次性:将位图转换为纹理**(请参见第二个代码示例)来解决。我猜想将应用程序移至后台时,**textures[0]**指针背后的纹理被删除了。

英文:

I am currently learning OpenGL (using Java / Android) and up until now every problem could be solved using a site called stackoverflow or google (you probably know both).

Up until now I only drew triangles (vertices with indices) using something like.

    // some math here to calculate vertices and indices
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, vertex_stride, vertex_buffer);
    gl.glColor4f(color.r, color.g, color.b, color.a);
    gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, index_buffer_size, GL10.GL_UNSIGNED_SHORT, index_buffer);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

vertex_buffer holding the verices and index_buffer holding the indices.
This works, I can draw rectangles, circles, arrows, and other simple shapes

Now I wanted to add a Texture. I did follow this: https://examples.javacodegeeks.com/android/games/opengl-es/opengl-es-texture-mapping/

On its own it also works:

    // once: bitmap to texture conversion
    gl.glGenTextures(1, textures, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    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);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    // do some math for the verices and the mapping

    // always: drawing
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, vertex_stride, vertex_buffer);
    gl.glTexCoordPointer(COORDS_PER_TEXTURE_COORD, GL10.GL_FLOAT, 0, texture_buffer);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, NUM_VERTICES);

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

textures[0] holding the pointer to the texture, vertex_buffer again the vertices and texture_buffer the mapping of the texture to the vertices, bitmap holds a bitmap.

Now if I use both I find that openGL only drawes the textures. All simple shapes are not displayed. If I than put the App in the background and than into the foreground again, suddenly all simple shapes get displayed but the textures become rectangles filled with a random color (probably the color I draw a the last simple shape with).
The result does not change if I draw the simple shapes first and than the textures or vice versa.

I am guessing that calling only
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
for the simple shapes and than both gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); and gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); for the textures somehow clashes.

Is there a way to to use both for the same "frame"?

Perhaps I need to configure something in openGL within the Render class?

class OpenGLRenderer implements GLSurfaceView.Renderer {

    public OpenGLRenderer(Context c, int screen_width_px, int screen_height_px){
        context = c;
        this.screen_width_px = screen_width_px;
        this.screen_height_px = screen_height_px;
    }


    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig egl_config){
        gl10.glEnable(GL10.GL_TEXTURE_2D);
        gl10.glShadeModel(GL10.GL_SMOOTH);

        gl10.glClearColor(0.5f, 0.5f, 0.0f, 0.5f);
        gl10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
        gl10.glEnable(GL10.GL_DEPTH_TEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height){
        screen_height_px = height;
        screen_width_px = width;

        GLES20.glViewport(0,0,width,height);
        float ratio  = (float) width / (float) height;
        gl10.glMatrixMode(GL10.GL_PROJECTION);
        gl10.glLoadIdentity();

        float near = 1.0f;
        float far = -zoom+1;
        float bottom = -1.0f;
        float top = 1.0f;
        float left = -ratio;
        float right = ratio;
        gl10.glFrustumf(left , right , bottom, top, near, far);
    }

    @Override
    public void onDrawFrame(GL10 gl10){

        prepareFrame(gl10);

        // HERE I would call all simple_shapes and Textures in two for loops
    }

    void prepareFrame(GL10 gl10){
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        gl10.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl10.glMatrixMode(GL10.GL_MODELVIEW);
        gl10.glLoadIdentity();
        gl10.glTranslatef(0.0f, 0.0f, zoom);
        gl10.glEnable(GL10.GL_BLEND);
        gl10.glEnable(GL10.GL_TEXTURE_2D);
        gl10.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    }  
}

I think that is all the relevant code. I dont know if it is apropriated to post a link to the (Github)project here but if requested I can make a branch and link it too.


Problem solved: In a nutshell I needed to enable 2DTexture gl10.glEnable(GL10.GL_TEXTURE_2D) before drawing the texture, and disable it gl10.glDisable(GL10.GL_TEXTURE_2D) afterwards. (I just enabled it.) For a detailed answer see the accepted Answer.

The problem that after moving the app into background and back to foreground, the textures vanish is unrelated. It was solved by calling the part below // once: bitmap to texture conversion (see second code sample) again. I guess the texture behnd textures[0] pointer gets deleted by moving th app into background.

答案1

得分: 3

OpenGL是一个状态引擎。一旦设置了状态,它将保持不变,直到再次更改。在Legacy OpenGL中,要启用2D纹理处理,需要使用gl10.glEnable(GL10.GL_TEXTURE_2D);。一旦设置了这个状态,它将保持不变。如果启用了2D纹理处理并且未提供纹理坐标,则网格的所有纹理坐标属性必须默认为(0, 0),并且当前绑定的纹理的纹素将在整个网格上重复。

在绘制带有纹理的几何体之前,您必须启用2D纹理处理:

gl10.glEnable(GL10.GL_TEXTURE_2D);
// 用纹理绘制网格

在绘制没有纹理的几何体之前,您必须禁用2D纹理处理:

gl10.glDisable(GL10.GL_TEXTURE_2D);
// 用颜色绘制网格
英文:

OpenGL is a state engine. once a state is set, it is kept until it is changed again. At Legacy OpenGL 2 dimensional textureing has to be enabled by gl10.glEnable(GL10.GL_TEXTURE_2D);. Once this state is set, it is kept. If 2 dimensional texturing is enabled and not texture coordinates are provided, then all the texture coordinates attributes of the mesh have to default value of (0, 0) and the texel of the currently bound texture at this coordinate is wrapped on the entire mesh.

You have to enable 2 dimensional texturing before before drawing a geometry with a texture:

gl10.glEnable(GL10.GL_TEXTURE_2D);
// draw mesh with texture

and you have to disable 2 dimensional texturing before before drawing a geometry without a texture:

gl10.glDisable(GL10.GL_TEXTURE_2D);
// draw mesh with color

huangapple
  • 本文由 发表于 2020年7月31日 18:32:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63190193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定