diff --git a/Android_Java/Chapter_10/MultiTexture/.classpath b/Android_Java/Chapter_10/MultiTexture/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_10/MultiTexture/.project b/Android_Java/Chapter_10/MultiTexture/.project
new file mode 100644
index 0000000..35ab13d
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/.project
@@ -0,0 +1,33 @@
+
+
+ Ch10_MultiTexture
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_10/MultiTexture/AndroidManifest.xml b/Android_Java/Chapter_10/MultiTexture/AndroidManifest.xml
new file mode 100644
index 0000000..fb89a3d
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_10/MultiTexture/assets/shaders/fragmentShader.frag b/Android_Java/Chapter_10/MultiTexture/assets/shaders/fragmentShader.frag
new file mode 100644
index 0000000..72d9955
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/assets/shaders/fragmentShader.frag
@@ -0,0 +1,21 @@
+#version 300 es
+
+precision mediump float;
+
+in vec2 v_texCoord;
+
+layout(location = 0) out vec4 outColor;
+
+uniform sampler2D s_baseMap;
+uniform sampler2D s_lightMap;
+
+void main()
+{
+ vec4 baseColor;
+ vec4 lightColor;
+
+ baseColor = texture( s_baseMap, v_texCoord );
+ lightColor = texture( s_lightMap, v_texCoord );
+
+ outColor = baseColor * (lightColor + 0.25);
+}
\ No newline at end of file
diff --git a/Android_Java/Chapter_10/MultiTexture/assets/shaders/vertexShader.vert b/Android_Java/Chapter_10/MultiTexture/assets/shaders/vertexShader.vert
new file mode 100644
index 0000000..fcb3e8d
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/assets/shaders/vertexShader.vert
@@ -0,0 +1,12 @@
+#version 300 es
+
+layout(location = 0) in vec4 a_position;
+layout(location = 1) in vec2 a_texCoord;
+
+out vec2 v_texCoord;
+
+void main()
+{
+ gl_Position = a_position;
+ v_texCoord = a_texCoord;
+}
\ No newline at end of file
diff --git a/Android_Java/Chapter_10/MultiTexture/assets/textures/basemap.png b/Android_Java/Chapter_10/MultiTexture/assets/textures/basemap.png
new file mode 100644
index 0000000..084fead
Binary files /dev/null and b/Android_Java/Chapter_10/MultiTexture/assets/textures/basemap.png differ
diff --git a/Android_Java/Chapter_10/MultiTexture/assets/textures/lightmap.png b/Android_Java/Chapter_10/MultiTexture/assets/textures/lightmap.png
new file mode 100644
index 0000000..40cd00b
Binary files /dev/null and b/Android_Java/Chapter_10/MultiTexture/assets/textures/lightmap.png differ
diff --git a/Android_Java/Chapter_10/MultiTexture/default.properties b/Android_Java/Chapter_10/MultiTexture/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_10/MultiTexture/proguard.cfg b/Android_Java/Chapter_10/MultiTexture/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_10/MultiTexture/res/drawable-hdpi/icon.png b/Android_Java/Chapter_10/MultiTexture/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_10/MultiTexture/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_10/MultiTexture/res/drawable-ldpi/icon.png b/Android_Java/Chapter_10/MultiTexture/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_10/MultiTexture/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_10/MultiTexture/res/drawable-mdpi/icon.png b/Android_Java/Chapter_10/MultiTexture/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_10/MultiTexture/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_10/MultiTexture/res/values/strings.xml b/Android_Java/Chapter_10/MultiTexture/res/values/strings.xml
new file mode 100644
index 0000000..30e693a
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch10_MultiTexture
+
diff --git a/Android_Java/Chapter_10/MultiTexture/src/com/openglesbook/multitexture/MultiTexture.java b/Android_Java/Chapter_10/MultiTexture/src/com/openglesbook/multitexture/MultiTexture.java
new file mode 100644
index 0000000..cf4834a
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/src/com/openglesbook/multitexture/MultiTexture.java
@@ -0,0 +1,65 @@
+package com.openglesbook.multitexture;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class MultiTexture extends Activity {
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new MultiTextureRenderer(this));
+ }
+ else
+ {
+ Log.e("MultiTexture", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_10/MultiTexture/src/com/openglesbook/multitexture/MultiTextureRenderer.java b/Android_Java/Chapter_10/MultiTexture/src/com/openglesbook/multitexture/MultiTextureRenderer.java
new file mode 100644
index 0000000..08919ae
--- /dev/null
+++ b/Android_Java/Chapter_10/MultiTexture/src/com/openglesbook/multitexture/MultiTextureRenderer.java
@@ -0,0 +1,202 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MultiTexture
+//
+// This is an example that draws a quad with a basemap and
+// lightmap to demonstrate multitexturing.
+//
+
+package com.openglesbook.multitexture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+
+
+public class MultiTextureRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public MultiTextureRenderer(Context context)
+ {
+ mContext = context;
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ ///
+ // Load texture from asset
+ //
+ private int loadTextureFromAsset ( String fileName )
+ {
+ int[] textureId = new int[1];
+ Bitmap bitmap = null;
+ InputStream is = null;
+
+ try {
+ is = mContext.getAssets().open(fileName);
+ } catch (IOException ioe) {
+ is = null;
+ }
+
+ if (is == null)
+ return 0;
+
+ bitmap = BitmapFactory.decodeStream(is);
+
+ GLES30.glGenTextures ( 1, textureId, 0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, textureId[0] );
+
+ GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
+
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE );
+
+ return textureId[0];
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ // Load shaders from 'assets' and get a linked program object
+ mProgramObject = ESShader.loadProgramFromAsset(mContext,
+ "shaders/vertexShader.vert",
+ "shaders/fragmentShader.frag");
+
+ // Get the sampler locations
+ mBaseMapLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_baseMap" );
+ mLightMapLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_lightMap" );
+
+ // Load the texture images from 'assets'
+ mBaseMapTexId = loadTextureFromAsset("textures/basemap.png");
+ mLightMapTexId = loadTextureFromAsset("textures/lightmap.png");
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the view-port
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex position
+ mVertices.position(0);
+ GLES30.glVertexAttribPointer ( 0, 3, GLES30.GL_FLOAT,
+ false,
+ 5 * 4, mVertices );
+ // Load the texture coordinate
+ mVertices.position(3);
+ GLES30.glVertexAttribPointer ( 1, 2, GLES30.GL_FLOAT,
+ false,
+ 5 * 4,
+ mVertices );
+
+ GLES30.glEnableVertexAttribArray ( 0 );
+ GLES30.glEnableVertexAttribArray ( 1 );
+
+
+ // Bind the base map
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, mBaseMapTexId );
+
+ // Set the base map sampler to texture unit to 0
+ GLES30.glUniform1i ( mBaseMapLoc, 0 );
+
+ // Bind the light map
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE1 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, mLightMapTexId );
+
+ // Set the light map sampler to texture unit 1
+ GLES30.glUniform1i ( mLightMapLoc, 1 );
+
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Sampler location
+ private int mBaseMapLoc;
+ private int mLightMapLoc;
+
+ // Texture handle
+ private int mBaseMapTexId;
+ private int mLightMapTexId;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private ShortBuffer mIndices;
+ private Context mContext;
+
+ private final float[] mVerticesData =
+ {
+ -0.5f, 0.5f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2, 0, 2, 3
+ };
+
+}
diff --git a/Android_Java/Chapter_14/ParticleSystem/.classpath b/Android_Java/Chapter_14/ParticleSystem/.classpath
new file mode 100644
index 0000000..b76ec6c
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/.classpath
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/Android_Java/Chapter_14/ParticleSystem/.project b/Android_Java/Chapter_14/ParticleSystem/.project
new file mode 100644
index 0000000..0e664e9
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/.project
@@ -0,0 +1,33 @@
+
+
+ Ch14_ParticleSystem
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_14/ParticleSystem/AndroidManifest.xml b/Android_Java/Chapter_14/ParticleSystem/AndroidManifest.xml
new file mode 100644
index 0000000..8c67ded
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_14/ParticleSystem/assets/smoke.png b/Android_Java/Chapter_14/ParticleSystem/assets/smoke.png
new file mode 100644
index 0000000..828308d
Binary files /dev/null and b/Android_Java/Chapter_14/ParticleSystem/assets/smoke.png differ
diff --git a/Android_Java/Chapter_14/ParticleSystem/default.properties b/Android_Java/Chapter_14/ParticleSystem/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_14/ParticleSystem/proguard.cfg b/Android_Java/Chapter_14/ParticleSystem/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_14/ParticleSystem/res/drawable-hdpi/icon.png b/Android_Java/Chapter_14/ParticleSystem/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_14/ParticleSystem/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_14/ParticleSystem/res/drawable-ldpi/icon.png b/Android_Java/Chapter_14/ParticleSystem/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_14/ParticleSystem/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_14/ParticleSystem/res/drawable-mdpi/icon.png b/Android_Java/Chapter_14/ParticleSystem/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_14/ParticleSystem/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_14/ParticleSystem/res/values/strings.xml b/Android_Java/Chapter_14/ParticleSystem/res/values/strings.xml
new file mode 100644
index 0000000..ebb4c7b
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch14_ParticleSystem
+
diff --git a/Android_Java/Chapter_14/ParticleSystem/src/com/openglesbook/particlesystem/ParticleSystem.java b/Android_Java/Chapter_14/ParticleSystem/src/com/openglesbook/particlesystem/ParticleSystem.java
new file mode 100644
index 0000000..1c3d193
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/src/com/openglesbook/particlesystem/ParticleSystem.java
@@ -0,0 +1,66 @@
+package com.openglesbook.particlesystem;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class ParticleSystem extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 2.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new ParticleSystemRenderer(this));
+ }
+ else
+ {
+ Log.e("HelloTriangle", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_14/ParticleSystem/src/com/openglesbook/particlesystem/ParticleSystemRenderer.java b/Android_Java/Chapter_14/ParticleSystem/src/com/openglesbook/particlesystem/ParticleSystemRenderer.java
new file mode 100644
index 0000000..80f16a9
--- /dev/null
+++ b/Android_Java/Chapter_14/ParticleSystem/src/com/openglesbook/particlesystem/ParticleSystemRenderer.java
@@ -0,0 +1,302 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ParticleSystem
+//
+// This is an example that demonstrates rendering a particle system
+// using a vertex shader and point sprites.
+//
+
+package com.openglesbook.particlesystem;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import com.openglesbook.common.ESShader;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.os.SystemClock;
+
+public class ParticleSystemRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public ParticleSystemRenderer(Context context)
+ {
+ mContext = context;
+
+ // Fill in particle data array
+ for ( int i = 0; i < (NUM_PARTICLES * PARTICLE_SIZE); i+=PARTICLE_SIZE )
+ {
+ // Lifetime of particle
+ mParticleData[i + 0] = ( (float)( (int)(Math.random() * 10000) % 10000) / 10000.0f );;
+
+ // End position of particle
+ mParticleData[i + 1] = ( (float)( (int)(Math.random() * 10000) % 10000) / 5000.0f ) - 1.0f;
+ mParticleData[i + 2] = ( (float)( (int)(Math.random() * 10000) % 10000) / 5000.0f ) - 1.0f;
+ mParticleData[i + 3] = ( (float)( (int)(Math.random() * 10000) % 10000) / 5000.0f ) - 1.0f;
+
+ // Start position of particle
+ mParticleData[i + 4] = ( (float)( (int)(Math.random() * 10000) % 10000) / 40000.0f ) - 0.125f;
+ mParticleData[i + 5] = ( (float)( (int)(Math.random() * 10000) % 10000) / 40000.0f ) - 0.125f;
+ mParticleData[i + 6] = ( (float)( (int)(Math.random() * 10000) % 10000) / 40000.0f ) - 0.125f;
+ }
+
+ mParticles = ByteBuffer.allocateDirect(mParticleData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mParticles.put(mParticleData).position(0);
+ }
+
+ ///
+ // Load texture from asset
+ //
+ private int loadTextureFromAsset ( String fileName )
+ {
+ int[] textureId = new int[1];
+ Bitmap bitmap = null;
+ InputStream is = null;
+
+ try {
+ is = mContext.getAssets().open(fileName);
+ } catch (IOException ioe) {
+ is = null;
+ }
+
+ if (is == null)
+ return 0;
+
+ bitmap = BitmapFactory.decodeStream(is);
+
+ GLES30.glGenTextures ( 1, textureId, 0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, textureId[0] );
+
+ GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
+
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE );
+
+ return textureId[0];
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "uniform float u_time; \n" +
+ "uniform vec3 u_centerPosition; \n" +
+ "layout(location = 0) in float a_lifetime; \n" +
+ "layout(location = 1) in vec3 a_startPosition; \n" +
+ "layout(location = 2) in vec3 a_endPosition; \n" +
+ "out float v_lifetime; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " if ( u_time <= a_lifetime ) \n" +
+ " { \n" +
+ " gl_Position.xyz = a_startPosition + \n" +
+ " (u_time * a_endPosition); \n" +
+ " gl_Position.xyz += u_centerPosition; \n" +
+ " gl_Position.w = 1.0; \n" +
+ " } \n" +
+ " else \n" +
+ " gl_Position = vec4( -1000, -1000, 0, 0 ); \n" +
+ " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n" +
+ " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n" +
+ " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n" +
+ "} \n";
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "uniform vec4 u_color; \n" +
+ "in float v_lifetime; \n" +
+ "layout(location = 0) out vec4 fragColor; \n" +
+ "uniform sampler2D s_texture; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " vec4 texColor; \n" +
+ " texColor = texture( s_texture, gl_PointCoord ); \n" +
+ " fragColor = vec4( u_color ) * texColor; \n" +
+ " fragColor.a *= v_lifetime; \n" +
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ // Get the uniform locations
+ mTimeLoc = GLES30.glGetUniformLocation ( mProgramObject, "u_time" );
+ mCenterPositionLoc = GLES30.glGetUniformLocation ( mProgramObject, "u_centerPosition" );
+ mColorLoc = GLES30.glGetUniformLocation ( mProgramObject, "u_color" );
+ mSamplerLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_texture" );
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Load the texture images from 'assets'
+ mTextureId = loadTextureFromAsset("smoke.png");
+
+ // Initialize time to cause reset on first update
+ mTime = 1.0f;
+ }
+
+ private void update()
+ {
+ if (mLastTime == 0)
+ mLastTime = SystemClock.uptimeMillis();
+ long curTime = SystemClock.uptimeMillis();
+ long elapsedTime = curTime - mLastTime;
+ float deltaTime = elapsedTime / 1000.0f;
+ mLastTime = curTime;
+
+ mTime += deltaTime;
+
+ GLES30.glUseProgram(mProgramObject);
+
+ if ( mTime >= 1.0f )
+ {
+ float [] centerPos = new float[3];
+ float [] color = new float[4];
+
+ mTime = 0.0f;
+
+ // Pick a new start location and color
+ centerPos[0] = ( (float)( (int)(Math.random() * 10000) % 10000) / 10000.0f ) - 0.5f;
+ centerPos[1] = ( (float)( (int)(Math.random() * 10000) % 10000) / 10000.0f ) - 0.5f;
+ centerPos[2] = ( (float)( (int)(Math.random() * 10000) % 10000) / 10000.0f ) - 0.5f;
+
+ GLES30.glUniform3f ( mCenterPositionLoc, centerPos[0], centerPos[1], centerPos[2] );
+
+ // Random color
+ color[0] = ( (float)( (int)(Math.random() * 1000) % 10000) / 20000.0f ) + 0.5f;
+ color[1] = ( (float)( (int)(Math.random() * 1000) % 10000) / 20000.0f ) + 0.5f;
+ color[2] = ( (float)( (int)(Math.random() * 1000) % 10000) / 20000.0f ) + 0.5f;
+ color[3] = 0.5f;
+
+ GLES30.glUniform4f ( mColorLoc, color[0], color[1], color[2], color[3] );
+ }
+
+ // Load uniform time variable
+ GLES30.glUniform1f ( mTimeLoc, mTime );
+ }
+
+ ///
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ update();
+
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex attributes
+ //[0]
+ mParticles.position(0);
+ GLES30.glVertexAttribPointer ( ATTRIBUTE_LIFETIME_LOCATION, 1, GLES30.GL_FLOAT,
+ false, PARTICLE_SIZE * (4),
+ mParticles );
+
+ //[1]
+ mParticles.position(1);
+ GLES30.glVertexAttribPointer ( ATTRIBUTE_ENDPOSITION_LOCATION, 3, GLES30.GL_FLOAT,
+ false, PARTICLE_SIZE * (4),
+ mParticles );
+
+ //[4]
+ mParticles.position(4);
+ GLES30.glVertexAttribPointer ( ATTRIBUTE_STARTPOSITION_LOCATION, 3, GLES30.GL_FLOAT,
+ false, PARTICLE_SIZE * (4),
+ mParticles );
+
+
+ GLES30.glEnableVertexAttribArray ( ATTRIBUTE_LIFETIME_LOCATION );
+ GLES30.glEnableVertexAttribArray ( ATTRIBUTE_ENDPOSITION_LOCATION );
+ GLES30.glEnableVertexAttribArray ( ATTRIBUTE_STARTPOSITION_LOCATION );
+
+ // Blend particles
+ GLES30.glEnable ( GLES30.GL_BLEND );
+ GLES30.glBlendFunc ( GLES30.GL_SRC_ALPHA, GLES30.GL_ONE );
+
+ // Bind the texture
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, mTextureId );
+
+ // Set the sampler texture unit to 0
+ GLES30.glUniform1i ( mSamplerLoc, 0 );
+
+ GLES30.glDrawArrays( GLES30.GL_POINTS, 0, NUM_PARTICLES );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Uniform location
+ private int mTimeLoc;
+ private int mColorLoc;
+ private int mCenterPositionLoc;
+ private int mSamplerLoc;
+
+ // Texture handle
+ private int mTextureId;
+
+ // Current time
+ float time;
+
+ // Additional Member variables
+ private int mWidth;
+ private int mHeight;
+ private long mLastTime = 0;
+
+ private final int NUM_PARTICLES = 1000;
+ private final int PARTICLE_SIZE = 7;
+
+ private final int ATTRIBUTE_LIFETIME_LOCATION = 0;
+ private final int ATTRIBUTE_STARTPOSITION_LOCATION = 1;
+ private final int ATTRIBUTE_ENDPOSITION_LOCATION = 2;
+
+ // Particle vertex data
+ private float [] mParticleData = new float[ NUM_PARTICLES * PARTICLE_SIZE ];
+
+ private FloatBuffer mParticles;
+
+ private float mTime;
+ private Context mContext;
+}
diff --git a/Android_Java/Chapter_2/Hello_Triangle/.classpath b/Android_Java/Chapter_2/Hello_Triangle/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_2/Hello_Triangle/.project b/Android_Java/Chapter_2/Hello_Triangle/.project
new file mode 100644
index 0000000..d0fce14
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/.project
@@ -0,0 +1,33 @@
+
+
+ Ch2_Hello_Triangle
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_2/Hello_Triangle/AndroidManifest.xml b/Android_Java/Chapter_2/Hello_Triangle/AndroidManifest.xml
new file mode 100644
index 0000000..e9b1f47
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_2/Hello_Triangle/default.properties b/Android_Java/Chapter_2/Hello_Triangle/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_2/Hello_Triangle/proguard.cfg b/Android_Java/Chapter_2/Hello_Triangle/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_2/Hello_Triangle/res/drawable-hdpi/icon.png b/Android_Java/Chapter_2/Hello_Triangle/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_2/Hello_Triangle/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_2/Hello_Triangle/res/drawable-ldpi/icon.png b/Android_Java/Chapter_2/Hello_Triangle/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_2/Hello_Triangle/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_2/Hello_Triangle/res/drawable-mdpi/icon.png b/Android_Java/Chapter_2/Hello_Triangle/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_2/Hello_Triangle/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_2/Hello_Triangle/res/values/strings.xml b/Android_Java/Chapter_2/Hello_Triangle/res/values/strings.xml
new file mode 100644
index 0000000..dcc2e6f
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch2_Hello_Triangle
+
diff --git a/Android_Java/Chapter_2/Hello_Triangle/src/com/openglesbook/hellotriangle/HelloTriangle.java b/Android_Java/Chapter_2/Hello_Triangle/src/com/openglesbook/hellotriangle/HelloTriangle.java
new file mode 100644
index 0000000..697be8e
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/src/com/openglesbook/hellotriangle/HelloTriangle.java
@@ -0,0 +1,66 @@
+package com.openglesbook.hellotriangle;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class HelloTriangle extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new HelloTriangleRenderer(this));
+ }
+ else
+ {
+ Log.e("HelloTriangle", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_2/Hello_Triangle/src/com/openglesbook/hellotriangle/HelloTriangleRenderer.java b/Android_Java/Chapter_2/Hello_Triangle/src/com/openglesbook/hellotriangle/HelloTriangleRenderer.java
new file mode 100644
index 0000000..9384404
--- /dev/null
+++ b/Android_Java/Chapter_2/Hello_Triangle/src/com/openglesbook/hellotriangle/HelloTriangleRenderer.java
@@ -0,0 +1,181 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Hello_Triangle
+//
+// This is a simple example that draws a single triangle with
+// a minimal vertex/fragment shader. The purpose of this
+// example is to demonstrate the basic concepts of
+// OpenGL ES 3.0 rendering.
+
+package com.openglesbook.hellotriangle;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+import android.util.Log;
+
+public class HelloTriangleRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public HelloTriangleRenderer(Context context)
+ {
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+ }
+
+ ///
+ // Create a shader object, load the shader source, and
+ // compile the shader.
+ //
+ private int LoadShader(int type, String shaderSrc)
+ {
+ int shader;
+ int[] compiled = new int[1];
+
+ // Create the shader object
+ shader = GLES30.glCreateShader(type);
+
+ if (shader == 0)
+ return 0;
+
+ // Load the shader source
+ GLES30.glShaderSource(shader, shaderSrc);
+
+ // Compile the shader
+ GLES30.glCompileShader(shader);
+
+ // Check the compile status
+ GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compiled, 0);
+
+ if (compiled[0] == 0)
+ {
+ Log.e(TAG, GLES30.glGetShaderInfoLog(shader));
+ GLES30.glDeleteShader(shader);
+ return 0;
+ }
+ return shader;
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n"
+ + "in vec4 vPosition; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " gl_Position = vPosition; \n"
+ + "} \n";
+
+ String fShaderStr =
+ "#version 300 es \n"
+ + "precision mediump float; \n"
+ + "out vec4 fragColor; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"
+ + "} \n";
+
+ int vertexShader;
+ int fragmentShader;
+ int programObject;
+ int[] linked = new int[1];
+
+ // Load the vertex/fragment shaders
+ vertexShader = LoadShader(GLES30.GL_VERTEX_SHADER, vShaderStr);
+ fragmentShader = LoadShader(GLES30.GL_FRAGMENT_SHADER, fShaderStr);
+
+ // Create the program object
+ programObject = GLES30.glCreateProgram();
+
+ if (programObject == 0)
+ return;
+
+ GLES30.glAttachShader(programObject, vertexShader);
+ GLES30.glAttachShader(programObject, fragmentShader);
+
+ // Bind vPosition to attribute 0
+ GLES30.glBindAttribLocation(programObject, 0, "vPosition");
+
+ // Link the program
+ GLES30.glLinkProgram(programObject);
+
+ // Check the link status
+ GLES30.glGetProgramiv(programObject, GLES30.GL_LINK_STATUS, linked, 0);
+
+ if (linked[0] == 0)
+ {
+ Log.e(TAG, "Error linking program:");
+ Log.e(TAG, GLES30.glGetProgramInfoLog(programObject));
+ GLES30.glDeleteProgram(programObject);
+ return;
+ }
+
+ // Store the program object
+ mProgramObject = programObject;
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex data
+ GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, mVertices);
+ GLES30.glEnableVertexAttribArray(0);
+
+ GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3);
+ }
+
+ // /
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ // Member variables
+ private int mProgramObject;
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private static String TAG = "HelloTriangleRenderer";
+
+ private final float[] mVerticesData =
+ { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f };
+
+}
diff --git a/Android_Java/Chapter_6/Example_6_3/.classpath b/Android_Java/Chapter_6/Example_6_3/.classpath
new file mode 100644
index 0000000..4d67fc6
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_6/Example_6_3/.project b/Android_Java/Chapter_6/Example_6_3/.project
new file mode 100644
index 0000000..d647781
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/.project
@@ -0,0 +1,33 @@
+
+
+ Ch6_Example_6_3
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_6/Example_6_3/AndroidManifest.xml b/Android_Java/Chapter_6/Example_6_3/AndroidManifest.xml
new file mode 100644
index 0000000..747662b
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_6/Example_6_3/default.properties b/Android_Java/Chapter_6/Example_6_3/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_6/Example_6_3/proguard.cfg b/Android_Java/Chapter_6/Example_6_3/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_6/Example_6_3/res/drawable-hdpi/icon.png b/Android_Java/Chapter_6/Example_6_3/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_6/Example_6_3/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/Example_6_3/res/drawable-ldpi/icon.png b/Android_Java/Chapter_6/Example_6_3/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_6/Example_6_3/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_6/Example_6_3/res/drawable-mdpi/icon.png b/Android_Java/Chapter_6/Example_6_3/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_6/Example_6_3/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/Example_6_3/res/values/strings.xml b/Android_Java/Chapter_6/Example_6_3/res/values/strings.xml
new file mode 100644
index 0000000..68f9915
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch6_Example_6_3
+
diff --git a/Android_Java/Chapter_6/Example_6_3/src/com/openglesbook/example6_3/Example6_3.java b/Android_Java/Chapter_6/Example_6_3/src/com/openglesbook/example6_3/Example6_3.java
new file mode 100644
index 0000000..40c11a5
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/src/com/openglesbook/example6_3/Example6_3.java
@@ -0,0 +1,66 @@
+package com.openglesbook.example6_3;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class Example6_3 extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new Example6_3Renderer(this));
+ }
+ else
+ {
+ Log.e("SimpleTexture2D", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_6/Example_6_3/src/com/openglesbook/example6_3/Example6_3Renderer.java b/Android_Java/Chapter_6/Example_6_3/src/com/openglesbook/example6_3/Example6_3Renderer.java
new file mode 100644
index 0000000..f97a44b
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_3/src/com/openglesbook/example6_3/Example6_3Renderer.java
@@ -0,0 +1,133 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Example_6_3
+//
+// This example demonstrates using client-side vertex arrays
+// and a constant vertex attribute
+//
+
+package com.openglesbook.example6_3;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class Example6_3Renderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public Example6_3Renderer(Context context)
+ {
+
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "layout(location = 0) in vec4 a_color; \n" +
+ "layout(location = 1) in vec4 a_position; \n" +
+ "out vec4 v_color; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " v_color = a_color; \n" +
+ " gl_Position = a_position; \n" +
+ "}";
+
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec4 v_color; \n" +
+ "out vec4 o_fragColor; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " o_fragColor = v_color; \n" +
+ "}" ;
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Set the vertex color to red
+ GLES30.glVertexAttrib4f( 0, 1.0f, 0.0f, 0.0f, 1.0f );
+
+ // Load the vertex position
+ mVertices.position(0);
+ GLES30.glVertexAttribPointer ( 1, 3, GLES30.GL_FLOAT,
+ false,
+ 0, mVertices );
+
+ GLES30.glEnableVertexAttribArray ( 1 );
+
+ GLES30.glDrawArrays ( GLES30.GL_TRIANGLES, 0, 3 );
+
+ GLES30.glDisableVertexAttribArray ( 1 );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+
+ private final float[] mVerticesData =
+ {
+ 0.0f, 0.5f, 0.0f, // v0
+ -0.5f, -0.5f, 0.0f, // v1
+ 0.5f, -0.5f, 0.0f // v2
+ };
+}
diff --git a/Android_Java/Chapter_6/Example_6_6/.classpath b/Android_Java/Chapter_6/Example_6_6/.classpath
new file mode 100644
index 0000000..4d67fc6
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_6/Example_6_6/.project b/Android_Java/Chapter_6/Example_6_6/.project
new file mode 100644
index 0000000..e41d267
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/.project
@@ -0,0 +1,33 @@
+
+
+ Ch6_Example_6_6
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_6/Example_6_6/AndroidManifest.xml b/Android_Java/Chapter_6/Example_6_6/AndroidManifest.xml
new file mode 100644
index 0000000..5e59d29
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_6/Example_6_6/default.properties b/Android_Java/Chapter_6/Example_6_6/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_6/Example_6_6/proguard.cfg b/Android_Java/Chapter_6/Example_6_6/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_6/Example_6_6/res/drawable-hdpi/icon.png b/Android_Java/Chapter_6/Example_6_6/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_6/Example_6_6/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/Example_6_6/res/drawable-ldpi/icon.png b/Android_Java/Chapter_6/Example_6_6/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_6/Example_6_6/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_6/Example_6_6/res/drawable-mdpi/icon.png b/Android_Java/Chapter_6/Example_6_6/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_6/Example_6_6/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/Example_6_6/res/values/strings.xml b/Android_Java/Chapter_6/Example_6_6/res/values/strings.xml
new file mode 100644
index 0000000..47003db
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch6_Example_6_6
+
diff --git a/Android_Java/Chapter_6/Example_6_6/src/com/openglesbook/example6_6/Example6_6.java b/Android_Java/Chapter_6/Example_6_6/src/com/openglesbook/example6_6/Example6_6.java
new file mode 100644
index 0000000..f2b61e5
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/src/com/openglesbook/example6_6/Example6_6.java
@@ -0,0 +1,66 @@
+package com.openglesbook.example6_6;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class Example6_6 extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new Example6_6Renderer(this));
+ }
+ else
+ {
+ Log.e("SimpleTexture2D", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_6/Example_6_6/src/com/openglesbook/example6_6/Example6_6Renderer.java b/Android_Java/Chapter_6/Example_6_6/src/com/openglesbook/example6_6/Example6_6Renderer.java
new file mode 100644
index 0000000..521a4f4
--- /dev/null
+++ b/Android_Java/Chapter_6/Example_6_6/src/com/openglesbook/example6_6/Example6_6Renderer.java
@@ -0,0 +1,215 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Example_6_6
+//
+// This example demonstrates drawing a primitive with
+// a separate VBO per attribute
+//
+//
+
+package com.openglesbook.example6_6;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class Example6_6Renderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public Example6_6Renderer(Context context)
+ {
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+
+ mColors = ByteBuffer.allocateDirect(mColorData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mColors.put(mColorData).position(0);
+
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec4 a_color; \n" +
+ "out vec4 v_color; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " v_color = a_color; \n" +
+ " gl_Position = a_position; \n" +
+ "}";
+
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec4 v_color; \n" +
+ "out vec4 o_fragColor; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " o_fragColor = v_color; \n" +
+ "}" ;
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ mVBOIds[0] = 0;
+ mVBOIds[1] = 0;
+ mVBOIds[2] = 0;
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ drawPrimitiveWithVBOs();
+ }
+
+ private void drawPrimitiveWithVBOs()
+ {
+ int numVertices = 3;
+ int numIndices = 3;
+
+ // mVBOIds[0] - used to store vertex position
+ // mVBOIds[1] - used to store vertex color
+ // mVBOIds[2] - used to store element indices
+ if ( mVBOIds[0] == 0 && mVBOIds[1] == 0 && mVBOIds[2] == 0)
+ {
+ // Only allocate on the first draw
+ GLES30.glGenBuffers(3, mVBOIds, 0);
+
+ mVertices.position(0);
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[0]);
+ GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vtxStrides[0] * numVertices,
+ mVertices, GLES30.GL_STATIC_DRAW);
+
+ mColors.position(0);
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[1]);
+ GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vtxStrides[1] * numVertices,
+ mColors, GLES30.GL_STATIC_DRAW);
+
+ mIndices.position(0);
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[2]);
+ GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, 2 * numIndices,
+ mIndices, GLES30.GL_STATIC_DRAW);
+ }
+
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[0]);
+
+ GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
+ GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
+ GLES30.GL_FLOAT, false, vtxStrides[0], 0);
+
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[1]);
+
+ GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
+ GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
+ GLES30.GL_FLOAT, false, vtxStrides[1], 0);
+
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[2]);
+
+ GLES30.glDrawElements(GLES30.GL_TRIANGLES, numIndices,
+ GLES30.GL_UNSIGNED_SHORT, 0);
+
+ GLES30.glDisableVertexAttribArray(VERTEX_POS_INDX);
+ GLES30.glDisableVertexAttribArray(VERTEX_COLOR_INDX);
+
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private FloatBuffer mColors;
+ private ShortBuffer mIndices;
+
+ // VertexBufferObject Ids
+ private int [] mVBOIds = new int[3];
+
+ // 3 vertices, with (x,y,z) ,(r, g, b, a) per-vertex
+ private final float[] mVerticesData =
+ {
+ 0.0f, 0.5f, 0.0f, // v0
+ -0.5f, -0.5f, 0.0f, // v1
+ 0.5f, -0.5f, 0.0f // v2
+ };
+
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2
+ };
+
+ private final float [] mColorData =
+ {
+ 1.0f, 0.0f, 0.0f, 1.0f, // c0
+ 0.0f, 1.0f, 0.0f, 1.0f, // c1
+ 0.0f, 0.0f, 1.0f, 1.0f // c2
+ };
+
+ final int VERTEX_POS_SIZE = 3; // x, y and z
+ final int VERTEX_COLOR_SIZE = 4; // r, g, b, and a
+
+ final int VERTEX_POS_INDX = 0;
+ final int VERTEX_COLOR_INDX = 1;
+
+ private int vtxStrides[] =
+ {
+ VERTEX_POS_SIZE * 4,
+ VERTEX_COLOR_SIZE * 4
+ };
+}
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/.classpath b/Android_Java/Chapter_6/VertexArrayObjects/.classpath
new file mode 100644
index 0000000..4d67fc6
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/.project b/Android_Java/Chapter_6/VertexArrayObjects/.project
new file mode 100644
index 0000000..3e90c2d
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/.project
@@ -0,0 +1,33 @@
+
+
+ Ch6_VertexArrayObjects
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/AndroidManifest.xml b/Android_Java/Chapter_6/VertexArrayObjects/AndroidManifest.xml
new file mode 100644
index 0000000..d38c0a5
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/default.properties b/Android_Java/Chapter_6/VertexArrayObjects/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/proguard.cfg b/Android_Java/Chapter_6/VertexArrayObjects/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-hdpi/icon.png b/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-ldpi/icon.png b/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-mdpi/icon.png b/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_6/VertexArrayObjects/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/res/values/strings.xml b/Android_Java/Chapter_6/VertexArrayObjects/res/values/strings.xml
new file mode 100644
index 0000000..948033b
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch6_VertexArrayObjects
+
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/src/com/openglesbook/VertexArrayObjects/VAO.java b/Android_Java/Chapter_6/VertexArrayObjects/src/com/openglesbook/VertexArrayObjects/VAO.java
new file mode 100644
index 0000000..0819f4a
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/src/com/openglesbook/VertexArrayObjects/VAO.java
@@ -0,0 +1,66 @@
+package com.openglesbook.VertexArrayObjects;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class VAO extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new VAORenderer(this));
+ }
+ else
+ {
+ Log.e("SimpleTexture2D", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_6/VertexArrayObjects/src/com/openglesbook/VertexArrayObjects/VAORenderer.java b/Android_Java/Chapter_6/VertexArrayObjects/src/com/openglesbook/VertexArrayObjects/VAORenderer.java
new file mode 100644
index 0000000..d32f79d
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexArrayObjects/src/com/openglesbook/VertexArrayObjects/VAORenderer.java
@@ -0,0 +1,193 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// VertexArrayObjects
+//
+// This is a simple example drawing a primitive with
+// Vertex Array Objects (VAOs)
+//
+
+package com.openglesbook.VertexArrayObjects;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class VAORenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public VAORenderer(Context context)
+ {
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec4 a_color; \n" +
+ "out vec4 v_color; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " v_color = a_color; \n" +
+ " gl_Position = a_position; \n" +
+ "}";
+
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec4 v_color; \n" +
+ "out vec4 o_fragColor; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " o_fragColor = v_color; \n" +
+ "}" ;
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ // Generate VBO Ids and load the VBOs with data
+ GLES30.glGenBuffers(2, mVBOIds, 0);
+
+ GLES30.glBindBuffer ( GLES30.GL_ARRAY_BUFFER, mVBOIds[0] );
+
+ mVertices.position(0);
+ GLES30.glBufferData ( GLES30.GL_ARRAY_BUFFER, mVerticesData.length * 4,
+ mVertices, GLES30.GL_STATIC_DRAW);
+
+ GLES30.glBindBuffer ( GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1]);
+
+ mIndices.position(0);
+ GLES30.glBufferData ( GLES30.GL_ELEMENT_ARRAY_BUFFER, 2 * mIndicesData.length,
+ mIndices, GLES30.GL_STATIC_DRAW );
+
+ // Generate VAO Id
+ GLES30.glGenVertexArrays ( 1, mVAOId, 0 );
+
+ // Bind the VAO and then setup the vertex
+ // attributes
+ GLES30.glBindVertexArray ( mVAOId[0] );
+
+ GLES30.glBindBuffer( GLES30.GL_ARRAY_BUFFER, mVBOIds[0] );
+ GLES30.glBindBuffer( GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1] );
+
+ GLES30.glEnableVertexAttribArray( VERTEX_POS_INDX );
+ GLES30.glEnableVertexAttribArray( VERTEX_COLOR_INDX );
+
+ GLES30.glVertexAttribPointer ( VERTEX_POS_INDX, VERTEX_POS_SIZE,
+ GLES30.GL_FLOAT, false, VERTEX_STRIDE,
+ 0 );
+
+ GLES30.glVertexAttribPointer ( VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
+ GLES30.GL_FLOAT, false, VERTEX_STRIDE,
+ (VERTEX_POS_SIZE * 4) );
+
+ // Reset to the default VAO
+ GLES30.glBindVertexArray ( 0 );
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Bind the VAO
+ GLES30.glBindVertexArray ( mVAOId[0] );
+
+ // Draw with the VAO settings
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, mIndicesData.length, GLES30.GL_UNSIGNED_SHORT, 0 );
+
+ // Return to the default VAO
+ GLES30.glBindVertexArray ( 0 );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private ShortBuffer mIndices;
+
+ // VertexBufferObject Ids
+ private int [] mVBOIds = new int[2];
+
+ // VertexArrayObject Id
+ private int [] mVAOId = new int[1];
+
+ // 3 vertices, with (x,y,z) ,(r, g, b, a) per-vertex
+ private final float[] mVerticesData =
+ {
+ 0.0f, 0.5f, 0.0f, // v0
+ 1.0f, 0.0f, 0.0f, 1.0f, // c0
+ -0.5f, -0.5f, 0.0f, // v1
+ 0.0f, 1.0f, 0.0f, 1.0f, // c1
+ 0.5f, -0.5f, 0.0f, // v2
+ 0.0f, 0.0f, 1.0f, 1.0f, // c2
+ };
+
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2
+ };
+
+ final int VERTEX_POS_SIZE = 3; // x, y and z
+ final int VERTEX_COLOR_SIZE = 4; // r, g, b, and a
+
+ final int VERTEX_POS_INDX = 0;
+ final int VERTEX_COLOR_INDX = 1;
+
+ final int VERTEX_STRIDE = ( 4 * ( VERTEX_POS_SIZE + VERTEX_COLOR_SIZE ) );
+}
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/.classpath b/Android_Java/Chapter_6/VertexBufferObjects/.classpath
new file mode 100644
index 0000000..4d67fc6
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/.project b/Android_Java/Chapter_6/VertexBufferObjects/.project
new file mode 100644
index 0000000..559cc10
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/.project
@@ -0,0 +1,33 @@
+
+
+ Ch6_VertexBufferObjects
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/AndroidManifest.xml b/Android_Java/Chapter_6/VertexBufferObjects/AndroidManifest.xml
new file mode 100644
index 0000000..d554f76
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/default.properties b/Android_Java/Chapter_6/VertexBufferObjects/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/proguard.cfg b/Android_Java/Chapter_6/VertexBufferObjects/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-hdpi/icon.png b/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-ldpi/icon.png b/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-mdpi/icon.png b/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_6/VertexBufferObjects/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/res/values/strings.xml b/Android_Java/Chapter_6/VertexBufferObjects/res/values/strings.xml
new file mode 100644
index 0000000..24aebf8
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch6_VertexBufferObjects
+
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/src/com/openglesbook/VertexBufferObjects/VBO.java b/Android_Java/Chapter_6/VertexBufferObjects/src/com/openglesbook/VertexBufferObjects/VBO.java
new file mode 100644
index 0000000..51d0e49
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/src/com/openglesbook/VertexBufferObjects/VBO.java
@@ -0,0 +1,66 @@
+package com.openglesbook.VertexBufferObjects;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class VBO extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new VBORenderer(this));
+ }
+ else
+ {
+ Log.e("SimpleTexture2D", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_6/VertexBufferObjects/src/com/openglesbook/VertexBufferObjects/VBORenderer.java b/Android_Java/Chapter_6/VertexBufferObjects/src/com/openglesbook/VertexBufferObjects/VBORenderer.java
new file mode 100644
index 0000000..dca5fd5
--- /dev/null
+++ b/Android_Java/Chapter_6/VertexBufferObjects/src/com/openglesbook/VertexBufferObjects/VBORenderer.java
@@ -0,0 +1,237 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// VertexBufferObjects
+//
+// This example demonstrates drawing a primitive with
+// and without Vertex Buffer Objects (VBOs)
+//
+
+package com.openglesbook.VertexBufferObjects;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class VBORenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public VBORenderer(Context context)
+ {
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+
+ // Offset the vertex positions so both can be seen
+ for ( int i = 0; i < 3; i++ )
+ {
+ mVerticesData[ i * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE) + 0] += 1.0f;
+ }
+
+ mVertices1 = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices1.put(mVerticesData).position(0);
+
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec4 a_color; \n" +
+ "out vec4 v_color; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " v_color = a_color; \n" +
+ " gl_Position = a_position; \n" +
+ "}";
+
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec4 v_color; \n" +
+ "out vec4 o_fragColor; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " o_fragColor = v_color; \n" +
+ "}" ;
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ mVBOIds[0] = 0;
+ mVBOIds[1] = 0;
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // without VBOs
+ drawPrimitiveWithoutVBOs();
+
+ // with VBOs
+ drawPrimitiveWithVBOs();
+ }
+
+ private void drawPrimitiveWithoutVBOs()
+ {
+ int numIndices = 3;
+ int vtxStride = 4 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE);
+
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
+ GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
+
+ mVertices.position(0);
+ GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
+ GLES30.GL_FLOAT, false, vtxStride, mVertices);
+
+ mVertices.position(VERTEX_POS_SIZE);
+ GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
+ GLES30.GL_FLOAT, false, vtxStride, mVertices);
+
+ GLES30.glDrawElements(GLES30.GL_TRIANGLES, numIndices,
+ GLES30.GL_UNSIGNED_SHORT, mIndices);
+
+ GLES30.glDisableVertexAttribArray(VERTEX_POS_INDX);
+ GLES30.glDisableVertexAttribArray(VERTEX_COLOR_INDX);
+ }
+
+ private void drawPrimitiveWithVBOs()
+ {
+ int offset = 0;
+ int numVertices = 3;
+ int numIndices = 3;
+ int vtxStride = 4 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE);
+
+ // mVBOIds[0] - used to store vertex attribute data
+ // mVBOIds[l] - used to store element indices
+ if ( mVBOIds[0] == 0 && mVBOIds[1] == 0)
+ {
+ // Only allocate on the first draw
+ GLES30.glGenBuffers(2, mVBOIds, 0);
+
+ mVertices1.position(0);
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[0]);
+ GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vtxStride * numVertices,
+ mVertices1, GLES30.GL_STATIC_DRAW);
+
+ mIndices.position(0);
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1]);
+ GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, 2 * numIndices,
+ mIndices, GLES30.GL_STATIC_DRAW);
+ }
+
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[0]);
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1]);
+
+ GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
+ GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
+
+ GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
+ GLES30.GL_FLOAT, false, vtxStride, offset);
+ offset += VERTEX_POS_SIZE * 4;
+
+ GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
+ GLES30.GL_FLOAT, false, vtxStride, offset);
+
+ GLES30.glDrawElements(GLES30.GL_TRIANGLES, numIndices,
+ GLES30.GL_UNSIGNED_SHORT, 0);
+
+ GLES30.glDisableVertexAttribArray(VERTEX_POS_INDX);
+ GLES30.glDisableVertexAttribArray(VERTEX_COLOR_INDX);
+
+ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
+ GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private FloatBuffer mVertices1;
+ private ShortBuffer mIndices;
+
+ // VertexBufferObject Ids
+ private int [] mVBOIds = new int[2];
+
+ // 3 vertices, with (x,y,z) ,(r, g, b, a) per-vertex
+ private final float[] mVerticesData =
+ {
+ -0.5f, 0.5f, 0.0f, // v0
+ 1.0f, 0.0f, 0.0f, 1.0f, // c0
+ -1.0f, -0.5f, 0.0f, // v1
+ 0.0f, 1.0f, 0.0f, 1.0f, // c1
+ 0.0f, -0.5f, 0.0f, // v2
+ 0.0f, 0.0f, 1.0f, 1.0f, // c2
+ };
+
+ // Index buffer data
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2
+ };
+
+ final int VERTEX_POS_SIZE = 3; // x, y and z
+ final int VERTEX_COLOR_SIZE = 4; // r, g, b, and a
+
+ final int VERTEX_POS_INDX = 0;
+ final int VERTEX_COLOR_INDX = 1;
+
+ final int VERTEX_STRIDE = ( 4 * ( VERTEX_POS_SIZE + VERTEX_COLOR_SIZE ) );
+}
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/.classpath b/Android_Java/Chapter_8/Simple_VertexShader/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/.project b/Android_Java/Chapter_8/Simple_VertexShader/.project
new file mode 100644
index 0000000..481b0b7
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/.project
@@ -0,0 +1,33 @@
+
+
+ Ch8_Simple_VertexShader
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/AndroidManifest.xml b/Android_Java/Chapter_8/Simple_VertexShader/AndroidManifest.xml
new file mode 100644
index 0000000..6174d2c
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/AndroidManifest.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/default.properties b/Android_Java/Chapter_8/Simple_VertexShader/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/proguard.cfg b/Android_Java/Chapter_8/Simple_VertexShader/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-hdpi/icon.png b/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-ldpi/icon.png b/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-mdpi/icon.png b/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_8/Simple_VertexShader/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/res/values/strings.xml b/Android_Java/Chapter_8/Simple_VertexShader/res/values/strings.xml
new file mode 100644
index 0000000..3662cbf
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ SimpleVertexShader
+
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/src/com/openglesbook/simplevertexshader/SimpleVertexShader.java b/Android_Java/Chapter_8/Simple_VertexShader/src/com/openglesbook/simplevertexshader/SimpleVertexShader.java
new file mode 100644
index 0000000..f1c2527
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/src/com/openglesbook/simplevertexshader/SimpleVertexShader.java
@@ -0,0 +1,66 @@
+package com.openglesbook.simplevertexshader;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class SimpleVertexShader extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 2.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new SimpleVertexShaderRenderer(this));
+ }
+ else
+ {
+ Log.e("HelloTriangle", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_8/Simple_VertexShader/src/com/openglesbook/simplevertexshader/SimpleVertexShaderRenderer.java b/Android_Java/Chapter_8/Simple_VertexShader/src/com/openglesbook/simplevertexshader/SimpleVertexShaderRenderer.java
new file mode 100644
index 0000000..9148f05
--- /dev/null
+++ b/Android_Java/Chapter_8/Simple_VertexShader/src/com/openglesbook/simplevertexshader/SimpleVertexShaderRenderer.java
@@ -0,0 +1,184 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_VertexShader
+//
+// This is a simple example that draws a rotating cube in perspective
+// using a vertex shader to transform the object
+//
+
+package com.openglesbook.simplevertexshader;
+
+import com.openglesbook.common.ESShapes;
+import com.openglesbook.common.ESShader;
+import com.openglesbook.common.ESTransform;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+import android.os.SystemClock;
+
+public class SimpleVertexShaderRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public SimpleVertexShaderRenderer(Context context)
+ {
+
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "uniform mat4 u_mvpMatrix; \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec4 a_color; \n" +
+ "out vec4 v_color; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " v_color = a_color; \n" +
+ " gl_Position = u_mvpMatrix * a_position; \n" +
+ "} \n";
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec4 v_color; \n" +
+ "layout(location = 0) out vec4 outColor; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " outColor = v_color; \n" +
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ // Get the uniform locations
+ mMVPLoc = GLES30.glGetUniformLocation(mProgramObject, "u_mvpMatrix");
+
+ // Generate the vertex data
+ mCube.genCube(1.0f);
+
+ // Starting rotation angle for the cube
+ mAngle = 45.0f;
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ private void update()
+ {
+ if (mLastTime == 0)
+ mLastTime = SystemClock.uptimeMillis();
+ long curTime = SystemClock.uptimeMillis();
+ long elapsedTime = curTime - mLastTime;
+ float deltaTime = elapsedTime / 1000.0f;
+ mLastTime = curTime;
+
+ ESTransform perspective = new ESTransform();
+ ESTransform modelview = new ESTransform();
+ float aspect;
+
+ // Compute a rotation angle based on time to rotate the cube
+ mAngle += (deltaTime * 40.0f);
+ if (mAngle >= 360.0f)
+ mAngle -= 360.0f;
+
+ // Compute the window aspect ratio
+ aspect = (float) mWidth / (float) mHeight;
+
+ // Generate a perspective matrix with a 60 degree FOV
+ perspective.matrixLoadIdentity();
+ perspective.perspective(60.0f, aspect, 1.0f, 20.0f);
+
+ // Generate a model view matrix to rotate/translate the cube
+ modelview.matrixLoadIdentity();
+
+ // Translate away from the viewer
+ modelview.translate(0.0f, 0.0f, -2.0f);
+
+ // Rotate the cube
+ modelview.rotate(mAngle, 1.0f, 0.0f, 1.0f);
+
+ // Compute the final MVP by multiplying the
+ // modevleiw and perspective matrices together
+ mMVPMatrix.matrixMultiply(modelview.get(), perspective.get());
+ }
+
+ ///
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ update();
+
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex data
+ GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false,
+ 0, mCube.getVertices());
+ GLES30.glEnableVertexAttribArray(0);
+
+ // Set the vertex color to red
+ GLES30.glVertexAttrib4f( 1, 1.0f, 0.0f, 0.0f, 1.0f );
+
+ // Load the MVP matrix
+ GLES30.glUniformMatrix4fv(mMVPLoc, 1, false,
+ mMVPMatrix.getAsFloatBuffer());
+
+ // Draw the cube
+ GLES30.glDrawElements(GLES30.GL_TRIANGLES, mCube.getNumIndices(),
+ GLES30.GL_UNSIGNED_SHORT, mCube.getIndices());
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Uniform locations
+ private int mMVPLoc;
+
+ // Vertex data
+ private ESShapes mCube = new ESShapes();
+
+ // Rotation angle
+ private float mAngle;
+
+ // MVP matrix
+ private ESTransform mMVPMatrix = new ESTransform();
+
+ // Additional Member variables
+ private int mWidth;
+ private int mHeight;
+ private long mLastTime = 0;
+}
diff --git a/Android_Java/Chapter_9/MipMap2D/.classpath b/Android_Java/Chapter_9/MipMap2D/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_9/MipMap2D/.project b/Android_Java/Chapter_9/MipMap2D/.project
new file mode 100644
index 0000000..86f4b5b
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/.project
@@ -0,0 +1,33 @@
+
+
+ Ch9_MipMap2D
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_9/MipMap2D/AndroidManifest.xml b/Android_Java/Chapter_9/MipMap2D/AndroidManifest.xml
new file mode 100644
index 0000000..4d3e05e
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_9/MipMap2D/assets/shaders/fragmentShader.frag b/Android_Java/Chapter_9/MipMap2D/assets/shaders/fragmentShader.frag
new file mode 100644
index 0000000..446bb3f
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/assets/shaders/fragmentShader.frag
@@ -0,0 +1,14 @@
+#version 300 es
+
+precision mediump float;
+
+in vec2 v_texCoord;
+
+layout(location = 0) out vec4 outColor;
+
+uniform sampler2D s_texture;
+
+void main()
+{
+ outColor = texture( s_texture, v_texCoord );
+}
\ No newline at end of file
diff --git a/Android_Java/Chapter_9/MipMap2D/assets/shaders/vertexShader.vert b/Android_Java/Chapter_9/MipMap2D/assets/shaders/vertexShader.vert
new file mode 100644
index 0000000..f59c13a
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/assets/shaders/vertexShader.vert
@@ -0,0 +1,16 @@
+#version 300 es
+
+uniform float u_offset;
+
+layout(location = 0) in vec4 a_position;
+layout(location = 1) in vec2 a_texCoord;
+
+out vec2 v_texCoord;
+
+void main()
+{
+ gl_Position = a_position;
+ gl_Position.x += u_offset;
+
+ v_texCoord = a_texCoord;
+}
\ No newline at end of file
diff --git a/Android_Java/Chapter_9/MipMap2D/default.properties b/Android_Java/Chapter_9/MipMap2D/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_9/MipMap2D/proguard.cfg b/Android_Java/Chapter_9/MipMap2D/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_9/MipMap2D/res/drawable-hdpi/icon.png b/Android_Java/Chapter_9/MipMap2D/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_9/MipMap2D/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/MipMap2D/res/drawable-ldpi/icon.png b/Android_Java/Chapter_9/MipMap2D/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_9/MipMap2D/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_9/MipMap2D/res/drawable-mdpi/icon.png b/Android_Java/Chapter_9/MipMap2D/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_9/MipMap2D/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/MipMap2D/res/values/strings.xml b/Android_Java/Chapter_9/MipMap2D/res/values/strings.xml
new file mode 100644
index 0000000..637300f
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch9_MipMap2D
+
diff --git a/Android_Java/Chapter_9/MipMap2D/src/com/openglesbook/mipmap2d/MipMap2D.java b/Android_Java/Chapter_9/MipMap2D/src/com/openglesbook/mipmap2d/MipMap2D.java
new file mode 100644
index 0000000..b32dbb3
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/src/com/openglesbook/mipmap2d/MipMap2D.java
@@ -0,0 +1,65 @@
+package com.openglesbook.mipmap2d;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class MipMap2D extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 2.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new MipMap2DRenderer(this));
+ }
+ else
+ {
+ Log.e("MipMap2D", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_9/MipMap2D/src/com/openglesbook/mipmap2d/MipMap2DRenderer.java b/Android_Java/Chapter_9/MipMap2D/src/com/openglesbook/mipmap2d/MipMap2DRenderer.java
new file mode 100644
index 0000000..1eac4ad
--- /dev/null
+++ b/Android_Java/Chapter_9/MipMap2D/src/com/openglesbook/mipmap2d/MipMap2DRenderer.java
@@ -0,0 +1,332 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MipMap2D
+//
+// This is a simple example that demonstrates generating a mipmap chain
+// and rendering with it
+//
+
+package com.openglesbook.mipmap2d;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class MipMap2DRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public MipMap2DRenderer(Context context)
+ {
+ mContext = context;
+
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ ///
+ // From an RGB8 source image, generate the next level mipmap
+ //
+ private byte[] genMipMap2D( byte[] src,int srcWidth, int srcHeight, int dstWidth, int dstHeight )
+ {
+ int x,
+ y;
+ int texelSize = 3;
+
+ byte[] dst = new byte[texelSize * (dstWidth) * (dstHeight)];
+
+ for ( y = 0; y < dstHeight; y++ )
+ {
+ for( x = 0; x < dstWidth; x++ )
+ {
+ int[] srcIndex = new int[4];
+ float r = 0.0f,
+ g = 0.0f,
+ b = 0.0f;
+ int sample;
+
+ // Compute the offsets for 2x2 grid of pixels in previous
+ // image to perform box filter
+ srcIndex[0] =
+ (((y * 2) * srcWidth) + (x * 2)) * texelSize;
+ srcIndex[1] =
+ (((y * 2) * srcWidth) + (x * 2 + 1)) * texelSize;
+ srcIndex[2] =
+ ((((y * 2) + 1) * srcWidth) + (x * 2)) * texelSize;
+ srcIndex[3] =
+ ((((y * 2) + 1) * srcWidth) + (x * 2 + 1)) * texelSize;
+
+ // Sum all pixels
+ for ( sample = 0; sample < 4; sample++ )
+ {
+ r += src[srcIndex[sample]];
+ g += src[srcIndex[sample] + 1];
+ b += src[srcIndex[sample] + 2];
+ }
+
+ // Average results
+ r /= 4.0;
+ g /= 4.0;
+ b /= 4.0;
+
+ // Store resulting pixels
+ dst[ ( y * (dstWidth) + x ) * texelSize ] = (byte)( r );
+ dst[ ( y * (dstWidth) + x ) * texelSize + 1] = (byte)( g );
+ dst[ ( y * (dstWidth) + x ) * texelSize + 2] = (byte)( b );
+ }
+ }
+ return dst;
+ }
+
+ ///
+ // Generate an RGB8 checkerboard image
+ //
+ private byte[] genCheckImage( int width, int height, int checkSize )
+ {
+ int x,
+ y;
+ byte[] pixels = new byte[width * height * 3];
+
+
+ for ( y = 0; y < height; y++ )
+ for ( x = 0; x < width; x++ )
+ {
+ byte rColor = 0;
+ byte bColor = 0;
+
+ if ( ( x / checkSize ) % 2 == 0 )
+ {
+ rColor = (byte)(127 * ( ( y / checkSize ) % 2 ));
+ bColor = (byte)(127 * ( 1 - ( ( y / checkSize ) % 2 ) ));
+ }
+ else
+ {
+ bColor = (byte)(127 * ( ( y / checkSize ) % 2 ));
+ rColor = (byte)(127 * ( 1 - ( ( y / checkSize ) % 2 ) ));
+ }
+
+ pixels[(y * height + x) * 3] = rColor;
+ pixels[(y * height + x) * 3 + 1] = 0;
+ pixels[(y * height + x) * 3 + 2] = bColor;
+ }
+
+ return pixels;
+ }
+
+
+ ///
+ // Create a mipmapped 2D texture image
+ //
+ private int createMipMappedTexture2D( )
+ {
+ // Texture object handle
+ int[] textureId = new int[1];
+ int width = 256,
+ height = 256;
+ int level;
+ byte[] pixels;
+ byte[] prevImage;
+ byte[] newImage;
+
+ pixels = genCheckImage( width, height, 8 );
+
+ // Generate a texture object
+ GLES30.glGenTextures ( 1, textureId, 0 );
+
+ // Bind the texture object
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, textureId[0] );
+
+ // Load mipmap level 0
+ ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(width * height * 3);
+ pixelBuffer.put(pixels).position(0);
+
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGB, width, height,
+ 0, GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, pixelBuffer );
+
+ level = 1;
+ prevImage = pixels;
+
+ while ( width > 1 && height > 1 )
+ {
+ int newWidth,
+ newHeight;
+
+ newWidth = width / 2;
+ if ( newWidth <= 0 )
+ newWidth = 1;
+
+ newHeight = height / 2;
+ if ( newHeight <= 0 )
+ newHeight = 1;
+
+ // Generate the next mipmap level
+ newImage = genMipMap2D( prevImage, width, height, newWidth, newHeight );
+
+ // Load the mipmap level
+ pixelBuffer = ByteBuffer.allocateDirect(newWidth * newHeight * 3);
+ pixelBuffer.put(newImage).position(0);
+ GLES30.glTexImage2D( GLES30.GL_TEXTURE_2D, level, GLES30.GL_RGB,
+ newWidth, newHeight, 0, GLES30.GL_RGB,
+ GLES30.GL_UNSIGNED_BYTE, pixelBuffer );
+
+ // Set the previous image for the next iteration
+ prevImage = newImage;
+ level++;
+
+ // Half the width and height
+ width = newWidth;
+ height = newHeight;
+ }
+
+
+ // Set the filtering mode
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST_MIPMAP_NEAREST );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR );
+
+ return textureId[0];
+
+ }
+
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+
+
+ // Load the shaders from "assets" and get a linked program object
+ mProgramObject = ESShader.loadProgramFromAsset(mContext,
+ "shaders/vertexShader.vert",
+ "shaders/fragmentShader.frag");
+
+ // Get the sampler location
+ mSamplerLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_texture" );
+
+ // Get the offset location
+ mOffsetLoc = GLES30.glGetUniformLocation( mProgramObject, "u_offset" );
+
+ // Load the texture
+ mTextureId = createMipMappedTexture2D();
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ ///
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex position
+ mVertices.position(0);
+ GLES30.glVertexAttribPointer ( 0, 4, GLES30.GL_FLOAT,
+ false,
+ 6 * 4, mVertices );
+ // Load the texture coordinate
+ mVertices.position(4);
+ GLES30.glVertexAttribPointer ( 1, 2, GLES30.GL_FLOAT,
+ false,
+ 6 * 4,
+ mVertices );
+
+ GLES30.glEnableVertexAttribArray( 0 );
+ GLES30.glEnableVertexAttribArray( 1 );
+
+ // Bind the texture
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, mTextureId );
+
+ // Set the sampler texture unit to 0
+ GLES30.glUniform1i ( mSamplerLoc, 0 );
+
+ // Draw quad with nearest sampling
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST );
+ GLES30.glUniform1f ( mOffsetLoc, -0.6f );
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+
+ // Draw quad with trilinear filtering
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR );
+ GLES30.glUniform1f ( mOffsetLoc, 0.6f );
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Sampler location
+ private int mSamplerLoc;
+
+ // Offset location
+ private int mOffsetLoc;
+
+ // Texture handle
+ private int mTextureId;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private ShortBuffer mIndices;
+
+ private final float[] mVerticesData =
+ {
+ -0.5f, 0.5f, 0.0f, 1.5f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, 0.75f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, 0.75f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, 1.5f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2, 0, 2, 3
+ };
+
+ private Context mContext;
+}
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/.classpath b/Android_Java/Chapter_9/Simple_Texture2D/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/.project b/Android_Java/Chapter_9/Simple_Texture2D/.project
new file mode 100644
index 0000000..42ecaa0
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/.project
@@ -0,0 +1,33 @@
+
+
+ Ch9_Simple_Texture2D
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/AndroidManifest.xml b/Android_Java/Chapter_9/Simple_Texture2D/AndroidManifest.xml
new file mode 100644
index 0000000..441943a
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/default.properties b/Android_Java/Chapter_9/Simple_Texture2D/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/proguard.cfg b/Android_Java/Chapter_9/Simple_Texture2D/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-hdpi/icon.png b/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-ldpi/icon.png b/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-mdpi/icon.png b/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_9/Simple_Texture2D/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/res/values/strings.xml b/Android_Java/Chapter_9/Simple_Texture2D/res/values/strings.xml
new file mode 100644
index 0000000..7a469b0
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch9_Simple_Texture2D
+
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/src/com/openglesbook/simpletexture2d/SimpleTexture2D.java b/Android_Java/Chapter_9/Simple_Texture2D/src/com/openglesbook/simpletexture2d/SimpleTexture2D.java
new file mode 100644
index 0000000..4ec8c40
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/src/com/openglesbook/simpletexture2d/SimpleTexture2D.java
@@ -0,0 +1,66 @@
+package com.openglesbook.simpletexture2d;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class SimpleTexture2D extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new SimpleTexture2DRenderer(this));
+ }
+ else
+ {
+ Log.e("SimpleTexture2D", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_9/Simple_Texture2D/src/com/openglesbook/simpletexture2d/SimpleTexture2DRenderer.java b/Android_Java/Chapter_9/Simple_Texture2D/src/com/openglesbook/simpletexture2d/SimpleTexture2DRenderer.java
new file mode 100644
index 0000000..2595259
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_Texture2D/src/com/openglesbook/simpletexture2d/SimpleTexture2DRenderer.java
@@ -0,0 +1,209 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_Texture2D
+//
+// This is a simple example that draws a quad with a 2D
+// texture image. The purpose of this example is to demonstrate
+// the basics of 2D texturing
+//
+
+package com.openglesbook.simpletexture2d;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class SimpleTexture2DRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public SimpleTexture2DRenderer(Context context)
+ {
+
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ //
+ // Create a simple 2x2 texture image with four different colors
+ //
+ private int createSimpleTexture2D( )
+ {
+ // Texture object handle
+ int[] textureId = new int[1];
+
+ // 2x2 Image, 3 bytes per pixel (R, G, B)
+ byte[] pixels =
+ {
+ (byte) 0xff, 0, 0, // Red
+ 0, (byte) 0xff, 0, // Green
+ 0, 0, (byte) 0xff, // Blue
+ (byte) 0xff, (byte) 0xff, 0 // Yellow
+ };
+ ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4*3);
+ pixelBuffer.put(pixels).position(0);
+
+ // Use tightly packed data
+ GLES30.glPixelStorei ( GLES30.GL_UNPACK_ALIGNMENT, 1 );
+
+ // Generate a texture object
+ GLES30.glGenTextures ( 1, textureId, 0 );
+
+ // Bind the texture object
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, textureId[0] );
+
+ // Load the texture
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGB, 2, 2, 0, GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, pixelBuffer );
+
+ // Set the filtering mode
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST );
+
+ return textureId[0];
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec2 a_texCoord; \n" +
+ "out vec2 v_texCoord; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " gl_Position = a_position; \n" +
+ " v_texCoord = a_texCoord; \n" +
+ "} \n";
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec2 v_texCoord; \n" +
+ "layout(location = 0) out vec4 outColor; \n" +
+ "uniform sampler2D s_texture; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " outColor = texture( s_texture, v_texCoord ); \n" +
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ // Get the sampler location
+ mSamplerLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_texture" );
+
+ // Load the texture
+ mTextureId = createSimpleTexture2D ();
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ // /
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex position
+ mVertices.position(0);
+ GLES30.glVertexAttribPointer ( 0, 3, GLES30.GL_FLOAT,
+ false,
+ 5 * 4, mVertices );
+ // Load the texture coordinate
+ mVertices.position(3);
+ GLES30.glVertexAttribPointer ( 1, 2, GLES30.GL_FLOAT,
+ false,
+ 5 * 4,
+ mVertices );
+
+ GLES30.glEnableVertexAttribArray ( 0 );
+ GLES30.glEnableVertexAttribArray ( 1 );
+
+ // Bind the texture
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, mTextureId );
+
+ // Set the sampler texture unit to 0
+ GLES30.glUniform1i ( mSamplerLoc, 0 );
+
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Sampler location
+ private int mSamplerLoc;
+
+ // Texture handle
+ private int mTextureId;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private ShortBuffer mIndices;
+
+ private final float[] mVerticesData =
+ {
+ -0.5f, 0.5f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2, 0, 2, 3
+ };
+
+}
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/.classpath b/Android_Java/Chapter_9/Simple_TextureCubemap/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/.project b/Android_Java/Chapter_9/Simple_TextureCubemap/.project
new file mode 100644
index 0000000..9083c72
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/.project
@@ -0,0 +1,33 @@
+
+
+ Ch9_Simple_TextureCubemap
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/AndroidManifest.xml b/Android_Java/Chapter_9/Simple_TextureCubemap/AndroidManifest.xml
new file mode 100644
index 0000000..f2c12aa
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/default.properties b/Android_Java/Chapter_9/Simple_TextureCubemap/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/proguard.cfg b/Android_Java/Chapter_9/Simple_TextureCubemap/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-hdpi/icon.png b/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-ldpi/icon.png b/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-mdpi/icon.png b/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_9/Simple_TextureCubemap/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/res/values/strings.xml b/Android_Java/Chapter_9/Simple_TextureCubemap/res/values/strings.xml
new file mode 100644
index 0000000..48c317a
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch9_Simple_TextureCubemap
+
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/src/com/openglesbook/simpletexturecubemap/SimpleTextureCubemap.java b/Android_Java/Chapter_9/Simple_TextureCubemap/src/com/openglesbook/simpletexturecubemap/SimpleTextureCubemap.java
new file mode 100644
index 0000000..ac28107
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/src/com/openglesbook/simpletexturecubemap/SimpleTextureCubemap.java
@@ -0,0 +1,65 @@
+package com.openglesbook.simpletexturecubemap;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class SimpleTextureCubemap extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new SimpleTextureCubemapRenderer(this));
+ }
+ else
+ {
+ Log.e("SimpleTextureCubemap", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_9/Simple_TextureCubemap/src/com/openglesbook/simpletexturecubemap/SimpleTextureCubemapRenderer.java b/Android_Java/Chapter_9/Simple_TextureCubemap/src/com/openglesbook/simpletexturecubemap/SimpleTextureCubemapRenderer.java
new file mode 100644
index 0000000..e0a0195
--- /dev/null
+++ b/Android_Java/Chapter_9/Simple_TextureCubemap/src/com/openglesbook/simpletexturecubemap/SimpleTextureCubemapRenderer.java
@@ -0,0 +1,212 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MipMap2D
+//
+// This is a simple example that demonstrates generating a mipmap chain
+// and rendering with it
+//
+
+package com.openglesbook.simpletexturecubemap;
+
+import java.nio.ByteBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+import com.openglesbook.common.ESShapes;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class SimpleTextureCubemapRenderer implements GLSurfaceView.Renderer
+{
+ ///
+ // Constructor
+ //
+ public SimpleTextureCubemapRenderer(Context context)
+ {
+ }
+
+ ///
+ // Create a simple cubemap with a 1x1 face with a different
+ // color for each face
+ private int createSimpleTextureCubemap( )
+ {
+ int[] textureId = new int[1];
+
+ // Face 0 - Red
+ byte[] cubePixels0 = { 127, 0, 0 };
+ // Face 1 - Green
+ byte[] cubePixels1 = { 0, 127, 0 };
+ // Face 2 - Blue
+ byte[] cubePixels2 = { 0, 0, 127 };
+ // Face 3 - Yellow
+ byte[] cubePixels3 = { 127, 127, 0 };
+ // Face 4 - Purple
+ byte[] cubePixels4 = { 127, 0, 127 };
+ // Face 5 - White
+ byte[] cubePixels5 = { 127, 127, 127 };
+
+ ByteBuffer cubePixels = ByteBuffer.allocateDirect(3);
+
+ // Generate a texture object
+ GLES30.glGenTextures ( 1, textureId, 0 );
+
+ // Bind the texture object
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_CUBE_MAP, textureId[0] );
+
+ // Load the cube face - Positive X
+ cubePixels.put(cubePixels0).position(0);
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GLES30.GL_RGB, 1, 1, 0,
+ GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, cubePixels );
+
+ // Load the cube face - Negative X
+ cubePixels.put(cubePixels1).position(0);
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GLES30.GL_RGB, 1, 1, 0,
+ GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, cubePixels );
+
+ // Load the cube face - Positive Y
+ cubePixels.put(cubePixels2).position(0);
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GLES30.GL_RGB, 1, 1, 0,
+ GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, cubePixels );
+
+ // Load the cube face - Negative Y
+ cubePixels.put(cubePixels3).position(0);
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GLES30.GL_RGB, 1, 1, 0,
+ GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, cubePixels );
+
+ // Load the cube face - Positive Z
+ cubePixels.put(cubePixels4).position(0);
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GLES30.GL_RGB, 1, 1, 0,
+ GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, cubePixels );
+
+ // Load the cube face - Negative Z
+ cubePixels.put(cubePixels5).position(0);
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GLES30.GL_RGB, 1, 1, 0,
+ GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, cubePixels );
+
+ // Set the filtering mode
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_CUBE_MAP, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST );
+
+ return textureId[0];
+ }
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+
+ "#version 300 es \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec3 a_normal; \n" +
+ "out vec3 v_normal; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " gl_Position = a_position; \n" +
+ " v_normal = a_normal; \n" +
+ "} \n";
+
+ String fShaderStr =
+
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec3 v_normal; \n" +
+ "layout(location = 0) out vec4 outColor; \n" +
+ "uniform samplerCube s_texture; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " outColor = texture( s_texture, v_normal ); \n" +
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ // Get the sampler location
+ mSamplerLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_texture" );
+
+ // Load the texture
+ mTextureId = createSimpleTextureCubemap ();
+
+ // Generate the vertex data
+ mSphere.genSphere( 20, 0.75f );
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ ///
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ GLES30.glCullFace(GLES30.GL_BACK);
+ GLES30.glEnable(GLES30.GL_CULL_FACE);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex position
+ GLES30.glVertexAttribPointer ( 0, 3, GLES30.GL_FLOAT,
+ false, 0, mSphere.getVertices());
+ // Load the texture coordinate
+
+ GLES30.glVertexAttribPointer ( 1, 3, GLES30.GL_FLOAT,
+ false, 0, mSphere.getNormals());
+
+ GLES30.glEnableVertexAttribArray( 0 );
+ GLES30.glEnableVertexAttribArray( 1 );
+
+ // Bind the texture
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_CUBE_MAP, mTextureId );
+
+ // Set the sampler texture unit to 0
+ GLES30.glUniform1i ( mSamplerLoc, 0 );
+
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, mSphere.getNumIndices(), GLES30.GL_UNSIGNED_SHORT, mSphere.getIndices() );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Sampler location
+ private int mSamplerLoc;
+
+ // Texture ID
+ private int mTextureId;
+
+ // Vertex data
+ private ESShapes mSphere = new ESShapes();
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+}
diff --git a/Android_Java/Chapter_9/TextureWrap/.classpath b/Android_Java/Chapter_9/TextureWrap/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Chapter_9/TextureWrap/.project b/Android_Java/Chapter_9/TextureWrap/.project
new file mode 100644
index 0000000..c559ab7
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/.project
@@ -0,0 +1,33 @@
+
+
+ Ch9_TextureWrap
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Chapter_9/TextureWrap/AndroidManifest.xml b/Android_Java/Chapter_9/TextureWrap/AndroidManifest.xml
new file mode 100644
index 0000000..a43f3ab
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Chapter_9/TextureWrap/default.properties b/Android_Java/Chapter_9/TextureWrap/default.properties
new file mode 100644
index 0000000..5ccd841
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library.reference.1=../../Common/
diff --git a/Android_Java/Chapter_9/TextureWrap/proguard.cfg b/Android_Java/Chapter_9/TextureWrap/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Chapter_9/TextureWrap/res/drawable-hdpi/icon.png b/Android_Java/Chapter_9/TextureWrap/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Chapter_9/TextureWrap/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/TextureWrap/res/drawable-ldpi/icon.png b/Android_Java/Chapter_9/TextureWrap/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Chapter_9/TextureWrap/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Chapter_9/TextureWrap/res/drawable-mdpi/icon.png b/Android_Java/Chapter_9/TextureWrap/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Chapter_9/TextureWrap/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Chapter_9/TextureWrap/res/values/strings.xml b/Android_Java/Chapter_9/TextureWrap/res/values/strings.xml
new file mode 100644
index 0000000..44b8696
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Ch9_TextureWrap
+
diff --git a/Android_Java/Chapter_9/TextureWrap/src/com/openglesbook/texturewrap/TextureWrap.java b/Android_Java/Chapter_9/TextureWrap/src/com/openglesbook/texturewrap/TextureWrap.java
new file mode 100644
index 0000000..5d0ddb9
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/src/com/openglesbook/texturewrap/TextureWrap.java
@@ -0,0 +1,65 @@
+package com.openglesbook.texturewrap;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity class for example program that detects OpenGL ES 3.0.
+ **/
+public class TextureWrap extends Activity {
+
+ private final int CONTEXT_CLIENT_VERSION = 3;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ if (detectOpenGLES30())
+ {
+ // Tell the surface view we want to create an OpenGL ES 3.0-compatible
+ // context, and set an OpenGL ES 3.0-compatible renderer.
+ mGLSurfaceView.setEGLContextClientVersion(CONTEXT_CLIENT_VERSION);
+ mGLSurfaceView.setRenderer(new TextureWrapRenderer(this));
+ }
+ else
+ {
+ Log.e("TextureWrap", "OpenGL ES 3.0 not supported on device. Exiting...");
+ finish();
+ }
+ setContentView(mGLSurfaceView);
+ }
+
+ private boolean detectOpenGLES30()
+ {
+ ActivityManager am =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ConfigurationInfo info = am.getDeviceConfigurationInfo();
+ return (info.reqGlEsVersion >= 0x30000);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/Android_Java/Chapter_9/TextureWrap/src/com/openglesbook/texturewrap/TextureWrapRenderer.java b/Android_Java/Chapter_9/TextureWrap/src/com/openglesbook/texturewrap/TextureWrapRenderer.java
new file mode 100644
index 0000000..2ac8be3
--- /dev/null
+++ b/Android_Java/Chapter_9/TextureWrap/src/com/openglesbook/texturewrap/TextureWrapRenderer.java
@@ -0,0 +1,263 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// TextureWrap
+//
+// This is an example that demonstrates the three texture
+// wrap modes available on 2D textures
+//
+
+package com.openglesbook.texturewrap;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.openglesbook.common.ESShader;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+public class TextureWrapRenderer implements GLSurfaceView.Renderer
+{
+
+ ///
+ // Constructor
+ //
+ public TextureWrapRenderer(Context context)
+ {
+
+ mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mVertices.put(mVerticesData).position(0);
+ mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+ mIndices.put(mIndicesData).position(0);
+ }
+
+ ///
+ // Generate an RGB8 checkerboard image
+ //
+ private ByteBuffer genCheckImage( int width, int height, int checkSize )
+ {
+ int x,
+ y;
+ byte[] pixels = new byte[width * height * 3];
+
+
+ for ( y = 0; y < height; y++ )
+ for ( x = 0; x < width; x++ )
+ {
+ byte rColor = 0;
+ byte bColor = 0;
+
+ if ( ( x / checkSize ) % 2 == 0 )
+ {
+ rColor = (byte)(127 * ( ( y / checkSize ) % 2 ));
+ bColor = (byte)(127 * ( 1 - ( ( y / checkSize ) % 2 ) ));
+ }
+ else
+ {
+ bColor = (byte)(127 * ( ( y / checkSize ) % 2 ));
+ rColor = (byte)(127 * ( 1 - ( ( y / checkSize ) % 2 ) ));
+ }
+
+ pixels[(y * height + x) * 3] = rColor;
+ pixels[(y * height + x) * 3 + 1] = 0;
+ pixels[(y * height + x) * 3 + 2] = bColor;
+ }
+
+ ByteBuffer result = ByteBuffer.allocateDirect(width*height*3);
+ result.put(pixels).position(0);
+ return result;
+ }
+
+ ///
+ // Create a 2D texture image
+ //
+ private int createTexture2D( )
+ {
+ // Texture object handle
+ int[] textureId = new int[1];
+ int width = 256,
+ height = 256;
+ ByteBuffer pixels;
+
+ pixels = genCheckImage( width, height, 64 );
+
+ // Generate a texture object
+ GLES30.glGenTextures ( 1, textureId, 0 );
+
+ // Bind the texture object
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, textureId[0] );
+
+ // Load mipmap level 0
+ GLES30.glTexImage2D ( GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGB, width, height,
+ 0, GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, pixels );
+
+ // Set the filtering mode
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR );
+
+ return textureId[0];
+ }
+
+
+
+ ///
+ // Initialize the shader and program object
+ //
+ public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+ {
+ String vShaderStr =
+ "#version 300 es \n" +
+ "uniform float u_offset; \n" +
+ "layout(location = 0) in vec4 a_position; \n" +
+ "layout(location = 1) in vec2 a_texCoord; \n" +
+ "out vec2 v_texCoord; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " gl_Position = a_position; \n" +
+ " gl_Position.x += u_offset; \n" +
+ " v_texCoord = a_texCoord; \n" +
+ "} \n";
+
+ String fShaderStr =
+ "#version 300 es \n" +
+ "precision mediump float; \n" +
+ "in vec2 v_texCoord; \n" +
+ "layout(location = 0) out vec4 outColor; \n" +
+ "uniform sampler2D s_texture; \n" +
+ "void main() \n" +
+ "{ \n" +
+ " outColor = texture( s_texture, v_texCoord ); \n" +
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
+
+ // Get the sampler location
+ mSamplerLoc = GLES30.glGetUniformLocation ( mProgramObject, "s_texture" );
+
+ // Get the offset location
+ mOffsetLoc = GLES30.glGetUniformLocation( mProgramObject, "u_offset" );
+
+ // Load the texture
+ mTextureId = createTexture2D ();
+
+ GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ ///
+ // Draw a triangle using the shader pair created in onSurfaceCreated()
+ //
+ public void onDrawFrame(GL10 glUnused)
+ {
+ // Set the viewport
+ GLES30.glViewport(0, 0, mWidth, mHeight);
+
+ // Clear the color buffer
+ GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+
+ // Use the program object
+ GLES30.glUseProgram(mProgramObject);
+
+ // Load the vertex position
+ mVertices.position(0);
+ GLES30.glVertexAttribPointer ( 0, 4, GLES30.GL_FLOAT,
+ false,
+ 6 * 4, mVertices );
+ // Load the texture coordinate
+ mVertices.position(4);
+ GLES30.glVertexAttribPointer ( 1, 2, GLES30.GL_FLOAT,
+ false,
+ 6 * 4,
+ mVertices );
+
+ GLES30.glEnableVertexAttribArray( 0 );
+ GLES30.glEnableVertexAttribArray( 1 );
+
+ // Bind the texture
+ GLES30.glActiveTexture ( GLES30.GL_TEXTURE0 );
+ GLES30.glBindTexture ( GLES30.GL_TEXTURE_2D, mTextureId );
+
+ // Set the sampler texture unit to 0
+ GLES30.glUniform1i ( mSamplerLoc, 0 );
+
+ // Draw quad with repeat wrap mode
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT );
+ GLES30.glUniform1f ( mOffsetLoc, -0.7f );
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+
+ // Draw quad with clamp to edge wrap mode
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE );
+ GLES30.glUniform1f ( mOffsetLoc, 0.0f );
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+
+ // Draw quad with mirrored repeat
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_MIRRORED_REPEAT );
+ GLES30.glTexParameteri ( GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_MIRRORED_REPEAT );
+ GLES30.glUniform1f ( mOffsetLoc, 0.7f );
+ GLES30.glDrawElements ( GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, mIndices );
+ }
+
+ ///
+ // Handle surface changes
+ //
+ public void onSurfaceChanged(GL10 glUnused, int width, int height)
+ {
+ mWidth = width;
+ mHeight = height;
+ }
+
+
+ // Handle to a program object
+ private int mProgramObject;
+
+ // Sampler location
+ private int mSamplerLoc;
+
+ // Offset location
+ private int mOffsetLoc;
+
+ // Texture handle
+ private int mTextureId;
+
+ // Additional member variables
+ private int mWidth;
+ private int mHeight;
+ private FloatBuffer mVertices;
+ private ShortBuffer mIndices;
+
+ private final float[] mVerticesData =
+ {
+ -0.3f, 0.3f, 0.0f, 1.0f, // Position 0
+ -1.0f, -1.0f, // TexCoord 0
+ -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
+ -1.0f, 2.0f, // TexCoord 1
+ 0.3f, -0.3f, 0.0f, 1.0f, // Position 2
+ 2.0f, 2.0f, // TexCoord 2
+ 0.3f, 0.3f, 0.0f, 1.0f, // Position 3
+ 2.0f, -1.0f // TexCoord 3
+ };
+
+ private final short[] mIndicesData =
+ {
+ 0, 1, 2, 0, 2, 3
+ };
+
+}
diff --git a/Android_Java/Common/.classpath b/Android_Java/Common/.classpath
new file mode 100644
index 0000000..ce8b321
--- /dev/null
+++ b/Android_Java/Common/.classpath
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android_Java/Common/.project b/Android_Java/Common/.project
new file mode 100644
index 0000000..4a3847a
--- /dev/null
+++ b/Android_Java/Common/.project
@@ -0,0 +1,33 @@
+
+
+ Common
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Android_Java/Common/AndroidManifest.xml b/Android_Java/Common/AndroidManifest.xml
new file mode 100644
index 0000000..c3572aa
--- /dev/null
+++ b/Android_Java/Common/AndroidManifest.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android_Java/Common/default.properties b/Android_Java/Common/default.properties
new file mode 100644
index 0000000..32d7696
--- /dev/null
+++ b/Android_Java/Common/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-18
+android.library=true
diff --git a/Android_Java/Common/proguard.cfg b/Android_Java/Common/proguard.cfg
new file mode 100644
index 0000000..8ad7d33
--- /dev/null
+++ b/Android_Java/Common/proguard.cfg
@@ -0,0 +1,34 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/Android_Java/Common/res/drawable-hdpi/icon.png b/Android_Java/Common/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/Android_Java/Common/res/drawable-hdpi/icon.png differ
diff --git a/Android_Java/Common/res/drawable-ldpi/icon.png b/Android_Java/Common/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/Android_Java/Common/res/drawable-ldpi/icon.png differ
diff --git a/Android_Java/Common/res/drawable-mdpi/icon.png b/Android_Java/Common/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/Android_Java/Common/res/drawable-mdpi/icon.png differ
diff --git a/Android_Java/Common/res/values/strings.xml b/Android_Java/Common/res/values/strings.xml
new file mode 100644
index 0000000..e57957d
--- /dev/null
+++ b/Android_Java/Common/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Common
+
diff --git a/Android_Java/Common/src/com/openglesbook/common/ESShader.java b/Android_Java/Common/src/com/openglesbook/common/ESShader.java
new file mode 100644
index 0000000..357bd83
--- /dev/null
+++ b/Android_Java/Common/src/com/openglesbook/common/ESShader.java
@@ -0,0 +1,235 @@
+//
+// Book: OpenGL(R) ES 3.0 Programming Guide
+// Authors: Dan Ginsburg, Dave Shreiner, Aaftab Munshi
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESShader
+//
+// Utility functions for loading GLSL ES 3.0 shaders and creating program objects.
+//
+
+package com.openglesbook.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.content.Context;
+import android.opengl.GLES30;
+import android.util.Log;
+
+public class ESShader {
+ //
+ ///
+ /// \brief Read a shader source into a String
+ /// \param context Application context
+ /// \param fileName Name of shader file
+ /// \return A String object containing shader source, otherwise null
+ //
+ private static String readShader(Context context, String fileName) {
+ String shaderSource = null;
+
+ if (fileName == null)
+ return shaderSource;
+
+ // Read the shader file from assets
+ InputStream is = null;
+ byte [] buffer;
+
+ try {
+ is = context.getAssets().open(fileName);
+
+ // Create a buffer that has the same size as the InputStream
+ buffer = new byte[is.available()];
+
+ // Read the text file as a stream, into the buffer
+ is.read(buffer);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ // Write this buffer to the output stream
+ os.write (buffer);
+
+ // Close input and output streams
+ os.close();
+ is.close();
+
+ shaderSource = os.toString();
+ } catch (IOException ioe) {
+ is = null;
+ }
+
+ if (is == null)
+ return shaderSource;
+
+ return shaderSource;
+ }
+
+ //
+ ///
+ /// \brief Load a shader, check for compile errors, print error messages to
+ /// output log
+ /// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+ /// \param shaderSrc Shader source string
+ /// \return A new shader object on success, 0 on failure
+ //
+ public static int loadShader(int type, String shaderSrc) {
+ int shader;
+ int[] compiled = new int[1];
+
+ // Create the shader object
+ shader = GLES30.glCreateShader(type);
+
+ if (shader == 0)
+ return 0;
+
+ // Load the shader source
+ GLES30.glShaderSource(shader, shaderSrc);
+
+ // Compile the shader
+ GLES30.glCompileShader(shader);
+
+ // Check the compile status
+ GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compiled, 0);
+
+ if (compiled[0] == 0) {
+ Log.e("ESShader", GLES30.glGetShaderInfoLog(shader));
+ GLES30.glDeleteShader(shader);
+ return 0;
+ }
+ return shader;
+ }
+
+ //
+ ///
+ /// \brief Load a vertex and fragment shader, create a program object, link
+ /// program.
+ /// Errors output to log.
+ /// \param vertShaderSrc Vertex shader source code
+ /// \param fragShaderSrc Fragment shader source code
+ /// \return A new program object linked with the vertex/fragment shader
+ /// pair, 0 on failure
+ //
+ public static int loadProgram(String vertShaderSrc, String fragShaderSrc) {
+ int vertexShader;
+ int fragmentShader;
+ int programObject;
+ int[] linked = new int[1];
+
+ // Load the vertex/fragment shaders
+ vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertShaderSrc);
+ if (vertexShader == 0)
+ return 0;
+
+ fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragShaderSrc);
+ if (fragmentShader == 0) {
+ GLES30.glDeleteShader(vertexShader);
+ return 0;
+ }
+
+ // Create the program object
+ programObject = GLES30.glCreateProgram();
+
+ if (programObject == 0)
+ return 0;
+
+ GLES30.glAttachShader(programObject, vertexShader);
+ GLES30.glAttachShader(programObject, fragmentShader);
+
+ // Link the program
+ GLES30.glLinkProgram(programObject);
+
+ // Check the link status
+ GLES30.glGetProgramiv(programObject, GLES30.GL_LINK_STATUS, linked, 0);
+
+ if (linked[0] == 0) {
+ Log.e("ESShader", "Error linking program:");
+ Log.e("ESShader", GLES30.glGetProgramInfoLog(programObject));
+ GLES30.glDeleteProgram(programObject);
+ return 0;
+ }
+
+ // Free up no longer needed shader resources
+ GLES30.glDeleteShader(vertexShader);
+ GLES30.glDeleteShader(fragmentShader);
+
+ return programObject;
+ }
+
+ //
+ ///
+ /// \brief Load a vertex and fragment shader from "assets", create a program object, link
+ /// program.
+ /// Errors output to log.
+ /// \param vertShaderFileName Vertex shader source file name
+ /// \param fragShaderFileName Fragment shader source file name
+ /// \return A new program object linked with the vertex/fragment shader
+ /// pair, 0 on failure
+ //
+ public static int loadProgramFromAsset(Context context, String vertexShaderFileName, String fragShaderFileName) {
+ int vertexShader;
+ int fragmentShader;
+ int programObject;
+ int[] linked = new int[1];
+
+ String vertShaderSrc = null;
+ String fragShaderSrc = null;
+
+ // Read vertex shader from assets
+ vertShaderSrc = readShader(context, vertexShaderFileName);
+
+ if (vertShaderSrc == null)
+ return 0;
+
+ // Read fragment shader from assets
+ fragShaderSrc = readShader(context, fragShaderFileName);
+
+ if (fragShaderSrc == null)
+ return 0;
+
+ // Load the vertex shader
+ vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertShaderSrc);
+ if (vertexShader == 0)
+ return 0;
+
+ // Load the fragment shader
+ fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragShaderSrc);
+ if (fragmentShader == 0) {
+ GLES30.glDeleteShader(vertexShader);
+ return 0;
+ }
+
+ // Create the program object
+ programObject = GLES30.glCreateProgram();
+
+ if (programObject == 0)
+ return 0;
+
+ GLES30.glAttachShader(programObject, vertexShader);
+ GLES30.glAttachShader(programObject, fragmentShader);
+
+ // Link the program
+ GLES30.glLinkProgram(programObject);
+
+ // Check the link status
+ GLES30.glGetProgramiv(programObject, GLES30.GL_LINK_STATUS, linked, 0);
+
+ if (linked[0] == 0) {
+ Log.e("ESShader", "Error linking program:");
+ Log.e("ESShader", GLES30.glGetProgramInfoLog(programObject));
+ GLES30.glDeleteProgram(programObject);
+ return 0;
+ }
+
+ // Free up no longer needed shader resources
+ GLES30.glDeleteShader(vertexShader);
+ GLES30.glDeleteShader(fragmentShader);
+
+ return programObject;
+ }
+}
diff --git a/Android_Java/Common/src/com/openglesbook/common/ESShapes.java b/Android_Java/Common/src/com/openglesbook/common/ESShapes.java
new file mode 100644
index 0000000..724b573
--- /dev/null
+++ b/Android_Java/Common/src/com/openglesbook/common/ESShapes.java
@@ -0,0 +1,175 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESShapes
+//
+// Utility cass for generating shapes
+//
+
+package com.openglesbook.common;
+
+import java.lang.Math;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+public class ESShapes {
+
+ public int genSphere(int numSlices, float radius) {
+ int i;
+ int j;
+ int numParallels = numSlices;
+ int numVertices = (numParallels + 1) * (numSlices + 1);
+ int numIndices = numParallels * numSlices * 6;
+ float angleStep = ((2.0f * (float) Math.PI) / numSlices);
+
+ // Allocate memory for buffers
+ mVertices = ByteBuffer.allocateDirect(numVertices * 3 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mNormals = ByteBuffer.allocateDirect(numVertices * 3 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTexCoords = ByteBuffer.allocateDirect(numVertices * 2 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mIndices = ByteBuffer.allocateDirect(numIndices * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+
+ for (i = 0; i < numParallels + 1; i++) {
+ for (j = 0; j < numSlices + 1; j++) {
+ int vertex = (i * (numSlices + 1) + j) * 3;
+
+ mVertices
+ .put(vertex + 0,
+ (float) (radius
+ * Math.sin(angleStep * (float) i) * Math
+ .sin(angleStep * (float) j)));
+
+ mVertices.put(vertex + 1,
+ (float) (radius * Math.cos(angleStep * (float) i)));
+ mVertices
+ .put(vertex + 2,
+ (float) (radius
+ * Math.sin(angleStep * (float) i) * Math
+ .cos(angleStep * (float) j)));
+
+ mNormals.put(vertex + 0, mVertices.get(vertex + 0) / radius);
+ mNormals.put(vertex + 1, mVertices.get(vertex + 1) / radius);
+ mNormals.put(vertex + 2, mVertices.get(vertex + 2) / radius);
+
+ int texIndex = (i * (numSlices + 1) + j) * 2;
+ mTexCoords.put(texIndex + 0, (float) j / (float) numSlices);
+ mTexCoords.put(texIndex + 1, (1.0f - (float) i)
+ / (float) (numParallels - 1));
+ }
+ }
+
+ int index = 0;
+ for (i = 0; i < numParallels; i++) {
+ for (j = 0; j < numSlices; j++) {
+ mIndices.put(index++, (short) (i * (numSlices + 1) + j));
+ mIndices.put(index++, (short) ((i + 1) * (numSlices + 1) + j));
+ mIndices.put(index++,
+ (short) ((i + 1) * (numSlices + 1) + (j + 1)));
+
+ mIndices.put(index++, (short) (i * (numSlices + 1) + j));
+ mIndices.put(index++,
+ (short) ((i + 1) * (numSlices + 1) + (j + 1)));
+ mIndices.put(index++, (short) (i * (numSlices + 1) + (j + 1)));
+
+ }
+ }
+ mNumIndices = numIndices;
+
+ return numIndices;
+ }
+
+ public int genCube(float scale) {
+ int i;
+ int numVertices = 24;
+ int numIndices = 36;
+
+ float[] cubeVerts = { -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f,
+ 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f,
+ -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
+ 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, };
+
+ float[] cubeNormals = { 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, };
+
+ float[] cubeTex = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, };
+
+ // Allocate memory for buffers
+ mVertices = ByteBuffer.allocateDirect(numVertices * 3 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mNormals = ByteBuffer.allocateDirect(numVertices * 3 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTexCoords = ByteBuffer.allocateDirect(numVertices * 2 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mIndices = ByteBuffer.allocateDirect(numIndices * 2)
+ .order(ByteOrder.nativeOrder()).asShortBuffer();
+
+ mVertices.put(cubeVerts).position(0);
+ for (i = 0; i < numVertices * 3; i++) {
+ mVertices.put(i, mVertices.get(i) * scale);
+ }
+
+ mNormals.put(cubeNormals).position(0);
+ mTexCoords.put(cubeTex).position(0);
+
+ short[] cubeIndices = { 0, 2, 1, 0, 3, 2, 4, 5, 6, 4, 6, 7, 8, 9, 10,
+ 8, 10, 11, 12, 15, 14, 12, 14, 13, 16, 17, 18, 16, 18, 19, 20,
+ 23, 22, 20, 22, 21 };
+
+ mIndices.put(cubeIndices).position(0);
+ mNumIndices = numIndices;
+ return numIndices;
+ }
+
+ public FloatBuffer getVertices() {
+ return mVertices;
+ }
+
+ public FloatBuffer getNormals() {
+ return mNormals;
+ }
+
+ public FloatBuffer getTexCoords() {
+ return mTexCoords;
+ }
+
+ public ShortBuffer getIndices() {
+ return mIndices;
+ }
+
+ public int getNumIndices() {
+ return mNumIndices;
+ }
+
+ // Member variables
+ private FloatBuffer mVertices;
+ private FloatBuffer mNormals;
+ private FloatBuffer mTexCoords;
+ private ShortBuffer mIndices;
+ private int mNumIndices;
+}
diff --git a/Android_Java/Common/src/com/openglesbook/common/ESTransform.java b/Android_Java/Common/src/com/openglesbook/common/ESTransform.java
new file mode 100644
index 0000000..212f1e0
--- /dev/null
+++ b/Android_Java/Common/src/com/openglesbook/common/ESTransform.java
@@ -0,0 +1,214 @@
+package com.openglesbook.common;
+
+import java.lang.Math;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+public class ESTransform {
+ public ESTransform() {
+ mMatrixFloatBuffer = ByteBuffer.allocateDirect(16 * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ }
+
+ public void scale(float sx, float sy, float sz) {
+ mMatrix[0 * 4 + 0] *= sx;
+ mMatrix[0 * 4 + 1] *= sx;
+ mMatrix[0 * 4 + 2] *= sx;
+ mMatrix[0 * 4 + 3] *= sx;
+
+ mMatrix[1 * 4 + 0] *= sy;
+ mMatrix[1 * 4 + 1] *= sy;
+ mMatrix[1 * 4 + 2] *= sy;
+ mMatrix[1 * 4 + 3] *= sy;
+
+ mMatrix[2 * 4 + 0] *= sz;
+ mMatrix[2 * 4 + 1] *= sz;
+ mMatrix[2 * 4 + 2] *= sz;
+ mMatrix[2 * 4 + 3] *= sz;
+ }
+
+ public void translate(float tx, float ty, float tz) {
+ mMatrix[3 * 4 + 0] += (mMatrix[0 * 4 + 0] * tx + mMatrix[1 * 4 + 0]
+ * ty + mMatrix[2 * 4 + 0] * tz);
+ mMatrix[3 * 4 + 1] += (mMatrix[0 * 4 + 1] * tx + mMatrix[1 * 4 + 1]
+ * ty + mMatrix[2 * 4 + 1] * tz);
+ mMatrix[3 * 4 + 2] += (mMatrix[0 * 4 + 2] * tx + mMatrix[1 * 4 + 2]
+ * ty + mMatrix[2 * 4 + 2] * tz);
+ mMatrix[3 * 4 + 3] += (mMatrix[0 * 4 + 3] * tx + mMatrix[1 * 4 + 3]
+ * ty + mMatrix[2 * 4 + 3] * tz);
+ }
+
+ public void rotate(float angle, float x, float y, float z) {
+ float sinAngle, cosAngle;
+ float mag = (float) Math.sqrt((double) (x * x + y * y + z * z));
+
+ sinAngle = (float) Math.sin((double) (angle * Math.PI / 180.0));
+ cosAngle = (float) Math.cos((double) (angle * Math.PI / 180.0));
+ if (mag > 0.0f) {
+ float xx, yy, zz, xy, yz, zx, xs, ys, zs;
+ float oneMinusCos;
+ float[] rotMat = new float[16];
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * sinAngle;
+ ys = y * sinAngle;
+ zs = z * sinAngle;
+ oneMinusCos = 1.0f - cosAngle;
+
+ rotMat[0 * 4 + 0] = (oneMinusCos * xx) + cosAngle;
+ rotMat[0 * 4 + 1] = (oneMinusCos * xy) - zs;
+ rotMat[0 * 4 + 2] = (oneMinusCos * zx) + ys;
+ rotMat[0 * 4 + 3] = 0.0F;
+
+ rotMat[1 * 4 + 0] = (oneMinusCos * xy) + zs;
+ rotMat[1 * 4 + 1] = (oneMinusCos * yy) + cosAngle;
+ rotMat[1 * 4 + 2] = (oneMinusCos * yz) - xs;
+ rotMat[1 * 4 + 3] = 0.0F;
+
+ rotMat[2 * 4 + 0] = (oneMinusCos * zx) - ys;
+ rotMat[2 * 4 + 1] = (oneMinusCos * yz) + xs;
+ rotMat[2 * 4 + 2] = (oneMinusCos * zz) + cosAngle;
+ rotMat[2 * 4 + 3] = 0.0F;
+
+ rotMat[3 * 4 + 0] = 0.0F;
+ rotMat[3 * 4 + 1] = 0.0F;
+ rotMat[3 * 4 + 2] = 0.0F;
+ rotMat[3 * 4 + 3] = 1.0F;
+
+ matrixMultiply(rotMat, mMatrix);
+ }
+ }
+
+ public void frustum(float left, float right, float bottom, float top,
+ float nearZ, float farZ) {
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ float[] frust = new float[16];
+
+ if ((nearZ <= 0.0f) || (farZ <= 0.0f) || (deltaX <= 0.0f)
+ || (deltaY <= 0.0f) || (deltaZ <= 0.0f))
+ return;
+
+ frust[0 * 4 + 0] = 2.0f * nearZ / deltaX;
+ frust[0 * 4 + 1] = frust[0 * 4 + 2] = frust[0 * 4 + 3] = 0.0f;
+
+ frust[1 * 4 + 1] = 2.0f * nearZ / deltaY;
+ frust[1 * 4 + 0] = frust[1 * 4 + 2] = frust[1 * 4 + 3] = 0.0f;
+
+ frust[2 * 4 + 0] = (right + left) / deltaX;
+ frust[2 * 4 + 1] = (top + bottom) / deltaY;
+ frust[2 * 4 + 2] = -(nearZ + farZ) / deltaZ;
+ frust[2 * 4 + 3] = -1.0f;
+
+ frust[3 * 4 + 2] = -2.0f * nearZ * farZ / deltaZ;
+ frust[3 * 4 + 0] = frust[3 * 4 + 1] = frust[3 * 4 + 3] = 0.0f;
+
+ matrixMultiply(frust, mMatrix);
+ }
+
+ public void perspective(float fovy, float aspect, float nearZ, float farZ) {
+ float frustumW, frustumH;
+
+ frustumH = (float) Math.tan(fovy / 360.0 * Math.PI) * nearZ;
+ frustumW = frustumH * aspect;
+
+ frustum(-frustumW, frustumW, -frustumH, frustumH, nearZ, farZ);
+ }
+
+ public void ortho(float left, float right, float bottom, float top,
+ float nearZ, float farZ) {
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ float[] orthoMat = makeIdentityMatrix();
+
+ if ((deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f))
+ return;
+
+ orthoMat[0 * 4 + 0] = 2.0f / deltaX;
+ orthoMat[3 * 4 + 0] = -(right + left) / deltaX;
+ orthoMat[1 * 4 + 1] = 2.0f / deltaY;
+ orthoMat[3 * 4 + 1] = -(top + bottom) / deltaY;
+ orthoMat[2 * 4 + 2] = -2.0f / deltaZ;
+ orthoMat[3 * 4 + 2] = -(nearZ + farZ) / deltaZ;
+
+ matrixMultiply(orthoMat, mMatrix);
+ }
+
+ public void matrixMultiply(float[] srcA, float[] srcB) {
+ float[] tmp = new float[16];
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i * 4 + 0] = (srcA[i * 4 + 0] * srcB[0 * 4 + 0])
+ + (srcA[i * 4 + 1] * srcB[1 * 4 + 0])
+ + (srcA[i * 4 + 2] * srcB[2 * 4 + 0])
+ + (srcA[i * 4 + 3] * srcB[3 * 4 + 0]);
+
+ tmp[i * 4 + 1] = (srcA[i * 4 + 0] * srcB[0 * 4 + 1])
+ + (srcA[i * 4 + 1] * srcB[1 * 4 + 1])
+ + (srcA[i * 4 + 2] * srcB[2 * 4 + 1])
+ + (srcA[i * 4 + 3] * srcB[3 * 4 + 1]);
+
+ tmp[i * 4 + 2] = (srcA[i * 4 + 0] * srcB[0 * 4 + 2])
+ + (srcA[i * 4 + 1] * srcB[1 * 4 + 2])
+ + (srcA[i * 4 + 2] * srcB[2 * 4 + 2])
+ + (srcA[i * 4 + 3] * srcB[3 * 4 + 2]);
+
+ tmp[i * 4 + 3] = (srcA[i * 4 + 0] * srcB[0 * 4 + 3])
+ + (srcA[i * 4 + 1] * srcB[1 * 4 + 3])
+ + (srcA[i * 4 + 2] * srcB[2 * 4 + 3])
+ + (srcA[i * 4 + 3] * srcB[3 * 4 + 3]);
+ }
+
+ mMatrix = tmp;
+ }
+
+ public void matrixLoadIdentity() {
+ for (int i = 0; i < 16; i++)
+ mMatrix[i] = 0.0f;
+
+ mMatrix[0 * 4 + 0] = 1.0f;
+ mMatrix[1 * 4 + 1] = 1.0f;
+ mMatrix[2 * 4 + 2] = 1.0f;
+ mMatrix[3 * 4 + 3] = 1.0f;
+ }
+
+ private float[] makeIdentityMatrix() {
+ float[] result = new float[16];
+
+ for (int i = 0; i < 16; i++)
+ result[i] = 0.0f;
+
+ result[0 * 4 + 0] = 1.0f;
+ result[1 * 4 + 1] = 1.0f;
+ result[2 * 4 + 2] = 1.0f;
+ result[3 * 4 + 3] = 1.0f;
+
+ return result;
+ }
+
+ public FloatBuffer getAsFloatBuffer() {
+ mMatrixFloatBuffer.put(mMatrix).position(0);
+ return mMatrixFloatBuffer;
+ }
+
+ public float[] get() {
+ return mMatrix;
+ }
+
+ private float[] mMatrix = new float[16];
+ private FloatBuffer mMatrixFloatBuffer;
+
+}
\ No newline at end of file