我已经成功地在所有 6 个面(例如一个板条箱)上展示了一个具有相同纹理的立方体,但我现在正在尝试制作一个天空盒(每面 6 个不同的纹理 1)。天空盒仅在所有侧面显示白色。每个纹理都适用于板条箱立方体,因此纹理很好(我认为。)这是我的代码和一些屏幕截图。
TexturedCube 类(用于板条箱等的类)
package com.dissertation.dnativeapp;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;
/*
* A cube with texture.
* Define the vertices for only one representative face.
* Render the cube by translating and rotating the face.
*/
public class TexturedCube {
private static final String TAG = "texcube";
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private FloatBuffer texBuffer; // Buffer for texture-coords-array (NEW)
private float[] vertices = { // Vertices for a face
-1.0f, -1.0f, 0.0f, // 0. left-bottom-front
1.0f, -1.0f, 0.0f, // 1. right-bottom-front
-1.0f, 1.0f, 0.0f, // 2. left-top-front
1.0f, 1.0f, 0.0f // 3. right-top-front
};
float[] texCoords = { // Texture coords for the above face (NEW)
0.0f, 1.0f, // A. left-bottom (NEW)
1.0f, 1.0f, // B. right-bottom (NEW)
0.0f, 0.0f, // C. left-top (NEW)
1.0f, 0.0f // D. right-top (NEW)
};
int[] textureIDs = new int[1]; // Array for 1 texture-ID (NEW)
// Constructor - Set up the buffers
public TexturedCube() {
// Setup vertex-array buffer. Vertices in float. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
vertexBuffer.put(vertices); // Copy data into buffer
vertexBuffer.position(0); // Rewind
// Setup texture-coords-array buffer, in float. An float has 4 bytes (NEW)
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
texBuffer.put(texCoords);
texBuffer.position(0);
}
// Draw the shape
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise orientation
gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
gl.glCullFace(GL10.GL_BACK); // Cull the back face (don't display)
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable texture-coords-array (NEW)
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer (NEW)
// front
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// left
gl.glPushMatrix();
gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Disable texture-coords-array (NEW)
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
// Load an image into GL texture
public void loadTexture(GL10 gl, Context context) {
gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array
Log.d(TAG, "gen number = " + textureIDs[0]);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]); // Bind to texture ID
// Set up texture filters
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Construct an input stream to texture image "res\drawable\nehe.png"
InputStream istream = context.getResources().openRawResource(R.drawable.crate);
Bitmap bitmap;
try {
// Read and decode input as bitmap
bitmap = BitmapFactory.decodeStream(istream);
} finally {
try {
istream.close();
} catch(IOException e) { }
}
// Build Texture from loaded bitmap for the currently-bind texture ID
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
天空盒类
package com.dissertation.dnativeapp;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;
/*
* A photo cube with 6 pictures (textures) on its 6 faces.
*/
public class SkyBox {
private static final String TAG = "skybox";
private FloatBuffer vertexBuffer; // Vertex Buffer
private FloatBuffer texBuffer; // Texture Coords Buffer
private int numFaces = 6;
private int[] imageFileIDs = { // Image file IDs
R.drawable.front3,
R.drawable.left3,
R.drawable.back3,
R.drawable.right3,
R.drawable.top3,
R.drawable.bot3
};
private int[] textureIDs = new int[numFaces];
private Bitmap[] bitmap = new Bitmap[numFaces];
private float cubeHalfSize = 1.2f;
// Constructor - Set up the vertex buffer
public SkyBox(Context context) {
// Allocate vertex buffer. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
// Read images. Find the aspect ratio and adjust the vertices accordingly.
for (int face = 0; face < numFaces; face++) {
bitmap[face] = BitmapFactory.decodeStream(
context.getResources().openRawResource(imageFileIDs[face]));
int imgWidth = bitmap[face].getWidth();
int imgHeight = bitmap[face].getHeight();
float faceWidth = 2.0f;
float faceHeight = 2.0f;
// Adjust for aspect ratio
if (imgWidth > imgHeight) {
faceHeight = faceHeight * imgHeight / imgWidth;
} else {
faceWidth = faceWidth * imgWidth / imgHeight;
}
float faceLeft = -faceWidth / 2;
float faceRight = -faceLeft;
float faceTop = faceHeight / 2;
float faceBottom = -faceTop;
// Define the vertices for this face
float[] vertices = {
faceLeft, faceBottom, 0.0f, // 0. left-bottom-front
faceRight, faceBottom, 0.0f, // 1. right-bottom-front
faceLeft, faceTop, 0.0f, // 2. left-top-front
faceRight, faceTop, 0.0f, // 3. right-top-front
};
vertexBuffer.put(vertices); // Populate
}
vertexBuffer.position(0); // Rewind
// Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces.
float[] texCoords = {
0.0f, 1.0f, // A. left-bottom
1.0f, 1.0f, // B. right-bottom
0.0f, 0.0f, // C. left-top
1.0f, 0.0f // D. right-top
};
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
for (int face = 0; face < numFaces; face++) {
texBuffer.put(texCoords);
}
texBuffer.position(0); // Rewind
}
// Render the shape
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer);
// front
gl.glPushMatrix();
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// left
gl.glPushMatrix();
gl.glRotatef(270.0f, 0f, 1f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[1]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
gl.glPopMatrix();
// back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0f, 1f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[2]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0f, 1f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[3]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1f, 0f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[4]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1f, 0f, 0f);
gl.glTranslatef(0f, 0f, cubeHalfSize);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[5]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
// Load images into 6 GL textures
public void loadTexture(GL10 gl) {
gl.glGenTextures(6, textureIDs, 0); // Generate texture-ID array for 6 IDs
Log.d(TAG, "gen number = " + textureIDs[0]);
// Generate OpenGL texture images
for (int face = 0; face < numFaces; face++) {
Log.d(TAG, "gen number " + face + " = " + textureIDs[face]);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]);
// Build Texture from loaded bitmap for the currently-bind texture ID
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0);
bitmap[face].recycle();
}
}
}
我的 GLR 渲染器
package com.dissertation.dnativeapp;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.util.Log;
import com.dissertation.dnativeapp.GVariables;
public class MyGLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "render";
private Context context; // Application context needed to read image (NEW)
private TexturedCube cube;
private Cube cube1;
private SkyBox skybox;
private int scene;
private int number;
// For controlling cube's z-position, x and y angles and speeds (NEW)
float angleX = 0;
float angleY = 0;
float speedX = 0;
float speedY = 0;
float z = -6.0f;
// Constructor
public MyGLRenderer(Context context) {
this.context = context; // Get the application context (NEW)
cube = new TexturedCube();
cube1 = new Cube();
skybox = new SkyBox(context);
//get scene value
scene = GVariables.getScene();
}
// Call back when the surface is first created or re-created.
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color's clear-value to black
gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest
gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden surface removal
gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice perspective view
gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color
gl.glDisable(GL10.GL_DITHER); // Disable dithering for better performance
if(scene == 1)
{
// Setup Texture, each time the surface is created (NEW)
cube.loadTexture(gl, context); // Load image into Texture (NEW)
}
if(scene == 2)
{
skybox.loadTexture(gl);
}
gl.glEnable(GL10.GL_TEXTURE_2D); // Enable texture (NEW)
}
// Call back after onSurfaceCreated() or whenever the window's size changes.
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0) height = 1; // To prevent divide by zero
float aspect = (float)width / height;
// Set the viewport (display area) to cover the entire window
gl.glViewport(0, 0, width, height);
// Setup perspective projection, with aspect ratio matches viewport
gl.glMatrixMode(GL10.GL_PROJECTION); // Select projection matrix
gl.glLoadIdentity(); // Reset projection matrix
// Use perspective projection
GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f);
gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix
gl.glLoadIdentity(); // Reset
// You OpenGL|ES display re-sizing code here
// ......
}
// Call back to draw the current frame.
public void onDrawFrame(GL10 gl) {
//get number of objects
Log.d(TAG, "getting number");
number = GVariables.getNumberOfObjects();
Log.d(TAG, "number got");
// Clear color and depth buffers
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
if(scene == 1)
{
for(int i = 0; i < number; i++)
{
// ----- Render the Cube -----
gl.glLoadIdentity(); // Reset the current model-view matrix
gl.glTranslatef((-3 + (3*i)), 0.0f, z); // Translate into the screen
gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
gl.glScalef(0.8f, 0.8f, 0.8f);
cube.draw(gl);
}
}
if(scene == 0)
{
for(int i = 0; i < number; i++)
{
gl.glLoadIdentity();
gl.glTranslatef((-3 + (3*i)), 0.0f, z);
gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
gl.glScalef(0.8f, 0.8f, 0.8f);
cube1.draw(gl);
}
}
if(scene == 2)
{
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, z);
gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
gl.glScalef(1.0f, 1.0f, 1.0f);
skybox.draw(gl);
}
// Update the rotational angle after each refresh (NEW)
angleX += speedX;
angleY += speedY;
}
}
如果你需要它 MainActivity
package com.dissertation.dnativeapp;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.util.Log;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
int scene;
int number;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scene = 0;
Button basic = (Button) findViewById(R.id.Basic_Button);
Button textured = (Button) findViewById(R.id.Textured_Button);
Button complicated = (Button) findViewById(R.id.Complicated_Button);
final CheckBox cb1 = (CheckBox) findViewById(R.id.checkBox1);
final CheckBox cb2 = (CheckBox) findViewById(R.id.checkBox2);
final CheckBox cb3 = (CheckBox) findViewById(R.id.checkBox3);
cb1.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked)
{
cb2.setChecked(false);
cb3.setChecked(false);
}
});
cb2.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
cb1.setChecked(false);
cb3.setChecked(false);
}
});
cb3.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
cb1.setChecked(false);
cb2.setChecked(false);
}
});
basic.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(cb1.isChecked())
{
GVariables.setNumberOfObjects(1);
}
else if(cb2.isChecked())
{
GVariables.setNumberOfObjects(2);
}
else if(cb3.isChecked())
{
GVariables.setNumberOfObjects(3);
}
else
{
GVariables.setNumberOfObjects(1);
}
scene = 0;
GVariables.setScene(scene);
Intent myIntent = new Intent(view.getContext(), MyGLActivity.class);
startActivityForResult(myIntent, 0);
}
});
textured.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(cb1.isChecked())
{
GVariables.setNumberOfObjects(1);
}
else if(cb2.isChecked())
{
GVariables.setNumberOfObjects(2);
}
else if(cb3.isChecked())
{
GVariables.setNumberOfObjects(3);
}
else
{
GVariables.setNumberOfObjects(1);
}
scene = 1;
GVariables.setScene(scene);
Intent myIntent = new Intent(v.getContext(), MyGLActivity.class);
startActivityForResult(myIntent, 0);
}
});
complicated.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
scene = 2;
GVariables.setScene(scene);
Intent myIntent = new Intent(v.getContext(), MyGLActivity.class);
startActivityForResult(myIntent, 0);
}
});
}
}
- 编辑我不能发布图像,但天空盒的白脸