diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation.sln b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation.sln
new file mode 100644
index 0000000..efefa00
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGLInsightsTessellation", "OpenGLInsightsTessellation\OpenGLInsightsTessellation.vcxproj", "{C293EC5B-5EF8-4BBC-A474-D8B0A71D37A5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C293EC5B-5EF8-4BBC-A474-D8B0A71D37A5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C293EC5B-5EF8-4BBC-A474-D8B0A71D37A5}.Debug|Win32.Build.0 = Debug|Win32
+ {C293EC5B-5EF8-4BBC-A474-D8B0A71D37A5}.Release|Win32.ActiveCfg = Release|Win32
+ {C293EC5B-5EF8-4BBC-A474-D8B0A71D37A5}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/Makefile b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/Makefile
new file mode 100644
index 0000000..b6d7c7d
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/Makefile
@@ -0,0 +1,19 @@
+CC=g++
+CCFLAGS=-I. -I/usr/include -g -D_LINUX -rdynamic
+LIBS=-lglut -lGL -lGLEW -lIL -ltinyxml -L/usr/lib
+FILES= vsFontLib.cpp \
+ vsGLInfoLib.cpp \
+ vsLogLib.cpp \
+ vsShaderLib.cpp \
+ vsMathLib.cpp \
+ vsTerrainLib.cpp \
+ vsResourceLib.cpp \
+ vsTerrainLODSingleScaledLib.cpp \
+ terrainTessDemo.cpp
+
+main: $(FILES)
+ $(CC) -o $@ $^ $(CCFLAGS) $(LIBS)
+
+clean:
+ rm -f *.o *~ main
+
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj
new file mode 100644
index 0000000..007fd9f
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj
@@ -0,0 +1,109 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {C293EC5B-5EF8-4BBC-A474-D8B0A71D37A5}
+ Win32Proj
+ OpenGLInsightsTessellation
+
+
+
+ Application
+ true
+ Unicode
+
+
+ Application
+ false
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+
+
+ Console
+ true
+ libcmt.lib
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+
+
+ Console
+ true
+ true
+ true
+ libcmt.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj.filters b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj.filters
new file mode 100644
index 0000000..286a33c
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj.filters
@@ -0,0 +1,95 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {a583fe43-df6e-45d7-a7f7-ccaf5741e26f}
+
+
+ {35e1490a-dcf1-4c9e-ba07-b53c46dbdb09}
+
+
+
+
+ Source Files
+
+
+ Source Files\VSL
+
+
+ Source Files\VSL
+
+
+ Source Files\VSL
+
+
+ Source Files\VSL
+
+
+ Source Files\VSL
+
+
+ Source Files\VSL
+
+
+ Source Files\VSL
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Shaders
+
+
+ Shaders
+
+
+ Shaders
+
+
+ Shaders
+
+
+ Shaders
+
+
+ Shaders
+
+
+
\ No newline at end of file
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj.user b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/OpenGLInsightsTessellation.vcxproj.user
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/fonts/couriernew10.tga b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/fonts/couriernew10.tga
new file mode 100644
index 0000000..71e2177
Binary files /dev/null and b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/fonts/couriernew10.tga differ
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/fonts/couriernew10.xml b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/fonts/couriernew10.xml
new file mode 100644
index 0000000..0741428
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/fonts/couriernew10.xml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/dirlightdiffambpix.frag b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/dirlightdiffambpix.frag
new file mode 100644
index 0000000..ecb53ef
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/dirlightdiffambpix.frag
@@ -0,0 +1,39 @@
+#version 330
+
+layout (std140) uniform Material {
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ vec4 emissive;
+ float shininess;
+ int texCount;
+};
+
+uniform sampler2D texUnit;
+
+in vec3 Normal;
+in vec2 TexCoord;
+out vec4 outputF;
+
+void main()
+{
+ vec4 color, emission,amb;
+ float intensity;
+ vec3 lightDir, n;
+
+ lightDir = normalize(vec3(1.0,1.0,1.0));
+ n = normalize(Normal);
+ intensity = max(dot(lightDir,n),0.0);
+
+ if (texCount == 0) {
+ color = diffuse;
+ amb = ambient;
+ emission = emissive;
+ }
+ else {
+ color = texture(texUnit, TexCoord) * diffuse;
+ amb = color * ambient;
+ emission = texture(texUnit, TexCoord) * emissive;
+ }
+ outputF = (color * intensity) + amb + emission;
+}
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/dirlightdiffambpix.vert b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/dirlightdiffambpix.vert
new file mode 100644
index 0000000..46ae62a
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/dirlightdiffambpix.vert
@@ -0,0 +1,24 @@
+#version 330
+
+layout (std140) uniform Matrices {
+
+ mat4 projMatrix;
+ mat4 modelviewMatrix;
+ mat4 projModelViewMatrix;
+ mat3 normalMatrix;
+};
+
+in vec3 position;
+in vec3 normal;
+in vec2 texCoord;
+
+out vec2 TexCoord;
+out vec3 Normal;
+
+void main()
+{
+// Normal = normalize(vec3(modelviewMatrix * vec4(normal, 0.0)));
+ Normal = normalize(normalMatrix * normal);
+ TexCoord = vec2(texCoord);
+ gl_Position = projModelViewMatrix * vec4(position, 1.0);
+}
\ No newline at end of file
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.frag b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.frag
new file mode 100644
index 0000000..8fe7382
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.frag
@@ -0,0 +1,54 @@
+#version 410
+
+layout (std140) uniform Matrices {
+
+ mat4 projMatrix;
+ mat4 modelviewMatrix;
+ mat4 projModelViewMatrix;
+ mat3 normalMatrix;
+};
+
+uniform sampler2D texUnit,heightMap;
+uniform float heightStep;
+uniform float gridSpacing;
+uniform int scaleFactor;
+
+
+in vec2 uvTE;
+
+out vec4 outputF;
+
+
+float height(float u, float v) {
+
+ return (texture(heightMap, vec2(u,v)).r * heightStep);
+}
+
+void main() {
+
+ vec4 color;
+ float intensity;
+ vec3 lightDir,n;
+
+ float delta = 1.0 / (textureSize(heightMap,0).x * scaleFactor) ;
+
+ vec3 deltaX = vec3(
+ 2.0 * gridSpacing,
+ height(uvTE.s + delta, uvTE.t) - height(uvTE.s - delta, uvTE.t) ,
+ 0.0) ;
+
+ vec3 deltaZ = vec3(
+ 0.0,
+ height(uvTE.s, uvTE.t + delta) - height(uvTE.s, uvTE.t - delta) ,
+ 2.0 * gridSpacing) ;
+
+// vec3 normalF = normalize(vec3(modelviewMatrix * vec4( cross(deltaZ, deltaX),0.0)));
+ vec3 normalF = normalize(normalMatrix * cross(deltaZ, deltaX));
+ lightDir = vec3(0.577,0.577,0.577);
+ intensity = max(dot(lightDir,normalF),0.0);
+
+ color = texture(texUnit, uvTE) * vec4(0.8, 0.8, 0.8, 1.0);
+ color = color * intensity + color * vec4(0.2, 0.2, 0.2, 1.0);
+
+ outputF = color;
+}
\ No newline at end of file
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.tesc b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.tesc
new file mode 100644
index 0000000..a823e91
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.tesc
@@ -0,0 +1,195 @@
+#version 410
+
+
+layout(vertices = 1) out;
+
+layout (std140) uniform Matrices {
+
+ mat4 projMatrix;
+ mat4 modelviewMatrix;
+ mat4 projModelViewMatrix;
+ mat3 normalMatrix;
+};
+
+uniform float heightStep;
+uniform float gridSpacing;
+//uniform mat4 mvGroundCamMat;
+uniform mat4 pvm;
+uniform ivec2 viewportDim;
+uniform sampler2D roughFactor;
+uniform sampler2D heightMap;
+uniform int useRoughness;
+uniform int pixelsPerEdge;
+uniform int culling;
+uniform int scaleFactor;
+uniform float patchSize;
+
+in vec2 posV[];
+
+out vec2 posTC[];
+
+#define ID gl_InvocationID
+
+float height(float u, float v) {
+
+ return (texture(heightMap, vec2(u,v)).r * heightStep);
+}
+
+
+
+// Checks if a segment is at least partially inside the frustum
+// Need to add a little tolerance in here
+bool segmentInFrustum(vec4 p1, vec4 p2) {
+
+ if ((p1.x < -p1.w && p2.x < -p2.w) || (p1.x > p1.w && p2.x > p2.w) ||
+// (p1.y < -p1.w && p2.y < -p2.w) || (p1.y > p1.w && p2.y > p2.w) ||
+ (p1.z < -p1.w && p2.z < -p2.w) || (p1.z > p1.w && p2.z > p2.w))
+ return false;
+ else
+ return true;
+
+}
+
+
+
+// Measures the screen size of segment p1-p2
+float screenSphereSize(vec4 p1, vec4 p2) {
+
+ vec4 viewCenter = (p1+p2) * 0.5;
+ vec4 viewUp = viewCenter;
+ viewUp.y += distance(p1,p2);
+ vec4 p1Proj = viewCenter;
+ vec4 p2Proj = viewUp;
+/* vec4 p1Proj = projMatrix * viewCenter;
+ vec4 p2Proj = projMatrix * viewUp;
+*/
+ vec4 p1NDC, p2NDC;
+ p1NDC = p1Proj/p1Proj.w;
+ p2NDC = p2Proj/p2Proj.w;
+
+ return( clamp(length((p2NDC.xy - p1NDC.xy) * viewportDim * 0.5) / (pixelsPerEdge), 1.0, patchSize));
+}
+
+
+
+
+float getRoughness(vec2 disp) {
+
+ return (pow(( 1.8 - texture(roughFactor, posV[0]+ disp /textureSize(roughFactor,0)).x ),4));
+// return (texture(roughFactor, posV[0]+ disp /textureSize(roughFactor,0)).x );
+}
+
+
+
+void main() {
+
+ int scaleF;
+ if (scaleFactor == 0)
+ scaleF = 1;
+ else
+ scaleF = scaleFactor;
+
+ vec2 iLevel;
+ vec4 oLevel;
+
+ vec4 posTransV[4];
+ vec2 pAux;
+ vec2 posTCAux[4];
+
+ ivec2 tSize = textureSize(heightMap,0) * scaleF;// * 2;
+ float div = patchSize / tSize.x;
+
+ posTC[gl_InvocationID] = posV[gl_InvocationID];
+
+
+ posTCAux[0] = posV[0];
+ posTCAux[1] = posV[0] + vec2(0.0, div);
+ posTCAux[2] = posV[0] + vec2(div,0.0);
+ posTCAux[3] = posV[0] + vec2(div,div);
+
+/* for (int i = 0; i < 4; ++i ) {
+ pAux = posTCAux[i] * tSize * gridSpacing;
+ posTransV[i] = pvm *vec4(pAux[0], height(posTCAux[i].x,posTCAux[i].y), pAux[1], 1.0);
+ }
+*/
+ pAux = posTCAux[0] * tSize * gridSpacing;
+ posTransV[0] = pvm * vec4(pAux[0], height(posTCAux[0].x,posTCAux[0].y), pAux[1], 1.0);
+
+ pAux = posTCAux[1] * tSize * gridSpacing;
+ posTransV[1] = pvm * vec4(pAux[0], height(posTCAux[1].x,posTCAux[1].y), pAux[1], 1.0);
+
+ pAux = posTCAux[2] * tSize * gridSpacing;
+ posTransV[2] = pvm * vec4(pAux[0], height(posTCAux[2].x,posTCAux[2].y), pAux[1], 1.0);
+
+ pAux = posTCAux[3] * tSize * gridSpacing;
+ posTransV[3] = pvm * vec4(pAux[0], height(posTCAux[3].x,posTCAux[3].y), pAux[1], 1.0);
+
+/* pAux = posTCAux[0] * tSize * gridSpacing;
+ posTransV[0] = mvGroundCamMat * vec4(pAux[0], height(posTCAux[0].x,posTCAux[0].y), pAux[1], 1.0);
+
+ pAux = posTCAux[1] * tSize * gridSpacing;
+ posTransV[1] = mvGroundCamMat * vec4(pAux[0], height(posTCAux[1].x,posTCAux[1].y), pAux[1], 1.0);
+
+ pAux = posTCAux[2] * tSize * gridSpacing;
+ posTransV[2] = mvGroundCamMat * vec4(pAux[0], height(posTCAux[2].x,posTCAux[2].y), pAux[1], 1.0);
+
+ pAux = posTCAux[3] * tSize * gridSpacing;
+ posTransV[3] = mvGroundCamMat * vec4(pAux[0], height(posTCAux[3].x,posTCAux[3].y), pAux[1], 1.0);
+*/
+
+ if (culling == 0 ||(
+ segmentInFrustum(posTransV[ID], posTransV[ID+1]) ||
+ segmentInFrustum(posTransV[ID], posTransV[ID+2]) ||
+ segmentInFrustum(posTransV[ID+2], posTransV[ID+3]) ||
+ segmentInFrustum(posTransV[ID+3], posTransV[ID+1]))) {
+
+ if (useRoughness == 1) {
+ float roughness[4];
+ float roughnessForCentralPatch = getRoughness(vec2(0.5));
+ roughness[0] = max(roughnessForCentralPatch, getRoughness(vec2(-0.5,0.5)));
+ roughness[1] = max(roughnessForCentralPatch, getRoughness(vec2(0.5,-0.5)));
+ roughness[2] = max(roughnessForCentralPatch, getRoughness(vec2(1.5,0.5)));
+ roughness[3] = max(roughnessForCentralPatch, getRoughness(vec2(0.5,1.5)));
+ oLevel =
+ vec4(clamp(screenSphereSize(posTransV[ID], posTransV[ID+1]) * roughness[0],1,patchSize),
+ clamp(screenSphereSize(posTransV[ID+0], posTransV[ID+2]) * roughness[1],1,patchSize),
+ clamp(screenSphereSize(posTransV[ID+2], posTransV[ID+3]) * roughness[2],1,patchSize),
+ clamp(screenSphereSize(posTransV[ID+3], posTransV[ID+1]) * roughness[3],1,patchSize)) ;
+// oLevel = clamp(oLevel, vec4(1),vec4(patchSize));
+ iLevel = vec2(max(oLevel[1] , oLevel[3]) , max(oLevel[0] , oLevel[2]) );
+ }
+ else if (useRoughness == 0) {
+
+ // Screen size based LOD
+
+ oLevel = vec4(screenSphereSize(posTransV[ID], posTransV[ID+1]),
+ screenSphereSize(posTransV[ID+0], posTransV[ID+2]),
+ screenSphereSize(posTransV[ID+2], posTransV[ID+3]),
+ screenSphereSize(posTransV[ID+3], posTransV[ID+1]));
+ iLevel = vec2(max(oLevel[1] , oLevel[3]) , max(oLevel[0] , oLevel[2]) );
+
+ }
+ else {
+ oLevel = vec4(patchSize);
+ iLevel = vec2(patchSize);
+
+ }
+ }
+ else if (culling == 1) {
+ oLevel = vec4(0);
+ iLevel = vec2(0);
+
+ }
+ else {
+ oLevel = vec4(patchSize);
+ iLevel = vec2(patchSize);
+
+ }
+
+ gl_TessLevelOuter[0] = oLevel[0];
+ gl_TessLevelOuter[1] = oLevel[1];
+ gl_TessLevelOuter[2] = oLevel[2];
+ gl_TessLevelOuter[3] = oLevel[3];
+ gl_TessLevelInner[0] = iLevel[0];
+ gl_TessLevelInner[1] = iLevel[1];
+}
\ No newline at end of file
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.tese b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.tese
new file mode 100644
index 0000000..50b5981
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.tese
@@ -0,0 +1,57 @@
+#version 410
+
+layout(quads, fractional_even_spacing, cw) in;
+
+layout (std140) uniform Matrices {
+
+ mat4 projMatrix;
+ mat4 modelviewMatrix;
+ mat4 projModelViewMatrix;
+ mat3 normalMatrix;
+};
+
+uniform sampler2D heightMap;
+uniform float heightStep;
+uniform float gridSpacing;
+uniform int scaleFactor;
+uniform mat4 pvm;
+uniform float patchSize;
+
+
+in vec2 posTC[];
+
+out vec2 uvTE;
+
+
+
+#define sizeFactor 1.0/patchSize
+#define uv gl_TessCoord
+
+
+float height(float u, float v) {
+
+ return (texture(heightMap, vec2(u,v)).r * heightStep);
+}
+
+
+void main() {
+
+ ivec2 tSize = textureSize(heightMap,0) * scaleFactor;
+ float div = tSize.x * sizeFactor;
+
+ // Compute texture coordinates
+// uvTE.s = (posTC[0].x + uv.s/div) ;
+// uvTE.t = (posTC[0].y + uv.t/div) ;
+ uvTE = posTC[0].xy + uv.st/div;
+
+ // compute vertex position [0 .. tSize * gridSpacing]
+ vec4 res;
+ res.x = uvTE.s * tSize.x * gridSpacing;
+ res.z = uvTE.t * tSize.y * gridSpacing;
+ res.y = height(uvTE.s, uvTE.t) ;
+ res.w = 1.0;
+
+ //gl_Position = pvm * res;
+ gl_Position = projModelViewMatrix * res;
+}
+
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.vert b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.vert
new file mode 100644
index 0000000..9d71cf6
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/shaders/terrainTessDemoSingleScaled.vert
@@ -0,0 +1,14 @@
+#version 410
+
+in vec2 pos;
+out vec2 posV;
+
+void main() {
+
+ posV = pos;
+
+}
+
+
+
+
diff --git a/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/terrainTessDemo.cpp b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/terrainTessDemo.cpp
new file mode 100644
index 0000000..183cf78
--- /dev/null
+++ b/Chapter 10 GPU Tessellation We Still Have a LOD of Terrain to Cover/OpenGLInsightsTessellation/terrainTessDemo.cpp
@@ -0,0 +1,525 @@
+
+
+/*
+
+This code is provided as a companion to the text in the chapter
+"GPU Tessellation: We still have a LOD of terrain to cover"
+from the book "OpenGL Insights"
+
+The code comes with no warranties, it is provided only as a demo
+
+*/
+
+// Have Fun :-)
+
+// include GLEW to access OpenGL 3.3 functions
+#include
+
+// GLUT is the toolkit to interface with the OS
+#include
+
+#include
+#include
+#include