Cannot get samplerCube / textureCube to work in OpenGL ES 2.0 (Android)

I desperately need help getting samplerCube / textureCube to work. I've spent many hours experimenting but cannot get it to work. I've searched Google but I cannot find a full example that works and that I can copy from.

The code below displays a tumbling dark blue cube with the central lines (placed there to help debugging). The presence of the central lines implies to me that the texture co-ordinates are being defined correctly. What I cannot do is to check the loading of the textures - each of which is a 48x48 px image.

What am I doing wrong?

public class HelloTexturedCubeRenderer implements GLSurfaceView.Renderer
{   //  constructor
    //  ===========

    public HelloTexturedCubeRenderer( GLSurfaceView view )
    {   m_view             = view;
        m_matrixModel      = new float[ 16 ];
        m_matrixProjection = new float[ 16 ];
        m_matrixView       = new float[ 16 ];
        m_matrixViewProj   = new float[ 16 ];

        float[] faces   =  {  1.0f,  1.0f,  1.0f,    -1.0f,  1.0f,  1.0f,    -1.0f, -1.0f,  1.0f,     1.0f, -1.0f,  1.0f,
                              1.0f,  1.0f,  1.0f,     1.0f, -1.0f,  1.0f,     1.0f, -1.0f, -1.0f,     1.0f,  1.0f, -1.0f,
                              1.0f, -1.0f, -1.0f,    -1.0f, -1.0f, -1.0f,    -1.0f,  1.0f, -1.0f,     1.0f,  1.0f, -1.0f,
                             -1.0f,  1.0f,  1.0f,    -1.0f,  1.0f, -1.0f,    -1.0f, -1.0f, -1.0f,    -1.0f, -1.0f,  1.0f,
                              1.0f,  1.0f,  1.0f,     1.0f,  1.0f, -1.0f,    -1.0f,  1.0f, -1.0f,    -1.0f,  1.0f,  1.0f,
                              1.0f, -1.0f,  1.0f,    -1.0f, -1.0f,  1.0f,    -1.0f, -1.0f, -1.0f,     1.0f, -1.0f, -1.0f,
                           };
        short[] indices  = {  0,  1,  2,     0,  2,  3,
                              4,  5,  6,     4,  6,  7,
                              8,  9, 10,     8, 10, 11,
                             12, 13, 14,    12, 14, 15,
                             16, 17, 18,    16, 18, 19,
                             20, 21, 22,    20, 22, 23
                           };
        float[] vertices = {  1.0f,  1.0f,  1.0f,    -1.0f,  1.0f,  1.0f,    -1.0f, -1.0f,  1.0f,     1.0f, -1.0f,  1.0f,
                              1.0f,  1.0f,  1.0f,     1.0f, -1.0f,  1.0f,     1.0f, -1.0f, -1.0f,     1.0f,  1.0f, -1.0f,
                              1.0f, -1.0f, -1.0f,    -1.0f, -1.0f, -1.0f,    -1.0f,  1.0f, -1.0f,     1.0f,  1.0f, -1.0f,
                             -1.0f,  1.0f,  1.0f,    -1.0f,  1.0f, -1.0f,    -1.0f, -1.0f, -1.0f,    -1.0f, -1.0f,  1.0f,
                              1.0f,  1.0f,  1.0f,     1.0f,  1.0f, -1.0f,    -1.0f,  1.0f, -1.0f,    -1.0f,  1.0f,  1.0f,
                              1.0f, -1.0f,  1.0f,    -1.0f, -1.0f,  1.0f,    -1.0f, -1.0f, -1.0f,     1.0f, -1.0f, -1.0f
                           };

        ByteBuffer byteBuffer;

        byteBuffer = ByteBuffer.allocateDirect( 4 * faces.length );
        byteBuffer.order( ByteOrder.nativeOrder( ));
        m_bufferFaces = byteBuffer.asFloatBuffer( );
        m_bufferFaces.put( faces );
        m_bufferFaces.position( 0 );

        byteBuffer = ByteBuffer.allocateDirect( 4 * indices.length );
        byteBuffer.order( ByteOrder.nativeOrder( ));
        m_bufferIndices = byteBuffer.asShortBuffer( );
        m_bufferIndices.put( indices );
        m_bufferIndices.position( 0 );

        byteBuffer = ByteBuffer.allocateDirect( 4 * vertices.length );
        byteBuffer.order( ByteOrder.nativeOrder( ));
        m_bufferVertex = byteBuffer.asFloatBuffer( );
        m_bufferVertex.put( vertices );
        m_bufferVertex.position( 0 );
    }

