Question

I have small cubes that make up a grid to make 3D cube. On each small cube I use a bitmap to texture the surface, but I want to use more then one picture. I can build more textures within loadTextures and add them tofinal int[] textureHandle = new int[1]; and return them. How do I instantiate them to each small cube I'm drawing though?

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
{


mLastRequestedCubeFactor = mActualCubeFactor = 3;
generateCubes(mActualCubeFactor, false, false);         

// Set the background clear color to black.
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

// Use culling to remove back faces.
GLES20.glEnable(GLES20.GL_CULL_FACE);

// Enable depth testing
GLES20.glEnable(GLES20.GL_DEPTH_TEST);                      

// Position the eye in front of the origin.
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = -0.5f;

// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;

// Set our up vector. This is where our head would be pointing were we holding the camera.
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;

// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);        

final String vertexShader = RawResourceReader.readTextFileFromRawResource(mLessonSevenActivity, R.raw.lesson_seven_vertex_shader);          
final String fragmentShader = RawResourceReader.readTextFileFromRawResource(mLessonSevenActivity, R.raw.lesson_seven_fragment_shader);

final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);       
final int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);     

mProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, 
        new String[] {"a_Position",  "a_Normal", "a_TexCoordinate"});                   

// Load the texture
mAndroidDataHandle = TextureHelper.loadTexture(mLessonSevenActivity, R.drawable.usb_android);       
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);          

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mAndroidDataHandle);     
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);       

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mAndroidDataHandle);     
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);     

// Initialize the accumulated rotation matrix
Matrix.setIdentityM(mAccumulatedRotation, 0);        
}

public class TextureHelper
{
    public static int loadTexture(final Context context, final int resourceId)
    {
        final int[] textureHandle = new int[1];

        GLES20.glGenTextures(1, textureHandle, 0);

        if (textureHandle[0] != 0)
        {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;   // No pre-scaling

            // Read in the resource
            final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);

            // Bind to the texture in OpenGL
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

            // Set filtering
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

            // Load the bitmap into the bound texture.
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

            // Recycle the bitmap, since its data has been loaded into OpenGL.
            bitmap.recycle();                       
        }

        if (textureHandle[0] == 0)
        {
            throw new RuntimeException("Error loading texture.");
        }

        return textureHandle[0];
    }
}
Was it helpful?

Solution

How do I instantiate them to each small cube I'm drawing though?

In short, you don't.

Even in desktop GL, where vertex instancing is a core feature, there is no way to change texture bindings without splitting the draw into multiple draw calls.

You could use a texture atlas, array texture or geometry shader to sample from a different (already bound) texture or a different part of a single texture. Alternatively, you could use bindless textures. Each one of those things I mentioned requires a newer version of GL than the last.

The only way to do this in ES is going to be either multiple draw calls, or a texture atlas/binding textures to multiple texture units. But since instancing is not a core feature, computing the texture coordinate / unit dynamically is a tremendous pain and will involve duplicating vertex data.

The bottom line is, what do you really mean by instantiated cube? Are you trying to draw 500 cubes in a single operation, or are you drawing them separately by calling some method in your cube class? Instancing has different meanings depending on the context.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top