1 // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "shader_util.h"
10 #include "transforms.h"
14 static const size_t kVertexCount = 24;
15 static const int kIndexCount = 36;
17 Cube::Cube(SharedOpenGLContext opengl_context)
18 : opengl_context_(opengl_context),
21 eye_[0] = eye_[1] = 0.0f;
23 orientation_[0] = 0.0f;
24 orientation_[1] = 0.0f;
25 orientation_[2] = 0.0f;
26 orientation_[3] = 1.0f;
30 glDeleteBuffers(3, cube_vbos_);
31 glDeleteProgram(shader_program_object_);
34 void Cube::PrepareOpenGL() {
37 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
38 glEnable(GL_DEPTH_TEST);
41 void Cube::Resize(int width, int height) {
42 width_ = std::max(width, 1);
43 height_ = std::max(height, 1);
45 glViewport(0, 0, width_, height_);
46 // Compute the perspective projection matrix with a 60 degree FOV.
47 GLfloat aspect = static_cast<GLfloat>(width_) / static_cast<GLfloat>(height_);
48 transform_4x4::LoadIdentity(perspective_proj_);
49 transform_4x4::Perspective(perspective_proj_, 60.0f, aspect, 1.0f, 20.0f);
53 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
55 // Compute a new model-view matrix, then use that to make the composite
56 // model-view-projection matrix: MVP = MV . P.
57 GLfloat model_view[16];
58 ComputeModelViewTransform(model_view);
59 transform_4x4::Multiply(mvp_matrix_, model_view, perspective_proj_);
61 glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
62 glUseProgram(shader_program_object_);
63 glEnableVertexAttribArray(position_location_);
64 glVertexAttribPointer(position_location_,
70 glEnableVertexAttribArray(color_location_);
71 glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
72 glVertexAttribPointer(color_location_,
78 glUniformMatrix4fv(mvp_location_, 1, GL_FALSE, mvp_matrix_);
79 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
80 glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
81 glBindBuffer(GL_ARRAY_BUFFER, 0);
82 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
85 bool Cube::CreateShaders() {
86 const char vertex_shader_src[] =
87 "uniform mat4 u_mvpMatrix; \n"
88 "attribute vec4 a_position; \n"
89 "attribute vec3 a_color; \n"
90 "varying lowp vec4 v_color; \n"
93 " v_color.xyz = a_color; \n"
94 " v_color.w = 1.0; \n"
95 " gl_Position = u_mvpMatrix * a_position; \n"
98 const char fragment_shader_src[] =
99 "varying lowp vec4 v_color; \n"
102 " gl_FragColor = v_color; \n"
105 // Load the shaders and get a linked program object
106 shader_program_object_ =
107 shader_util::CreateProgramFromVertexAndFragmentShaders(
108 vertex_shader_src, fragment_shader_src);
109 if (shader_program_object_ == 0)
111 position_location_ = glGetAttribLocation(shader_program_object_,
113 color_location_ = glGetAttribLocation(shader_program_object_, "a_color");
114 mvp_location_ = glGetUniformLocation(shader_program_object_, "u_mvpMatrix");
118 void Cube::CreateCube() {
119 static const GLfloat cube_vertices[] = {
120 // Vertex coordinates interleaved with color values
153 static const GLfloat cube_colors[] = {
154 // Vertex coordinates interleaved with color values
187 static const GLushort cube_indices[] = {
208 // Generate the VBOs and upload them to the graphics context.
209 glGenBuffers(3, cube_vbos_);
210 glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
211 glBufferData(GL_ARRAY_BUFFER,
212 kVertexCount * sizeof(GLfloat) * 3,
215 glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
216 glBufferData(GL_ARRAY_BUFFER,
217 kVertexCount * sizeof(GLfloat) * 3,
220 glBindBuffer(GL_ARRAY_BUFFER, 0);
221 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
222 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
223 kIndexCount * sizeof(GL_UNSIGNED_SHORT),
226 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
229 void Cube::ComputeModelViewTransform(GLfloat* model_view) {
230 // This method takes into account the possiblity that |orientation_|
231 // might not be normalized.
232 double sqrx = orientation_[0] * orientation_[0];
233 double sqry = orientation_[1] * orientation_[1];
234 double sqrz = orientation_[2] * orientation_[2];
235 double sqrw = orientation_[3] * orientation_[3];
236 double sqrLength = 1.0 / (sqrx + sqry + sqrz + sqrw);
238 transform_4x4::LoadIdentity(model_view);
239 model_view[0] = (sqrx - sqry - sqrz + sqrw) * sqrLength;
240 model_view[5] = (-sqrx + sqry - sqrz + sqrw) * sqrLength;
241 model_view[10] = (-sqrx - sqry + sqrz + sqrw) * sqrLength;
243 double temp1 = orientation_[0] * orientation_[1];
244 double temp2 = orientation_[2] * orientation_[3];
245 model_view[1] = 2.0 * (temp1 + temp2) * sqrLength;
246 model_view[4] = 2.0 * (temp1 - temp2) * sqrLength;
248 temp1 = orientation_[0] * orientation_[2];
249 temp2 = orientation_[1] * orientation_[3];
250 model_view[2] = 2.0 * (temp1 - temp2) * sqrLength;
251 model_view[8] = 2.0 * (temp1 + temp2) * sqrLength;
252 temp1 = orientation_[1] * orientation_[2];
253 temp2 = orientation_[0] * orientation_[3];
254 model_view[6] = 2.0 * (temp1 + temp2) * sqrLength;
255 model_view[9] = 2.0 * (temp1 - temp2) * sqrLength;
258 model_view[11] = 0.0;
260 // Concatenate the translation to the eye point.
261 model_view[12] = -eye_[0];
262 model_view[13] = -eye_[1];
263 model_view[14] = -eye_[2];
264 model_view[15] = 1.0;
267 } // namespace tumbler