我正在尝试使用OpenGL ES2绘制3D立方体,而我的代码只绘制了立方体的正面(正方形),如此image所示。我无法弄清楚什么是错的。我已经尝试过基于其他教程实现我的立方体,但没有运气。
我的代码有什么问题?我在某处错过了一些重要的代码吗?
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glEnable(GLES20.GL_CULL_FACE);
Matrix.setLookAtM(mVMatrix,0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
}
DrawFrame方法
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
//Calling draw method of shapes
square.draw(mMVPMatrix);
}
多维数据集类
// x, y, z
static float squareCoords[] = {-1f, -1f, 1f,//Bottom Left
1f, -1f, 1f, //Bottom Right
1f, 1f, 1f, //Top Right
-1f, 1f, 1f, //Top left
-1f, -1f, -1f,//Bottom Left
1f, -1f, -1f, //Bottom Right
1f, 1f, -1f, //Top Right
-1f, 1f, -1f //Top left
};
private short drawOrder[] = {0,1,2, 0,2,3,//front
0,3,7, 0,7,4,//Left
0,1,5, 0,5,4,//Bottom
6,7,4, 6,4,5,//Back
6,7,3, 6,3,2,//top
6,2,1, 6,1,5//right
}; //Order to draw vertices
private int vertaxCount = 0; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
private int vertaxStride = 0; //4 are how many bytes in a float
private float [] color = new float[]{
0.1f, 0.5f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 10.0f, 0.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
public Square()
{
//initialising vertex byte buffer for shape coordinates
// (number of coordinate values * 4 bytes per float)
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
//Initialise byte buffer for the draw list
//(number of draw values * 2 bytes per short )
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer colors = ByteBuffer.allocateDirect(color.length * 4);
colors.order(ByteOrder.nativeOrder());
bufferColor = colors.asFloatBuffer();
bufferColor.put(color);
bufferColor.position(0);
int vertexShader = Shaders.loadShader(GLES20.GL_VERTEX_SHADER, Shaders.vertexShaderCode);
int fragmentShader = Shaders.loadShader(GLES20.GL_FRAGMENT_SHADER, Shaders.fragmentShaderCode);
mProg = GLES20.glCreateProgram();
GLES20.glAttachShader(mProg, vertexShader);
GLES20.glAttachShader(mProg, fragmentShader);
GLES20.glLinkProgram(mProg);
vertaxCount = squareCoords.length / COORDS_PER_VERTEX; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
vertaxStride = COORDS_PER_VERTEX * 4; //4 are how many bytes in a float
}
public void draw(float[] mMVPMatrix)
{
//Add program to OpenGL environment
GLES20.glUseProgram(mProg);
//Get Handle to the vertices
int mPositionHandle = GLES20.glGetAttribLocation(mProg, "vPosition");
//Prepare the shape coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertaxStride, vertexBuffer);
//Enable a handle to the shape vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
int mColorHandle = GLES20.glGetUniformLocation(mProg, "v_color");
GLES20.glVertexAttribPointer(mColorHandle, 3, GLES20.GL_FLOAT, false, 0, bufferColor);
GLES20.glEnableVertexAttribArray(mColorHandle);
float [] tm = new float[16];
float [] rm = new float[16];
Matrix.scaleM(mMVPMatrix, 0, 0.35f, 0.35f, 0);
Matrix.translateM(tm, 0, mMVPMatrix, 0, 0f, 0f, 0);
Matrix.rotateM(rm, 0, tm, 0, 45f, 0, 0, 1);
// get handle to shape's transformation matrix
int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProg, "u_MVPMatrix");
// Apply the projection and view transformation
//GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, rm, 0);
//Draw the shape
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertaxCount);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
//Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
答案 0 :(得分:0)
class Cube {
private FloatBuffer mVertexBuffer;
private FloatBuffer mColorBuffer;
private ShortBuffer mIndexBuffer;
private int mProgram, mPositionHandle, mColorHandle, mMVPMatrixHandle ;
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute vec4 aColor;" +
"varying vec4 vColor;" +
"void main() {" +
"vColor = aColor;" +
"gl_Position = vPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
"gl_FragColor = vColor;" + // vec4(0.0, 1.0, 0.0, 1.0);" +
"}";
private float vertices[] = {
-0.5f, -0.5f, 0.5f,//Bottom Left
0.5f, -0.5f, 0.5f, //Bottom Right
0.5f, 0.5f, 0.5f, //Top Right
-0.5f, 0.5f, 0.5f, //Top left
-0.5f, -0.5f, -0.5f,//Bottom Left
0.5f, -0.5f, -0.5f, //Bottom Right
0.5f, 0.5f, -0.5f, //Top Right
-0.5f, 0.5f, -0.5f //Top left
};
private float colors[] = {
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f
};
private short indices[] = {
0,1,2, 0,2,3,//front
0,3,7, 0,7,4,//Left
0,1,5, 0,5,4,//Bottom
6,7,4, 6,4,5,//Back
6,7,3, 6,3,2,//top
6,2,1, 6,1,5//right
};
public Cube() {
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mVertexBuffer = byteBuf.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(colors.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mColorBuffer = byteBuf.asFloatBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(indices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mIndexBuffer = byteBuf.asShortBuffer();
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram);
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void draw (float[] mvpMatrix){
//GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
12, mVertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mColorHandle, 4,
GLES20.GL_FLOAT, false,
0, mColorBuffer);
// Set color for drawing the triangle
// GLES20.glUniform2fv(mColorHandle, 1,colors, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mColorHandle);
}
}
public abstract class GLRenderer implements GLSurfaceView.Renderer {
boolean mFirstDraw;
boolean mSurfaceCreated;
int mWidth;
int mHeight;
long mLastTime;
int mFPS;
float[] mProjMatrix = new float[16];
float[] mVMatrix = new float[16];
float[] mMVPMatrix = new float[16];
private float[] rotationMatrix = new float[16];
private float angle = 0f;
GLRenderer() {
mFirstDraw = true;
mSurfaceCreated = false;
mWidth = -1;
mHeight = -1;
mLastTime = System.currentTimeMillis();
mFPS = 0;
}
@Override
public void onDrawFrame(GL10 arg0) {
// TODO Auto-generated method stub
Cube mCube = new Cube();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
if (mFirstDraw)
mFirstDraw = false;
angle += 0.7f;
if (angle > 360f)
angle = 0f;
Matrix.setLookAtM(mVMatrix, 0, 0f, 0f, 4f, 0f, 0f, 0f, 0f, 1f, 0f);
// projection x view = modelView
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Creating rotation matrix
Matrix.setRotateM(rotationMatrix, 0, angle, 0f, 0f, -1f);
// rotation x camera = modelView
float[] duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
Matrix.setRotateM(rotationMatrix, 0, angle, 0f, -1f, 0f);
duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
Matrix.setRotateM(rotationMatrix, 0, angle, -1f, 0f, 0f);
duplicateMatrix = Arrays.copyOf(mMVPMatrix, 16);
Matrix.multiplyMM(mMVPMatrix, 0, duplicateMatrix, 0, rotationMatrix, 0);
// rotation x camera = modelView
mCube.draw(mMVPMatrix);
}
@Override
public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
mWidth = arg1;
mHeight = arg2;
GLES20.glViewport(0, 0, mWidth, mHeight);
float ratio = (float) mWidth / mHeight;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -1, 1, -1, 1, 3, 7);
}
@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
// TODO Auto-generated method stub
mSurfaceCreated = true;
mWidth = -1;
mHeight = -1;
GLES20.glClearColor(0f, 0f, 0f, 0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
}
}
public class MainActivity extends Activity {
GLSurfaceView glView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
if(hasGL20()){
glView = new GLSurfaceView(getApplicationContext());
glView.setEGLContextClientVersion(2);
glView.setPreserveEGLContextOnPause(true);
glView.setRenderer(new GL20Renderer());
}else{
Log.v ("No Req Version","");
}
setContentView(glView);
}
@Override
protected void onPause() {
super.onPause();
if(glView != null)
glView.onPause();
}
@Override
protected void onResume() {
super.onResume();
if(glView != null)
glView.onResume();
}
private boolean hasGL20(){
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return info.reqGlEsVersion >= 0x20000;
}
}
答案 1 :(得分:0)
可能是你的三角形并非全部以一致的方向缠绕。尝试禁用背面剔除:
GLES20.glDisable(GLES20.GL_CULL_FACE);
或者,将CullFace反转到前面:
GLES20.glCullFace(GLES20.GL_FRONT);
如果这会改变立方体的哪一面被渲染,那么你的三角形并非全部以一致的方向缠绕。