title: Android openGL ES normals
body: <p>So yesterday I wrote WaveFront .obj 3D model loader which now works fine(doesn't support everything tho) so I wrote simple test to draw any 3D model on the screen which all worked fine until I was adding lighting to the scene. The light appeared but it seems like the normals are still in their default state. I am very unsure what should i use as target when generating buffers(as theres GL_NORMAL_ARRAY, GL_ARRAY_BUFFER etc.) for normals as I couldn't find any tutorial about it using buffer objects for those:</p>
  
  <pre><code>package com.Ruuhkis.opengl;
  
  import static javax.microedition.khronos.opengles.GL10.GL_COLOR_BUFFER_BIT;
  import static javax.microedition.khronos.opengles.GL10.GL_VERTEX_ARRAY;
  
  import java.nio.ByteBuffer;
  import java.nio.ByteOrder;
  import java.nio.FloatBuffer;
  import java.nio.ShortBuffer;
  
  import javax.microedition.khronos.egl.EGLConfig;
  import javax.microedition.khronos.opengles.GL10;
  import javax.microedition.khronos.opengles.GL11;
  
  import android.content.Context;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.BitmapFactory.Options;
  import android.opengl.GLSurfaceView.Renderer;
  import android.opengl.GLU;
  import android.opengl.GLUtils;
  import android.util.Log;
  
  import com.Ruuhkis.opengl.model.Indices;
  import com.Ruuhkis.opengl.model.Loader;
  import com.Ruuhkis.opengl.model.Model;
  import com.Ruuhkis.opengl.model.Polygon;
  import com.Ruuhkis.opengl.model.Vertex;
  
  public class TextureRenderer implements Renderer {
  
      private FloatBuffer vertexBuffer, normalBuffer;
      private ShortBuffer indexBuffer;
      private int attribVBO, attribIBO, attribNBO;
      private Context context;
      private float rotation = 0;
      private float[] vertices = 
          {-0.8f, -0.8f, 0f,
          0.8f, -0.8f, 0f,
          0.8f, 0.8f, 0f,
          -0.8f, 0.8f, 0f};
  
      private float[] normals = 
          {0f};
  
      private short[] indices =
          {0, 3, 2,
          0, 2, 1};
  
      public TextureRenderer(Context context) {
          this.context = context;
  
          Model model = Loader.loadModel(context.getAssets(), "test.txt");
  
          vertices = new float[model.getVerticeList().size() * 3];
  
          int i = 0;
  
          for(Vertex v: model.getVerticeList()) {
              vertices[i++] = v.getX();
              vertices[i++] = v.getY();
              vertices[i++] = v.getZ();
              //Log.v("vertice", v.toString() + " sa");
          }
  
          i = 0;
  
          indices = new short[model.getPolygonList().size() * 3];
          normals = new float[model.getPolygonList().size() * 3];
  
          for(Polygon p: model.getPolygonList()) {
              for(Indices in: p.getIndiceList()) {
                  normals[i] = vertices[in.getNormalIndex()];
                  indices[i++] = (short) in.getVertexIndex();         
              }
          }
  
          ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * 4);
          buffer.order(ByteOrder.nativeOrder());
          vertexBuffer = buffer.asFloatBuffer();
          vertexBuffer.put(vertices);
          vertexBuffer.flip();
  
          buffer = ByteBuffer.allocateDirect(normals.length * 4);
          buffer.order(ByteOrder.nativeOrder());
          normalBuffer = buffer.asFloatBuffer();
          normalBuffer.put(normals);
          normalBuffer.flip();
  
          buffer = ByteBuffer.allocateDirect(indices.length * 2);
          buffer.order(ByteOrder.nativeOrder());
          indexBuffer = buffer.asShortBuffer();
          indexBuffer.put(indices);
          indexBuffer.flip();
  
  
      }
  
      @Override
      public void onDrawFrame(GL10 gl) {
  
          gl.glColor4f(1f, 0f, 0f, 1f);
          gl.glClear(GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
  
          gl.glLoadIdentity();
          gl.glPushMatrix();
          gl.glTranslatef(0f, 0f, -10f);
          rotation += 1f;
          gl.glRotatef(rotation, 1f, 1f, 0f);
          gl.glEnableClientState(GL_VERTEX_ARRAY);
          gl.glEnableClientState(GL11.GL_NORMAL_ARRAY);
  
          GL11 gl11 = (GL11) gl;
  
          gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, attribVBO);
          gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, attribIBO);
          gl11.glBindBuffer(GL11.GL_NORMAL_ARRAY, attribNBO);
          gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
          gl11.glNormalPointer(3, GL10.GL_FLOAT, 0);
          gl11.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, 0);
  
          gl.glDisableClientState(GL11.GL_NORMAL_ARRAY);
          gl.glDisableClientState(GL_VERTEX_ARRAY);
          gl.glPopMatrix();
          gl.glFlush();
      }
  
      @Override
      public void onSurfaceChanged(GL10 gl, int width, int height) {
          gl.glViewport(0, 0, width, height);
          gl.glMatrixMode(GL10.GL_PROJECTION);
          gl.glLoadIdentity();
          GLU.gluPerspective(gl, 45f, (float)width / (float)height, 1f, 100f);
          gl.glMatrixMode(GL10.GL_MODELVIEW);
          gl.glEnable(GL10.GL_DEPTH_TEST);
          //gl.glEnable(GL10.GL_LIGHTING);
          gl.glEnable(GL10.GL_LIGHTING);
          gl.glEnable(GL10.GL_LIGHT1);
          gl.glEnable(GL10.GL_COLOR_MATERIAL);
          gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, FloatBuffer.wrap(new float[]{0f, 0f, 0f, 1f}));
          gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, FloatBuffer.wrap(new float[]{1f, 1f, 1f, 1f}));
          gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, FloatBuffer.wrap(new float[]{1f, 1f, 1f, 1f}));
  
          gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, FloatBuffer.wrap(new float[]{1f, 1f, 1f, 1f}));
          gl.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS,128f);
          gl.glShadeModel(GL10.GL_SMOOTH);
      }
  
      @Override
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
          gl.glClearColor(0.8f, 0.8f, 0.8f, 1f);
          GL11 gl11 = (GL11) gl;
          int[] buffer = new int[1];
          gl11.glGenBuffers(1, buffer, 0);
          attribVBO = buffer[0];
          gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, attribVBO);
          gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertices.length * 4, vertexBuffer, GL11.GL_STATIC_DRAW);
          gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, -1);
  
          gl11.glGenBuffers(1, buffer, 0);
          attribIBO = buffer[0];
          gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, attribIBO);
          gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indices.length * 2, indexBuffer, GL11.GL_STATIC_DRAW);
          gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, -1);
  
          gl11.glGenBuffers(1, buffer, 0);
          attribNBO = buffer[0];
          gl11.glBindBuffer(GL11.GL_NORMAL_ARRAY, attribNBO);
          gl11.glBufferData(GL11.GL_NORMAL_ARRAY, normals.length * 4, normalBuffer, GL11.GL_STATIC_DRAW);
          gl11.glBindBuffer(GL11.GL_NORMAL_ARRAY, -1);
      }
  }
  </code></pre>
  
  <p><img src="https://i.stack.imgur.com/azDkv.png" alt="enter image description here"></p>
  
  <p>so, the default normals are 0, 0, -1 or 0, 0, 1 and the default camera is looking at -5, and as the model rotates the light just goes away just like it is when theres no normals, I've got something similar to this work with computer but i didn't use VBOs etc. so I can't compare the code, I am pretty sure theres something wrong with uploading the normal buffer or binding it! :( help me! :(</p>