    //  loadProgram
    //  ===========

    private void loadProgram( )
    {   m_programId        = -1;
        int fragmentShader = loadShader( FragmentShaderCode, GLES20.GL_FRAGMENT_SHADER );
        int vertexShader   = loadShader( VertexShaderCode,   GLES20.GL_VERTEX_SHADER   );

        if( fragmentShader == 0 || vertexShader == 0 )
            return;

        m_programId = GLES20.glCreateProgram( );

        GLES20.glAttachShader( m_programId, vertexShader   );
        GLES20.glAttachShader( m_programId, fragmentShader );
        GLES20.glLinkProgram( m_programId );
        GLES20.glDeleteShader( vertexShader   );
        GLES20.glDeleteShader( fragmentShader );
    }

    //  loadShader
    //  ==========

    private int loadShader( String source, int type )
    {   int[] array  = new int[ 1 ];
        int   shader = GLES20.glCreateShader( type );

        GLES20.glShaderSource( shader, source );
        GLES20.glCompileShader( shader );
        GLES20.glGetShaderiv( shader, GLES20.GL_COMPILE_STATUS, array, 0 );

        if( array[ 0 ] != 0 )
            return shader;

        GLES20.glGetShaderiv( shader, GLES20.GL_INFO_LOG_LENGTH, array, 0 );
        Log.e( "loadShader", "compile of shader failed - shader log: " + GLES20.glGetShaderInfoLog( shader ));

        return 0;
    }

    //  loadTexture
    //  ===========

    private void loadTexture( )
    {
        int textures[] = new int[ 1 ];

        GLES20.glGenTextures( 1, textures, 0 );
        GLES20.glBindTexture( GLES20.GL_TEXTURE_CUBE_MAP, textures[ 0 ]);

        GLUtils.texImage2D( GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, BitmapFactory.decodeResource( m_view.getResources( ), R.raw.brick1 ), 0 );
        GLUtils.texImage2D( GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, BitmapFactory.decodeResource( m_view.getResources( ), R.raw.brick2 ), 0 );
        GLUtils.texImage2D( GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, BitmapFactory.decodeResource( m_view.getResources( ), R.raw.brick3 ), 0 );
        GLUtils.texImage2D( GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, BitmapFactory.decodeResource( m_view.getResources( ), R.raw.brick4 ), 0 );
        GLUtils.texImage2D( GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, BitmapFactory.decodeResource( m_view.getResources( ), R.raw.brick5 ), 0 );
        GLUtils.texImage2D( GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, BitmapFactory.decodeResource( m_view.getResources( ), R.raw.brick6 ), 0 );

        GLES20.glGenerateMipmap( GLES20.GL_TEXTURE_CUBE_MAP );

        GLES20.glTexParameteri( GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST );
        GLES20.glTexParameteri( GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST );
        GLES20.glTexParameteri( GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_WRAP_S,     GLES20.GL_CLAMP_TO_EDGE        );
        GLES20.glTexParameteri( GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_WRAP_T,     GLES20.GL_CLAMP_TO_EDGE        );

        m_textureId = textures[ 0 ];
    }

    //  onDrawFrame
    //  ===========

    public void onDrawFrame( GL10 unused )
    {   GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT );
        GLES20.glUseProgram( m_programId );

        float angle = (SystemClock.uptimeMillis( ) / 15) % 360;
        Matrix.setRotateM( m_matrixModel, 0, angle, 1.0f, 1.0f, 1.0f );

        Matrix.multiplyMM( m_matrixViewProj, 0, m_matrixView,       0, m_matrixModel,    0 );
        Matrix.multiplyMM( m_matrixViewProj, 0, m_matrixProjection, 0, m_matrixViewProj, 0 );

