summaryrefslogtreecommitdiffstats
path: root/native_client_sdk/src
diff options
context:
space:
mode:
authorbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-04 17:19:34 +0000
committerbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-04 17:19:34 +0000
commit8d114757f5aa1a38a83a3da15203535a312be123 (patch)
treedfc36ef339bd633c348b99c4b1a124c4f16b6b39 /native_client_sdk/src
parent1730e8e02bc85a445a394c676e7a2c4377eac16b (diff)
downloadchromium_src-8d114757f5aa1a38a83a3da15203535a312be123.zip
chromium_src-8d114757f5aa1a38a83a3da15203535a312be123.tar.gz
chromium_src-8d114757f5aa1a38a83a3da15203535a312be123.tar.bz2
[NaCl SDK] Simplify graphics3d example.
* Rewrote in ppapi_cpp * Remove URL loading (data is static in the .nexe) * Cube data is no longer generated * Added sliders for cube rotation (useful for testing) BUG=none R=noelallen@chromium.org Review URL: https://codereview.chromium.org/23838002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk/src')
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/example.dsc15
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/example.js41
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag8
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc984
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/index.html27
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/texture.cc64
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert12
7 files changed, 572 insertions, 579 deletions
diff --git a/native_client_sdk/src/examples/api/graphics_3d/example.dsc b/native_client_sdk/src/examples/api/graphics_3d/example.dsc
index c7535b4..6d637e3 100644
--- a/native_client_sdk/src/examples/api/graphics_3d/example.dsc
+++ b/native_client_sdk/src/examples/api/graphics_3d/example.dsc
@@ -4,18 +4,17 @@
{
'NAME' : 'graphics_3d',
'TYPE' : 'main',
- 'SOURCES' : ['graphics_3d.cc', 'matrix.cc', 'matrix.h'],
- 'CXXFLAGS': [
- '-I../../src',
- '-I../../src/ppapi/lib/gl'
+ 'SOURCES' : [
+ 'graphics_3d.cc',
+ 'matrix.cc',
+ 'matrix.h',
+ 'texture.cc',
],
- 'LIBS': ['ppapi_gles2', 'ppapi', 'pthread']
+ 'LIBS': ['ppapi_gles2', 'ppapi_cpp', 'ppapi', 'pthread']
}
],
'DATA': [
- 'fragment_shader_es2.frag',
- 'hello.raw',
- 'vertex_shader_es2.vert'
+ 'example.js'
],
'DEST': 'examples/api',
'NAME': 'graphics_3d',
diff --git a/native_client_sdk/src/examples/api/graphics_3d/example.js b/native_client_sdk/src/examples/api/graphics_3d/example.js
new file mode 100644
index 0000000..edd8e16
--- /dev/null
+++ b/native_client_sdk/src/examples/api/graphics_3d/example.js
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function $(id) {
+ return document.getElementById(id);
+}
+
+function postAngleMessage() {
+ var xAngle = parseFloat($('xAngle').value);
+ var yAngle = parseFloat($('yAngle').value);
+ common.naclModule.postMessage([xAngle, yAngle]);
+}
+
+// Add event listeners after the NaCl module has loaded. These listeners will
+// forward messages to the NaCl module via postMessage()
+function attachListeners() {
+ $('xAngle').addEventListener('change', postAngleMessage);
+ $('yAngle').addEventListener('change', postAngleMessage);
+ $('animateOff').addEventListener('click', function() {
+ $('animateOn').checked = '';
+ common.naclModule.postMessage(false);
+ });
+ $('animateOn').addEventListener('click', function() {
+ $('animateOff').checked = '';
+ common.naclModule.postMessage(true);
+ });
+}
+
+// Handle a message coming from the NaCl module.
+function handleMessage(event) {
+ if (!(event.data instanceof Array))
+ return;
+ if (event.data.length != 2)
+ return;
+
+ var xAngle = event.data[0];
+ var yAngle = event.data[1];
+ $('xAngle').value = xAngle;
+ $('yAngle').value = yAngle;
+}
diff --git a/native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag b/native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag
deleted file mode 100644
index 247c559..0000000
--- a/native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag
+++ /dev/null
@@ -1,8 +0,0 @@
-precision mediump float;
-varying vec3 v_color;
-varying vec2 v_texCoord;
-uniform sampler2D s_texture;
-void main()
-{
- gl_FragColor = texture2D( s_texture, vec2(v_texCoord.x,1.0 - v_texCoord.y) ) + vec4(v_color.x,v_color.y,v_color.z,1);
-} \ No newline at end of file
diff --git a/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc b/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc
index 4c85266..3ac8410 100644
--- a/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc
+++ b/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc
@@ -1,616 +1,502 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-//-----------------------------------------------------------------------------
-// The spinning Cube
-//-----------------------------------------------------------------------------
-
-#define _USE_MATH_DEFINES 1
-#include <limits.h>
+#include <GLES2/gl2.h>
#include <math.h>
-#include <stdarg.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include "ppapi/c/pp_completion_callback.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/pp_graphics_3d.h"
-#include "ppapi/c/pp_module.h"
-#include "ppapi/c/pp_stdint.h"
-#include "ppapi/c/pp_var.h"
-#include "ppapi/c/ppb.h"
-#include "ppapi/c/ppb_core.h"
-#include "ppapi/c/ppb_graphics_3d.h"
-#include "ppapi/c/ppb_instance.h"
-#include "ppapi/c/ppb_messaging.h"
-#include "ppapi/c/ppb_opengles2.h"
-#include "ppapi/c/ppb_url_loader.h"
-#include "ppapi/c/ppb_url_request_info.h"
-#include "ppapi/c/ppb_var.h"
-#include "ppapi/c/ppp.h"
-#include "ppapi/c/ppp_instance.h"
-#include "ppapi/c/ppp_messaging.h"
-
-#include "ppapi/c/ppp_graphics_3d.h"
-#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
-
-#include <GLES2/gl2.h>
#include "matrix.h"
+#include "ppapi/cpp/graphics_3d.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/cpp/var_array.h"
+#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
+#include "ppapi/utility/completion_callback_factory.h"
-static PPB_Messaging* ppb_messaging_interface = NULL;
-static PPB_Var* ppb_var_interface = NULL;
-static PPB_Core* ppb_core_interface = NULL;
-static PPB_Graphics3D* ppb_g3d_interface = NULL;
-static PPB_Instance* ppb_instance_interface = NULL;
-static PPB_URLRequestInfo* ppb_urlrequestinfo_interface = NULL;
-static PPB_URLLoader* ppb_urlloader_interface = NULL;
-
-static PP_Instance g_instance;
-static PP_Resource g_context;
-
-GLuint g_positionLoc;
-GLuint g_texCoordLoc;
-GLuint g_colorLoc;
-GLuint g_MVPLoc;
-GLuint g_vboID;
-GLuint g_ibID;
-GLubyte g_Indices[36];
-
-GLuint g_programObj;
-GLuint g_vertexShader;
-GLuint g_fragmentShader;
-
-GLuint g_textureLoc = 0;
-GLuint g_textureID = 0;
-
-float g_fSpinX = 0.0f;
-float g_fSpinY = 0.0f;
-
-//-----------------------------------------------------------------------------
-// Rendering Assets
-//-----------------------------------------------------------------------------
-struct Vertex {
- float tu, tv;
- float color[3];
- float loc[3];
-};
-
-Vertex* g_quadVertices = NULL;
-const char* g_TextureData = NULL;
-const char* g_VShaderData = NULL;
-const char* g_FShaderData = NULL;
-int g_LoadCnt = 0;
-
-//-----------------------------------------------------------------------------
-// PROTOTYPES
-//-----------------------------------------------------------------------------
-void PostMessage(const char* fmt, ...);
-char* LoadFile(const char* fileName);
-
-void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]);
-Vertex* BuildCube(void);
-
-void InitGL(void);
-void InitProgram(void);
-void Render(void);
+#ifdef WIN32
+#undef PostMessage
+// Allow 'this' in initializer list
+#pragma warning(disable : 4355)
+#endif
-static struct PP_Var CStrToVar(const char* str) {
- if (ppb_var_interface != NULL) {
- return ppb_var_interface->VarFromUtf8(str, strlen(str));
- }
- return PP_MakeUndefined();
-}
+extern const uint8_t kRLETextureData[];
+extern const size_t kRLETextureDataLength;
-void PostMessage(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
+namespace {
- char msg[4096];
- vsnprintf(msg, sizeof(msg), fmt, args);
+const float kFovY = 45.0f;
+const float kZNear = 1.0f;
+const float kZFar = 10.0f;
+const float kCameraZ = -4.0f;
+const float kXAngleDelta = 2.0f;
+const float kYAngleDelta = 0.5f;
- if (ppb_messaging_interface)
- ppb_messaging_interface->PostMessage(g_instance, CStrToVar(msg));
+const size_t kTextureDataLength = 128 * 128 * 3; // 128x128, 3 Bytes/pixel.
- va_end(args);
-}
+// The decompressed data is written here.
+uint8_t g_texture_data[kTextureDataLength];
-void MainLoop(void* foo, int bar) {
- if (g_LoadCnt == 3) {
- InitProgram();
- g_LoadCnt++;
- }
- if (g_LoadCnt > 3) {
- Render();
- PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
- ppb_g3d_interface->SwapBuffers(g_context, cc);
- } else {
- PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
- ppb_core_interface->CallOnMainThread(0, cc, 0);
- }
-}
-
-void InitGL(void) {
- int32_t attribs[] = {
- PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
- PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
- PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
- PP_GRAPHICS3DATTRIB_SAMPLES, 0,
- PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
- PP_GRAPHICS3DATTRIB_WIDTH, 640,
- PP_GRAPHICS3DATTRIB_HEIGHT, 480,
- PP_GRAPHICS3DATTRIB_NONE
+void DecompressTexture() {
+ // The image is first encoded with a very simple RLE scheme:
+ // <value0> <count0> <value1> <count1> ...
+ // Because a <count> of 0 is useless, we use it to represent 256.
+ //
+ // It is then Base64 encoded to make it use only printable characters (it
+ // stores more easily in a source file that way).
+ //
+ // To decompress, we have to reverse the process.
+ static const uint8_t kBase64Decode[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
+ 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
};
+ const uint8_t* input = &kRLETextureData[0];
+ const uint8_t * const input_end = &kRLETextureData[kRLETextureDataLength];
+ uint8_t* output = &g_texture_data[0];
+ const uint8_t * const output_end = &g_texture_data[kTextureDataLength];
+
+ uint8_t decoded[4];
+ int decoded_count = 0;
+
+ while (input < input_end || decoded_count > 0) {
+ if (decoded_count < 2) {
+ assert(input + 4 <= input_end);
+ // Grab four base-64 encoded (6-bit) bytes.
+ uint32_t data = 0;
+ data |= (kBase64Decode[*input++] << 18);
+ data |= (kBase64Decode[*input++] << 12);
+ data |= (kBase64Decode[*input++] << 6);
+ data |= (kBase64Decode[*input++] );
+ // And decode it to 3 (8-bit) bytes.
+ decoded[decoded_count++] = (data >> 16) & 0xff;
+ decoded[decoded_count++] = (data >> 8) & 0xff;
+ decoded[decoded_count++] = (data ) & 0xff;
+
+ // = is the base64 end marker. Remove decoded bytes if we see any.
+ if (input[-1] == '=') decoded_count--;
+ if (input[-2] == '=') decoded_count--;
+ }
- g_context = ppb_g3d_interface->Create(g_instance, 0, attribs);
- int32_t success = ppb_instance_interface->BindGraphics(g_instance, g_context);
- if (success == PP_FALSE) {
- glSetCurrentContextPPAPI(0);
- printf("Failed to set context.\n");
- return;
+ int value = decoded[0];
+ int count = decoded[1];
+ decoded_count -= 2;
+ // Move the other decoded bytes (if any) down.
+ decoded[0] = decoded[2];
+ decoded[1] = decoded[3];
+
+ // Expand the RLE data.
+ if (count == 0)
+ count = 256;
+ assert(output <= output_end);
+ memset(output, value, count);
+ output += count;
}
- glSetCurrentContextPPAPI(g_context);
-
- glViewport(0, 0, 640, 480);
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ assert(output == output_end);
}
-GLuint compileShader(GLenum type, const char* data) {
- const char* shaderStrings[1];
- shaderStrings[0] = data;
-
+GLuint CompileShader(GLenum type, const char* data) {
GLuint shader = glCreateShader(type);
- glShaderSource(shader, 1, shaderStrings, NULL);
+ glShaderSource(shader, 1, &data, NULL);
glCompileShader(shader);
+
+ GLint compile_status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
+ if (compile_status != GL_TRUE) {
+ // Shader failed to compile, let's see what the error is.
+ char buffer[1024];
+ GLsizei length;
+ glGetShaderInfoLog(shader, sizeof(buffer), &length, &buffer[0]);
+ fprintf(stderr, "Shader failed to compile: %s\n", buffer);
+ return 0;
+ }
+
return shader;
}
-void InitProgram(void) {
- glSetCurrentContextPPAPI(g_context);
-
- g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData);
- g_fragmentShader = compileShader(GL_FRAGMENT_SHADER, g_FShaderData);
+GLuint LinkProgram(GLuint frag_shader, GLuint vert_shader) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, frag_shader);
+ glAttachShader(program, vert_shader);
+ glLinkProgram(program);
+
+ GLint link_status;
+ glGetProgramiv(program, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ // Program failed to link, let's see what the error is.
+ char buffer[1024];
+ GLsizei length;
+ glGetProgramInfoLog(program, sizeof(buffer), &length, &buffer[0]);
+ fprintf(stderr, "Program failed to link: %s\n", buffer);
+ return 0;
+ }
- g_programObj = glCreateProgram();
- glAttachShader(g_programObj, g_vertexShader);
- glAttachShader(g_programObj, g_fragmentShader);
- glLinkProgram(g_programObj);
+ return program;
+}
- glGenBuffers(1, &g_vboID);
- glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
- glBufferData(GL_ARRAY_BUFFER,
- 24 * sizeof(Vertex),
- (void*)&g_quadVertices[0],
- GL_STATIC_DRAW);
+const char kFragShaderSource[] =
+ "precision mediump float;\n"
+ "varying vec3 v_color;\n"
+ "varying vec2 v_texcoord;\n"
+ "uniform sampler2D u_texture;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(u_texture, v_texcoord);\n"
+ " gl_FragColor += vec4(v_color, 1);\n"
+ "}\n";
+
+const char kVertexShaderSource[] =
+ "uniform mat4 u_mvp;\n"
+ "attribute vec2 a_texcoord;\n"
+ "attribute vec3 a_color;\n"
+ "attribute vec4 a_position;\n"
+ "varying vec3 v_color;\n"
+ "varying vec2 v_texcoord;\n"
+ "void main() {\n"
+ " gl_Position = u_mvp * a_position;\n"
+ " v_color = a_color;\n"
+ " v_texcoord = a_texcoord;\n"
+ "}\n";
- glGenBuffers(1, &g_ibID);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
- 36 * sizeof(char),
- (void*)&g_Indices[0],
- GL_STATIC_DRAW);
+struct Vertex {
+ float loc[3];
+ float color[3];
+ float tex[2];
+};
- //
- // Create a texture to test out our fragment shader...
- //
- glGenTextures(1, &g_textureID);
- glBindTexture(GL_TEXTURE_2D, g_textureID);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGB,
- 128,
- 128,
- 0,
- GL_RGB,
- GL_UNSIGNED_BYTE,
- g_TextureData);
+const Vertex kCubeVerts[24] = {
+ // +Z (red arrow, black tip)
+ {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
+ {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {1.0, 1.0}},
+
+ // +X (green arrow, black tip)
+ {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
+ {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, +1.0, +1.0}, {0.0, 0.5, 0.0}, {0.0, 1.0}},
+ {{+1.0, -1.0, +1.0}, {0.0, 0.5, 0.0}, {1.0, 1.0}},
+
+ // +Y (blue arrow, black tip)
+ {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
+ {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, +1.0, +1.0}, {0.0, 0.0, 0.5}, {0.0, 1.0}},
+ {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.5}, {1.0, 1.0}},
+
+ // -Z (red arrow, red tip)
+ {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
+ {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0}},
+
+ // -X (green arrow, green tip)
+ {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
+ {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, -1.0, -1.0}, {0.0, 1.0, 0.0}, {0.0, 0.0}},
+ {{-1.0, +1.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0}},
+
+ // -Y (blue arrow, blue tip)
+ {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
+ {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, -1.0, -1.0}, {0.0, 0.0, 1.0}, {0.0, 0.0}},
+ {{-1.0, -1.0, +1.0}, {0.0, 0.0, 1.0}, {1.0, 0.0}},
+};
- //
- // Locate some parameters by name so we can set them later...
- //
- g_textureLoc = glGetUniformLocation(g_programObj, "arrowTexture");
- g_positionLoc = glGetAttribLocation(g_programObj, "a_position");
- g_texCoordLoc = glGetAttribLocation(g_programObj, "a_texCoord");
- g_colorLoc = glGetAttribLocation(g_programObj, "a_color");
- g_MVPLoc = glGetUniformLocation(g_programObj, "a_MVP");
-}
+const GLubyte kCubeIndexes[36] = {
+ 2, 1, 0, 3, 2, 0,
+ 6, 5, 4, 7, 6, 4,
+ 10, 9, 8, 11, 10, 8,
+ 14, 13, 12, 15, 14, 12,
+ 18, 17, 16, 19, 18, 16,
+ 22, 21, 20, 23, 22, 20,
+};
-void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
- static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f };
- static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f };
-
- for (int i = 0; i < 4; i++) {
- verts[i].tu = (1.0 - X[i]) / 2.0f;
- verts[i].tv = (Y[i] + 1.0f) / -2.0f * depth;
- verts[i].loc[axis[0]] = X[i] * depth;
- verts[i].loc[axis[1]] = Y[i] * depth;
- verts[i].loc[axis[2]] = depth;
- for (int j = 0; j < 3; j++)
- verts[i].color[j] = color[j] * (Y[i] + 1.0f) / 2.0f;
+} // namespace
+
+
+class Graphics3DInstance : public pp::Instance {
+ public:
+ explicit Graphics3DInstance(PP_Instance instance)
+ : pp::Instance(instance),
+ callback_factory_(this),
+ width_(0),
+ height_(0),
+ frag_shader_(0),
+ vertex_shader_(0),
+ program_(0),
+ texture_loc_(0),
+ position_loc_(0),
+ color_loc_(0),
+ mvp_loc_(0),
+ x_angle_(0),
+ y_angle_(0),
+ animating_(true) {}
+
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
+ return true;
}
-}
-Vertex* BuildCube() {
- Vertex* verts = new Vertex[24];
- for (int i = 0; i < 3; i++) {
- int Faxis[3];
- int Baxis[3];
- float Fcolor[3];
- float Bcolor[3];
- for (int j = 0; j < 3; j++) {
- Faxis[j] = (j + i) % 3;
- Baxis[j] = (j + i) % 3;
+ virtual void DidChangeView(const pp::View& view) {
+ int32_t new_width = view.GetRect().width();
+ int32_t new_height = view.GetRect().height();
+
+ if (context_.is_null()) {
+ if (!InitGL(new_width, new_height)) {
+ // failed.
+ return;
+ }
+
+ InitShaders();
+ InitBuffers();
+ InitTexture();
+ MainLoop(0);
+ } else {
+ // Resize the buffers to the new size of the module.
+ int32_t result = context_.ResizeBuffers(new_width, new_height);
+ if (result < 0) {
+ fprintf(stderr,
+ "Unable to resize buffers to %d x %d!\n",
+ new_width,
+ new_height);
+ return;
+ }
}
- memset(Fcolor, 0, sizeof(float) * 3);
- memset(Bcolor, 0, sizeof(float) * 3);
- Fcolor[i] = 0.5f;
- Bcolor[i] = 1.0f;
- BuildQuad(&verts[0 + i * 4], Faxis, 1.0f, Fcolor);
- BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor);
- }
- for (int i = 0; i < 6; i++) {
- g_Indices[i * 6 + 0] = 2 + i * 4;
- g_Indices[i * 6 + 1] = 1 + i * 4;
- g_Indices[i * 6 + 2] = 0 + i * 4;
- g_Indices[i * 6 + 3] = 3 + i * 4;
- g_Indices[i * 6 + 4] = 2 + i * 4;
- g_Indices[i * 6 + 5] = 0 + i * 4;
+ width_ = new_width;
+ height_ = new_height;
+ glViewport(0, 0, width_, height_);
}
- return verts;
-}
-
-void Render(void) {
- static float xRot = 0.0;
- static float yRot = 0.0;
-
- xRot += 2.0f;
- yRot += 0.5f;
- if (xRot >= 360.0f)
- xRot = 0.0;
- if (yRot >= 360.0f)
- yRot = 0.0;
-
- glClearColor(0.5, 0.5, 0.5, 1);
- glClearDepthf(1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
-
- //set what program to use
- glUseProgram(g_programObj);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, g_textureID);
- glUniform1i(g_textureLoc, 0);
-
- //create our perspective matrix
- float mpv[16];
- float trs[16];
- float rot[16];
-
- identity_matrix(mpv);
- glhPerspectivef2(&mpv[0], 45.0f, 640.0f / 480.0f, 1, 10);
-
- translate_matrix(0, 0, -4.0, trs);
- rotate_matrix(xRot, yRot, 0.0f, rot);
- multiply_matrix(trs, rot, trs);
- multiply_matrix(mpv, trs, mpv);
- glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*)mpv);
-
- //define the attributes of the vertex
- glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
- glVertexAttribPointer(g_positionLoc,
- 3,
- GL_FLOAT,
- GL_FALSE,
- sizeof(Vertex),
- (void*)offsetof(Vertex, loc));
- glEnableVertexAttribArray(g_positionLoc);
- glVertexAttribPointer(g_texCoordLoc,
- 2,
- GL_FLOAT,
- GL_FALSE,
- sizeof(Vertex),
- (void*)offsetof(Vertex, tu));
- glEnableVertexAttribArray(g_texCoordLoc);
- glVertexAttribPointer(g_colorLoc,
- 3,
- GL_FLOAT,
- GL_FALSE,
- sizeof(Vertex),
- (void*)offsetof(Vertex, color));
- glEnableVertexAttribArray(g_colorLoc);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
- glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
-}
-typedef void (*OpenCB)(void* dataPtr);
-struct OpenRequest {
- PP_Resource loader_;
- PP_Resource request_;
- char* buf_;
- void* data_;
- int64_t size_;
- int64_t avail_;
- OpenCB cb_;
-};
+ virtual void HandleMessage(const pp::Var& message) {
+ // A bool message sets whether the cube is animating or not.
+ if (message.is_bool()) {
+ animating_ = message.AsBool();
+ return;
+ }
-void FreeRequest(OpenRequest* req) {
- if (req) {
- ppb_core_interface->ReleaseResource(req->request_);
- ppb_core_interface->ReleaseResource(req->loader_);
- free(req);
- }
-}
+ // An array message sets the current x and y rotation.
+ if (!message.is_array()) {
+ fprintf(stderr, "Expected array message.\n");
+ return;
+ }
-static void URLPartialRead(void* user_data, int mode) {
- OpenRequest* req = (OpenRequest*)user_data;
- int64_t total;
- int32_t cnt;
+ pp::VarArray array(message);
+ if (array.GetLength() != 2) {
+ fprintf(stderr, "Expected array of length 2.\n");
+ return;
+ }
- if (mode < 0) {
- free(req->buf_);
- req->cb_(NULL);
- FreeRequest(req);
- return;
- }
+ pp::Var x_angle_var = array.Get(0);
+ if (x_angle_var.is_int()) {
+ x_angle_ = x_angle_var.AsInt();
+ } else if (x_angle_var.is_double()) {
+ x_angle_ = x_angle_var.AsDouble();
+ } else {
+ fprintf(stderr, "Expected value to be an int or double.\n");
+ }
- req->avail_ += mode;
- total = req->size_ - req->avail_;
-
- cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total;
- // If we still have more to do, re-issue the read.
- if (cnt > 0) {
- int32_t bytes = ppb_urlloader_interface->ReadResponseBody(
- req->loader_,
- (void*)&req->buf_[req->avail_],
- cnt,
- PP_MakeCompletionCallback(URLPartialRead, req));
-
- // If the reissue completes immediately, then process it.
- if (bytes != PP_OK_COMPLETIONPENDING) {
- URLPartialRead(user_data, bytes);
+ pp::Var y_angle_var = array.Get(1);
+ if (y_angle_var.is_int()) {
+ y_angle_ = y_angle_var.AsInt();
+ } else if (y_angle_var.is_double()) {
+ y_angle_ = y_angle_var.AsDouble();
+ } else {
+ fprintf(stderr, "Expected value to be an int or double.\n");
}
- return;
}
- // Nothing left, so signal complete.
- req->cb_(req);
- FreeRequest(req);
- printf("Loaded\n");
-}
+ private:
+ bool InitGL(int32_t new_width, int32_t new_height) {
+ if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) {
+ fprintf(stderr, "Unable to initialize GL PPAPI!\n");
+ return false;
+ }
-static void URLOpened(void* user_data, int mode) {
- OpenRequest* req = (OpenRequest*)user_data;
+ const int32_t attrib_list[] = {
+ PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
+ PP_GRAPHICS3DATTRIB_WIDTH, new_width,
+ PP_GRAPHICS3DATTRIB_HEIGHT, new_height,
+ PP_GRAPHICS3DATTRIB_NONE
+ };
- int64_t cur, total;
- int32_t cnt;
- ppb_urlloader_interface->GetDownloadProgress(req->loader_, &cur, &total);
+ context_ = pp::Graphics3D(this, attrib_list);
+ if (!BindGraphics(context_)) {
+ fprintf(stderr, "Unable to bind 3d context!\n");
+ context_ = pp::Graphics3D();
+ glSetCurrentContextPPAPI(0);
+ return false;
+ }
- // If we can't preallocate the buffer because the size is unknown, then
- // fail the load.
- if (total == -1) {
- req->cb_(NULL);
- FreeRequest(req);
- return;
+ glSetCurrentContextPPAPI(context_.pp_resource());
+ return true;
}
- // Otherwise allocate a buffer with enough space for a terminating
- // NULL in case we need one.
- cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total;
- req->buf_ = (char*)malloc(cnt + 1);
- req->buf_[cnt] = 0;
- req->size_ = cnt;
- int32_t bytes = ppb_urlloader_interface->ReadResponseBody(
- req->loader_,
- req->buf_,
- cnt,
- PP_MakeCompletionCallback(URLPartialRead, req));
-
- // Usually we are pending.
- if (bytes == PP_OK_COMPLETIONPENDING)
- return;
-
- // But if we did complete the read, then dispatch the handler.
- URLPartialRead(req, bytes);
-}
+ void InitShaders() {
+ frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, kFragShaderSource);
+ if (!frag_shader_)
+ return;
-void LoadURL(PP_Instance inst, const char* url, OpenCB cb, void* data) {
- OpenRequest* req = (OpenRequest*)malloc(sizeof(OpenRequest));
- memset(req, 0, sizeof(OpenRequest));
+ vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kVertexShaderSource);
+ if (!vertex_shader_)
+ return;
- req->loader_ = ppb_urlloader_interface->Create(inst);
- req->request_ = ppb_urlrequestinfo_interface->Create(inst);
- req->cb_ = cb;
- req->data_ = data;
+ program_ = LinkProgram(frag_shader_, vertex_shader_);
+ if (!program_)
+ return;
- if (!req->loader_ || !req->request_) {
- cb(NULL);
- FreeRequest(req);
- return;
+ texture_loc_ = glGetUniformLocation(program_, "u_texture");
+ position_loc_ = glGetAttribLocation(program_, "a_position");
+ texcoord_loc_ = glGetAttribLocation(program_, "a_texcoord");
+ color_loc_ = glGetAttribLocation(program_, "a_color");
+ mvp_loc_ = glGetUniformLocation(program_, "u_mvp");
}
- ppb_urlrequestinfo_interface->SetProperty(
- req->request_, PP_URLREQUESTPROPERTY_URL, CStrToVar(url));
- ppb_urlrequestinfo_interface->SetProperty(
- req->request_, PP_URLREQUESTPROPERTY_METHOD, CStrToVar("GET"));
- ppb_urlrequestinfo_interface->SetProperty(
- req->request_,
- PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS,
- PP_MakeBool(PP_TRUE));
-
- int val = ppb_urlloader_interface->Open(
- req->loader_, req->request_, PP_MakeCompletionCallback(URLOpened, req));
-
- if (val != PP_OK_COMPLETIONPENDING) {
- cb(NULL);
- free(req);
+ void InitBuffers() {
+ glGenBuffers(1, &vertex_buffer_);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(kCubeVerts), &kCubeVerts[0],
+ GL_STATIC_DRAW);
+
+ glGenBuffers(1, &index_buffer_);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kCubeIndexes),
+ &kCubeIndexes[0], GL_STATIC_DRAW);
}
-}
-void Loaded(void* data) {
- OpenRequest* req = (OpenRequest*)data;
- if (req && req->buf_) {
- char** pptr = (char**)req->data_;
- *pptr = req->buf_;
- g_LoadCnt++;
- return;
+ void InitTexture() {
+ DecompressTexture();
+ glGenTextures(1, &texture_);
+ glBindTexture(GL_TEXTURE_2D, texture_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ 128,
+ 128,
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ &g_texture_data[0]);
}
- PostMessage("Failed to load asset.\n");
-}
-/**
- * Called when the NaCl module is instantiated on the web page. The identifier
- * of the new instance will be passed in as the first argument (this value is
- * generated by the browser and is an opaque handle). This is called for each
- * instantiation of the NaCl module, which is each time the <embed> tag for
- * this module is encountered.
- *
- * If this function reports a failure (by returning @a PP_FALSE), the NaCl
- * module will be deleted and DidDestroy will be called.
- * @param[in] instance The identifier of the new instance representing this
- * NaCl module.
- * @param[in] argc The number of arguments contained in @a argn and @a argv.
- * @param[in] argn An array of argument names. These argument names are
- * supplied in the <embed> tag, for example:
- * <embed id="nacl_module" dimensions="2">
- * will produce two arguments, one named "id" and one named "dimensions".
- * @param[in] argv An array of argument values. These are the values of the
- * arguments listed in the <embed> tag. In the above example, there will
- * be two elements in this array, "nacl_module" and "2". The indices of
- * these values match the indices of the corresponding names in @a argn.
- * @return @a PP_TRUE on success.
- */
-static PP_Bool Instance_DidCreate(PP_Instance instance,
- uint32_t argc,
- const char* argn[],
- const char* argv[]) {
- g_instance = instance;
- LoadURL(instance, "hello.raw", Loaded, &g_TextureData);
- LoadURL(instance, "vertex_shader_es2.vert", Loaded, &g_VShaderData);
- LoadURL(instance, "fragment_shader_es2.frag", Loaded, &g_FShaderData);
- g_quadVertices = BuildCube();
- return PP_TRUE;
-}
+ void Animate() {
+ if (animating_) {
+ x_angle_ = fmod(360.0f + x_angle_ + kXAngleDelta, 360.0f);
+ y_angle_ = fmod(360.0f + y_angle_ + kYAngleDelta, 360.0f);
+
+ // Send new values to JavaScript.
+ pp::VarArray array;
+ array.SetLength(2);
+ array.Set(0, x_angle_);
+ array.Set(1, y_angle_);
+ PostMessage(array);
+ }
+ }
-/**
- * Called when the NaCl module is destroyed. This will always be called,
- * even if DidCreate returned failure. This routine should deallocate any data
- * associated with the instance.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- */
-static void Instance_DidDestroy(PP_Instance instance) {
- delete[] g_TextureData;
- delete[] g_VShaderData;
- delete[] g_FShaderData;
- delete[] g_quadVertices;
-}
+ void Render() {
+ glClearColor(0.5, 0.5, 0.5, 1);
+ glClearDepthf(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+
+ //set what program to use
+ glUseProgram(program_);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture_);
+ glUniform1i(texture_loc_, 0);
+
+ //create our perspective matrix
+ float mvp[16];
+ float trs[16];
+ float rot[16];
+
+ identity_matrix(mvp);
+ const float aspect_ratio = static_cast<float>(width_) / height_;
+ glhPerspectivef2(&mvp[0], kFovY, aspect_ratio, kZNear, kZFar);
+
+ translate_matrix(0, 0, kCameraZ, trs);
+ rotate_matrix(x_angle_, y_angle_, 0.0f, rot);
+ multiply_matrix(trs, rot, trs);
+ multiply_matrix(mvp, trs, mvp);
+ glUniformMatrix4fv(mvp_loc_, 1, GL_FALSE, mvp);
+
+ //define the attributes of the vertex
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+ glVertexAttribPointer(position_loc_,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ reinterpret_cast<void*>(offsetof(Vertex, loc)));
+ glEnableVertexAttribArray(position_loc_);
+ glVertexAttribPointer(color_loc_,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ reinterpret_cast<void*>(offsetof(Vertex, color)));
+ glEnableVertexAttribArray(color_loc_);
+ glVertexAttribPointer(texcoord_loc_,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ reinterpret_cast<void*>(offsetof(Vertex, tex)));
+ glEnableVertexAttribArray(texcoord_loc_);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
+ glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
+ }
-/**
- * Called when the position, the size, or the clip rect of the element in the
- * browser that corresponds to this NaCl module has changed.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- * @param[in] position The location on the page of this NaCl module. This is
- * relative to the top left corner of the viewport, which changes as the
- * page is scrolled.
- * @param[in] clip The visible region of the NaCl module. This is relative to
- * the top left of the plugin's coordinate system (not the page). If the
- * plugin is invisible, @a clip will be (0, 0, 0, 0).
- */
-static void Instance_DidChangeView(PP_Instance instance,
- PP_Resource view_resource) {
- if (g_context == 0) {
- InitGL();
- MainLoop(NULL, 0);
+ void MainLoop(int32_t) {
+ Animate();
+ Render();
+ context_.SwapBuffers(
+ callback_factory_.NewCallback(&Graphics3DInstance::MainLoop));
}
-}
-/**
- * Notification that the given NaCl module has gained or lost focus.
- * Having focus means that keyboard events will be sent to the NaCl module
- * represented by @a instance. A NaCl module's default condition is that it
- * will not have focus.
- *
- * Note: clicks on NaCl modules will give focus only if you handle the
- * click event. You signal if you handled it by returning @a true from
- * HandleInputEvent. Otherwise the browser will bubble the event and give
- * focus to the element on the page that actually did end up consuming it.
- * If you're not getting focus, check to make sure you're returning true from
- * the mouse click in HandleInputEvent.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- * @param[in] has_focus Indicates whether this NaCl module gained or lost
- * event focus.
- */
-static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
-
-/**
- * Handler that gets called after a full-frame module is instantiated based on
- * registered MIME types. This function is not called on NaCl modules. This
- * function is essentially a place-holder for the required function pointer in
- * the PPP_Instance structure.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
- * @return PP_FALSE.
- */
-static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
- PP_Resource url_loader) {
- /* NaCl modules do not need to handle the document load function. */
- return PP_FALSE;
-}
+ pp::CompletionCallbackFactory<Graphics3DInstance> callback_factory_;
+ pp::Graphics3D context_;
+ int32_t width_;
+ int32_t height_;
+ GLuint frag_shader_;
+ GLuint vertex_shader_;
+ GLuint program_;
+ GLuint vertex_buffer_;
+ GLuint index_buffer_;
+ GLuint texture_;
+
+ GLuint texture_loc_;
+ GLuint position_loc_;
+ GLuint texcoord_loc_;
+ GLuint color_loc_;
+ GLuint mvp_loc_;
+
+ float x_angle_;
+ float y_angle_;
+ bool animating_;
+};
-/**
- * Entry points for the module.
- * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
- * @param[in] a_module_id module ID
- * @param[in] get_browser pointer to PPB_GetInterface
- * @return PP_OK on success, any other value on failure.
- */
-PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
- PPB_GetInterface get_browser) {
- ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE));
- ppb_instance_interface = (PPB_Instance*)get_browser(PPB_INSTANCE_INTERFACE);
- ppb_messaging_interface =
- (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
- ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
- ppb_urlloader_interface =
- (PPB_URLLoader*)(get_browser(PPB_URLLOADER_INTERFACE));
- ppb_urlrequestinfo_interface =
- (PPB_URLRequestInfo*)(get_browser(PPB_URLREQUESTINFO_INTERFACE));
- ppb_g3d_interface = (PPB_Graphics3D*)get_browser(PPB_GRAPHICS_3D_INTERFACE);
- if (!glInitializePPAPI(get_browser))
- return PP_ERROR_FAILED;
- return PP_OK;
-}
+class Graphics3DModule : public pp::Module {
+ public:
+ Graphics3DModule() : pp::Module() {}
+ virtual ~Graphics3DModule() {}
-/**
- * Returns an interface pointer for the interface of the given name, or NULL
- * if the interface is not supported.
- * @param[in] interface_name name of the interface
- * @return pointer to the interface
- */
-PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
- if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
- static PPP_Instance instance_interface = {
- &Instance_DidCreate,
- &Instance_DidDestroy,
- &Instance_DidChangeView,
- &Instance_DidChangeFocus,
- &Instance_HandleDocumentLoad,
- };
- return &instance_interface;
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new Graphics3DInstance(instance);
}
- return NULL;
-}
+};
-/**
- * Called before the plugin module is unloaded.
- */
-PP_EXPORT void PPP_ShutdownModule() {}
+namespace pp {
+Module* CreateModule() { return new Graphics3DModule(); }
+} // namespace pp
diff --git a/native_client_sdk/src/examples/api/graphics_3d/index.html b/native_client_sdk/src/examples/api/graphics_3d/index.html
index 665ce4e..a481cd5 100644
--- a/native_client_sdk/src/examples/api/graphics_3d/index.html
+++ b/native_client_sdk/src/examples/api/graphics_3d/index.html
@@ -10,12 +10,35 @@ found in the LICENSE file.
<meta http-equiv="Expires" content="-1">
<title>{{title}}</title>
<script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="example.js"></script>
+ <style>
+ .label { display: inline-block; width: 100px; }
+ </style>
</head>
<body data-width="640" data-height="480" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <p>The Hello World GLES 2.0 example demonstrates how to create a 3D cube
- that rotates. It loads the assets using URLLoader.</p>
+ <p>The Graphics3D example demonstrates how to create a 3D cube that
+ rotates.</p>
+ <div>
+ <span class="label">X Angle</span>
+ <input type="range" id="xAngle" min="0" max="360" step="1" value="0">
+ </div>
+ <div>
+ <span class="label">Y Angle</span>
+ <input type="range" id="yAngle" min="0" max="360" step="1" value="0">
+ </div>
+ <div>
+ <span class="label">Animating</span>
+ <label>
+ off
+ <input type="radio" id="animateOff" value="false">
+ </label>
+ <label>
+ on
+ <input type="radio" id="animateOn" value="true" checked="true">
+ </label>
+ </div>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/examples/api/graphics_3d/texture.cc b/native_client_sdk/src/examples/api/graphics_3d/texture.cc
new file mode 100644
index 0000000..0f928c3
--- /dev/null
+++ b/native_client_sdk/src/examples/api/graphics_3d/texture.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <stdlib.h>
+
+
+extern const uint8_t kRLETextureData[] =
+ "/wD/AP8A/w8ACf8SAAn/AP9ZAAP/CQAD/wwAA/8JAAP/AP9WAAP/CQAD/wwAA/8JAAP/AP9WAAP/"
+ "CQAD/wwAA/8JAAP/AP9WAAP/CQAD/wwAA/8JAAP/AP9WAAP/CQAD/wMABv8DAAP/CQAD/wD/WQAJ"
+ "/wYABv8GAAn/AP9uAAP/AP96AAP/AP8A/x8AA/8A/3oACf8A/3QAD/8A/24AFf8A/2gAG/8A/2IA"
+ "If8A/1wAJ/8A/1YALf8A/1AAM/8A/0oAOf8A/0QAP/8A/z4ARf8A/zgAS/8A/zIAUf8A/ywAV/8A"
+ "/yYAXf8A/yAAY/8A/xoAaf8A/xQAb/8A/w4Adf8A/wgAe/8A/wIADP8JAAP/CQAb/wYAD/8GACr/"
+ "/AAS/wMACf8DAAkDAwQDABL/AwAS/wMALf/2ABX/AwAJ/wMABikD6AP8A78DGAMADP8DABL/AwAM"
+ "EwOzA+YDsgMSAwAV//AAGP8PAAa2AykDAgM7A68DAAz/AwAS/wMADKUDSwMAA0sDpAMAGP/qABv/"
+ "AwAJ/wMABvYD/wn1AwAM/wMAEv8DAAzzAwgDAAMIA/IDABv/5AAe/wMACf8DAAbDAwAY/wMAEv8D"
+ "AAzzAwgDAAMIA/IDAB7/3gAh/wMACf8DAAaIA1IDDgMAEv8DABL/AwAMpgNTAwADUwOkAwAh/9gA"
+ "If8JAAP/CQADDQOrA/gD2AN/AwAG/w8ABv8PAAYUA7kD8AO3AxIDACT/0gCx/8wAt//GAL3/wADD"
+ "/7oAyf+0AM//rgA2/wkAA/8JADD/BgAV/wYAOf+oADkFA/YDAAYBA/cDAwMAM/8DABj/AwA8/6IA"
+ "P+sDEAMAAxQD6AMABhMDswPmA7IDEgMABv8GKQPWA5UDAAz/AwAMHQPMA+gDRAP/AwA//5wAQtMD"
+ "OQP/AzwD0AMABqUDSwMAA0sDpAMACf8DswMrA1oDAAz/AwAMqgNhAwYDXwP/AwBC/5YARboDcgP/"
+ "A3QDuAMABvMDCAMAAwgD8gMACf8DCgMAEv8DAAzxAwkDAAMLA/8DAEX/kABIogOqA/8DrAOgAwAG"
+ "8wMIAwADCAPyAwAJ/wMAFf8DAAzyAwkDAAMLA/8DAEj/igBLiQPjA/8D5AOIAwAGpgNTAwADUwOk"
+ "AwAJ/wMAFf8DAAysA18DBQNfA/8DAEv/hABOcAP/A9oD/wNwAwAGFAO5A/ADtwMSAwAG/w8ABv8P"
+ "AAYeA8wD6ANFA/8GAEv/fgAAAAX/eAAAAAv/cgAAABH/bAAAABf/ZgAAAB3/YAAAACP/vQBm/wD/"
+ "GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm"
+ "/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/"
+ "GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm"
+ "/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/"
+ "GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8B"
+ "AAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEA"
+ "Av8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC"
+ "/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/"
+ "ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8B"
+ "AAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEA"
+ "Af8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC"
+ "/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/"
+ "AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8B"
+ "AAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oA"
+ "Zv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC"
+ "/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/"
+ "AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8B"
+ "AAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMA"
+ "Af8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC"
+ "/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/"
+ "HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8B"
+ "AAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMA"
+ "Av8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC"
+ "/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/"
+ "AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8B"
+ "AAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8A"
+ "Av8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC"
+ "/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/"
+ "AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8B"
+ "AAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEA"
+ "Av8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC"
+ "/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAMzwDADD/"
+ "HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8B"
+ "AAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMA"
+ "Av8BAAL/AQAC/wEAAv8BAAL/Og==";
+
+// Ignore \0 at the end of the string.
+extern const size_t kRLETextureDataLength = sizeof(kRLETextureData) - 1;
diff --git a/native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert b/native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert
deleted file mode 100644
index da616cb..0000000
--- a/native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert
+++ /dev/null
@@ -1,12 +0,0 @@
-uniform mat4 a_MVP;
-attribute vec2 a_texCoord;
-attribute vec3 a_color;
-attribute vec4 a_position;
-varying vec3 v_color;
-varying vec2 v_texCoord;
-void main()
-{
- gl_Position = a_MVP * a_position;
- v_color = a_color;
- v_texCoord = a_texCoord;
-} \ No newline at end of file