Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 //----------------------------------------------------------------------------- | 5 #include <GLES2/gl2.h> |
| 6 // The spinning Cube | |
| 7 //----------------------------------------------------------------------------- | |
| 8 | |
| 9 #define _USE_MATH_DEFINES 1 | |
| 10 #include <limits.h> | |
| 11 #include <math.h> | 6 #include <math.h> |
| 12 #include <stdarg.h> | |
| 13 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | |
| 14 #include <stdio.h> | 9 #include <stdio.h> |
| 15 #include <stdlib.h> | |
| 16 #include <string.h> | 10 #include <string.h> |
| 17 | 11 |
| 18 #include "ppapi/c/pp_completion_callback.h" | 12 #include "matrix.h" |
| 19 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/cpp/graphics_3d.h" |
| 20 #include "ppapi/c/pp_graphics_3d.h" | 14 #include "ppapi/cpp/instance.h" |
| 21 #include "ppapi/c/pp_module.h" | 15 #include "ppapi/cpp/module.h" |
| 22 #include "ppapi/c/pp_stdint.h" | 16 #include "ppapi/cpp/var.h" |
| 23 #include "ppapi/c/pp_var.h" | 17 #include "ppapi/cpp/var_array.h" |
| 24 #include "ppapi/c/ppb.h" | |
| 25 #include "ppapi/c/ppb_core.h" | |
| 26 #include "ppapi/c/ppb_graphics_3d.h" | |
| 27 #include "ppapi/c/ppb_instance.h" | |
| 28 #include "ppapi/c/ppb_messaging.h" | |
| 29 #include "ppapi/c/ppb_opengles2.h" | |
| 30 #include "ppapi/c/ppb_url_loader.h" | |
| 31 #include "ppapi/c/ppb_url_request_info.h" | |
| 32 #include "ppapi/c/ppb_var.h" | |
| 33 #include "ppapi/c/ppp.h" | |
| 34 #include "ppapi/c/ppp_instance.h" | |
| 35 #include "ppapi/c/ppp_messaging.h" | |
| 36 | |
| 37 #include "ppapi/c/ppp_graphics_3d.h" | |
| 38 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" | 18 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" |
| 39 | 19 #include "ppapi/utility/completion_callback_factory.h" |
| 40 #include <GLES2/gl2.h> | 20 |
| 41 #include "matrix.h" | 21 #ifdef WIN32 |
| 42 | 22 #undef PostMessage |
| 43 static PPB_Messaging* ppb_messaging_interface = NULL; | 23 // Allow 'this' in initializer list |
| 44 static PPB_Var* ppb_var_interface = NULL; | 24 #pragma warning(disable : 4355) |
| 45 static PPB_Core* ppb_core_interface = NULL; | 25 #endif |
| 46 static PPB_Graphics3D* ppb_g3d_interface = NULL; | 26 |
| 47 static PPB_Instance* ppb_instance_interface = NULL; | 27 extern const uint8_t kRLETextureData[]; |
| 48 static PPB_URLRequestInfo* ppb_urlrequestinfo_interface = NULL; | 28 extern const size_t kRLETextureDataLength; |
| 49 static PPB_URLLoader* ppb_urlloader_interface = NULL; | 29 |
| 50 | 30 namespace { |
| 51 static PP_Instance g_instance; | 31 |
| 52 static PP_Resource g_context; | 32 const float kFovY = 45.0f; |
| 53 | 33 const float kZNear = 1.0f; |
| 54 GLuint g_positionLoc; | 34 const float kZFar = 10.0f; |
| 55 GLuint g_texCoordLoc; | 35 const float kCameraZ = -4.0f; |
| 56 GLuint g_colorLoc; | 36 const float kXAngleDelta = 2.0f; |
| 57 GLuint g_MVPLoc; | 37 const float kYAngleDelta = 0.5f; |
| 58 GLuint g_vboID; | 38 |
| 59 GLuint g_ibID; | 39 const size_t kTextureDataLength = 128 * 128 * 3; // 128x128, 3 Bytes/pixel. |
| 60 GLubyte g_Indices[36]; | 40 |
| 61 | 41 // The decompressed data is written here. |
| 62 GLuint g_programObj; | 42 uint8_t g_texture_data[kTextureDataLength]; |
| 63 GLuint g_vertexShader; | 43 |
| 64 GLuint g_fragmentShader; | 44 void DecompressTexture() { |
| 65 | 45 // The image is first encoded with a very simple RLE scheme: |
| 66 GLuint g_textureLoc = 0; | 46 // <value0> <count0> <value1> <count1> ... |
| 67 GLuint g_textureID = 0; | 47 // Because a <count> of 0 is useless, we use it to represent 256. |
| 68 | 48 // |
| 69 float g_fSpinX = 0.0f; | 49 // It is then Base64 encoded to make it use only printable characters (it |
| 70 float g_fSpinY = 0.0f; | 50 // stores more easily in a source file that way). |
| 71 | 51 // |
| 72 //----------------------------------------------------------------------------- | 52 // To decompress, we have to reverse the process. |
| 73 // Rendering Assets | 53 static const uint8_t kBase64Decode[256] = { |
| 74 //----------------------------------------------------------------------------- | 54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 75 struct Vertex { | 55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 76 float tu, tv; | 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, |
| 77 float color[3]; | 57 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, |
| 78 float loc[3]; | 58 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| 79 }; | 59 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, |
| 80 | 60 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, |
| 81 Vertex* g_quadVertices = NULL; | 61 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, |
| 82 const char* g_TextureData = NULL; | 62 }; |
| 83 const char* g_VShaderData = NULL; | 63 const uint8_t* input = &kRLETextureData[0]; |
| 84 const char* g_FShaderData = NULL; | 64 const uint8_t * const input_end = &kRLETextureData[kRLETextureDataLength]; |
| 85 int g_LoadCnt = 0; | 65 uint8_t* output = &g_texture_data[0]; |
| 86 | 66 const uint8_t * const output_end = &g_texture_data[kTextureDataLength]; |
| 87 //----------------------------------------------------------------------------- | 67 |
| 88 // PROTOTYPES | 68 uint8_t decoded[4]; |
| 89 //----------------------------------------------------------------------------- | 69 int decoded_count = 0; |
| 90 void PostMessage(const char* fmt, ...); | 70 |
| 91 char* LoadFile(const char* fileName); | 71 while (input < input_end || decoded_count > 0) { |
| 92 | 72 if (decoded_count < 2) { |
| 93 void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]); | 73 assert(input + 4 <= input_end); |
| 94 Vertex* BuildCube(void); | 74 // Grab four base-64 encoded (6-bit) bytes. |
| 95 | 75 uint32_t data = 0; |
| 96 void InitGL(void); | 76 data |= (kBase64Decode[*input++] << 18); |
| 97 void InitProgram(void); | 77 data |= (kBase64Decode[*input++] << 12); |
| 98 void Render(void); | 78 data |= (kBase64Decode[*input++] << 6); |
| 99 | 79 data |= (kBase64Decode[*input++] ); |
| 100 static struct PP_Var CStrToVar(const char* str) { | 80 // And decode it to 3 (8-bit) bytes. |
| 101 if (ppb_var_interface != NULL) { | 81 decoded[decoded_count++] = (data >> 16) & 0xff; |
| 102 return ppb_var_interface->VarFromUtf8(str, strlen(str)); | 82 decoded[decoded_count++] = (data >> 8) & 0xff; |
| 103 } | 83 decoded[decoded_count++] = (data ) & 0xff; |
| 104 return PP_MakeUndefined(); | 84 |
| 85 // = is the base64 end marker. Remove decoded bytes if we see any. | |
| 86 if (input[-1] == '=') decoded_count--; | |
| 87 if (input[-2] == '=') decoded_count--; | |
| 88 } | |
| 89 | |
| 90 int value = decoded[0]; | |
| 91 int count = decoded[1]; | |
| 92 decoded_count -= 2; | |
| 93 // Move the other decoded bytes (if any) down. | |
| 94 decoded[0] = decoded[2]; | |
| 95 decoded[1] = decoded[3]; | |
| 96 | |
| 97 // Expand the RLE data. | |
| 98 if (count == 0) | |
| 99 count = 256; | |
| 100 assert(output <= output_end); | |
| 101 memset(output, value, count); | |
| 102 output += count; | |
| 103 } | |
| 104 assert(output == output_end); | |
| 105 } | 105 } |
| 106 | 106 |
| 107 void PostMessage(const char* fmt, ...) { | 107 GLuint CompileShader(GLenum type, const char* data) { |
| 108 va_list args; | |
| 109 va_start(args, fmt); | |
| 110 | |
| 111 char msg[4096]; | |
| 112 vsnprintf(msg, sizeof(msg), fmt, args); | |
| 113 | |
| 114 if (ppb_messaging_interface) | |
| 115 ppb_messaging_interface->PostMessage(g_instance, CStrToVar(msg)); | |
| 116 | |
| 117 va_end(args); | |
| 118 } | |
| 119 | |
| 120 void MainLoop(void* foo, int bar) { | |
| 121 if (g_LoadCnt == 3) { | |
| 122 InitProgram(); | |
| 123 g_LoadCnt++; | |
| 124 } | |
| 125 if (g_LoadCnt > 3) { | |
| 126 Render(); | |
| 127 PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0); | |
| 128 ppb_g3d_interface->SwapBuffers(g_context, cc); | |
| 129 } else { | |
| 130 PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0); | |
| 131 ppb_core_interface->CallOnMainThread(0, cc, 0); | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 void InitGL(void) { | |
| 136 int32_t attribs[] = { | |
| 137 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, | |
| 138 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, | |
| 139 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, | |
| 140 PP_GRAPHICS3DATTRIB_SAMPLES, 0, | |
| 141 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, | |
| 142 PP_GRAPHICS3DATTRIB_WIDTH, 640, | |
| 143 PP_GRAPHICS3DATTRIB_HEIGHT, 480, | |
| 144 PP_GRAPHICS3DATTRIB_NONE | |
| 145 }; | |
| 146 | |
| 147 g_context = ppb_g3d_interface->Create(g_instance, 0, attribs); | |
| 148 int32_t success = ppb_instance_interface->BindGraphics(g_instance, g_context); | |
| 149 if (success == PP_FALSE) { | |
| 150 glSetCurrentContextPPAPI(0); | |
| 151 printf("Failed to set context.\n"); | |
| 152 return; | |
| 153 } | |
| 154 glSetCurrentContextPPAPI(g_context); | |
| 155 | |
| 156 glViewport(0, 0, 640, 480); | |
| 157 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
| 158 } | |
| 159 | |
| 160 GLuint compileShader(GLenum type, const char* data) { | |
| 161 const char* shaderStrings[1]; | |
| 162 shaderStrings[0] = data; | |
| 163 | |
| 164 GLuint shader = glCreateShader(type); | 108 GLuint shader = glCreateShader(type); |
| 165 glShaderSource(shader, 1, shaderStrings, NULL); | 109 glShaderSource(shader, 1, &data, NULL); |
| 166 glCompileShader(shader); | 110 glCompileShader(shader); |
| 111 | |
| 112 GLint compile_status; | |
| 113 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | |
| 114 if (compile_status != GL_TRUE) { | |
| 115 // Shader failed to compile, let's see what the error is. | |
| 116 char buffer[1024]; | |
| 117 GLsizei length; | |
| 118 glGetShaderInfoLog(shader, 1024, &length, &buffer[0]); | |
|
noelallen1
2013/09/03 20:55:25
1024 vs sizeof(buffer)?
| |
| 119 fprintf(stderr, "Shader failed to compile: %s\n", buffer); | |
| 120 return 0; | |
| 121 } | |
| 122 | |
| 167 return shader; | 123 return shader; |
| 168 } | 124 } |
| 169 | 125 |
| 170 void InitProgram(void) { | 126 GLuint LinkProgram(GLuint frag_shader, GLuint vert_shader) { |
| 171 glSetCurrentContextPPAPI(g_context); | 127 GLuint program = glCreateProgram(); |
| 172 | 128 glAttachShader(program, frag_shader); |
| 173 g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData); | 129 glAttachShader(program, vert_shader); |
| 174 g_fragmentShader = compileShader(GL_FRAGMENT_SHADER, g_FShaderData); | 130 glLinkProgram(program); |
| 175 | 131 |
| 176 g_programObj = glCreateProgram(); | 132 GLint link_status; |
| 177 glAttachShader(g_programObj, g_vertexShader); | 133 glGetProgramiv(program, GL_LINK_STATUS, &link_status); |
| 178 glAttachShader(g_programObj, g_fragmentShader); | 134 if (link_status != GL_TRUE) { |
| 179 glLinkProgram(g_programObj); | 135 // Program failed to link, let's see what the error is. |
| 180 | 136 char buffer[1024]; |
| 181 glGenBuffers(1, &g_vboID); | 137 GLsizei length; |
| 182 glBindBuffer(GL_ARRAY_BUFFER, g_vboID); | 138 glGetProgramInfoLog(program, 1024, &length, &buffer[0]); |
|
noelallen1
2013/09/03 20:55:25
same
| |
| 183 glBufferData(GL_ARRAY_BUFFER, | 139 fprintf(stderr, "Program failed to link: %s\n", buffer); |
| 184 24 * sizeof(Vertex), | 140 return 0; |
| 185 (void*)&g_quadVertices[0], | 141 } |
| 186 GL_STATIC_DRAW); | 142 |
| 187 | 143 return program; |
| 188 glGenBuffers(1, &g_ibID); | |
| 189 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID); | |
| 190 glBufferData(GL_ELEMENT_ARRAY_BUFFER, | |
| 191 36 * sizeof(char), | |
| 192 (void*)&g_Indices[0], | |
| 193 GL_STATIC_DRAW); | |
| 194 | |
| 195 // | |
| 196 // Create a texture to test out our fragment shader... | |
| 197 // | |
| 198 glGenTextures(1, &g_textureID); | |
| 199 glBindTexture(GL_TEXTURE_2D, g_textureID); | |
| 200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 202 glTexImage2D(GL_TEXTURE_2D, | |
| 203 0, | |
| 204 GL_RGB, | |
| 205 128, | |
| 206 128, | |
| 207 0, | |
| 208 GL_RGB, | |
| 209 GL_UNSIGNED_BYTE, | |
| 210 g_TextureData); | |
| 211 | |
| 212 // | |
| 213 // Locate some parameters by name so we can set them later... | |
| 214 // | |
| 215 g_textureLoc = glGetUniformLocation(g_programObj, "arrowTexture"); | |
| 216 g_positionLoc = glGetAttribLocation(g_programObj, "a_position"); | |
| 217 g_texCoordLoc = glGetAttribLocation(g_programObj, "a_texCoord"); | |
| 218 g_colorLoc = glGetAttribLocation(g_programObj, "a_color"); | |
| 219 g_MVPLoc = glGetUniformLocation(g_programObj, "a_MVP"); | |
| 220 } | 144 } |
| 221 | 145 |
| 222 void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) { | 146 const char kFragShaderSource[] = |
| 223 static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f }; | 147 "precision mediump float;\n" |
| 224 static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f }; | 148 "varying vec3 v_color;\n" |
| 225 | 149 "varying vec2 v_texcoord;\n" |
| 226 for (int i = 0; i < 4; i++) { | 150 "uniform sampler2D u_texture;\n" |
| 227 verts[i].tu = (1.0 - X[i]) / 2.0f; | 151 "void main() {\n" |
| 228 verts[i].tv = (Y[i] + 1.0f) / -2.0f * depth; | 152 " gl_FragColor = texture2D(u_texture, v_texcoord);\n" |
| 229 verts[i].loc[axis[0]] = X[i] * depth; | 153 " gl_FragColor += vec4(v_color, 1);\n" |
| 230 verts[i].loc[axis[1]] = Y[i] * depth; | 154 "}\n"; |
| 231 verts[i].loc[axis[2]] = depth; | 155 |
| 232 for (int j = 0; j < 3; j++) | 156 const char kVertexShaderSource[] = |
| 233 verts[i].color[j] = color[j] * (Y[i] + 1.0f) / 2.0f; | 157 "uniform mat4 u_mvp;\n" |
| 234 } | 158 "attribute vec2 a_texcoord;\n" |
| 235 } | 159 "attribute vec3 a_color;\n" |
| 236 | 160 "attribute vec4 a_position;\n" |
| 237 Vertex* BuildCube() { | 161 "varying vec3 v_color;\n" |
| 238 Vertex* verts = new Vertex[24]; | 162 "varying vec2 v_texcoord;\n" |
| 239 for (int i = 0; i < 3; i++) { | 163 "void main() {\n" |
| 240 int Faxis[3]; | 164 " gl_Position = u_mvp * a_position;\n" |
| 241 int Baxis[3]; | 165 " v_color = a_color;\n" |
| 242 float Fcolor[3]; | 166 " v_texcoord = a_texcoord;\n" |
| 243 float Bcolor[3]; | 167 "}\n"; |
| 244 for (int j = 0; j < 3; j++) { | 168 |
| 245 Faxis[j] = (j + i) % 3; | 169 struct Vertex { |
| 246 Baxis[j] = (j + i) % 3; | 170 float loc[3]; |
| 247 } | 171 float color[3]; |
| 248 memset(Fcolor, 0, sizeof(float) * 3); | 172 float tex[2]; |
| 249 memset(Bcolor, 0, sizeof(float) * 3); | |
| 250 Fcolor[i] = 0.5f; | |
| 251 Bcolor[i] = 1.0f; | |
| 252 BuildQuad(&verts[0 + i * 4], Faxis, 1.0f, Fcolor); | |
| 253 BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor); | |
| 254 } | |
| 255 | |
| 256 for (int i = 0; i < 6; i++) { | |
| 257 g_Indices[i * 6 + 0] = 2 + i * 4; | |
| 258 g_Indices[i * 6 + 1] = 1 + i * 4; | |
| 259 g_Indices[i * 6 + 2] = 0 + i * 4; | |
| 260 g_Indices[i * 6 + 3] = 3 + i * 4; | |
| 261 g_Indices[i * 6 + 4] = 2 + i * 4; | |
| 262 g_Indices[i * 6 + 5] = 0 + i * 4; | |
| 263 } | |
| 264 return verts; | |
| 265 } | |
| 266 | |
| 267 void Render(void) { | |
| 268 static float xRot = 0.0; | |
| 269 static float yRot = 0.0; | |
| 270 | |
| 271 xRot += 2.0f; | |
| 272 yRot += 0.5f; | |
| 273 if (xRot >= 360.0f) | |
| 274 xRot = 0.0; | |
| 275 if (yRot >= 360.0f) | |
| 276 yRot = 0.0; | |
| 277 | |
| 278 glClearColor(0.5, 0.5, 0.5, 1); | |
| 279 glClearDepthf(1.0); | |
| 280 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
| 281 glEnable(GL_DEPTH_TEST); | |
| 282 | |
| 283 //set what program to use | |
| 284 glUseProgram(g_programObj); | |
| 285 glActiveTexture(GL_TEXTURE0); | |
| 286 glBindTexture(GL_TEXTURE_2D, g_textureID); | |
| 287 glUniform1i(g_textureLoc, 0); | |
| 288 | |
| 289 //create our perspective matrix | |
| 290 float mpv[16]; | |
| 291 float trs[16]; | |
| 292 float rot[16]; | |
| 293 | |
| 294 identity_matrix(mpv); | |
| 295 glhPerspectivef2(&mpv[0], 45.0f, 640.0f / 480.0f, 1, 10); | |
| 296 | |
| 297 translate_matrix(0, 0, -4.0, trs); | |
| 298 rotate_matrix(xRot, yRot, 0.0f, rot); | |
| 299 multiply_matrix(trs, rot, trs); | |
| 300 multiply_matrix(mpv, trs, mpv); | |
| 301 glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*)mpv); | |
| 302 | |
| 303 //define the attributes of the vertex | |
| 304 glBindBuffer(GL_ARRAY_BUFFER, g_vboID); | |
| 305 glVertexAttribPointer(g_positionLoc, | |
| 306 3, | |
| 307 GL_FLOAT, | |
| 308 GL_FALSE, | |
| 309 sizeof(Vertex), | |
| 310 (void*)offsetof(Vertex, loc)); | |
| 311 glEnableVertexAttribArray(g_positionLoc); | |
| 312 glVertexAttribPointer(g_texCoordLoc, | |
| 313 2, | |
| 314 GL_FLOAT, | |
| 315 GL_FALSE, | |
| 316 sizeof(Vertex), | |
| 317 (void*)offsetof(Vertex, tu)); | |
| 318 glEnableVertexAttribArray(g_texCoordLoc); | |
| 319 glVertexAttribPointer(g_colorLoc, | |
| 320 3, | |
| 321 GL_FLOAT, | |
| 322 GL_FALSE, | |
| 323 sizeof(Vertex), | |
| 324 (void*)offsetof(Vertex, color)); | |
| 325 glEnableVertexAttribArray(g_colorLoc); | |
| 326 | |
| 327 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID); | |
| 328 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0); | |
| 329 } | |
| 330 | |
| 331 typedef void (*OpenCB)(void* dataPtr); | |
| 332 struct OpenRequest { | |
| 333 PP_Resource loader_; | |
| 334 PP_Resource request_; | |
| 335 char* buf_; | |
| 336 void* data_; | |
| 337 int64_t size_; | |
| 338 int64_t avail_; | |
| 339 OpenCB cb_; | |
| 340 }; | 173 }; |
| 341 | 174 |
| 342 void FreeRequest(OpenRequest* req) { | 175 const Vertex kCubeVerts[24] = { |
| 343 if (req) { | 176 // +Z (red arrow, black tip) |
| 344 ppb_core_interface->ReleaseResource(req->request_); | 177 {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}}, |
| 345 ppb_core_interface->ReleaseResource(req->loader_); | 178 {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}}, |
| 346 free(req); | 179 {{+1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {0.0, 1.0}}, |
| 347 } | 180 {{-1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {1.0, 1.0}}, |
| 348 } | 181 |
| 349 | 182 // +X (green arrow, black tip) |
| 350 static void URLPartialRead(void* user_data, int mode) { | 183 {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}}, |
| 351 OpenRequest* req = (OpenRequest*)user_data; | 184 {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}}, |
| 352 int64_t total; | 185 {{+1.0, +1.0, +1.0}, {0.0, 0.5, 0.0}, {0.0, 1.0}}, |
| 353 int32_t cnt; | 186 {{+1.0, -1.0, +1.0}, {0.0, 0.5, 0.0}, {1.0, 1.0}}, |
| 354 | 187 |
| 355 if (mode < 0) { | 188 // +Y (blue arrow, black tip) |
| 356 free(req->buf_); | 189 {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}}, |
| 357 req->cb_(NULL); | 190 {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}}, |
| 358 FreeRequest(req); | 191 {{+1.0, +1.0, +1.0}, {0.0, 0.0, 0.5}, {0.0, 1.0}}, |
| 359 return; | 192 {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.5}, {1.0, 1.0}}, |
| 360 } | 193 |
| 361 | 194 // -Z (red arrow, red tip) |
| 362 req->avail_ += mode; | 195 {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}}, |
| 363 total = req->size_ - req->avail_; | 196 {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}}, |
| 364 | 197 {{-1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0}}, |
| 365 cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total; | 198 {{+1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0}}, |
| 366 // If we still have more to do, re-issue the read. | 199 |
| 367 if (cnt > 0) { | 200 // -X (green arrow, green tip) |
| 368 int32_t bytes = ppb_urlloader_interface->ReadResponseBody( | 201 {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}}, |
| 369 req->loader_, | 202 {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}}, |
| 370 (void*)&req->buf_[req->avail_], | 203 {{-1.0, -1.0, -1.0}, {0.0, 1.0, 0.0}, {0.0, 0.0}}, |
| 371 cnt, | 204 {{-1.0, +1.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0}}, |
| 372 PP_MakeCompletionCallback(URLPartialRead, req)); | 205 |
| 373 | 206 // -Y (blue arrow, blue tip) |
| 374 // If the reissue completes immediately, then process it. | 207 {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}}, |
| 375 if (bytes != PP_OK_COMPLETIONPENDING) { | 208 {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}}, |
| 376 URLPartialRead(user_data, bytes); | 209 {{-1.0, -1.0, -1.0}, {0.0, 0.0, 1.0}, {0.0, 0.0}}, |
| 377 } | 210 {{-1.0, -1.0, +1.0}, {0.0, 0.0, 1.0}, {1.0, 0.0}}, |
| 378 return; | 211 }; |
| 379 } | 212 |
| 380 | 213 const GLubyte kCubeIndexes[36] = { |
| 381 // Nothing left, so signal complete. | 214 2, 1, 0, 3, 2, 0, |
| 382 req->cb_(req); | 215 6, 5, 4, 7, 6, 4, |
| 383 FreeRequest(req); | 216 10, 9, 8, 11, 10, 8, |
| 384 printf("Loaded\n"); | 217 14, 13, 12, 15, 14, 12, |
| 385 } | 218 18, 17, 16, 19, 18, 16, |
| 386 | 219 22, 21, 20, 23, 22, 20, |
| 387 static void URLOpened(void* user_data, int mode) { | 220 }; |
| 388 OpenRequest* req = (OpenRequest*)user_data; | 221 |
| 389 | 222 } // namespace |
| 390 int64_t cur, total; | 223 |
| 391 int32_t cnt; | 224 |
| 392 ppb_urlloader_interface->GetDownloadProgress(req->loader_, &cur, &total); | 225 class Graphics3DInstance : public pp::Instance { |
| 393 | 226 public: |
| 394 // If we can't preallocate the buffer because the size is unknown, then | 227 explicit Graphics3DInstance(PP_Instance instance) |
| 395 // fail the load. | 228 : pp::Instance(instance), |
| 396 if (total == -1) { | 229 callback_factory_(this), |
| 397 req->cb_(NULL); | 230 width_(0), |
| 398 FreeRequest(req); | 231 height_(0), |
| 399 return; | 232 frag_shader_(0), |
| 400 } | 233 vertex_shader_(0), |
| 401 | 234 program_(0), |
| 402 // Otherwise allocate a buffer with enough space for a terminating | 235 texture_loc_(0), |
| 403 // NULL in case we need one. | 236 position_loc_(0), |
| 404 cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total; | 237 color_loc_(0), |
| 405 req->buf_ = (char*)malloc(cnt + 1); | 238 mvp_loc_(0), |
| 406 req->buf_[cnt] = 0; | 239 x_angle_(0), |
| 407 req->size_ = cnt; | 240 y_angle_(0), |
| 408 int32_t bytes = ppb_urlloader_interface->ReadResponseBody( | 241 animating_(true) {} |
| 409 req->loader_, | 242 |
| 410 req->buf_, | 243 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
| 411 cnt, | 244 return true; |
| 412 PP_MakeCompletionCallback(URLPartialRead, req)); | 245 } |
| 413 | 246 |
| 414 // Usually we are pending. | 247 virtual void DidChangeView(const pp::View& view) { |
| 415 if (bytes == PP_OK_COMPLETIONPENDING) | 248 int32_t new_width = view.GetRect().width(); |
| 416 return; | 249 int32_t new_height = view.GetRect().height(); |
| 417 | 250 |
| 418 // But if we did complete the read, then dispatch the handler. | 251 if (context_.is_null()) { |
| 419 URLPartialRead(req, bytes); | 252 if (!InitGL(new_width, new_height)) { |
| 420 } | 253 // failed. |
| 421 | 254 return; |
| 422 void LoadURL(PP_Instance inst, const char* url, OpenCB cb, void* data) { | 255 } |
| 423 OpenRequest* req = (OpenRequest*)malloc(sizeof(OpenRequest)); | 256 |
| 424 memset(req, 0, sizeof(OpenRequest)); | 257 InitShaders(); |
| 425 | 258 InitBuffers(); |
| 426 req->loader_ = ppb_urlloader_interface->Create(inst); | 259 InitTexture(); |
| 427 req->request_ = ppb_urlrequestinfo_interface->Create(inst); | 260 MainLoop(0); |
| 428 req->cb_ = cb; | 261 } else { |
| 429 req->data_ = data; | 262 // Resize the buffers to the new size of the module. |
| 430 | 263 int32_t result = context_.ResizeBuffers(new_width, new_height); |
| 431 if (!req->loader_ || !req->request_) { | 264 if (result < 0) { |
| 432 cb(NULL); | 265 fprintf(stderr, |
| 433 FreeRequest(req); | 266 "Unable to resize buffers to %d x %d!\n", |
| 434 return; | 267 new_width, |
| 435 } | 268 new_height); |
| 436 | 269 return; |
| 437 ppb_urlrequestinfo_interface->SetProperty( | 270 } |
| 438 req->request_, PP_URLREQUESTPROPERTY_URL, CStrToVar(url)); | 271 } |
| 439 ppb_urlrequestinfo_interface->SetProperty( | 272 |
| 440 req->request_, PP_URLREQUESTPROPERTY_METHOD, CStrToVar("GET")); | 273 width_ = new_width; |
| 441 ppb_urlrequestinfo_interface->SetProperty( | 274 height_ = new_height; |
| 442 req->request_, | 275 glViewport(0, 0, width_, height_); |
| 443 PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, | 276 } |
| 444 PP_MakeBool(PP_TRUE)); | 277 |
| 445 | 278 virtual void HandleMessage(const pp::Var& message) { |
| 446 int val = ppb_urlloader_interface->Open( | 279 // A bool message sets whether the cube is animating or not. |
| 447 req->loader_, req->request_, PP_MakeCompletionCallback(URLOpened, req)); | 280 if (message.is_bool()) { |
| 448 | 281 animating_ = message.AsBool(); |
| 449 if (val != PP_OK_COMPLETIONPENDING) { | 282 return; |
| 450 cb(NULL); | 283 } |
| 451 free(req); | 284 |
| 452 } | 285 // An array message sets the current x and y rotation. |
| 453 } | 286 if (!message.is_array()) { |
| 454 | 287 fprintf(stderr, "Expected array message.\n"); |
| 455 void Loaded(void* data) { | 288 return; |
| 456 OpenRequest* req = (OpenRequest*)data; | 289 } |
| 457 if (req && req->buf_) { | 290 |
| 458 char** pptr = (char**)req->data_; | 291 pp::VarArray array(message); |
| 459 *pptr = req->buf_; | 292 if (array.GetLength() != 2) { |
| 460 g_LoadCnt++; | 293 fprintf(stderr, "Expected array of length 2.\n"); |
| 461 return; | 294 return; |
| 462 } | 295 } |
| 463 PostMessage("Failed to load asset.\n"); | 296 |
| 464 } | 297 pp::Var x_angle_var = array.Get(0); |
| 465 | 298 if (x_angle_var.is_int()) { |
| 466 /** | 299 x_angle_ = x_angle_var.AsInt(); |
| 467 * Called when the NaCl module is instantiated on the web page. The identifier | 300 } else if (x_angle_var.is_double()) { |
| 468 * of the new instance will be passed in as the first argument (this value is | 301 x_angle_ = x_angle_var.AsDouble(); |
| 469 * generated by the browser and is an opaque handle). This is called for each | 302 } else { |
| 470 * instantiation of the NaCl module, which is each time the <embed> tag for | 303 fprintf(stderr, "Expected value to be an int or double.\n"); |
| 471 * this module is encountered. | 304 } |
| 472 * | 305 |
| 473 * If this function reports a failure (by returning @a PP_FALSE), the NaCl | 306 pp::Var y_angle_var = array.Get(1); |
| 474 * module will be deleted and DidDestroy will be called. | 307 if (y_angle_var.is_int()) { |
| 475 * @param[in] instance The identifier of the new instance representing this | 308 y_angle_ = y_angle_var.AsInt(); |
| 476 * NaCl module. | 309 } else if (y_angle_var.is_double()) { |
| 477 * @param[in] argc The number of arguments contained in @a argn and @a argv. | 310 y_angle_ = y_angle_var.AsDouble(); |
| 478 * @param[in] argn An array of argument names. These argument names are | 311 } else { |
| 479 * supplied in the <embed> tag, for example: | 312 fprintf(stderr, "Expected value to be an int or double.\n"); |
| 480 * <embed id="nacl_module" dimensions="2"> | 313 } |
| 481 * will produce two arguments, one named "id" and one named "dimensions". | 314 } |
| 482 * @param[in] argv An array of argument values. These are the values of the | 315 |
| 483 * arguments listed in the <embed> tag. In the above example, there will | 316 private: |
| 484 * be two elements in this array, "nacl_module" and "2". The indices of | 317 bool InitGL(int32_t new_width, int32_t new_height) { |
| 485 * these values match the indices of the corresponding names in @a argn. | 318 if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) { |
| 486 * @return @a PP_TRUE on success. | 319 fprintf(stderr, "Unable to initialize GL PPAPI!\n"); |
| 487 */ | 320 return false; |
| 488 static PP_Bool Instance_DidCreate(PP_Instance instance, | 321 } |
| 489 uint32_t argc, | 322 |
| 490 const char* argn[], | 323 const int32_t attrib_list[] = { |
| 491 const char* argv[]) { | 324 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, |
| 492 g_instance = instance; | 325 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, |
| 493 LoadURL(instance, "hello.raw", Loaded, &g_TextureData); | 326 PP_GRAPHICS3DATTRIB_WIDTH, new_width, |
| 494 LoadURL(instance, "vertex_shader_es2.vert", Loaded, &g_VShaderData); | 327 PP_GRAPHICS3DATTRIB_HEIGHT, new_height, |
| 495 LoadURL(instance, "fragment_shader_es2.frag", Loaded, &g_FShaderData); | 328 PP_GRAPHICS3DATTRIB_NONE |
| 496 g_quadVertices = BuildCube(); | |
| 497 return PP_TRUE; | |
| 498 } | |
| 499 | |
| 500 /** | |
| 501 * Called when the NaCl module is destroyed. This will always be called, | |
| 502 * even if DidCreate returned failure. This routine should deallocate any data | |
| 503 * associated with the instance. | |
| 504 * @param[in] instance The identifier of the instance representing this NaCl | |
| 505 * module. | |
| 506 */ | |
| 507 static void Instance_DidDestroy(PP_Instance instance) { | |
| 508 delete[] g_TextureData; | |
| 509 delete[] g_VShaderData; | |
| 510 delete[] g_FShaderData; | |
| 511 delete[] g_quadVertices; | |
| 512 } | |
| 513 | |
| 514 /** | |
| 515 * Called when the position, the size, or the clip rect of the element in the | |
| 516 * browser that corresponds to this NaCl module has changed. | |
| 517 * @param[in] instance The identifier of the instance representing this NaCl | |
| 518 * module. | |
| 519 * @param[in] position The location on the page of this NaCl module. This is | |
| 520 * relative to the top left corner of the viewport, which changes as the | |
| 521 * page is scrolled. | |
| 522 * @param[in] clip The visible region of the NaCl module. This is relative to | |
| 523 * the top left of the plugin's coordinate system (not the page). If the | |
| 524 * plugin is invisible, @a clip will be (0, 0, 0, 0). | |
| 525 */ | |
| 526 static void Instance_DidChangeView(PP_Instance instance, | |
| 527 PP_Resource view_resource) { | |
| 528 if (g_context == 0) { | |
| 529 InitGL(); | |
| 530 MainLoop(NULL, 0); | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 /** | |
| 535 * Notification that the given NaCl module has gained or lost focus. | |
| 536 * Having focus means that keyboard events will be sent to the NaCl module | |
| 537 * represented by @a instance. A NaCl module's default condition is that it | |
| 538 * will not have focus. | |
| 539 * | |
| 540 * Note: clicks on NaCl modules will give focus only if you handle the | |
| 541 * click event. You signal if you handled it by returning @a true from | |
| 542 * HandleInputEvent. Otherwise the browser will bubble the event and give | |
| 543 * focus to the element on the page that actually did end up consuming it. | |
| 544 * If you're not getting focus, check to make sure you're returning true from | |
| 545 * the mouse click in HandleInputEvent. | |
| 546 * @param[in] instance The identifier of the instance representing this NaCl | |
| 547 * module. | |
| 548 * @param[in] has_focus Indicates whether this NaCl module gained or lost | |
| 549 * event focus. | |
| 550 */ | |
| 551 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {} | |
| 552 | |
| 553 /** | |
| 554 * Handler that gets called after a full-frame module is instantiated based on | |
| 555 * registered MIME types. This function is not called on NaCl modules. This | |
| 556 * function is essentially a place-holder for the required function pointer in | |
| 557 * the PPP_Instance structure. | |
| 558 * @param[in] instance The identifier of the instance representing this NaCl | |
| 559 * module. | |
| 560 * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance. | |
| 561 * @return PP_FALSE. | |
| 562 */ | |
| 563 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, | |
| 564 PP_Resource url_loader) { | |
| 565 /* NaCl modules do not need to handle the document load function. */ | |
| 566 return PP_FALSE; | |
| 567 } | |
| 568 | |
| 569 /** | |
| 570 * Entry points for the module. | |
| 571 * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var. | |
| 572 * @param[in] a_module_id module ID | |
| 573 * @param[in] get_browser pointer to PPB_GetInterface | |
| 574 * @return PP_OK on success, any other value on failure. | |
| 575 */ | |
| 576 PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, | |
| 577 PPB_GetInterface get_browser) { | |
| 578 ppb_core_interface = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE)); | |
| 579 ppb_instance_interface = (PPB_Instance*)get_browser(PPB_INSTANCE_INTERFACE); | |
| 580 ppb_messaging_interface = | |
| 581 (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE)); | |
| 582 ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE)); | |
| 583 ppb_urlloader_interface = | |
| 584 (PPB_URLLoader*)(get_browser(PPB_URLLOADER_INTERFACE)); | |
| 585 ppb_urlrequestinfo_interface = | |
| 586 (PPB_URLRequestInfo*)(get_browser(PPB_URLREQUESTINFO_INTERFACE)); | |
| 587 ppb_g3d_interface = (PPB_Graphics3D*)get_browser(PPB_GRAPHICS_3D_INTERFACE); | |
| 588 if (!glInitializePPAPI(get_browser)) | |
| 589 return PP_ERROR_FAILED; | |
| 590 return PP_OK; | |
| 591 } | |
| 592 | |
| 593 /** | |
| 594 * Returns an interface pointer for the interface of the given name, or NULL | |
| 595 * if the interface is not supported. | |
| 596 * @param[in] interface_name name of the interface | |
| 597 * @return pointer to the interface | |
| 598 */ | |
| 599 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { | |
| 600 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { | |
| 601 static PPP_Instance instance_interface = { | |
| 602 &Instance_DidCreate, | |
| 603 &Instance_DidDestroy, | |
| 604 &Instance_DidChangeView, | |
| 605 &Instance_DidChangeFocus, | |
| 606 &Instance_HandleDocumentLoad, | |
| 607 }; | 329 }; |
| 608 return &instance_interface; | 330 |
| 609 } | 331 context_ = pp::Graphics3D(this, attrib_list); |
| 610 return NULL; | 332 if (!BindGraphics(context_)) { |
| 611 } | 333 fprintf(stderr, "Unable to bind 3d context!\n"); |
| 612 | 334 context_ = pp::Graphics3D(); |
| 613 /** | 335 glSetCurrentContextPPAPI(0); |
| 614 * Called before the plugin module is unloaded. | 336 return false; |
| 615 */ | 337 } |
| 616 PP_EXPORT void PPP_ShutdownModule() {} | 338 |
| 339 glSetCurrentContextPPAPI(context_.pp_resource()); | |
| 340 return true; | |
| 341 } | |
| 342 | |
| 343 void InitShaders() { | |
| 344 frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, kFragShaderSource); | |
| 345 if (!frag_shader_) | |
| 346 return; | |
| 347 | |
| 348 vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kVertexShaderSource); | |
| 349 if (!vertex_shader_) | |
| 350 return; | |
| 351 | |
| 352 program_ = LinkProgram(frag_shader_, vertex_shader_); | |
| 353 if (!program_) | |
| 354 return; | |
| 355 | |
| 356 texture_loc_ = glGetUniformLocation(program_, "u_texture"); | |
| 357 position_loc_ = glGetAttribLocation(program_, "a_position"); | |
| 358 texcoord_loc_ = glGetAttribLocation(program_, "a_texcoord"); | |
| 359 color_loc_ = glGetAttribLocation(program_, "a_color"); | |
| 360 mvp_loc_ = glGetUniformLocation(program_, "u_mvp"); | |
| 361 } | |
| 362 | |
| 363 void InitBuffers() { | |
| 364 glGenBuffers(1, &vertex_buffer_); | |
| 365 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | |
| 366 glBufferData(GL_ARRAY_BUFFER, sizeof(kCubeVerts), &kCubeVerts[0], | |
| 367 GL_STATIC_DRAW); | |
| 368 | |
| 369 glGenBuffers(1, &index_buffer_); | |
| 370 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_); | |
| 371 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kCubeIndexes), | |
| 372 &kCubeIndexes[0], GL_STATIC_DRAW); | |
| 373 } | |
| 374 | |
| 375 void InitTexture() { | |
| 376 DecompressTexture(); | |
| 377 glGenTextures(1, &texture_); | |
| 378 glBindTexture(GL_TEXTURE_2D, texture_); | |
| 379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 381 glTexImage2D(GL_TEXTURE_2D, | |
| 382 0, | |
| 383 GL_RGB, | |
| 384 128, | |
| 385 128, | |
| 386 0, | |
| 387 GL_RGB, | |
| 388 GL_UNSIGNED_BYTE, | |
| 389 &g_texture_data[0]); | |
| 390 } | |
| 391 | |
| 392 void Animate() { | |
| 393 if (animating_) { | |
| 394 x_angle_ = fmod(360.0f + x_angle_ + kXAngleDelta, 360.0f); | |
| 395 y_angle_ = fmod(360.0f + y_angle_ + kYAngleDelta, 360.0f); | |
| 396 | |
| 397 // Send new values to JavaScript. | |
| 398 pp::VarArray array; | |
| 399 array.SetLength(2); | |
| 400 array.Set(0, x_angle_); | |
| 401 array.Set(1, y_angle_); | |
| 402 PostMessage(array); | |
| 403 } | |
| 404 } | |
| 405 | |
| 406 void Render() { | |
| 407 glClearColor(0.5, 0.5, 0.5, 1); | |
| 408 glClearDepthf(1.0f); | |
| 409 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
| 410 glEnable(GL_DEPTH_TEST); | |
| 411 | |
| 412 //set what program to use | |
| 413 glUseProgram(program_); | |
| 414 glActiveTexture(GL_TEXTURE0); | |
| 415 glBindTexture(GL_TEXTURE_2D, texture_); | |
| 416 glUniform1i(texture_loc_, 0); | |
| 417 | |
| 418 //create our perspective matrix | |
| 419 float mvp[16]; | |
| 420 float trs[16]; | |
| 421 float rot[16]; | |
| 422 | |
| 423 identity_matrix(mvp); | |
| 424 const float aspect_ratio = static_cast<float>(width_) / height_; | |
| 425 glhPerspectivef2(&mvp[0], kFovY, aspect_ratio, kZNear, kZFar); | |
| 426 | |
| 427 translate_matrix(0, 0, kCameraZ, trs); | |
| 428 rotate_matrix(x_angle_, y_angle_, 0.0f, rot); | |
| 429 multiply_matrix(trs, rot, trs); | |
| 430 multiply_matrix(mvp, trs, mvp); | |
| 431 glUniformMatrix4fv(mvp_loc_, 1, GL_FALSE, mvp); | |
| 432 | |
| 433 //define the attributes of the vertex | |
| 434 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | |
| 435 glVertexAttribPointer(position_loc_, | |
| 436 3, | |
| 437 GL_FLOAT, | |
| 438 GL_FALSE, | |
| 439 sizeof(Vertex), | |
| 440 reinterpret_cast<void*>(offsetof(Vertex, loc))); | |
| 441 glEnableVertexAttribArray(position_loc_); | |
| 442 glVertexAttribPointer(color_loc_, | |
| 443 3, | |
| 444 GL_FLOAT, | |
| 445 GL_FALSE, | |
| 446 sizeof(Vertex), | |
| 447 reinterpret_cast<void*>(offsetof(Vertex, color))); | |
| 448 glEnableVertexAttribArray(color_loc_); | |
| 449 glVertexAttribPointer(texcoord_loc_, | |
| 450 2, | |
| 451 GL_FLOAT, | |
| 452 GL_FALSE, | |
| 453 sizeof(Vertex), | |
| 454 reinterpret_cast<void*>(offsetof(Vertex, tex))); | |
| 455 glEnableVertexAttribArray(texcoord_loc_); | |
| 456 | |
| 457 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_); | |
| 458 glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0); | |
| 459 } | |
| 460 | |
| 461 void MainLoop(int32_t) { | |
| 462 Animate(); | |
| 463 Render(); | |
| 464 context_.SwapBuffers( | |
| 465 callback_factory_.NewCallback(&Graphics3DInstance::MainLoop)); | |
| 466 } | |
| 467 | |
| 468 pp::CompletionCallbackFactory<Graphics3DInstance> callback_factory_; | |
| 469 pp::Graphics3D context_; | |
| 470 int32_t width_; | |
| 471 int32_t height_; | |
| 472 GLuint frag_shader_; | |
| 473 GLuint vertex_shader_; | |
| 474 GLuint program_; | |
| 475 GLuint vertex_buffer_; | |
| 476 GLuint index_buffer_; | |
| 477 GLuint texture_; | |
| 478 | |
| 479 GLuint texture_loc_; | |
| 480 GLuint position_loc_; | |
| 481 GLuint texcoord_loc_; | |
| 482 GLuint color_loc_; | |
| 483 GLuint mvp_loc_; | |
| 484 | |
| 485 float x_angle_; | |
| 486 float y_angle_; | |
| 487 bool animating_; | |
| 488 }; | |
| 489 | |
| 490 class Graphics3DModule : public pp::Module { | |
| 491 public: | |
| 492 Graphics3DModule() : pp::Module() {} | |
| 493 virtual ~Graphics3DModule() {} | |
| 494 | |
| 495 virtual pp::Instance* CreateInstance(PP_Instance instance) { | |
| 496 return new Graphics3DInstance(instance); | |
| 497 } | |
| 498 }; | |
| 499 | |
| 500 namespace pp { | |
| 501 Module* CreateModule() { return new Graphics3DModule(); } | |
| 502 } // namespace pp | |
| OLD | NEW |