开发者

Android OpenGL "glMaterialfv" function

Having constructed the following OpenGL-ES program which renders a simple textured cube using ambient light alone, I have come across a strange anomaly whilst attempting to implement the "glMaterialfv" function with either GL_FRONT or GL_BACK parameters. Whilst the material is correctly processes in conjuction with the GL_BACK_AND_FRONT parameter, neither GL_FRONT nor GL_BACK appear to procur the correct results. As my normals appear to work in the presence of a directional light source, I can only assume that I'm missing something quite obvious. Could this possibly be an issue with the Android emulator itself?

package tal.cube1;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.graphics.BitmapFactory;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.content.res.*;
import android.graphics.Bitmap;

public class OpenGLRenderer implements Renderer
{ 
 private final float mf_textureCoordinates[] =
 {
  0.0f, 0.0f,   0.0f, 1.0f,   1.0f, 1.0f,   1.0f, 0.0f,
  0.0f, 0.0f,   0.0f, 1.0f,   1.0f, 1.0f,   1.0f, 0.0f,
  0.0f, 0.0f,   0.0f, 1.0f,   1.0f, 1.0f,   1.0f, 0.0f,
  0.0f, 0.0f,   0.0f, 1.0f,   1.0f, 1.0f,   1.0f, 0.0f,
  0.0f, 0.0f,   0.0f, 1.0f,   1.0f, 1.0f,   1.0f, 0.0f,
  0.0f, 0.0f,   0.0f, 1.0f,   1.0f, 1.0f,   1.0f, 0.0f
 };

 private final float mf_normals[] = 
 { 0,  0,  1,    0,  0,  1,    0,  0,  1,    0,  0,  1,
   0,  1,  0,    0,  1,  0,    0,  1,  0,    0,  1,  0,
   0,  0, -1,    0,  0, -1,    0,  0, -1,    0,  0, -1,
   0, -1,  0,    0, -1,  0,    0, -1,  0,    0, -1,  0,
  -1,  0,  0,   -1,  0,  0,   -1,  0,  0,   -1,  0,  0,
   1,  0,  0,    1,  0,  0,    1,  0,  0,    1,  0,  0
 };

 private final float mf_vertices[] =
 {-1,  1,  1,   -1, -1,  1,    1, -1,  1,    1,  1,  1,
  -1,  1, -1,   -1,  1,  1,    1,  1,  1,    1,  1, -1,
   1,  1, -1,    1, -1, -1,   -1, -1, -1,   -1,  1, -1,
  -1, -1,  1,   -1, -1, -1,    1, -1, -1,    1, -1,  1,
  -1,  1, -1,   -1, -1, -1,   -1, -1,  1,   -1,  1,  1,
   1,  1,  1,    1, -1,  1,    1, -1, -1,    1,  1, -1
 };

 private final short mf_indices[] =
 { 0,  1,  2,    0,  2,  3,
   4,  5,  6,    4,  6,  7,
   8,  9, 10,    8, 10, 11,
  12, 13, 14,   12, 14, 15,
  16, 17, 18,   16, 18, 19,
  20, 21, 22,   20, 22, 23
 };

 private final float mf_ambientLight[] =
 {
  1.0f, 1.0f, 1.0f, 1.0f
 };

 private final float mf_ambientMaterial[] =
 {
  1.0f, 0.0f, 0.0f, 1.0f
 };

 private FloatBuffer m_vertexBuffer;
 private FloatBuffer m_normalBuffer;
 private FloatBuffer m_textureBuffer;
 private ShortBuffer m_indexBuffer;
 private Bitmap m_texture;
 private int m_textures[]; 
 private float m_angle = 0.0f;

 public OpenGLRenderer(Resources p_resources)
 {
  super();
  m_texture = BitmapFactory.decodeResource(p_resources, R.drawable.crate);
 }

