This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion
Parents
  • Note: This was originally posted on 28th March 2013 at http://forums.arm.com

    Hey Pete,

    Unfortunately I've tried to implement the below techniques, and now it both won't draw the cube and Console shows up with this repeated error:


    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501

    Well here is my changed loadTexture code:


    public static int loadCubeTexture(ETC1Texture landETC)
    {
      int[] landTexEnvironments = new int[1];
     
      GLES20.glGenTextures(1, landTexEnvironments, 0);
       
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
     
       int width, height;
          width = landETC.getWidth();
       height = landETC.getHeight();
      
       Buffer land_data_mip0 = landETC.getData();
       Buffer land_data_mip1 = landETC.getData();
       Buffer land_data_mip2 = landETC.getData();
       Buffer land_data_mip3 = landETC.getData();
       Buffer land_data_mip4 = landETC.getData();
       Buffer land_data_mip5 = landETC.getData();
       Buffer land_data_mip6 = landETC.getData();
       Buffer land_data_mip7 = landETC.getData();
      
      
      
       int imageSize0 = land_data_mip0.remaining();
       int imageSize1= land_data_mip1.remaining();
       int imageSize2 = land_data_mip2.remaining();
       int imageSize3 = land_data_mip3.remaining();
       int imageSize4 = land_data_mip4.remaining();
       int imageSize5 = land_data_mip5.remaining();
       int imageSize6 = land_data_mip6.remaining();
       int imageSize7 = land_data_mip7.remaining();
      
       if (ETC1Util.isETC1Supported())
       {
         GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, ETC1.ETC1_RGB8_OES, 128, 128, 0, imageSize0, land_data_mip0);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 0, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 1, ETC1.ETC1_RGB8_OES, 64, 64, 0, imageSize1, land_data_mip1);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 1, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 2, ETC1.ETC1_RGB8_OES, 32, 32, 0, imageSize2, land_data_mip2);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 2, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 3, ETC1.ETC1_RGB8_OES, 16, 16, 0, imageSize3, land_data_mip3);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 3, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 4, ETC1.ETC1_RGB8_OES, 8, 8, 0, imageSize4, land_data_mip4);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 4, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 5, ETC1.ETC1_RGB8_OES, 4, 4, 0, imageSize5, land_data_mip5);
              // ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 5, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 6, ETC1.ETC1_RGB8_OES, 2, 2, 0, imageSize6, land_data_mip6);
              // ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 6, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 7, ETC1.ETC1_RGB8_OES, 1, 1, 0, imageSize7, land_data_mip7);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 7, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
         
       } else
       {
         
           int pixelSize = 2;
           int stride = pixelSize * width;
           ByteBuffer decodedData = ByteBuffer.allocateDirect(stride*height)
               .order(ByteOrder.nativeOrder());
           ETC1.decodeImage(land_data_mip0, decodedData, 128, 128, pixelSize, stride);
           GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 128, 128, 0,
                   GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, decodedData);
           ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 0, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
       }
     
      //GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_COMPRESSED_TEXTURE_FORMATS, new_texture_air.getWidth(), new_texture_air.getHeight(), 0, image_size, imageBuffer1);          
     
          
           
           
               
            
               
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            //GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
           // GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            //GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
      
                  
           

            return landTexEnvironments[0];
     
     
    }

    I've made the loadCubeTexture (ETC1Texture landETC) function to return an int because the result of the function must be assigned to a textureHandle.  Then  the textureHandle is sent back to the shader code like this:


    // face 0
      
      
       mTextureHandle = LandRenderer.loadCubeTexture(land2ETC1);
       GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
       GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_BYTE, 0);

    The other faces of my cube are similar to the above code except the last face # 5 which uses a second textureHandle called mTextureHandle2. This is because I wanted 5/6 sides of the cube to have the same textures and the last side, which is the ground in my game, to have a different texture.


    // face 5
      
      
       mTextureHandle2 = LandRenderer.loadCubeTexture(land1ETC1);
       GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[5]);
       GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_BYTE, 0);



    mTextureUniformHandle = GLES20.glGetUniformLocation(env.mProgram, "uTexture");
       
       if (mTextureUniformHandle == -1)
       {
        throw new RuntimeException ("could not find location for uTexture");
       }
      
       GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
       
       GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, LandEnvironment.mTextureHandle);
      
       GLES20.glUniform1i(mTextureUniformHandle, 0);

    Finally my shader code is as follows:


    private final String vertexShaderCode =
          "uniform mat4 uMVPMatrix;      \n"     // A constant representing the combined model/view/projection matrix.
       + "uniform mat4 uAirMVPMatrix; \n"
       + "uniform mat4 uFireMVPMatrix; \n"
       + "uniform mat4 uLandMVPMatrix; \n"
       + "uniform mat4 uWaterMVPMatrix; \n"
      
        + "attribute vec4 aPosition;     \n"     // Per-vertex position information we will pass in.
       // + "attribute vec4 aColor;        \n"     // Per-vertex color information we will pass in.
        + "attribute vec2 aTexCoordinate; \n"
       
       // + "varying vec4 vColor;          \n"     // This will be passed into the fragment shader.
        + "varying vec2 vTexCoordinate;  \n"
       
        + "void main()                    \n"     // The entry point for our vertex shader.
        + "{                              \n"
        //+ "   vColor = aColor;          \n"     // Pass the color through to the fragment shader.
        + "   vTexCoordinate = aTexCoordinate; \n"
                                                  // It will be interpolated across the triangle.
        + "   gl_Position =  uMVPMatrix * uAirMVPMatrix * uFireMVPMatrix * uLandMVPMatrix * uWaterMVPMatrix * aPosition;   \n"     // Multiply the vertex by the matrix to get the final point in
        + "}                              \n";    // normalized screen coordinates.

      private final String fragmentShaderCode =
          "precision mediump float;       \n"     // Set the default precision to medium. We don't need as high of a
                                                  // precision in the fragment shader.
        + "uniform sampler2D uTexture;    \n"
        + "uniform sampler2D uTexture2; \n"
        + "uniform sampler2D uTexture3; \n"
        + "uniform sampler2D uTexture4; \n"
        + "uniform sampler2D uTexture5; \n"
        + "uniform sampler2D uTexture6; \n"
       
       
       
      
       
        + "varying vec2 vTexCoordinate;"
       // + "varying vec4 vColor;          \n"     // This is the color from the vertex shader interpolated across the
                                                  // triangle per fragment.
        + "void main()                    \n"     // The entry point for our fragment shader.
        + "{                              \n"
        + "   gl_FragColor = texture2D(uTexture, vTexCoordinate) * texture2D(uTexture2, vTexCoordinate) * texture2D(uTexture3, vTexCoordinate) * texture2D(uTexture4, vTexCoordinate) * texture2D(uTexture5, vTexCoordinate) * texture2D(uTexture6, vTexCoordinate);     \n"     // Pass the color directly through the pipeline.
        + "}                              \n";


    Hi,

    sounds like good progress! If the rest of the code is running without errors but you aren't seeing textures then my next guess is that OpenGL ES does not believe the texture is "complete". For instance, OpenGL ES defaults to using a minifying texture filtering mode using mipmaps. If you upload only the original base level of the texture, OpenGL ES will believe the other levels are missing, and refuse to render anything.

    There are 2 ways to solve this. The quickest and easiest is probably to change the filtering mode so OpenGL ES does not expect to find mipmap levels:


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);


    though you should note that if you display many of your textures on geometry smaller than the original texture size this will mean less efficient usage of the texture cache and may be sub optimal.

    The alternative (which makes better use of the texture cache) is to ask the Mali Texture Compression Tool to generate compressed textures for each mipmap level (e.g. 8x8, 4x4, 2x2 and 1x1) and load each one into the appropriate mipmap level:


    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, 8, 8, 0, 32, pMipmapLevel0);
    glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 4, 4, 0,  8, pMipmapLevel1);
    glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_OES, 2, 2, 0,  2, pMipmapLevel2);
    glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, 1, 1, 0,  1, pMipmapLevel3);


    Then OpenGL ES will select the most appropriate mipmap level for the size of the textured triangle on screen, and not waste space in the texture cache loading lots of texel data that will never be sampled.

    HTH, Pete
