Android OpenGL:为Square类添加Bitmap纹理及教程拓展咨询
How to Add Bitmap Texture to the Square Class in the Android OpenGL Tutorial
Great question! Let's walk through the step-by-step modifications needed to make your Square class use a Bitmap as a texture, plus cover the extension content available in the official tutorial.
1. Update the Square Class for Texture Support
First, modify your Square class to handle texture coordinates, texture IDs, and shader uniforms:
public class Square { // Existing variables (vertices, program handles, etc.) private FloatBuffer mVertexBuffer; private int mProgram; private int mPositionHandle; // New texture-related variables private int mTextureId; private int mTextureCoordinateHandle; private int mTextureUniformHandle; private FloatBuffer mTextureCoordinateBuffer; // Texture coordinate array (maps to square vertices) private final float[] mTextureCoordinates = { 0.0f, 0.0f, // Bottom-left 1.0f, 0.0f, // Bottom-right 0.0f, 1.0f, // Top-left 1.0f, 1.0f // Top-right }; public Square() { // Existing vertex buffer initialization... // Initialize texture coordinate buffer ByteBuffer byteBuf = ByteBuffer.allocateDirect(mTextureCoordinates.length * 4); byteBuf.order(ByteOrder.nativeOrder()); mTextureCoordinateBuffer = byteBuf.asFloatBuffer(); mTextureCoordinateBuffer.put(mTextureCoordinates); mTextureCoordinateBuffer.position(0); // Compile shaders (update this to use texture-enabled shaders) int vertexShader = loadShader(GLES32.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = loadShader(GLES32.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES32.glCreateProgram(); GLES32.glAttachShader(mProgram, vertexShader); GLES32.glAttachShader(mProgram, fragmentShader); GLES32.glLinkProgram(mProgram); // Get handles for texture attributes/uniforms mPositionHandle = GLES32.glGetAttribLocation(mProgram, "vPosition"); mTextureCoordinateHandle = GLES32.glGetAttribLocation(mProgram, "a_TexCoordinate"); mTextureUniformHandle = GLES32.glGetUniformLocation(mProgram, "u_Texture"); } // Setter for texture ID (called from renderer) public void setTextureId(int textureId) { mTextureId = textureId; } public void draw() { GLES32.glUseProgram(mProgram); // Enable vertex position attribute GLES32.glVertexAttribPointer(mPositionHandle, 3, GLES32.GL_FLOAT, false, 0, mVertexBuffer); GLES32.glEnableVertexAttribArray(mPositionHandle); // Enable texture coordinate attribute GLES32.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES32.GL_FLOAT, false, 0, mTextureCoordinateBuffer); GLES32.glEnableVertexAttribArray(mTextureCoordinateHandle); // Activate and bind the texture GLES32.glActiveTexture(GLES32.GL_TEXTURE0); GLES32.glBindTexture(GLES32.GL_TEXTURE_2D, mTextureId); GLES32.glUniform1i(mTextureUniformHandle, 0); // Tell shader to use texture unit 0 // Draw the square GLES32.glDrawArrays(GLES32.GL_TRIANGLE_STRIP, 0, 4); // Clean up GLES32.glDisableVertexAttribArray(mPositionHandle); GLES32.glDisableVertexAttribArray(mTextureCoordinateHandle); } // Existing loadShader method... // Updated shader code private final String vertexShaderCode = "#version 320 es\n" + "layout (location = 0) in vec4 vPosition;\n" + "layout (location = 1) in vec2 a_TexCoordinate;\n" + "out vec2 v_TexCoordinate;\n" + "void main() {\n" + " gl_Position = vPosition;\n" + " v_TexCoordinate = a_TexCoordinate;\n" + "}"; private final String fragmentShaderCode = "#version 320 es\n" + "precision mediump float;\n" + "uniform sampler2D u_Texture;\n" + "in vec2 v_TexCoordinate;\n" + "out vec4 fragColor;\n" + "void main() {\n" + " fragColor = texture(u_Texture, v_TexCoordinate);\n" + "}"; }
2. Load Bitmap as OpenGL Texture in MyGLRenderer
Add a method to convert a Bitmap into an OpenGL texture, then pass it to your Square instance:
public class MyGLRenderer implements GLSurfaceView.Renderer { private Square mSquare; private Context mContext; public MyGLRenderer(Context context) { mContext = context; } @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Set background color GLES32.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); mSquare = new Square(); // Load your bitmap (replace with your image resource) Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.your_texture_image); int textureId = loadTextureFromBitmap(bitmap); mSquare.setTextureId(textureId); } // Helper method to load texture from Bitmap private int loadTextureFromBitmap(Bitmap bitmap) { int[] textureIds = new int[1]; GLES32.glGenTextures(1, textureIds, 0); int textureId = textureIds[0]; // Bind texture and set parameters GLES32.glBindTexture(GLES32.GL_TEXTURE_2D, textureId); GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_MIN_FILTER, GLES32.GL_LINEAR); GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_MAG_FILTER, GLES32.GL_LINEAR); GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_WRAP_S, GLES32.GL_CLAMP_TO_EDGE); GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_WRAP_T, GLES32.GL_CLAMP_TO_EDGE); // Load bitmap data into texture GLUtils.texImage2D(GLES32.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); // Free bitmap memory return textureId; } // Existing onDrawFrame and onSurfaceChanged methods... }
Yes! The official Android OpenGL training series includes several advanced topics that build on the basic square example:
- 3D Graphics: Learn to render 3D objects, use perspective projection, and implement camera controls.
- Lighting & Materials: Add ambient, diffuse, and specular lighting to create realistic scene visuals.
- Framebuffer Objects: Implement off-screen rendering for effects like shadows, reflections, or post-processing.
- 3D Model Loading: Work with common 3D formats (e.g., OBJ) and load complex models into your app.
- Performance Optimization: Tips for reducing draw calls, using vertex buffer objects (VBOs) efficiently, and optimizing shader code.
These topics are part of the same training pathway you're already following, so you can continue exploring there for deeper dives.
内容的提问来源于stack exchange,提问作者TinFellow
相关产品推荐
相关产品推荐

