Learn OpenGL ES for Android - cube mapping

Keywords: github Mobile Java PHP

We have learned texture mapping before. We can build a cube from six 2D textures, and the cube map itself contains six 2D textures. Its advantage is that it can index / sample through a direction vector. As long as the center point of the cube map, the actual position vector of the cube can be used to sample the cube map.

Create a cube map

It's not much different from 2D texture. To create a cube map is to create a texture, but the parameters of our glBindTexture method should be changed to gles20.gl ﹣ text ﹣ cube ﹣ map, and then the wrapping and filtering methods should also be handled. Different from 2D texture, it needs to use 6 pictures to set six faces of the cube, and also uses the glutils.tesimiage2d method. Its target parameters are shown in the following table

Texture target Position
GL_TEXTURE_CUBE_MAP_POSITIVE_X right
GL_TEXTURE_CUBE_MAP_NEGATIVE_X Left
GL_TEXTURE_CUBE_MAP_POSITIVE_Y upper
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y lower
GL_TEXTURE_CUBE_MAP_POSITIVE_Z after
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z Front

Let's also encapsulate the cube map creation. The code is as follows

    /**
     * Cube map
     * @param context context
     * @param resIds  Map collection, in order:
     *                <ul><li>Right {@ link gles20 ×</li>
     *                <li>Left {@ link gles20 ×</li>
     *                <li>On {@ link gles20 ×</li>
     *                <li>Next {@ link gles20 ×</li>
     *                <li>After {@ link gles20 ×</li>
     *                <li>Before {@ link gles20 ×
     * @return int
     */
    public static int createTextureCube(Context context, int[] resIds) {
        if (resIds != null && resIds.length >= 6) {
            int[] texture = new int[1];
            //Generate texture
            GLES20.glGenTextures(1, texture, 0);
            checkGlError("glGenTexture");
            //Generate texture
            GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, texture[0]);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            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);
            if (OpenGLVersion > 2 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_WRAP_R, GLES20.GL_CLAMP_TO_EDGE);
            }

            Bitmap bitmap;
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;
            for (int i = 0; i < resIds.length; i++) {
                bitmap = BitmapFactory.decodeResource(context.getResources(),
                        resIds[i], options);
                if (bitmap == null) {
                    LogUtil.w("Resource ID " + resIds[i] + " could not be decoded.");
                    GLES20.glDeleteTextures(1, texture, 0);
                    return 0;
                }
                GLUtils.texImage2D(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, bitmap, 0);
                bitmap.recycle();
            }
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
            return texture[0];
        }
        return 0;
    }

The code of shader also needs to be modified. We need to use samplerCube to receive our cube map, and use texturecure to generate cube map. Similarly, we need to define vertex coordinates and texture coordinates of six faces. The code for the clip shader is as follows

precision mediump float;
varying vec3 TexCoord; // Direction vector representing 3D texture coordinates
uniform samplerCube skybox; // Texture sampler of cube map

void main() {
    gl_FragColor = textureCube(skybox, TexCoord);
}

Sky box

Imagine that we create a cube map, and we set the perspective in the middle of the cube map. At this time, we move the perspective direction, just like watching in all directions in a cube room. We can use this website( http://www.custommapmakers.org/skyboxes.php )Now we use the following six pictures to realize cube mapping,

Then draw a box and put it into our perspective. The key code is as follows

    @Override
    public void onDrawFrame(GL10 gl) {
        super.onDrawFrame(gl);

        drawTexture();
        GLES20.glDepthFunc(GLES20.GL_LEQUAL);
        drawSkyBox();
        GLES20.glDepthFunc(GLES20.GL_LESS);
    }

The effect is as follows:,

If we want to move our perspective, it's a little tedious to use touch events. Here, we use the rotation vector function in the sensor of the mobile phone, and our mobile phone can move the perspective in the sky box. In onSensorChanged, use getRotationMatrixFromVector to convert the rotation vector to the rotation matrix, and then transfer it to our Renderer for calculation. Source address https://github.com/jklwan/OpenGLProject/blob/master/sample/src/main/java/com/chends/opengl/renderer/advanced/opengl/CubeMapsRenderer.java , you can test the effect yourself. Corresponding documents of this chapter https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/06%20Cubemaps/.

 

Published 52 original articles, won praise 16, visited 20000+
Private letter follow

Posted by Bailz on Thu, 16 Jan 2020 11:15:58 -0800