 @Override public void onSurfaceCreated(GL10 p_gl, EGLConfig p_config)
 {
  ByteBuffer vbb = ByteBuffer.allocateDirect(mf_vertices.length * 4);
  vbb.order(ByteOrder.nativeOrder());
  m_vertexBuffer = vbb.asFloatBuffer();
  m_vertexBuffer.put(mf_vertices);
  m_vertexBuffer.position(0);

  ByteBuffer nbb = ByteBuffer.allocateDirect(mf_normals.length * 4);
  nbb.order(ByteOrder.nativeOrder());
  m_normalBuffer = nbb.asFloatBuffer();
  m_normalBuffer.put(mf_normals);
  m_normalBuffer.position(0);

  ByteBuffer tbb = ByteBuffer.allocateDirect(mf_textureCoordinates.length * 4);
  tbb.order(ByteOrder.nativeOrder());
  m_textureBuffer = tbb.asFloatBuffer();
  m_textureBuffer.put(mf_textureCoordinates);
  m_textureBuffer.position(0);

  ByteBuffer ibb = ByteBuffer.allocateDirect(mf_indices.length * 2);
  ibb.order(ByteOrder.nativeOrder());
  m_indexBuffer = ibb.asShortBuffer();
  m_indexBuffer.put(mf_indices);
  m_indexBuffer.position(0);

  m_textures = new int[1];
  p_gl.glBindTexture(GL10.GL_TEXTURE_2D, m_textures[0]);
  p_gl.glGenTextures(1, m_textures, 0);
  GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, m_texture, 0);

  p_gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  p_gl.glClearDepthf(1.0f);
  p_gl.glShadeModel(GL10.GL_FLAT);
  p_gl.glDepthFunc(GL10.GL_LEQUAL);
  p_gl.glFrontFace(GL10.GL_CCW);
  p_gl.glCullFace(GL10.GL_BACK);
  p_gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);

  p_gl.glDisable(GL10.GL_DITHER);
  p_gl.glEnable(GL10.GL_DEPTH_TEST);
  p_gl.glEnable(GL10.GL_CULL_FACE);
  p_gl.glEnable(GL10.GL_LIGHTING);
  p_gl.glEnable(GL10.GL_TEXTURE_2D);

  p_gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  
  p_gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  p_gl.glEnableClientState(GL11.GL_NORMAL_ARRAY);

  p_gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, m_textureBuffer);
  p_gl.glNormalPointer(GL10.GL_FLOAT, 0, m_normalBuffer);
  p_gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_vertexBuffer);

  p_gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, mf_ambientLight, 0);
  p_gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, mf_ambientMaterial, 0);
 }

 @Override public void onDrawFrame(GL10 p_gl)
 {
  p_gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
               GL10.GL_DEPTH_BUFFER_BIT);
  p_gl.glLoadIdentity();
  p_gl.glTranslatef(0.0f, 0.0f, -8);
  p_gl.glRotatef(m_angle, 1.0f, 1.0f, 1.0f);
  p_gl.glDrawElements(GL10.GL_TRIANGLES, m_indexBuffer.capacity(),
                      GL10.GL_UNSIGNED_SHORT, m_indexBuffer);
  m_angle += 1.0f;
 }

 @Override public void onSurfaceChanged(GL10 p_gl, int p_width, int p_height)
 {
  p_gl.glViewport(0, 0, p_width, p_height);
  p_gl.glMatrixMode(GL10.GL_PROJECTION);
  p_gl.glLoadIdentity();
  GLU.gluPerspective(p_gl, 45.0f, (float)p_width / (float)p_height,
        开发者_开发百科             0.1f, 100.0f);
  p_gl.glMatrixMode(GL10.GL_MODELVIEW);
  p_gl.glLoadIdentity();
 }
}


Having now reviewed the OpenGL-ES 1.1 documentation, I can now confirm that the GL_FRONT and GL_BACK parameters are only supported under the full OpenGL 1.1 specification. My advice for anyone currently developing for the OpenGL-ES platform, is to ensure that their documentation specifically covers the "ES" OpenGL subset. Due to some erroneous assumptions, not to mention a fair measure of lethargy, I have spent many hours needlessly testing features which are not supported by the target platform. Just like baking a cake, preparation is everything, and I deserve nothing less that a swift kick in the knackers for adopting such a school-boy approach to an otherwise solid API. Just to reiterate, whilst this may be common sense for most people, the full OpenGL specification is of little value if you're developing for its lesser "ES" counterpart.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