Reply
  • Note: This was originally posted on 28th March 2013 at http://forums.arm.com

    Hey Pete,

    Unfortunately I've tried to implement the below techniques, and now it both won't draw the cube and Console shows up with this repeated error:


    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501
    [2013-03-28 12:35:11 - Emulator] sdk/emulator/opengl/host/libs/Translator/GLcommon/TextureUtils.cpp:doCompressedTexImage2D:60 error 0x501

    Well here is my changed loadTexture code:


    public static int loadCubeTexture(ETC1Texture landETC)
    {
      int[] landTexEnvironments = new int[1];
     
      GLES20.glGenTextures(1, landTexEnvironments, 0);
       
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
     
       int width, height;
          width = landETC.getWidth();
       height = landETC.getHeight();
      
       Buffer land_data_mip0 = landETC.getData();
       Buffer land_data_mip1 = landETC.getData();
       Buffer land_data_mip2 = landETC.getData();
       Buffer land_data_mip3 = landETC.getData();
       Buffer land_data_mip4 = landETC.getData();
       Buffer land_data_mip5 = landETC.getData();
       Buffer land_data_mip6 = landETC.getData();
       Buffer land_data_mip7 = landETC.getData();
      
      
      
       int imageSize0 = land_data_mip0.remaining();
       int imageSize1= land_data_mip1.remaining();
       int imageSize2 = land_data_mip2.remaining();
       int imageSize3 = land_data_mip3.remaining();
       int imageSize4 = land_data_mip4.remaining();
       int imageSize5 = land_data_mip5.remaining();
       int imageSize6 = land_data_mip6.remaining();
       int imageSize7 = land_data_mip7.remaining();
      
       if (ETC1Util.isETC1Supported())
       {
         GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, ETC1.ETC1_RGB8_OES, 128, 128, 0, imageSize0, land_data_mip0);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 0, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 1, ETC1.ETC1_RGB8_OES, 64, 64, 0, imageSize1, land_data_mip1);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 1, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 2, ETC1.ETC1_RGB8_OES, 32, 32, 0, imageSize2, land_data_mip2);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 2, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 3, ETC1.ETC1_RGB8_OES, 16, 16, 0, imageSize3, land_data_mip3);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 3, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 4, ETC1.ETC1_RGB8_OES, 8, 8, 0, imageSize4, land_data_mip4);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 4, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 5, ETC1.ETC1_RGB8_OES, 4, 4, 0, imageSize5, land_data_mip5);
              // ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 5, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 6, ETC1.ETC1_RGB8_OES, 2, 2, 0, imageSize6, land_data_mip6);
              // ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 6, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
              
               GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 7, ETC1.ETC1_RGB8_OES, 1, 1, 0, imageSize7, land_data_mip7);
               //ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 7, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
               GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, landTexEnvironments[0]);
         
       } else
       {
         
           int pixelSize = 2;
           int stride = pixelSize * width;
           ByteBuffer decodedData = ByteBuffer.allocateDirect(stride*height)
               .order(ByteOrder.nativeOrder());
           ETC1.decodeImage(land_data_mip0, decodedData, 128, 128, pixelSize, stride);
           GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, 128, 128, 0,
                   GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, decodedData);
           ETC1Util.loadTexture(GLES20.GL_TEXTURE_2D, 0, 0,GLES20.GL_RGB , GLES20.GL_UNSIGNED_BYTE, landETC);
       }
     
      //GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_COMPRESSED_TEXTURE_FORMATS, new_texture_air.getWidth(), new_texture_air.getHeight(), 0, image_size, imageBuffer1);          
     
          
           
           
               
            
               
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            //GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
           // GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            //GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
      
                  
           

            return landTexEnvironments[0];
     
     
    }

    I've made the loadCubeTexture (ETC1Texture landETC) function to return an int because the result of the function must be assigned to a textureHandle.  Then  the textureHandle is sent back to the shader code like this:


    // face 0
      
      
       mTextureHandle = LandRenderer.loadCubeTexture(land2ETC1);
       GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
       GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_BYTE, 0);

    The other faces of my cube are similar to the above code except the last face # 5 which uses a second textureHandle called mTextureHandle2. This is because I wanted 5/6 sides of the cube to have the same textures and the last side, which is the ground in my game, to have a different texture.


    // face 5
      
      
       mTextureHandle2 = LandRenderer.loadCubeTexture(land1ETC1);
       GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[5]);
       GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_BYTE, 0);



    mTextureUniformHandle = GLES20.glGetUniformLocation(env.mProgram, "uTexture");
       
       if (mTextureUniformHandle == -1)
       {
        throw new RuntimeException ("could not find location for uTexture");
       }
      
       GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
       
       GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, LandEnvironment.mTextureHandle);
      
       GLES20.glUniform1i(mTextureUniformHandle, 0);

    Finally my shader code is as follows:


    private final String vertexShaderCode =
          "uniform mat4 uMVPMatrix;      \n"     // A constant representing the combined model/view/projection matrix.
       + "uniform mat4 uAirMVPMatrix; \n"
       + "uniform mat4 uFireMVPMatrix; \n"
       + "uniform mat4 uLandMVPMatrix; \n"
       + "uniform mat4 uWaterMVPMatrix; \n"
      
        + "attribute vec4 aPosition;     \n"     // Per-vertex position information we will pass in.
       // + "attribute vec4 aColor;        \n"     // Per-vertex color information we will pass in.
        + "attribute vec2 aTexCoordinate; \n"
       
       // + "varying vec4 vColor;          \n"     // This will be passed into the fragment shader.
        + "varying vec2 vTexCoordinate;  \n"
       
        + "void main()                    \n"     // The entry point for our vertex shader.
        + "{                              \n"
        //+ "   vColor = aColor;          \n"     // Pass the color through to the fragment shader.
        + "   vTexCoordinate = aTexCoordinate; \n"
                                                  // It will be interpolated across the triangle.
        + "   gl_Position =  uMVPMatrix * uAirMVPMatrix * uFireMVPMatrix * uLandMVPMatrix * uWaterMVPMatrix * aPosition;   \n"     // Multiply the vertex by the matrix to get the final point in
        + "}                              \n";    // normalized screen coordinates.

      private final String fragmentShaderCode =
          "precision mediump float;       \n"     // Set the default precision to medium. We don't need as high of a
                                                  // precision in the fragment shader.
        + "uniform sampler2D uTexture;    \n"
        + "uniform sampler2D uTexture2; \n"
        + "uniform sampler2D uTexture3; \n"
        + "uniform sampler2D uTexture4; \n"
        + "uniform sampler2D uTexture5; \n"
        + "uniform sampler2D uTexture6; \n"
       
       
       
      
       
        + "varying vec2 vTexCoordinate;"
       // + "varying vec4 vColor;          \n"     // This is the color from the vertex shader interpolated across the
                                                  // triangle per fragment.
        + "void main()                    \n"     // The entry point for our fragment shader.
        + "{                              \n"
        + "   gl_FragColor = texture2D(uTexture, vTexCoordinate) * texture2D(uTexture2, vTexCoordinate) * texture2D(uTexture3, vTexCoordinate) * texture2D(uTexture4, vTexCoordinate) * texture2D(uTexture5, vTexCoordinate) * texture2D(uTexture6, vTexCoordinate);     \n"     // Pass the color directly through the pipeline.
        + "}                              \n";


    Hi,

    sounds like good progress! If the rest of the code is running without errors but you aren't seeing textures then my next guess is that OpenGL ES does not believe the texture is "complete". For instance, OpenGL ES defaults to using a minifying texture filtering mode using mipmaps. If you upload only the original base level of the texture, OpenGL ES will believe the other levels are missing, and refuse to render anything.

    There are 2 ways to solve this. The quickest and easiest is probably to change the filtering mode so OpenGL ES does not expect to find mipmap levels:


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);


    though you should note that if you display many of your textures on geometry smaller than the original texture size this will mean less efficient usage of the texture cache and may be sub optimal.

    The alternative (which makes better use of the texture cache) is to ask the Mali Texture Compression Tool to generate compressed textures for each mipmap level (e.g. 8x8, 4x4, 2x2 and 1x1) and load each one into the appropriate mipmap level:


    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, 8, 8, 0, 32, pMipmapLevel0);
    glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 4, 4, 0,  8, pMipmapLevel1);
    glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_OES, 2, 2, 0,  2, pMipmapLevel2);
    glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, 1, 1, 0,  1, pMipmapLevel3);


    Then OpenGL ES will select the most appropriate mipmap level for the size of the textured triangle on screen, and not waste space in the texture cache loading lots of texel data that will never be sampled.

    HTH, Pete
Children
No data