        GLES20.glUniformMatrix4fv( m_vpMatrixPtr, 1, false, m_matrixViewProj, 0 );
        GLES20.glDrawElements( GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, m_bufferIndices );
    }

    //  onSurfaceChanged
    //  ================

    public void onSurfaceChanged( GL10 unused, int width, int height )
    {   GLES20.glViewport( 0, 0, width, height );

        float ratio = (float) width / height;
        Matrix.frustumM( m_matrixProjection, 0, -ratio, ratio, -1, 1, 1, 15 );
    }

    //  onSurfaceCreated
    //  ================

    public void onSurfaceCreated( GL10 unused, EGLConfig config )
    {   GLES20.glClearColor( 0.5f, 0.5f, 0.5f, 1.0f );

        GLES20.glEnable( GLES20.GL_DEPTH_TEST );
        GLES20.glDepthFunc( GLES20.GL_LEQUAL );
        GLES20.glFrontFace( GLES20.GL_CCW );

        GLES20.glEnable( GLES20.GL_CULL_FACE );
        GLES20.glCullFace( GLES20.GL_BACK );

        Matrix.setLookAtM( m_matrixView, 0, 0.0f, 0.0f, 4.0f,
                                            0.0f, 0.0f, 0.0f,
                                            0.0f, 1.0f, 0.0f );
        loadProgram( );

        m_facesPtr    = GLES20.glGetAttribLocation(  m_programId, "faces"    );
        m_texturePtr  = GLES20.glGetUniformLocation( m_programId, "texture"  );
        m_verticesPtr = GLES20.glGetAttribLocation(  m_programId, "vertices" );
        m_vpMatrixPtr = GLES20.glGetUniformLocation( m_programId, "vpMatrix" );

        GLES20.glUseProgram( m_programId );

        GLES20.glVertexAttribPointer( m_facesPtr,    3, GLES20.GL_FLOAT, false, 0, m_bufferFaces  );
        GLES20.glVertexAttribPointer( m_verticesPtr, 3, GLES20.GL_FLOAT, false, 0, m_bufferVertex );

        GLES20.glEnableVertexAttribArray( m_facesPtr    );
        GLES20.glEnableVertexAttribArray( m_verticesPtr );

        loadTexture( );

        GLES20.glActiveTexture( GLES20.GL_TEXTURE0 );
        GLES20.glBindTexture( GLES20.GL_TEXTURE_CUBE_MAP, m_textureId );
        GLES20.glUniform1i( m_texturePtr, 0 );
    }

    //  private stuff
    //  =============

    private FloatBuffer   m_bufferFaces;
    private ShortBuffer   m_bufferIndices;
    private FloatBuffer   m_bufferVertex;
    private int           m_facesPtr;
    private float[]       m_matrixModel;
    private float[]       m_matrixProjection;
    private float[]       m_matrixView;
    private float[]       m_matrixViewProj;
    private int           m_programId;
    private int           m_textureId;
    private int           m_texturePtr;
    private int           m_verticesPtr;
    private GLSurfaceView m_view;
    private int           m_vpMatrixPtr;

    private final String FragmentShaderCode = "precision mediump     float;n"   +
                                              "varying   vec3        face;n"    +
                                              "uniform   samplerCube texture;n" +

                                              "void main( )n"                   +
                                              "{    if( abs( face.x ) < 0.01 )"  +
                                              "         gl_FragColor = vec4( 1, 0, 0, 1 );n" +
                                              "     elsen"                      +
                                              "     if( abs( face.y ) < 0.01 )"  +
                                              "         gl_FragColor = vec4( 0, 1, 0, 1 );n" +
                                              "     elsen"                      +
                                              "     if( abs( face.z ) < 0.01 )"  +
                                              "         gl_FragColor = vec4( 0, 0, 1, 1 );n" +
                                              "     elsen"                      +
                                              "     {   gl_FragColor = textureCube( texture, face );n" +

                                              "         if( gl_FragColor.b < 0.01 )n" +
                                              "             gl_FragColor.b = 0.3;n"   +
                                              "     }n" +
                                              "}n";

    private final String VertexShaderCode  =  "varying   vec3 face;n"     +
                                              "attribute vec3 faces;n"    +
                                              "attribute vec4 vertices;n" +
                                              "uniform   mat4 vpMatrix;n" +

                                              "void main( )n"             +
                                              "{    face = faces;n"       +
                                              "     gl_Position = vpMatrix * vertices;n" +
                                              "}";
}

The problem was not in the code, it was in two of the images I used as textures.

Whilst they displayed properly when opened on my laptop, they must have been some problem with them. When I opened them in Gimp, did a little transformation stuff, reversed that transformation and resaved the images, all was well.

PHEW!!!!!

链接地址: http://www.djcxy.com/p/33600.html

上一篇: 为什么不用vec3来处理OpenGL ES 2.0 gl

下一篇: 无法让samplerCube / textureCube在OpenGL ES 2.0(Android)中工作