<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>db-in&#039;s blog &#187; Shaders</title>
	<atom:link href="http://db-in.com/blog/category/opengl/shaders/feed/" rel="self" type="application/rss+xml" />
	<link>http://db-in.com/blog</link>
	<description></description>
	<lastBuildDate>Mon, 05 Mar 2012 15:15:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Calculating Normals and Tangent Space</title>
		<link>http://db-in.com/blog/2012/03/calculating-normals-and-tangent-space/</link>
		<comments>http://db-in.com/blog/2012/03/calculating-normals-and-tangent-space/#comments</comments>
		<pubDate>Mon, 05 Mar 2012 15:15:19 +0000</pubDate>
		<dc:creator>Diney Bomfim</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Feature]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[GLSL ES]]></category>
		<category><![CDATA[OpenGL ES]]></category>

		<guid isPermaLink="false">http://db-in.com/blog/?p=1459</guid>
		<description><![CDATA[A full tutorial showing how to calculate Vertex Normals and Tangent Space. Using the most accurate approach creating a 100% function Normal, Tangent and Bitangent (also known as Binormal).]]></description>
			<content:encoded><![CDATA[<p>Hi guys!</p>
<p>In this article I&#8217;ll show how to calculate per-vertex Normals and the Tangent Space. Here you&#8217;ll see the most accurate technique, generating real Normals and breaking the vertex when necessary. This article is an intermediate part of the &#8220;All about Shaders&#8221; series. Would be nice if you&#8217;ve read the first part <a href="http://db-in.com/blog/2011/08/all-about-shaders-part-13/" title="All about Shaders – (part 1/3)" target="_blank">All about Shaders – (part 1/3)</a></p>
<p><span id="more-1459"></span></p>
<p><br/></p>
<h2><strong>At a glance</strong></h2>
<p>First off, the calculations and routines that we&#8217;ll create here is not an easy task, there are complexes concepts and calculations involved here. So, be sure you have this macro view:</p>
<ul>
<li>Usually the 3D softwares will export an Optimized Per-Vertex Normal, for those cases we can save our time, avoiding re-create the Normals. So we&#8217;ll create the Normal Vector ONLY when the Normals from 3D file was not optimized or don&#8217;t exist.</li>
<li>Non optimized Normals means that the same Normal vector was written many times by the 3D software. It happens in some 3D file formats, like COLLADA, that the same Normal vector can appear hundred times, making the parse processing very expensive.</li>
<li>It&#8217;s a good idea to calculate the Tangent Space always as possible (all that we need is Vertex Position and Vertex Texcoord).</li>
<li>The best way to deal with meshes using OpenGL is to use what we call &#8220;Array of Structures&#8221;, however I&#8217;ll show you a generice algorithym that can be used with &#8220;Structure of Arrays&#8221; as well.</li>
</ul>
<p>If these four bullets sounds like &#8220;Greek*&#8221; for you, I highly recommend you read some other articles before proceed:</p>
<ul>
<li><a href="http://db-in.com/blog/2011/01/all-about-opengl-es-2-x-part-13/" title="All about OpenGL ES 2.x – (part 1/3)" target="_blank">All about OpenGL ES 2.x – (part 1/3)</a></li>
<li><a href="http://db-in.com/blog/2011/02/all-about-opengl-es-2-x-part-23/" title="All about OpenGL ES 2.x – (part 2/3)" target="_blank">All about OpenGL ES 2.x – (part 2/3)</a></li>
<li><a href="http://db-in.com/blog/2011/05/all-about-opengl-es-2-x-part-33/" title="All about OpenGL ES 2.x – (part 3/3)" target="_blank">All about OpenGL ES 2.x – (part 3/3)</a></li>
</ul>
<p>(* well, if you are a greek guy, sorry for that and please, take this word as equivalent to &#8220;chinese&#8221; or something like that).</p>
<p>As I explained before, to calculate the Normals we just need the vertex position, but to calculate the Tangent Space we&#8217;ll need the texcoord already calculated. If the mesh we are working on doesn&#8217;t have texcoord we&#8217;ll skip the Tangent Space phase, because is not possible to create an arbitrary UV Map in the code, UV Maps are design dependents and change the way as the texture is made.</p>
<p>Hands at work!</p>
<p><br/></p>
<h2><strong>Calculating Normals &#8211; Step 1</strong></h2>
<p>In theory, the technique to calculate the face normals is simple: We&#8217;ll find the perpendicular vector for each face (triangle). However as you saw in the first tutorial of &#8220;<a href="http://db-in.com/blog/2011/08/all-about-shaders-part-13/#shading_types" target="_blank">All About Shaders</a>&#8220;, the face normals are not so good. So, we need to calculate the vertex normals.</p>
<p>The things become a little bit more complex when we try to calculate the vertex normals. Every Face Normal will affect the vertex that compose the face. One single vertex can be shared by multiple faces, so, the final Vertex Normal will be the averaged vector of each Face that share this Vertex. As each face has its own size, the averaged Vertex Normal vector should consider those differences.</p>
<div id="attachment_1461" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/09/adjacent_normal_example1.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/09/adjacent_normal_example1.jpg" alt="Vertices shared by multiple faces will have the resulting Normal as an average of all adjacent faces&#039; Normals." title="adjacent_normal_example" width="600" height="500" class="size-full wp-image-1461" /></a><p class="wp-caption-text">Vertices shared by multiple faces will have the resulting Normal as an average of all adjacent faces&#039; Normals.</p></div>
<p><a href="http://db-in.com/blog/wp-content/uploads/2011/09/teapot_strange1.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/09/teapot_strange1.jpg" alt="" title="teapot_strange" width="300" height="203" class="alignleft size-full wp-image-1462" /></a>Just with this concept, you can create the Normals, but they will seem strange in some meshes. Like this teapot at the left side. When I created my first Normals, I spent weeks trying to find what was wrong with my calculus or with this concept&#8230;  &#8220;Everything is OK, but only that fucking vertex is not. Why?&#8221;, I thought. Many others said that was a problem with my code, a problem with my memory allocation, and all other kinds of shits. But only after look closely to a great 3D software I found the problem. I&#8217;ll show you the same image that I spent hours looking to until I find the solution.</p>
<div id="attachment_1463" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/09/vertex_normal_example1.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/09/vertex_normal_example1.jpg" alt="Vertex Normals" title="vertex_normal_example" width="600" height="463" class="size-full wp-image-1463" /></a><p class="wp-caption-text">Vertex Normals</p></div>
<p>Did you notice something strange? This is a basic teapot mesh, many 3D softwares give you this to make tests with materials and lights. But this mesh has ONE single strange vertex: a vertex with 2 Normal Vectors. Is it possible? Actually, NO. The mesh structure must follow a pattern, so you can&#8217;t have all vertices with 1 Normal and only one vertex with 2 Normals. This is a very important point that no one talk about it, actually, I never seen anyone talking about this.</p>
<p>It&#8217;s time to understand what happens. Your mesh structure is not complete until you calculate the Normals. Why? Because some vertices will be &#8220;break/split&#8221; into two or more vertices by the Normals. This is what happens in that image. The 3D softwares will not show you this, but there are two vertices, with the same position and texcoords, but with different Normals. Obviously the 3D softwares prefer to omit this for performance reasons, but we can&#8217;t omit this fact to OpenGL. We must inform to the Shaders that there are two vertices instead of a single one.</p>
<p>And how will we know where to break a vertex? By the angle between faces. WOW, this thing of Normals is becoming very complex! Yeah, I told you that this is a very important and complex part. Let&#8217;s think by steps. Usually the light looks continuous on a surface until an angle of ~80º (like a sphere), however two faces with an angle > ~80º will form a hard edge, like the table&#8217;s corners. OK, now translating to English, this is what we&#8217;ll do:</p>
<ol>
<li>Calculate each face&#8217;s Normal.</li>
<li>Calculate the angle between face&#8217;s Normals.</li>
<li>At each group of ~80º we&#8217;ll create a new set of Normals.</li>
<li>Finally we&#8217;ll find the averaged Normal for each group, respecting the face&#8217;s size.</li>
</ol>
<p>Well, now it looks more simple, with just 4 simple steps. Nice! OK, let&#8217;s put our hands on code. First off, let&#8217;s create our Vector/Math functions.</p>
<table width="675">
<tbody>
<tr>
<th>Vector Math</th>
</tr>
</tbody>
</table>
<pre class="brush:cpp">
// Early in definitions...
typedef struct
{
	float x;
	float y;
} vec2;

// Vector's distance.
static inline vec2 vec2Subtract(vec2 vecA, vec2 vecB)
{
	return (vec2){vecA.x - vecB.x, vecA.y - vecB.y};
}

typedef struct
{
	float x;
	float y;
	float z;
} vec3;

static const vec3 kvec3Zero = {0.0f, 0.0f, 0.0f};

// Vector's length.
static inline float vec3Length(vec3 vec)
{
	// Square root.
	return sqrtf(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
}

// Vector's normalization.
static inline vec3 vec3Normalize(vec3 vec)
{
	// Find the magnitude/length. This variable is called inverse magnitude (iMag)
	// because instead divide each element by this magnitude, let's do multiplication, it's faster.
	float iMag = vec3Length(vec);

	// Avoid divisions by 0.
	if (iMag != 0.0f)
	{
		iMag = 1.0f / iMag;

		vec.x *= iMag;
		vec.y *= iMag;
		vec.z *= iMag;
	}

	return vec;
}

// Vector's sum.
static inline vec3 vec3Add(vec3 vecA, vec3 vecB)
{
	return (vec3){vecA.x + vecB.x, vecA.y + vecB.y, vecA.z + vecB.z};
}

// Vector's distance.
static inline vec3 vec3Subtract(vec3 vecA, vec3 vecB)
{
	return (vec3){vecA.x - vecB.x, vecA.y - vecB.y, vecA.z - vecB.z};
}

// Checks for zero values.
vec3IsZero(vec3 vec)
{
	return (vec.x == 0.0f &#038;&#038; vec.y == 0.0f &#038;&#038; vec.z == 0.0f);
}

// The dot product returns the cosine of the angle formed by two vectors.
static float vec3Dot(vec3 vecA, vec3 vecB)
{
	return vecA.x * vecB.x + vecA.y * vecB.y + vecA.z * vecB.z;
}

// The cross product returns an orthogonal vector with the other two,
// that means, the new vector is mutually perpendicular to the other two.
static vec3 vec3Cross(vec3 vecA, vec3 vecB)
{
	vec3 vec;

	vec.x = vecA.y * vecB.z - vecA.z * vecB.y;
	vec.y = vecA.z * vecB.x - vecA.x * vecB.z;
	vec.z = vecA.x * vecB.y - vecA.y * vecB.x;

	return vec;
}

// Checks if there is a NaN value inside the informed vector.
// If a NaN value is found, it's changed to 0.0f (zero).
static vec3 vec3Cleared(vec3 vec)
{
	vec3 cleared;
	cleared.x = (vec.x != vec.x) ? 0.0f : vec.x;
	cleared.y = (vec.y != vec.y) ? 0.0f : vec.y;
	cleared.z = (vec.z != vec.z) ? 0.0f : vec.z;

	return cleared;
}
</pre>
<p>Now we&#8217;re ready to go further:</p>
<table width="675">
<tbody>
<tr>
<th>Calculating Face Normals</th>
</tr>
</tbody>
</table>
<pre class="brush:cpp">
// Private variables...
// Assumes that all the variables that start with "_" is a private one
// and you must implement it by your self and some of those values must
// be present before you start:

// vec3 *_vertices    "array of vertices positions"   (required)
// vec3 *_texcoords   "array of texture coordinates"  (optional)
// vec3 *_normals     "array of normals"              (optional/to calculate)
// vec3 *_tangents    "array of tangents"             (to calculate)
// vec3 *_bitangents  "array of bitangents"           (to calculate)

// int  _vCount       "vertices count"                (required)
// int  _tCount       "texture coordinates count"     (optional)
// int  _nCount       "normals count"                 (optional/to calculate)
// int  _taCount      "tangents count"                (to calculate)
// int  _biCount      "bitangents count"              (to calculate)

// int *_faces        "array of face indices"         (required)
// int  _facesCount   "faces indices count"           (required)
// int  _facesStride  "stride of faces indices"       (required)

// Checks the crease angle for the normal calculations.
// This function creates and divides the normals for a vertex, recursively.
static unsigned int creaseAngle(unsigned int index, vec3 vector, vec3 **buffer, unsigned int *count, NSMutableDictionary *list)
{
	// Let's talk about this function later on.
}

// Calculating the Tangent Space.
void calculateTangentSpace()
{
	unsigned int i, length;
	unsigned int j, lengthJ;

	unsigned int *newFaces, *outFaces;
	unsigned int oldFaceStride = _facesStride;

	int i1, i2, i3;
	int vi1, vi2, vi3;
	int ti1, ti2, ti3;

	vec3 vA, vB, vC;
	vec2 tA, tB, tC;
	vec3 distBA, distCA;
	vec2 tdistBA, tdistCA;

	vec3 normal;
	vec3 tangent;
	vec3 bitangent;

	vec3 *normalBuffer;
	vec3 *tangentBuffer;
	vec3 *bitangentBuffer;

	NSMutableDictionary *multiples;

	Element *element;
	int vLength, vOffset;
	int nLength, nOffset;
	int tLength, tOffset;

	float area, delta;
	float *outValue;

	// Checks if the parsed mesh has Normals and Texture Coordinates.
	BOOL hasNormals = NO;// CUSTOM: Check if your mesh structure already has normals.
	BOOL hasTextures = YES;// CUSTOM: Check if your mesh structure already has texcoords.

	// Gets the vertex element.
	vLength = 4;// CUSTOM: Take the length of your vertex position component.
	vOffset = 0;// CUSTOM: Take the offset  of your vertex position component in the Array of Structures.

	// If the normal element doesn't exist yet, creates a new one.
	if (!hasNormals)
	{
		// CUSTOM: Create the Normal elements if it doesn't exist yet.
		// The element should be just as the vertex one, having a length and an offset.
		// IMPORTANT: Increate the stride of your Array of Structures (_facesStride).
	}

	// Gets the normal element.
	nLength = 3;// CUSTOM: Take the normal length.
	nOffset = 7;// CUSTOM: Take the normal offset. In this case (7) we consider it's after the texcoord.

	// If the texture coordinate element exist, gets it and create tangent and bitangent element.
	if (hasTextures)
	{
		tLength = 3;// CUSTOM: Take the texcoord length.
		tOffset = 4;// CUSTOM: Take the texcoord offset. In this case it's after the vertices positions.

		// CUSTOM: Here you should create the Tangent and Bitangent elements. Just as any
		// other element until here, they must have length and offset.
		// IMPORTANT: Increate the stride of your Array of Structures (_facesStride).
	}

	// Allocates memory to the new faces.
	newFaces = malloc(sizeof(int) * (_facesCount * _facesStride));

	// A priori, assumes that for each vertex exists only one normal.
	_nCount = _taCount = _biCount = _vCount;

	// Initializes the buffers for the tangent space elements.
	// This memory allocation must use calloc because they must be 0 (zero) value,
	// otherwise NaN values can be generated.
	normalBuffer = calloc(_nCount, sizeof(vec3));
	tangentBuffer = calloc(_taCount, sizeof(vec3));
	bitangentBuffer = calloc(_biCount, sizeof(vec3));

	// Initializes the dictionaries to deal with vertices with multiple normals in it.
	multiples = [[NSMutableDictionary alloc] init];

	// Loop through each triangle.
	length = _facesCount;
	for (i = 0; i < length; i += 3)
	{
		// Triangle Vertices. At this moment _faces is an ordered list of elements' indices:
		// iv1, it1, in1, iv2, in2, it2, iv3, it3, in3...
		//  |			   |			  |
		//  V			   V			  V
		// iv1,			  iv2,			 iv3
		// So the following lines will extract the indices of vertices that form a triangle.
		i1 = _faces[i * oldFaceStride + vOffset];
		i2 = _faces[(i + 1) * oldFaceStride + vOffset];
		i3 = _faces[(i + 2) * oldFaceStride + vOffset];

		// Calculates the vertex indices in the array of vertices.
		vi1 = i1 * vLength;
		vi2 = i2 * vLength;
		vi3 = i3 * vLength;

		// Retrieves 3 vertices from the array of vertices.
		vA = (vec3){_vertices[vi1], _vertices[vi1 + 1], _vertices[vi1 + 2]};
		vB = (vec3){_vertices[vi2], _vertices[vi2 + 1], _vertices[vi2 + 2]};
		vC = (vec3){_vertices[vi3], _vertices[vi3 + 1], _vertices[vi3 + 2]};

		// Calculates the vector of the edges, the distance between the vertices.
		distBA = vec3Subtract(vB, vA);
		distCA = vec3Subtract(vC, vA);

		//*************************
		//	Normals
		//*************************
		if (!hasNormals)
		{
			// Calculates the face normal to the current triangle.
			normal = vec3Cross(distBA, distCA);

			// Searches for crease angles considering the adjacent triangles.
			// This function also initialize new blocks of memory to the buffer, setting them to 0 (zero).
			i1 = creaseAngle(i1, normal, &#038;normalBuffer, &#038;_nCount, multiples);
			i2 = creaseAngle(i2, normal, &#038;normalBuffer, &#038;_nCount, multiples);
			i3 = creaseAngle(i3, normal, &#038;normalBuffer, &#038;_nCount, multiples);

			// Averages the new normal vector with the oldest buffered.
			normalBuffer[i1] = vec3Add(normal, normalBuffer[i1]);
			normalBuffer[i2] = vec3Add(normal, normalBuffer[i2]);
			normalBuffer[i3] = vec3Add(normal, normalBuffer[i3]);
		}
		else
		{
			// If the parsed file has normals in it, retrieves their indices in the array of normals.
			vi1 = _faces[i * oldFaceStride + nOffset] * nLength;
			vi2 = _faces[(i + 1) * oldFaceStride + nOffset] * nLength;
			vi3 = _faces[(i + 2) * oldFaceStride + nOffset] * nLength;

			// Retrieves the normals.
			vA = (vec3){_normals[vi1], _normals[vi1 + 1], _normals[vi1 + 2]};
			vB = (vec3){_normals[vi2], _normals[vi2 + 1], _normals[vi2 + 2]};
			vC = (vec3){_normals[vi3], _normals[vi3 + 1], _normals[vi3 + 2]};

			// Calculates the face normal to the current triangle.
			normal = vec3Add(vec3Add(vA, vB), vC);
		}

// CONTINUE...
</pre>
<p>Let's understand all those lines:</p>
<ul>
<li><strong>Lines 1-16</strong>: Definition of the output variables.</li>
<li><strong>Lines 20-23</strong>: A very important function to calculate the crease angle between faces. We'll discuss more about it later on.</li>
<li><strong>Lines 28-59</strong>: Defining the variables we'll use to calculate the Normals and the Tangent Space.</li>
<li><strong>Lines 62-63</strong>: CUSTOM CODE. Checks if there are Normals and Texture Coordinates already calculated in your mesh structure.</li>
<li><strong>Lines 66-67</strong>: CUSTOM CODE. Gets the length of each Vertex set (usually 3 or 4) and its offset in the Array of Faces.</li>
<li><strong>Lines 70-75</strong>: CUSTOM CODE. If there is no previous calculated Normals, create a new element and define its length (usually 3) and its offset in the Array of Faces.</li>
<li><strong>Lines 78-79</strong>: CUSTOM CODE. Gets the length of each Normal set (usually 3) and its offset in the Array of Faces.</li>
<li><strong>Lines 82-90</strong>: CUSTOM CODE. If there is a calculated Texture Coordinates, then create the Tangent and Bitangent elements. As both Tangent and Bitangent will follow the same elements rule, so you just need to define the length and offset in face for one of them.</li>
<li><strong>Lines 93-106</strong>: Allocating the necessary memory for the calculations.</li>
<li><strong>Lines 109-110</strong>: Starting the loop through all triangles of your mesh.</li>
<li><strong>Lines 118-120</strong>: Getting the indices form the current working triangle.</li>
<li><strong>Lines 123-130</strong>: Getting the vertices related to the current triangle.</li>
<li><strong>Lines 133-134</strong>: Calculating the distance between triangle's vertices. Depending on the order which you calculate this distance, the resulting normal vector direction can change. So, be careful about changing this order.</li>
<li><strong>Lines 142-153</strong>: If there are no previous normals. The cross product between the calculated distances will generate a perpendicular vector, it's the face normal to the current triangle (<a href="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/cross/index.htm" target="_blank">Cross Product info</a>). Then the crease angles are calculated, so we add the current normal vector to the normalBuffer. When we sum two vectors we are automatically calculating the middle vector. (<a href="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/index.htm" target="_blank">Add Vector info</a>).<br />
IMPORTANT: We're not normalizing the vector in this step, by doing so we make sure each triangle area (size) will be considered, because they have different lengths.</li>
<li><strong>Lines 158-168</strong>: If there are previous calculated normals. We calculate the current face normal, because the final format for normals are always vertex normal, not face normal. For the next steps we'll need the face normal.</li>
</ul>
<p><br/></p>
<h2><strong>The Crease Angle - Step 2</strong></h2>
<p>As I said before, the crease angle is a crucial part to create perfect normals, otherwise your normals will look correct for some meshes but very strange in other ones. My crease angle is recursive, that means, it will automatically break the vertex index and count as many times as necessary. So if one single vertex has 3 different normals, this function will break it 3 times.</p>
<p>This function must be called once per vertex. In the above code it's called at:<br />
<code>i1 = creaseAngle(i1, normal, &#038;normalBuffer, &#038;_nCount, multiples);<br />
i2 = creaseAngle(i2, normal, &#038;normalBuffer, &#038;_nCount, multiples);<br />
i3 = creaseAngle(i3, normal, &#038;normalBuffer, &#038;_nCount, multiples);</code></p>
<p>So the original vertex index can become a new index and this new one will be used in new normal vector and in tangent space (tangent and bitanget).</p>
<table width="675">
<tbody>
<tr>
<th>Calculating Crease Angle</th>
</tr>
</tbody>
</table>
<pre class="brush:cpp">
// Defines the maximum crease angle ~80.
#define kCreaseAngle		0.2

// Checks the crease angle for the normal calculations.
// This function creates and divides the normals to a vertex.
static unsigned int creaseAngle(unsigned int index,
								vec3 vector,
								vec3 **buffer,
								unsigned int *count,
								NSMutableDictionary *list)
{
	NSNumber *newIndex, *oldIndex;

	// Eliminates the NaN points.
	(*buffer)[index] = vec3Cleared((*buffer)[index]);

	// Checks if the informed normal vector is not zero.
	if (!vec3IsZero((*buffer)[index]))
	{
		// Calculates the cosine of the angle between the current normal vector and the
		// averaged normal in the buffer.
		float cos = vec3Dot(vec3Normalize(vector), vec3Normalize((*buffer)[index]));

		// If the cosine is greater than the crease angle, that means the current normal vector
		// forms an acceptable angle witht the averaged normal in the buffer. Otherwise, proceeds and
		// creates a new normal vector to the current triangle face.
		if (cos <= kCreaseAngle)
		{
			// Tries to retrieve an already buffered normal with the same bend.
			oldIndex = [NSNumber numberWithInt:index];
			newIndex = [list objectForKey:oldIndex];

			// If no buffer was found, create a new register to the current normal vector.
			if (newIndex == nil)
			{
				// Retrieves the new index and stores its value as a linked list to the old one.
				newIndex = [NSNumber numberWithInt:*count];
				[list setObject:newIndex forKey:oldIndex];
				index = [newIndex intValue];

				// Reallocates the buffer and set the new buffer value to zero, avoiding NaN.
				*buffer = realloc(*buffer, NGL_SIZE_VEC3 * ++*count);
				(*buffer)[index] = kvec3Zero;
			}
			// Otherwise, repeat the process with the buffered value to check for new crease angles.
			else
			{
				index = creaseAngle([newIndex intValue], vector, buffer, count, list);
			}
		}
	}

	return index;
}
</pre>
<p>Understanding line by line:</p>
<ul>
<li><strong>Line 12</strong>: Clearing any possible NaN value. If a NaN value is found, it'll be set to 0.0f (zero).</li>
<li><strong>Line 15</strong>: Making sure that an empty buffer index will be skipped, because there is no reason to calculate the crease angle between a face and no other.</li>
<li><strong>Line 19</strong>: Calculating the "dot" product (<a href="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/dot/index.htm" target="_blank">Dot Product info</a>) we get the cosine of the angle formed between two faces. These faces are: The new normal vector and the value that is already in the normal buffer. Both of them must be normalized at this point, otherwise their lengths will affect the resulting dot product.</li>
<li><strong>Line 24</strong>: Check if the calculated cosine is bellow the crease angle. So, if a cosine value is lower than the crease angle it means the calculated angle is higher than the maximum angle. Then the process of breaking the buffer index will start.</li>
<li><strong>Lines 27-31</strong>: Creating NSNumbers. The old value is, actually, the current index parameter. The line 28 tries to retrieve if there is an already calculated broken index referenced by the current index. If there is a previous calculated reference, that means, if the current index was broken before, then the crease angle function will be called again. Otherwise, the process of breaking the buffer index will continue.</li>
<li><strong>Lines 34-36</strong>: The new buffer index will be created in the end of the current buffer array. This new index will be stored and linked with the current index. So, if the current index appear again we already know where is it broken index.</li>
<li><strong>Lines 39-40</strong>: Reallocating the memory of the buffer array and setting the new index to zero, avoiding NaN values.</li>
<li><strong>Line 50</strong>: The returned index will always be one of these two situations:
<ol>
<li>An empty buffer index (zero vector).</li>
<li>A buffer index in which its stored normal forms an acceptable angle with the new normal.</li>
</ol>
</li>
</ul>
<p>Nice! Now we have the correct calculated Normals, respecting the crease angle. Besides if there is a previous calculated normals, this routine respects that and calculates only the face normal again.</p>
<p>Now it's time to enter in the Tanget Space.</p>
<p><br/></p>
<h2><strong>Calculating the Tanget Space - Step 3</strong></h2>
<p>As you know the Tangent Space is formed by the Tangent Vector and the Bitangent Vector. Just to make this point clear, the word "Binormal" is wrong in the 3D context. Because a 2D circle can have a Binormal, however there is only one Normal Vector in the 3D space. So the perpendicular angle between the Normal and the Tangent is the Bitangent. Some guys still calling as Binormal, we can understand what they want to say, but we know this term is a misspelling, there is no Binormal in the 3D space.</p>
<p>OK, now let's understand the concept of the Tangent Space.</p>
<p>The Tangent Space is a local stuff related at how the light interacts on each face of the surface. But the tangent space doesn't exist in the reality, right? Right, it doesn't. The tangent space is something created as a workaround to use the "Bump Technique". Now a day, there are many bump techniques, like bump map, parallax map , displacement map and many others. Independent of the technique the tangent space vector must be calculated.</p>
<p>The tangent and bitangent are orthogonal vector with the Normal and instruct us about the direction of the face's texture coordinate (U and V map directions). This direction will be used to calculate the light based on the RGB colors of the bump image file. </p>
<p>So in short, the Tangent Space is just a convention that we create as a workaround the bump technique. Here is how we'll calculate the Tangent Space.</p>
<table width="675">
<tbody>
<tr>
<th>Calculating Tangent Space</th>
</tr>
</tbody>
</table>
<pre class="brush:cpp">

// CONTINUING...

		//*************************
		//  Tangent Space
		//*************************
		if (hasTextures)
		{
			// The crease angle process produces splits on the per-vertex normals, as the tangent space
			// must be orthogonalized, the tangent and bitanget follow those splits.
			if (_nCount > _taCount)
			{
				// Normals, Tangents and Bitangents buffers will always have the same number of elements.
				tangentBuffer = realloc(tangentBuffer, sizeof(vec3) * _nCount);
				bitangentBuffer = realloc(bitangentBuffer, sizeof(vec3) * _nCount);

				// Setting the brand new buffers to 0 (zero).
				lengthJ = _nCount;
				for (j = _taCount - 1; j < lengthJ; ++j)
				{
					tangentBuffer[j] = kvec3Zero;
					bitangentBuffer[j] = kvec3Zero;
				}

				_taCount = _biCount = _nCount;
			}

			// Retrieves texture coordinate indices.
			ti1 = _faces[i * oldFaceStride + tOffset] * tLength;
			ti2 = _faces[(i + 1) * oldFaceStride + tOffset] * tLength;
			ti3 = _faces[(i + 2) * oldFaceStride + tOffset] * tLength;

			// Retrieves the texture coordinates.
			tA = (vec2){_texcoords[ti1], _texcoords[ti1 + 1]};
			tB = (vec2){_texcoords[ti2], _texcoords[ti2 + 1]};
			tC = (vec2){_texcoords[ti3], _texcoords[ti3 + 1]};

			// Calculates the vector of the texture coordinates edges, the distance between them.
			tdistBA = vec2Subtract(tB, tA);
			tdistCA = vec2Subtract(tC, tA);

			// Calculates the triangle's area.
			area = tdistBA.x * tdistCA.y - tdistBA.y * tdistCA.x;

			//*************************
			//  Tangent
			//*************************
			if (area == 0.0f)
			{
				tangent = kvec3Zero;
			}
			else
			{
				delta = 1.0f / area;

				// Calculates the face tangent to the current triangle.
				tangent.x = delta * ((distBA.x * tdistCA.y) + (distCA.x * -tdistBA.y));
				tangent.y = delta * ((distBA.y * tdistCA.y) + (distCA.y * -tdistBA.y));
				tangent.z = delta * ((distBA.z * tdistCA.y) + (distCA.z * -tdistBA.y));
			}

			// Averages the new tagent vector with the oldest buffered.
			tangentBuffer[i1] = vec3Add(tangent, tangentBuffer[i1]);
			tangentBuffer[i2] = vec3Add(tangent, tangentBuffer[i2]);
			tangentBuffer[i3] = vec3Add(tangent, tangentBuffer[i3]);

			//*************************
			//  Bitangent
			//*************************
			// Calculates the face bitangent to the current triangle,
			// completing the orthogonalized tangent space.
			bitangent = vec3Cross(normal, tangent);

			// Averages the new bitangent vector with the oldest buffered.
			bitangentBuffer[i1] = vec3Add(bitangent, bitangentBuffer[i1]);
			bitangentBuffer[i2] = vec3Add(bitangent, bitangentBuffer[i2]);
			bitangentBuffer[i3] = vec3Add(bitangent, bitangentBuffer[i3]);
		}

// CONTINUE...
</pre>
<p>Understanding line by line:</p>
<ul>
<li><strong>Line 6</strong>: Just create tangent space if there is texture coordinates on the mesh.</li>
<li><strong>Lines 10 - 25</strong>: Checking if the "Crease Angle" routine changed the normals. If so, adjust the tangents and bitangents buffers to have the same size as the normals buffer.</li>
<li><strong>Lines 27 - 42</strong>: Calculates the direction of the UV coordinates and the area of the current face (triangle).</li>
<li><strong>Lines 47 - 64</strong>: Calculates the tangent vector for the current triangle and add this value into the tangents buffer.</li>
<li><strong>Lines 71 - 76</strong>: As the Tangent Space is formed by three orthogonal vectors, we can calculate the last one (bitangent) very easy just by calculating the cross product between the Normal and Tangent.</li>
</ul>
<p>OK, that's all, it's done!<br />
Now we have all that we need: Normals, Tangents and Bitangents. They all are pretty perfect now and we just need to bring their values back into the arrays format. You can make this last step as you wish, I'll show you here a way that I'm used to.</p>
<p><br/></p>
<h2><strong>Updating the Original Arrays - Step 4</strong></h2>
<p>OK, as I told you at the start, we'll use the "Array of Structures" in our final format. So we need to create/update that array and its indices based on the new elements, which may include Normals, Tangents and Bitangents.</p>
<p>I'll rewrite the <code>"calculateTangentSpace()"</code> function just to you take a look at it without breaks/continues.</p>
<table width="675">
<tbody>
<tr>
<th>Puting All Together</th>
</tr>
</tbody>
</table>
<pre class="brush:cpp">

// CONTINUING...		

		// Copies the oldest face indices and inserts the new tangent space indices.
		outFaces = newFaces + (i * _faceStride);
		lengthJ = _faceStride;
		for (j = 0; j < lengthJ; ++j)
		{
			*outFaces++ = (j < oldFaceStride) ? _faces[i * oldFaceStride + j] : i1;
		}

		outFaces = newFaces + ((i + 1) * _faceStride);
		for (j = 0; j < lengthJ; ++j)
		{
			*outFaces++ = (j < oldFaceStride) ? _faces[(i + 1) * oldFaceStride + j] : i2;
		}

		outFaces = newFaces + ((i + 2) * _faceStride);
		for (j = 0; j < lengthJ; ++j)
		{
			*outFaces++ = (j < oldFaceStride) ? _faces[(i + 2) * oldFaceStride + j] : i3;
		}
	}

	// Commits the changes for the original array of faces. At this time, it could looks like:
	// iv1, it1, in1, ita1, ibt1, iv2, it2, in2, ita2, ibt2,...
	_faces = realloc(_faces, sizeof(int) * (_faceNumber * _faceStride));
	memcpy(_faces, newFaces, sizeof(int) * (_faceNumber * _faceStride));

	// Reallocates the memory for the array of normals, if needed.
	if (!hasNormals)
	{
		_normals = realloc(_normals, sizeof(vec3) * _nCount);
	}

	// Reallocates the memory for the array of tangents and array of bitangents, if needed.
	if (hasTextures)
	{
		_tangents = realloc(_tangents, sizeof(vec3) * _taCount);
		_bitangents = realloc(_bitangents, sizeof(vec3) * _biCount);
	}

	// Loops through all new values of the tangent space, normalizing all the averaged vectors.
	length = _nCount;
	for (i = 0; i < length; i++)
	{
		// Puts the new normals, if needed.
		if (!hasNormals)
		{
			normal = vec3Normalize(normalBuffer[i]);
			outValue = _normals + (i * 3);
			*outValue++ = normal.x;
			*outValue++ = normal.y;
			*outValue = normal.z;
		}

		// Puts the new tangent and bitangent, if needed.
		// Isn't necessary here the Gram–Schmidt Orthogonalization process, because all the vectors
		// of the tangent space are already orthogonalized in reason of the crease angle approach.
		if (hasTextures)
		{
			tangent = vec3Normalize(tangentBuffer[i]);
			bitangent = vec3Normalize(bitangentBuffer[i]);

			outValue = _tangents + (i * 3);
			*outValue++ = tangent.x;
			*outValue++ = tangent.y;
			*outValue = tangent.z;

			outValue = _bitangents + (i * 3);
			*outValue++ = bitangent.x;
			*outValue++ = bitangent.y;
			*outValue = bitangent.z;
		}
	}

	// Frees the memories.
	free(newFaces);
	free(normalBuffer);
	free(tangentBuffer);
	free(bitangentBuffer);

	[multiples release];
}
</pre>
<p>Let's understand more about those last lines:</p>
<ul>
<li><strong>Lines 4 - 21</strong>: Using a pointer to insert the new face indices in the "newFaces" array, pointers is much faster than accessing the array by indices. These lines also respect the old face indices to place the new ones in the last positions.</li>
<li><strong>Lines 26 - 27</strong>: Updating the original "array of faces". As you can see in the comments, at this point the new "array of faces" will be as "index of vertex 1, index of texcoord 1, index of normal 1, index of tangent 1, index of bitangent 1, index of vertex 2, ...". Remember that in this article I'll not include the job of converting those array into one single "array of structures", however with this "array of faces" you can do it very easy.</li>
<li><strong>Lines 30 - 40</strong>: Preparing the Normals, Tangents and Bitangents to receive the calculated values.</li>
<li><strong>Lines 43 - 74</strong>: Updating the Normals, Tangents and Bitangents values using pointers.</li>
<li><strong>Lines 77 - 82</strong>: Clearing the allocated memory.</li>
</ul>
<p><br/><a name="conclusion"></a></p>
<h2><strong>Conclusion</strong></h2>
<p>WOW, a lot of code in this article, don't you think? I'll try to simplify the steps, as you may notice was only 4 steps until here. So, here is all that you need:</p>
<ol>
<li>Calculate the Normals or use the Face Normals you already has.</li>
<li>When you need to calculate the Normals you must calculate the crease angle and split the Normals according to this calculation.</li>
<li>Calculate the Tangent Space, which includes Tangent and Bitangent.</li>
<li>Update the original arrays, including the Normals, Tangents and Bitangents.</li>
</ol>
<p>OK, my friends, now you have all that you need to construct your preferable array for OpenGL ("array of structures" or "structure of arrays").</p>
<p>In my next article will continue the series about shaders. Let's talk about shader some techniques advanced skills in OpenGL ES Shaders.</p>
<p>If you have any doubts, just Tweet me:<br />
<script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script><br />
<a href="http://twitter.com/share?&#038;url=&#038;text=@dineybomfim &#038;related=dineybomfim" class="twitter-share-button" data-related="dineybomfim" data-text="@dineybomfim " data-count="none" data-url="">Tweet</a> </p>
<p>See you soon!</p>
<p><iframe scrolling="no" src="http://db-in.com/downloads/apple/tribute_to_jobs.html" width="100%" height="130px"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://db-in.com/blog/2012/03/calculating-normals-and-tangent-space/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>All about Shaders &#8211; (part 1/3)</title>
		<link>http://db-in.com/blog/2011/08/all-about-shaders-part-13/</link>
		<comments>http://db-in.com/blog/2011/08/all-about-shaders-part-13/#comments</comments>
		<pubDate>Thu, 11 Aug 2011 18:32:00 +0000</pubDate>
		<dc:creator>Diney Bomfim</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Feature]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[GLSL ES]]></category>
		<category><![CDATA[OpenGL ES]]></category>

		<guid isPermaLink="false">http://db-in.com/blog/?p=1440</guid>
		<description><![CDATA[A series of  full tutorials about OpenGL ES Shader Language (GLSL ES) focused on iOS using Objective-C and Xcode.]]></description>
			<content:encoded><![CDATA[<p>Hello again, my friends!</p>
<p>Let&#8217;s start a new series of tutorials, at this time let&#8217;s go deep in shaders universe, the most exciting part of OpenGL programmable pipeline. We&#8217;ll treat about textures, lights, shadows, per-pixel effects, bump, reflections and more.</p>
<p>This series is composed by 3 parts:</p>
<ul>
<li>Part 1 &#8211; Basic concepts about GLSL ES (Beginners)</li>
<li>Part 2 &#8211; Shaders Effects (Intermediate)</li>
<li>Part 3 &#8211; Mastering effects with OpenGL Shader Language (Advanced)</li>
</ul>
<p><span id="more-1440"></span><br />
<a name="list_contents"></a><br />
Here is a little list of contents to orient your reading:</p>
<table width="675">
<tr>
<th colspan=2>List of Contents to this Tutorial</th>
</tr>
<tr>
<td valign="top">
<ul>
<li><a href="#shading_types">Shading Types</a></li>
<li><a href="#opengl_shaders">OpenGL Shaders</a></li>
<li><a href="#normal">Normal Vector</a>
<ul>
<li><a href="#smooth_angle">Normal&#8217;s Smooth Angle</a></li>
</ul>
</li>
<li><a href="#tangent">Tangent Space</a></li>
<li><a href="#texcoord">Texture Coordinates</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</td>
</tr>
</table>
<p><br/></p>
<h2><strong>At a glance</strong></h2>
<p><a href="http://db-in.com/blog/wp-content/uploads/2011/07/glsles_featured.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/07/glsles_featured-300x300.jpg" alt="" title="glsles_featured" width="300" height="300" class="alignleft size-medium wp-image-1453" /></a>We&#8217;ll study in-depth the shaders language (more specifically the GLSL ES, the shader language for Embedded Systems) and let&#8217;s make great effects using the shaders like specular lights and reflections, bump maps, refractions, reflections and more.</p>
<p>In this first part I&#8217;ll cover the basic concepts sobre shaders and GLSL ES. We&#8217;ll need to drill deep in something called Tangent Space, which is an intermediate level, so I&#8217;ll create an article between the part 1 and 2 specific to treat Tangent Space concepts and its creation.</p>
<p>In the second part let&#8217;s start creating some interesting effects like specular lights, reflections and refractions. Besides, on the second one let&#8217;s create the environment mappings by using the cube texture.</p>
<p>Finally in the last part let&#8217;s make the most advanced effect, the bump mapping and see what is the difference between Normal Mapping, Bump Mapping and Parallax Mapping.</p>
<p>Hands to work!</p>
<p><br/><a name="shading_types"></a></p>
<h2><strong>Shading Types</strong></h2>
<p><a href="#list_contents">top</a><br />
First off, we need to understand the evolution of that we call shader. Today we have many computations on the GPU and several shader techniques that achieve really good results, but how did we get here?</p>
<p>Once upon a time, there was a single shading technique, called <strong>Flat Shading</strong>. It defines that light is computed with the normal vector and each FACE of the mesh has a normal vector. The term &#8220;FACE&#8221; here means a polygon (usually a triangle).</p>
<div id="attachment_1449" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_flat.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_flat.jpg" alt="Flat Shading" title="shader_techniques_flat" width="600" height="503" class="size-full wp-image-1449" /></a><p class="wp-caption-text">Flat Shading</p></div>
<p>With the evolution of the hardwares we start to process values for each vertex, this improvement took us into a new level, making more light effects. This shading technique was called <strong>Goraud Shading</strong>.</p>
<div id="attachment_1450" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_goraud.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_goraud.jpg" alt="Goraud Shading" title="shader_techniques_goraud" width="600" height="503" class="size-full wp-image-1450" /></a><p class="wp-caption-text">Goraud Shading</p></div>
<p>Then we discovered something that produces really nice results, the <em>interpolation</em>. It&#8217;s a process which we calculate all the intermediate points between two other points. We use it all the time. For example, if a point A has a texture coordinate U:1 V:2 and a point B has U:2 V:5, the interpolation will calculate all the middle points from 1,2 to 2,5. This is know as <strong>Phong Shading</strong>.</p>
<div id="attachment_1451" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_phong.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_phong.jpg" alt="Phong Shading" title="shader_techniques_phong" width="600" height="503" class="size-full wp-image-1451" /></a><p class="wp-caption-text">Phong Shading</p></div>
<p>But for many reasons, to simulate the real world, we need more than a linear interpolation. Surfaces have many details that change the way the light and shadow reacts. So we discovered a way to produce infinities values over a surface using less processing time. This technique was called <strong>Bump Shading</strong>.</p>
<div id="attachment_1452" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_bump.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/07/shader_techniques_bump.jpg" alt="Bump Shading" title="shader_techniques_bump" width="600" height="503" class="size-full wp-image-1452" /></a><p class="wp-caption-text">Bump Shading</p></div>
<p>Today we have some advanced Bump&#8217;s techniques, but all of them have the same basic concept: store each value surface deformation value as a set of RGB color. So, basically, the Bump Shading takes advantage of a texture map that store coordinates within a RGB format. The coordinates in there can be used for many things: Normals, Tangents, Bitangents, Vertices positions or anything else we want. Usually the textures for <strong>Bump Shading</strong> is called Normal Maps, because we store the Normal Vector value in it.</p>
<p>By default, OpenGL uses the Phong Shading, making the interpolations between the Vertex Shader&#8217;s outputs and Fragment Shader&#8217;s inputs. This information is very important, so I&#8217;ll repeat: &#8220;Vertex Shader&#8217;s outputs are interpolated to Fragment Shader&#8217;s inputs&#8221;. Technically, this is what happens:</p>
<table style="text-align:center;">
<tr>
<th colspan="3">Interpolation Table</th>
</tr>
<tr>
<th>&nbsp;</th>
<th>Vertex Shader</th>
<th>Fragment Shader</th>
</tr>
<tr>
<th>Vertex A</th>
<td>0.0</td>
<td>0.0</td>
</tr>
<tr>
<th>&nbsp;</th>
<td>-</td>
<td>0.25</td>
</tr>
<tr>
<th>&nbsp;</th>
<td>-</td>
<td>0.50</td>
</tr>
<tr>
<th>&nbsp;</th>
<td>-</td>
<td>0.75</td>
</tr>
<tr>
<th>Vertex B</th>
<td>1.0</td>
<td>1.0</td>
</tr>
</table>
<p><br/><a name="opengl_shaders"></a></p>
<h2><strong>OpenGL Shaders</strong></h2>
<p><a href="#list_contents">top</a><br />
Here is a brief review about the shaders that we&#8217;ve seen on previous tutorials:</p>
<ul>
<li>Shader is the way to calculate everything related to our 3D objects by our own (from the vertices positions to the most complex light equations).</li>
<li>Vertex Shaders (VSH) are processed one time for each object&#8217;s vertex. Fragment Shader (FSH) are processed one time for each fragment (not necessarely a pixel) of the visible object (<a href="http://db-in.com/blog/2011/01/all-about-opengl-es-2-x-part-13/" title="All about OpenGL ES (2/3)" target="_blank">http://db-in.com/blog/2011/01/all-about-opengl-es-2-x-part-13/</a>).</li>
<li>You can set constant values for Uniforms to work throughout the VSH and FSH processing (<a href="http://db-in.com/blog/2011/02/all-about-opengl-es-2-x-part-23/" title="All about OpenGL ES (2/3)" target="_blank">http://db-in.com/blog/2011/02/all-about-opengl-es-2-x-part-23/</a>).</li>
<li>Dynamic variables can be assigned only to the Attribute kind, which is exclusive of VSH. You can send a variable from VSH to FSH via Varyings, but remember that those values will be <span style="color:#FF0000"><strong>interpolated</strong></span>!</li>
</ul>
<p>The shaders are small pieces of code that will be processed directly in the GPU. Unfortunately, even in these days (2011) our hardwares are very poor and slow if compared with the real amount of calculations that exist in the real world. The most advanced hardware trying to calculate a real phenomenon of the sun light passing through the water in a pool could take days to calculate a single frame. In the other hand, the real nature calculates all physical phenomenon instantly (OK, the mother nature makes a kind of &#8220;calculation&#8221;, not exactly an equation).</p>
<p>While we stay on the &#8220;Era of Bits&#8221; we can&#8217;t try to calculate the real phenomenons (I wrote an article about the &#8220;<a href="http://db-in.com/blog/2011/05/binary-world/" target="_blank">Binary World</a>&#8221; where I talked about the new Era of Quantum computers, maybe there, in the &#8220;Era of Quantums&#8221;, we&#8217;ll be able to reproduce our 3D world closest from the reality).</p>
<p>Anyway, what I meant is that the shaders are something trying to reproduce the real world with a very very abstractly code, making a bunch of simplifications of the real world. So if you want to mastering the shader, you must learn to extract some abstract pieces of code from the real world phenomenons. But don&#8217;t worry too much about it now, in the right time you&#8217;ll see that it&#8217;s an easy task and can be cool as well.</p>
<p>It&#8217;s important to start thinking in the concept of &#8220;Shader Program&#8221;. It&#8217;s a set of 2 (and only 2) shaders: a vertex shader and a fragment shader. So, we must think in the render as 2 different steps (vertex and fragment). Usually the Fragment shader is processed a lot of times more than the Vertex one. If a mesh has 10.000 vertices that means its Vertex Shader will generate 10.000 outputs to the Fragment Shader. Remember that those outputs will always be interpolated to the Fragment processing. So, to increase the performance we always try to place hard calculus in the Vertex Shader. Obviously there are calculus that we can&#8217;t accept interpolation to their values, like the bump effect, just in these cases we make the calculus inside the Fragment Shader.</p>
<p>However, make sure you got the correct distinction between the concept of making the calculus inside the Vertex Shader and another thing called Per-Vertex/Per-Fragment Light. We&#8217;ll see those concept in-depth later on, but just to clarify:</p>
<ul>
<li><strong>Per-Vertex Light</strong> means you have all the light calculus inside the Vertex Shader and them you interpolate the result to Fragment Shader.</li>
<li><strong>Per-Fragment Light</strong> means you have all last light calculus (the output value) inside the Fragment Shader, independent if the first steps was made in the Vertex or in the Fragment Shader.</li>
</ul>
<p>The interpolation happens on all Vertex Attributes, like the Texture Coordinates. As shown above in the Interpolation Table, the interpolated values from a texture coordinate can retrieve all the pixels from a texture. The Texture Coordinates usually is defined by a technique called &#8220;UV Map&#8221; or &#8220;UV Unwrap Map&#8221;, which is an artistic job, actually is almost impossible to create detailed UV Maps only with the code. Often a professional 3D software export the Texture Coordinates values within the model coordinates, based on definitions from an user friendly UV editor.</p>
<p>But there is another per-vertex Attribute very important to 3D world. With the shaders we calculate lights, shadows, reflections, refractions and any other effects we want. All of them need something in common, a <strong>Normal</strong> vector.</p>
<p><br/><a name="normal"></a></p>
<h2><strong>Normal Vector</strong></h2>
<p><a href="#list_contents">top</a><br />
This is one of the most important per-vertex attributes and its concept is very easy to understand. In the real world, basically, there are two things that can alter how the light rays affect a surface: the material (reflectiveness, refraction, specularity, shininess, etc.) and the surface&#8217;s angle. Well, actually, the point of view (the viewer&#8217;s eyes) also affect how we see the light, but let&#8217;s focus on the first two things. The normal vector is related to the surface&#8217;s angle. As the performance is something crucial to us, instead to re-calculate the angle of each surface (triangle) at every shader processing, we are used to pre-calculate a normal vector to every surface (triangle).</p>
<p>In simple words, the normal vector is an unit vector (magnitude equals to 1.0 and all axis range vary between [0.0, 1.0]) which represents the surface&#8217;s angle. Nice, now, how we can calculate it?</p>
<p>Well, that&#8217;s not an easy task, my friend. I had to read/watch/try a bunch of tutorials until I found the right formula. There are many people trying to teach how to calculate the normals. Some say that you must calculate per-face normals and store them into a buffer, others say to calculate the averaged normals between adjacent faces, some even say that you need to calculate each surface area to include in your final calculation. But no one gave me the right formula! I had to find it by my self, with the help of a great 3D software called MODO (by the way, I love it!).</p>
<p>Unfortunately, I&#8217;ll not explain how to calculate the normals in this first tutorial. I&#8217;ll create a separated article to show you how to get the right formula to calculate the normals. The normals deserve more attention than a simple subject inside one tutorial.</p>
<p>The most valuable point here is you understand that the Normal is an unit vector and visualize how the normals work together and how they fit into our shaders&#8217; context.</p>
<p><br/><a name="smooth_angle"></a></p>
<h3>Normal&#8217;s Smooth Angle</h3>
<p><a href="#list_contents">top</a><br />
<a href="http://db-in.com/blog/wp-content/uploads/2011/08/shaders_bowling_example.jpeg"><img src="http://db-in.com/blog/wp-content/uploads/2011/08/shaders_bowling_example-300x240.jpg" alt="" title="shaders_bowling_example" width="300" height="240" class="alignright size-medium wp-image-1455" /></a>As we always make an abstraction of the real world, trying to simplify it, we have created a concept that does not exist in the real world: the Smooth Angle. Imagine this: in the real world the surfaces has infinities vertices, take for example the image of an sphere, maybe a bowling ball.</p>
<p>Try to imagine the smallest face/triangle that composes that bowling ball. Even if we try to use a microscope, we never will see a faceted area. Now take a look at our virtual spheres, even if we create a 3D mesh using a stupidly high resolution of 8 millions polygons, we&#8217;ll stay very very far from the perfection of the real world. By the way, for our 3D applications and games, we must work around thousands polygons, not millions. Does that means our 3D lights will seem ugly on low meshes? Fortunately we have a solution.</p>
<div id="attachment_1454" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/08/shaders_sphere_example.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/08/shaders_sphere_example.jpg" alt="Our 3D world always will have imperfections." title="shaders_sphere_example" width="600" height="570" class="size-full wp-image-1454" /></a><p class="wp-caption-text">Our 3D world always will have imperfections.</p></div>
<p>This problem can be solved with the Normal&#8217;s Smooth Angle. With simple words, it represents the maximum angle on which the light will looks continuous when reflected by a surface. The following picture helps us to understand this point better:</p>
<div id="attachment_1456" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/08/shaders_smooth_angle.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/08/shaders_smooth_angle.jpg" alt="The Smooth Angle is the angle between two adjacent faces." title="shaders_smooth_angle" width="600" height="600" class="size-full wp-image-1456" /></a><p class="wp-caption-text">The Smooth Angle is the angle between two adjacent faces.</p></div>
<p>Remember that smooth angle should be calculated when we calculate the Normals, so any post-change to the smooth angle will affect the entire Normals. I&#8217;ll talk more about the smooth angle in the article of the Normals calculations.</p>
<p><br/><a name="tangent"></a></p>
<h2><strong>Tangent Space</strong></h2>
<p><a href="#list_contents">top</a><br />
The Tangent Space is composed by two different components, actually there are three properties, the third one is the Normal Vector. As we&#8217;ve talked about the normals, let&#8217;s focus on the other two: Tangent and Bitangent (also known as Binormal, but the term &#8220;Binormal&#8221; is a mistake).</p>
<p>The Tangent and Bitangent are unit vectors, just as the Normal, the combination of these three components must form an Orthogonal and Orthonormal set. Before we go ahead, let me explain in simple words these two concepts:</p>
<ul>
<li><strong>Orthogonal</strong>: Two vectors that are perpendicular (form an angle of 90 degrees).</li>
<li><strong>Orthonormal</strong>: A set of vectors that are all Orthogonals and unit vectors.</li>
</ul>
<p>OK, these set of three vectors called Tangent Space is defined per-vertex. It&#8217;s purpose is define a local space for each face/vertex, which will be used to interpret the surface&#8217;s imperfection (bump map). The bump map (also known as normal map) is a RGB map that defines each relief of the surface.</p>
<p>It could sound confused to a text explanation. Just try to imagine this, as we always optimize everything in 3D world, the bump map is a technique that stores the surface&#8217;s deformations into a single image file. The Tangent Space is a set of vectors that allow us to parse the bump informations for each fragment, independent of the mesh&#8217;s rotation, position or scale. The following image illustrate the Tangent Space and its connection with the Texture Coordinates.</p>
<div id="attachment_1457" class="wp-caption aligncenter" style="width: 610px"><a href="http://db-in.com/blog/wp-content/uploads/2011/08/tangent_space_example.jpg"><img src="http://db-in.com/blog/wp-content/uploads/2011/08/tangent_space_example.jpg" alt="The Tangent Space is a set of 3 vectors." title="tangent_space_example" width="600" height="600" class="size-full wp-image-1457" /></a><p class="wp-caption-text">The Tangent Space is a set of 3 vectors.</p></div>
<p>Basically the Tangent Vector points to where the &#8220;<strong>S</strong>&#8221; coordinate increases (S Tangent) and the Bitangent points to where the &#8220;<strong>T</strong>&#8221; coordinate increases (T Tangent).</p>
<p>It&#8217;s possible to exist more than a Tangent Space for a single vertex, in this case the vertex will break into two or more vertices with the same value for position, actually there are other important concepts in Tanget Space, but I&#8217;ll not bother you with the details in here. Just as the Normal&#8217;s calculations, I&#8217;ll let this complex part to another article dedicated to that subject. The important thing here is to you understand what is the bump maps and how the Tangent Space is important to make bump effects.</p>
<p><br/><a name="texcoord"></a></p>
<h2><strong>Texture Coordinates</strong></h2>
<p><a href="#list_contents">top</a><br />
This is the most common vector component for shaders. It&#8217;s responsible to place an image on a mesh&#8217;s surface. The Texture Coordinates (texcoord for short), is defined per-vertex. It&#8217;ll be interpolated along two vertices to achieve a per-fragment result. The texcoord is usually given in the range [0.0, 1.0], representing the order [S, T], which are the normalized values from the [U, V] notation.</p>
<p>The texcoord have more to do with the artistic work than with our code, usually the 3D softwares are responsible for generating it. The texcoord will directly affects how the texture image file should be created, I mean, the image of the texture must be created based on the texcoord positions. There are some 3D softwares that accept multiple texcoord channels. It could be good for some situations which multiple designers are working together, but it&#8217;s not good to the performance and optimization. There is nothing that multiple texcoord channels can make that a single channel can&#8217;t. So, keep it simple, always try to work with a single texcoord channel.</p>
<p>The texcoord is very important to create the Tangent Space. Multiple texcoord channels will need multiple Tangent Spaces as well. So, multiple channels is never a good idea.</p>
<p><br/><a name="conclusion"></a></p>
<h2><strong>Conclusion</strong></h2>
<p><a href="#list_contents">top</a><br />
OK, my friends, I don&#8217;t want to make this first tutorial too long, so these are the basic concepts about the Shader. Now you know how the shaders work, what are their limitations, where is their power and what we need to have before enter in the shaders&#8217; world.</p>
<p>In this tutorial you saw:</p>
<ul>
<li>The Shaders are responsible for all the visual results of our 3D world, including lights, shadows, reflections, refractions, etc.</li>
<li>There are four shading techniques most used: Flat Shading, Goraud Shading, Phong Shading and Bump Shading. OpenGL by default will use the Phong Shading.</li>
<li>The values from Vertex Shader to Fragment Shader will always be interpolated.</li>
<li>We have 3 very important per-vertex vectors: Position, Normal and Texture Coordinate.</li>
<li>The Normal Vector + 2 others form the Tangent Space, fundamental concept to produce the Bump Shading and any other displacement technique (like the Parallax Mapping).</li>
<li>Always try to use only one texcoord channel.</li>
</ul>
<p>Well done!<br />
My next article will not be the second part of this series, instead, it&#8217;ll be a short article covering how to calculate the Normal Vector and the Tangent Space. We&#8217;ll need to have those vectors very correct before enter in the real calculus inside the shaders&#8217; world.</p>
<p>If you have any doubts, just Tweet me:<br />
<script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script><br />
<a href="http://twitter.com/share?&#038;url=&#038;text=@dineybomfim &#038;related=dineybomfim" class="twitter-share-button" data-related="dineybomfim" data-text="@dineybomfim " data-count="none" data-url="">Tweet</a> </p>
<p>See you soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://db-in.com/blog/2011/08/all-about-shaders-part-13/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

