其他分享
首页 > 其他分享> > android – OpenGL ES 2.0 1仅使用最后绑定纹理

android – OpenGL ES 2.0 1仅使用最后绑定纹理

作者:互联网

请参阅编辑结束以获取进度.

我正在尝试学习OpenGL ES 2.0(我将在Android设备上开发)

我对Vertex和Fragment着色器有点困惑.我理解他们的目的,但是如果我从自定义构建的类(比如’点’)构建一个形状并设置它的大小和颜色或应用纹理并假设两个着色器最初在对象类的构造函数中声明和定义,这是否意味着该类的每个实例都拥有它自己的着色器对?

这是我的第一个问题.我的第二个是如果是这种情况(每个对象的着色器对)………这是要走的路吗?我听说有一个着色器对并切换它的参数不是一个好主意,因为性能,但如果我有100个精灵所有相同的大小和颜色(或纹理)是否有意义,他们都有一个不同的着色器对具有完全相同的参数?

我希望我问的是正确的问题,我没有长时间研究ES 2.0,所以发现它有点令人困惑.我目前对OpenGL的理解有限!

编辑

按要求添加代码.

public class Dot {

    int iProgId;
    int iPosition;
    float size = 10;
    FloatBuffer vertexBuf;
    float r = 1f;
    float g = 1f;
    float b = 1f;
    float a = 1f;
    int iBaseMap;
    int texID; 
    Bitmap imgTexture;


    //Constructor
    public Dot() {

        float[] vertices = {
                        0,0,0f              
                        };

    //Create vertex shader
    String strVShader =  
              "attribute vec4 a_position;\n"+
              "void main()\n" +
              "{\n" +
              "gl_PointSize = " +size+ ";\n" +
              "gl_Position = a_position;\n"+                 
              "}";

    //Create fragment shader
    String strFShader = 
              "precision mediump float;" +
              "void main() " +
              "{" +
              "gl_FragColor = vec4(0,0,0,1);" +
              "}";
              iProgId = Utils.LoadProgram(strVShader, strFShader);
              iPosition = GLES20.glGetAttribLocation(iProgId, "a_position");

                  vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

                  vertexBuf.put(vertices).position(0);


        }

我的setTexture方法

public void setTexture(GLSurfaceView view, Bitmap imgTexture){
    this.imgTexture=imgTexture;

    //Create vertex shader
    String strVShader =  
            "attribute vec4 a_position;\n"+
            "void main()\n" +
            "{\n" +
            "gl_PointSize = " +size+ ";\n" +
            "gl_Position = a_position;\n"+                 
            "}";

    //Fragment shader
    String strFShader =
            "precision mediump float;" +
            "uniform sampler2D u_baseMap;" +
            "void main()" +
            "{" +
            "vec4 color;" +
            "color = texture2D(u_baseMap, gl_PointCoord);" +
            "gl_FragColor = color;" +
            "}";

    iProgId = Utils.LoadProgram(strVShader, strFShader);
    iBaseMap = GLES20.glGetUniformLocation(iProgId, "u_baseMap");

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glUniform1i(iBaseMap, 0);

    texID = Utils.LoadTexture(view, imgTexture);  //See code below
}

我的Utils类的LoadTexture()方法:

public static int LoadTexture(GLSurfaceView view, Bitmap imgTex) {
    int textures[] = new int[1];
    try {
        GLES20.glGenTextures(1, textures, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, imgTex, 0);
    } catch
    }
    return textures[0];
}

最后我的绘图方法:

public void drawDot(float x, float y){

        float[] vertices = {
                x,y,0f              
                };

         vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
         vertexBuf.put(vertices).position(0);
        GLES20.glUseProgram(iProgId);
        GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 0, vertexBuf);
        GLES20.glEnableVertexAttribArray(iPosition);
        GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
    }

所以我可以创建这样的东西:

Dot dot1 = new Dot();
dot1.setSize(40);
setTexture(myBitmap); //(created earlier with BitmapFactory)
drawDot(0,0);

谢谢!

编辑1:到目前为止,感谢您的回答.在进一步的研究中,似乎有一些人有这个完全相同的问题.问题似乎是我在渲染例程中没有调用glBindTexture,因此OpenGL只是使用它加载的最后一个纹理,我觉得这很有道理.

如果我将以下内容放入我的渲染例程:

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 1);

它将应用第一个位图并显示它

如果我把:

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 2);

它将应用第二个位图并显示它

所以,去某个地方!但我现在的问题是如何让我的渲染方法根据调用它的对象(渲染例程)自动知道要使用哪个位图?

再次感谢

解决方法:

工作原理(简要)

着色器只是在显卡中运行的程序.您编译并链接它们,然后您可以传递一些变量来修改顶点和片段的属性.
这意味着当您调用某些绘图函数(例如glDrawElements或glDrawArrays)时,顶点数据(这意味着位置,纹理坐标,法线,颜色等取决于您要发送的内容)将被发送到管道.
这意味着当前加载的顶点着色器将逐个获取顶点并运行其代码以应用它需要的任何变换.之后,OpenGL将应用光栅化来生成当前帧的片段.然后片段着色器将获取每个片段并相应地修改它.

您始终可以卸载着色器并加载另一个着色器.如果需要不同对象的不同着色器,则可以根据其着色器对对象进行分组,并在为每个组重新加载相应着色器时单独渲染它们.

但是,有时将一些参数传递给着色器并为每个对象更改它们会更容易.例如,如果要渲染3D模型,可以将其拆分为子网格,每个子网格都具有不同的纹理.然后,当您传递网格的顶点数据时,加载纹理并将其传递给着色器.对于下一个网格,您将传递另一个纹理,依此类推.

在现实世界中,一切都比较复杂,但我希望你能够了解它是如何工作的.

你的榜样

您正在构造函数上加载一对着色器(没有纹理),然后在每次设置纹理时创建一个新着色器.我不确定这是更好的方法.

不知道Utils.LoadShader做什么很难知道,但每次调用时都可以记录结果.也许你第二次链接着色器它不起作用.

如果我是你,我会在点对象外面使用一对着色器.您可以将参数传递给着色器(使用glUniform …),指示点大小,纹理等.
setTexture函数只是绑定新纹理而不加载着色器.然后在开始时编译(在设置GL上下文之后等等).

当这种方法有效时,您可以考虑每次都更改着色器,只有在确实需要时才这样做.

标签:point,android,object,textures,opengl-es-2-0
来源: https://codeday.me/bug/20190901/1781241.html