title: LWJGL per face lighting
body: <p>I tried making something that works out normals from faces, I dont know if it works and i get smooth shading on my model.</p>
  
  <p>It seems to work fine as a quad, but when i tried a cube, it only rendered 1 quad at the top which gets randomly smooth shaded, and everything else is black. If i turn off lighting, it only renders 1 quad which is at the top.</p>
  
  <p>Model class:</p>
  
  <pre><code>public class Model {
  private int vbo, ibo, vao, tbo, nbo;
  private int count = 0;
  
  private float[] normal;
  
  private Matrix4f modelMatrix;
  private Vector3f position, rotation;
  
  private Texture texture;
  private boolean hasTexture = false;
  
  private String matrixName;
  
  public Model(float[] vertices, String matrixName, int[] ... indices) {
      if (!initialized) {
          log.err("JORL not initialized", "Run 'init()' at the start of your program");
          System.exit(1);
      }
  
      this.matrixName = matrixName;
  
      vao = glGenVertexArrays();
      vbo = glGenBuffers();
      ibo = glGenBuffers();
      nbo = glGenBuffers();
  
      for (int[] face : indices)
          count += face.length;
  
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
      for (int[] face : indices)
          glBufferData(GL_ELEMENT_ARRAY_BUFFER, put(face), GL_STATIC_DRAW);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  
      glBindVertexArray(vao);
      glBindBuffer(GL_ARRAY_BUFFER, vbo);
      glBufferData(GL_ARRAY_BUFFER, put(vertices), GL_STATIC_DRAW);
      glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindVertexArray(0);
  
      normal = new float[count];
      int current = 0;
      for (int[] face : indices) {
          Vector3f p1 = new Vector3f(vertices[face[0] * 3], vertices[face[0] * 3 + 1], vertices[face[0] * 3 + 2]);
          Vector3f p2 = new Vector3f(vertices[face[1] * 3], vertices[face[1] * 3 + 1], vertices[face[1] * 3 + 2]);
          Vector3f p3 = new Vector3f(vertices[face[2] * 3], vertices[face[2] * 3 + 1], vertices[face[2] * 3 + 2]);
  
          log.info(p1.toString());
          log.info(p2.toString());
          log.info(p3.toString());
  
          Vector3f U = p2;
          Vector3f V = p3;
          U.sub(p1);
          V.sub(p1);
  
          normal[current * 3] = (U.y * V.z) - (U.z * V.y);
          normal[current * 3 + 1] = (U.z * V.x) - (U.x * V.z);
          normal[current * 3 + 2] = (U.x * V.y) - (U.y * V.x);
  
          System.out.println(normal[current * 3]);
          System.out.println(normal[current * 3 + 1]);
          System.out.println(normal[current * 3 + 2]);
  
  
          current++;
      }
  
      glBindVertexArray(vao);
      glBindBuffer(GL_ARRAY_BUFFER, nbo);
      glBufferData(GL_ARRAY_BUFFER, put(normal), GL_STATIC_DRAW);
      glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, 0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindVertexArray(0);
  
      modelMatrix = new Matrix4f();
      position = new Vector3f(0, 0, 0);
      rotation = new Vector3f(0, 0, 0);
  }
  
  public void setTexture(ShaderProgram shader, Texture texture, float[] coords) {
      this.texture = texture;
      hasTexture = true;
      shader.bind();
      shader.editUniform(1, "has_texture");
      shader.editUniform(texture.getSampler(), "tex");
      shader.bind();
  
      tbo = glGenBuffers();
      glBindVertexArray(vao);
      glBindBuffer(GL_ARRAY_BUFFER, tbo);
      glBufferData(GL_ARRAY_BUFFER, put(coords), GL_STATIC_DRAW);
      glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindVertexArray(0);
  }
  
  private FloatBuffer put(float[] data) {
      FloatBuffer pData = BufferUtils.createFloatBuffer(data.length);
      pData.put(data).flip();
      return pData;
  }
  
  private IntBuffer put(int[] data) {
      IntBuffer pData = BufferUtils.createIntBuffer(data.length);
      pData.put(data).flip();
      return pData;
  }
  
  public void increaseX(float increase) { position.x += increase; }
  public void increaseY(float increase) { position.y += increase; }
  public void increaseZ(float increase) { position.z += increase; }
  
  public void increaseRotX(float increase) { rotation.x += increase; }
  public void increaseRotY(float increase) { rotation.y += increase; }
  public void increaseRotZ(float increase) { rotation.z += increase; }
  
  public void render(ShaderProgram shader) {
      modelMatrix.identity();
  
      modelMatrix.translate(position);
      modelMatrix.rotateX((float) Math.toRadians(rotation.x));
      modelMatrix.rotateY((float) Math.toRadians(rotation.y));
      modelMatrix.rotateZ((float) Math.toRadians(rotation.z));
  
      shader.editUniform(modelMatrix, matrixName);
  
      glBindVertexArray(vao);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
      glEnableVertexAttribArray(0);
      glEnableVertexAttribArray(2);
      if (hasTexture) {
          glEnableVertexAttribArray(1);
          texture.bind();
      }
  
      glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
  
      glDisableVertexAttribArray(2);
      glDisableVertexAttribArray(0);
      if (hasTexture) {
          glDisableVertexAttribArray(1);
          texture.unbind();
      }
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
      glBindVertexArray(0);
  }
  
  public void delete() {
      glDeleteBuffers(vbo);
      glDeleteBuffers(ibo);
      glDeleteBuffers(nbo);
      if (hasTexture) {
          glDeleteBuffers(tbo);
          texture.delete();
      }
      glDeleteVertexArrays(vao);
  }
  </code></pre>
  
  <p>}</p>
  
  <p>I have a light class which just outputs a colour and position vector to the shader.
  The camera is working fine and everything else works fine if i dont use lighting. (apart from more than 1 face).</p>
  
  <p>geometry shader:</p>
  
  <pre><code>    #version 400
  
  layout(triangles) in;
  layout(triangle_strip, max_vertices = 3) out;
  
  in vec4 colour[];
  in vec2 pass_tex_coords[];
  
  in vec3 pass_normal[];
  out vec3 t_normal;
  out vec3 t_light;
  
  out vec2 pass_tex_coords_;
  out vec4 pass_colour;
  
  uniform mat4 projection;
  uniform mat4 view;
  uniform mat4 model;
  
  uniform vec3 light_position;
  
  void main(void) {
      for (int i = 0; i &lt; gl_in.length(); i++) {
          vec4 world_pos = projection * view * model * gl_in[i].gl_Position;
          gl_Position = world_pos;
  
          pass_tex_coords_ = pass_tex_coords[i];
          pass_colour = colour[i];
  
          t_normal = (view * model * vec4(pass_normal[i], 0)).xyz;
          t_light = (view * vec4(light_position, 1)).xyz;
  
          EmitVertex();
      }
  
      EndPrimitive();
  }
  </code></pre>
  
  <p>fragment shader:</p>
  
  <pre><code>#version 400
  
  in vec4 pass_colour;
  in vec2 pass_tex_coords_;
  
  in vec3 t_normal;
  in vec3 t_light;
  
  out vec4 out_colour;
  
  uniform int has_texture;
  uniform sampler2D tex;
  
  uniform vec4 light_colour;
  
  void main(void) {
      vec3 n_normal = normalize(t_normal);
      vec3 n_light = normalize(t_light);
      float cosTheta = dot(n_normal, n_light);
  
      if (has_texture != 1) {
          out_colour = texture(tex, pass_tex_coords_) * pass_colour * cosTheta;
      } else {
          out_colour = pass_colour;
      }
  }
  </code></pre>
  
  <p>If anybody has any links to per face lighting that would be great, I couldnt find any.
  I do think this has something to do with my messy Model class with the indices parameter.</p>
  
  <p>EDIT
  All faces render now, now how do i fix the weird smooth gradient lighting to be a per face flat lighting?</p>