Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Every object in your 3D world has a <em><a href="http://en.wikipedia.org/wiki/Surface_normal" rel="noreferrer">normal</a></em>, where it helps OpenGL to determine how much light an object need to reflect. You've probably forgot to specify the <em>normals</em> for your surfaces. Without specifying them, OpenGL will light all objects in your world in the same way. </p> <p>In order to get a surface's normal in 3D you need at least three vertices, which means it at least is a triangle.</p> <p><strong>Sample stuff</strong>:</p> <p>In order to calculate a surface's normal you need two vectors. Since you have three vertices in 3D space that means that these sample points could contain a triangle:</p> <pre><code>// Top triangle, three points in 3D space. vertices = new float[] { -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, } </code></pre> <p>Given these three points, you can now define two vectors by the following:</p> <pre><code>// Simple vector class, created by you. Vector3f vector1 = new Vector3f(); Vector3f vector2 = new Vector3f(); vector1.x = vertices[0] - vertices[3]; vector1.y = vertices[1] - vertices[4]; vector1.z = vertices[2] - vertices[5]; vector2.x = vertices[3] - vertices[6]; vector2.y = vertices[4] - vertices[7]; vector2.z = vertices[5] - vertices[8]; </code></pre> <p>Now when you have two vectors, you can finally get the surface's normal by using the <a href="http://en.wikipedia.org/wiki/Cross_product" rel="noreferrer">Cross Product</a>. Shortly, the cross product is an operation which results in a new vector containing an angle that is perpendicular to the input vectors. This is the <em>normal</em> that we need. </p> <p>To get the cross product in your code you have to write your own method that calculates it. In theory you calculate the cross product given this formula:</p> <blockquote> <p>A <strong>X</strong> B = (A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x)</p> </blockquote> <p>In code (by using the vectors above):</p> <pre><code>public Vector3f crossProduct(Vector3f vector1, Vector3f vector2) { Vector3f normalVector = new Vector3f(); // Cross product. The normalVector contains the normal for the // surface, which is perpendicular both to vector1 and vector2. normalVector.x = vector1.y * vector2.z - vector1.z * vector2.y; normalVector.y = vector1.z * vector2.x - vector1.x * vector2.z; normalVector.z = vector1.x * vector2.y - vector1.y * vector2.x; return normalVector; } </code></pre> <p><strong>Before any further comments</strong>; you can specify your normals in an array and just put them into OpenGL when needed, but your understanding of this topic will be much better if you dig into it and your code will be much more flexible.</p> <p>So now we have a normal which you can loop through, assign the vector values to your normal array (like NeHe's ports, but dynamically) and set up OpenGL to use <code>GL_NORMAL_ARRAY</code> in order to get OpenGL to reflect the light on the object correctly:</p> <pre><code>gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); // I'm assuming you know how to put it into a FloatBuffer. gl.glNormalPointer(GL10.GL_FLOAT, 0, mNormalsBuffer); // Draw your surface... </code></pre> <p>Another last comment; if you're using other vertices values (like 5.0f, 10.0f or bigger) you might wanna <a href="http://en.wikipedia.org/wiki/Normalized_vector" rel="noreferrer">normalize</a> the vector that returns from the <code>crossProduct()</code> method in order to gain some performance. Otherwise OpenGL must calculate the new vector to get the <em>unit vector</em> and that might be a performance issue.</p> <p>Also, your <code>new float[] {-4f, 0.9f, 6f, 1f}</code> for <code>GL_POSITION</code> is not quite correct. When the fourth value is set to <code>1.0f</code> it means that the light position is <code>0, 0, 0</code>, no matter what the first three values are. In order to specify a vector for your light position, change the fourth value to <code>0.0f</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload