1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: gx_VertexBuffer.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 47228 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/os.h>
17 #include <nn/fnd.h>
18 #include <nn/gx.h>
19 #include <nn/math.h>
20 #include <nn/fs.h>
21 #include <nn/init.h>
22 #include <nn/applet.h>
23
24 #include "demo.h"
25
26 namespace
27 {
28 // Specify whether the vertex buffer and the index buffer are copied into main memory as well as whether they are allocated in main memory, VRAMA, or VRAMB.
29 //
30 //
31 //
32 enum
33 {
34 // (a) When there is a copy to main memory and when PICA accesses the copy in main memory
35 USE_VBO_MEM_MAIN_COPY = 0,
36
37 // (b) When there is no copy in main memory and PICA directly accesses main memory
38 USE_VBO_MEM_MAIN_NO_COPY,
39
40 // (c) When there is a copy in main memory and PICA accesses VRAMA
41 // Sends data from the copy in main memory to VRAMA using DMA transfer, and PICA accesses that VRAMA.
42 USE_VBO_VRAMA_COPY,
43
44 // (d) When there is no copy in main memory and PICA accesses VRAMA
45 // Sends data from main memory to VRAMA using DMA transfer, and PICA accesses that VRAMA.
46 USE_VBO_VRAMA_NO_COPY,
47
48 // (e) When there is a copy in main memory and PICA accesses VRAMB
49 // Sends data from the copy in main memory to VRAMB using DMA transfer, and PICA accesses that VRAMB.
50 USE_VBO_VRAMB_COPY,
51
52 // (f) When there is no copy in main memory and PICA accesses VRAMB
53 // Sends data from main memory to VRAMB using DMA transfer, and PICA accesses that VRAMB.
54 USE_VBO_VRAMB_NO_COPY
55 };
56
57 u32 s_VertexBufferPattern = USE_VBO_MEM_MAIN_COPY;
58 // u32 s_VertexBufferPattern = USE_VBO_MEM_MAIN_NO_COPY;
59 // u32 s_VertexBufferPattern = USE_VBO_VRAMA_COPY;
60 // u32 s_VertexBufferPattern = USE_VBO_VRAMA_NO_COPY;
61 // u32 s_VertexBufferPattern = USE_VBO_VRAMB_COPY;
62 // u32 s_VertexBufferPattern = USE_VBO_VRAMB_NO_COPY;
63
64 GLenum s_ArrayBufferDataType = GL_ARRAY_BUFFER;
65 GLenum s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER;
66
67 GLuint s_ProgramId = 0;
68 GLuint s_ShaderId = 0;
69
70 nn::fnd::ExpHeap s_AppHeap;
71 uptr s_AddrForGxHeap;
72 const u32 s_GxHeapSize = 0x400000;
73
74 demo::RenderSystem s_RenderSystem;
75
76 nn::math::Vector3 s_CameraPosition(0.0f, 2.0f, 2.0f);
77 nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
78 nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
79
80 nn::math::Matrix34 s_ViewMatrix;
81 nn::math::Matrix44 s_Display0ProjectionMatrix;
82 nn::math::Matrix44 s_Display1ProjectionMatrix;
83
84 f32 s_GlobalAmbientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f};
85 f32 s_Light0Ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f};
86 f32 s_Light0Diffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f};
87 f32 s_Light0Position[] = { 10.0f, 10.0f, 10.0f, 1.0f};
88
89 f32 s_MaterialAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f};
90 f32 s_MaterialDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
91
92 const u32 VERTEX_POSITION_ATTRIBUTE_INDEX = 0;
93 const u32 VERTEX_COLOR_ATTRIBUTE_INDEX = 1;
94 const u32 VERTEX_NORMAL_ATTRIBUTE_INDEX = 2;
95 const u32 VERTEX_ATTRIBUTES_NUM = 3;
96
97 const u32 VERTEX_POSITION_ATTRIBUTE_SIZE = 4;
98 const u32 VERTEX_COLOR_ATTRIBUTE_SIZE = 4;
99 const u32 VERTEX_NORMAL_ATTRIBUTE_SIZE = 3;
100
101 const u32 s_VerticesNum = 24;
102 const u32 s_TrianglesNum = 12;
103 const u32 s_PositionArraySize = s_VerticesNum * VERTEX_POSITION_ATTRIBUTE_SIZE * 4;
104 const u32 s_ColorArraySize = s_VerticesNum * VERTEX_COLOR_ATTRIBUTE_SIZE * 4;
105 const u32 s_NormalArraySize = s_VerticesNum * VERTEX_NORMAL_ATTRIBUTE_SIZE * 4;
106 const u32 s_IndexArraySize = s_TrianglesNum * 3 * 2;
107
108 GLfloat* s_PositionArray = NULL;
109 GLfloat* s_ColorArray = NULL;
110 GLfloat* s_NormalArray = NULL;
111 GLushort* s_IndexArray = NULL;
112
113 GLuint s_ArrayBufferIdArray[3];
114 GLuint s_ElementArrayBufferId = 0;
115
116 f32 s_CubeHalfEdge[3];
117 nn::math::MTX44 s_WorldMatrix;
118 f32 s_Position[3];
119 f32 s_Angle[3];
120 }
121
122 void InitializeGraphics(void);
123 void InitializeCube(void);
124 void InitializeShader(void);
125
126 void AllocateCube(void);
127 void SetCube(void);
128 void UpdateCubeVBO(const bool& updatePosition=true, const bool& updateColor=true,
129 const bool& updateNormal=true, const bool& updateIndex=true);
130
131 void SetCubePosition(void);
132 void SetCubeColor(const f32& red, const f32& green, const f32& blue, const f32& alpha);
133 void SetCubeNormal(void);
134 void SetCubeIndex(void);
135
136 void FinalizeCube(void);
137 void DeallocateCube(void);
138
139 void UseShader(void);
140 void UpdateCamera(void);
141 void DrawDisplay0(void);
142 void DrawDisplay1(void);
143
144 void UpdateCube(void);
145 void DrawCube(void);
146
Initialize(void)147 void Initialize(void)
148 {
149 // fs initialization
150 nn::fs::Initialize();
151
152 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
153 static char buffer[ROMFS_BUFFER_SIZE];
154 NN_UTIL_PANIC_IF_FAILED(
155 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
156
157 InitializeGraphics();
158 }
159
InitializeGraphics(void)160 void InitializeGraphics(void)
161 {
162 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
163 nn::os::GetDeviceMemorySize() );
164 s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
165
166 s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
167
168 // Stops executing the command list.
169 nngxStopCmdlist();
170
171 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
172 glClearDepthf(1.f);
173
174 glEnable(GL_DEPTH_TEST);
175 glDepthFunc(GL_LESS);
176
177 glEnable(GL_CULL_FACE);
178 glFrontFace(GL_CCW);
179 glCullFace(GL_BACK);
180
181 InitializeShader();
182
183 // Initialize projection matrix
184 nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f,
185 demo::DISPLAY0_ASPECT, 0.2f, 100.0f,
186 nn::math::PIVOT_UPSIDE_TO_TOP);
187
188 nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f,
189 demo::DISPLAY1_ASPECT, 0.2f, 100.0f,
190 nn::math::PIVOT_UPSIDE_TO_TOP);
191
192 InitializeCube();
193
194 NN_LOG("Update vertex color to RED->GREEN->BLUE.\n");
195 }
196
InitializeShader(void)197 void InitializeShader(void)
198 {
199 s_ProgramId = glCreateProgram();
200
201 // Load vertex shader
202 s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
203 nn::fs::FileReader file(L"rom:/shader.shbin");
204 size_t fileSize = file.GetSize();
205 void* buf = s_AppHeap.Allocate(fileSize);
206 s32 read = file.Read(buf, fileSize);
207 glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
208 file.Finalize();
209 s_AppHeap.Free(buf);
210
211 glAttachShader(s_ProgramId, s_ShaderId);
212 glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
213
214 glBindAttribLocation(s_ProgramId, VERTEX_POSITION_ATTRIBUTE_INDEX, "aPosition");
215 glBindAttribLocation(s_ProgramId, VERTEX_COLOR_ATTRIBUTE_INDEX, "aColor");
216 glBindAttribLocation(s_ProgramId, VERTEX_NORMAL_ATTRIBUTE_INDEX, "aNormal");
217
218 glLinkProgram(s_ProgramId);
219 glValidateProgram(s_ProgramId);
220
221 demo::InitializeUniforms(s_ProgramId);
222 }
223
InitializeCube(void)224 void InitializeCube(void)
225 {
226 // (a) When there is a copy to main memory and when PICA accesses the copy in main memory
227 if ( s_VertexBufferPattern == USE_VBO_MEM_MAIN_COPY )
228 {
229 s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP;
230 s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP;
231 NN_LOG("Allocate the vertex buffer in main memory with COPY.\n");
232 NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP\n");
233 NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP\n");
234 }
235 // (b) When there is no copy in main memory and PICA directly accesses main memory
236 else if ( s_VertexBufferPattern == USE_VBO_MEM_MAIN_NO_COPY )
237 {
238 s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
239 s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
240 NN_LOG("Allocate the vertex buffer in main memory with NO_COPY.\n");
241 NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP\n");
242 NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP\n");
243 }
244 // (c) When there is a copy in main memory and PICA accesses VRAMA
245 else if ( s_VertexBufferPattern == USE_VBO_VRAMA_COPY )
246 {
247 s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP;
248 s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP;
249 NN_LOG("Allocate the vertex buffer in VRAMA with FCRAM COPY.\n");
250 NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP\n");
251 NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP\n");
252 }
253 // (d) When there is no copy in main memory and PICA accesses VRAMA
254 else if ( s_VertexBufferPattern == USE_VBO_VRAMA_NO_COPY )
255 {
256 s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP;
257 s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP;
258 NN_LOG("Allocate the vertex buffer in VRAMA with FCRAM NO_COPY.\n");
259 NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP\n");
260 NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP\n");
261 }
262 // (e) When there is a copy in main memory and PICA accesses VRAMB
263 else if ( s_VertexBufferPattern == USE_VBO_VRAMB_COPY )
264 {
265 s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP;
266 s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP;
267 NN_LOG("Allocate the vertex buffer in VRAMB with FCRAM COPY.\n");
268 NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP\n");
269 NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP\n");
270 }
271 // (f) When there is no copy in main memory and PICA accesses VRAMB
272 else if ( s_VertexBufferPattern == USE_VBO_VRAMB_NO_COPY )
273 {
274 s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP;
275 s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP;
276 NN_LOG("Allocate the vertex buffer in VRAMB with FCRAM NO_COPY.\n");
277 NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP\n");
278 NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP\n");
279 }
280
281 // Allocates the arrays for vertex data and indices
282 AllocateCube();
283
284 SetCube();
285
286 // Generates the vertex buffer
287 for (u32 index = 0; index < 3; index++)
288 {
289 s_ArrayBufferIdArray[index] = 0;
290 }
291 glGenBuffers(3, s_ArrayBufferIdArray);
292 if ( s_ArrayBufferIdArray == NULL )
293 {
294 NN_PANIC("FILE(%s), LINE(%d) : s_ArrayBufferIdArray is 0.\n", __FILE__, __LINE__);
295 }
296
297 // POSITION : Allocates the vertex buffer
298 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_POSITION_ATTRIBUTE_INDEX]);
299 glBufferData(s_ArrayBufferDataType, s_PositionArraySize, s_PositionArray, GL_STATIC_DRAW);
300
301 // COLOR Allocates the vertex buffer
302 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_COLOR_ATTRIBUTE_INDEX]);
303 glBufferData(s_ArrayBufferDataType, s_ColorArraySize, s_ColorArray, GL_STATIC_DRAW);
304
305 // NORMAL : Allocates the vertex buffer
306 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_NORMAL_ATTRIBUTE_INDEX]);
307 glBufferData(s_ArrayBufferDataType, s_NormalArraySize, s_NormalArray, GL_STATIC_DRAW);
308
309 // Generates the index buffer
310 glGenBuffers(1, &s_ElementArrayBufferId);
311 if ( s_ElementArrayBufferId == 0 )
312 {
313 NN_PANIC("FILE(%s), LINE(%d) : s_ElementArrayBufferId is 0.\n", __FILE__, __LINE__);
314 }
315
316 // INDEX
317 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferId);
318 glBufferData(s_ElementArrayBufferDataType, s_IndexArraySize, s_IndexArray, GL_STATIC_DRAW);
319
320 // Updates the vertex buffer and index buffer.
321 UpdateCubeVBO();
322
323 DEMO_ASSERT_GL_ERROR();
324 }
325
AllocateCube(void)326 void AllocateCube(void)
327 {
328 // If there is no copy in main memory (cases (b), (d) (f)), the vertex data must be allocated from device memory.
329 //
330 // In this demo, all vertex data is allocated from device memory.
331
332 // Allocate vertex arrays from device memory
333 s_PositionArray = (f32*)demo::Alloc(s_PositionArraySize);
334 if ( s_PositionArray == NULL )
335 {
336 NN_PANIC("FILE(%s), LINE(%d) : s_PositionArray is NULL.\n", __FILE__, __LINE__);
337 }
338
339 s_ColorArray = (f32*)demo::Alloc(s_ColorArraySize);
340 if ( s_ColorArray == NULL )
341 {
342 NN_PANIC("FILE(%s), LINE(%d) : s_ColorArray is NULL.\n", __FILE__, __LINE__);
343 }
344
345 s_NormalArray = (f32*)demo::Alloc(s_NormalArraySize);
346 if ( s_NormalArray == NULL )
347 {
348 NN_PANIC("FILE(%s), LINE(%d) : s_NormalArray is NULL.\n", __FILE__, __LINE__);
349 }
350
351 // Allocate index arrays from device memory
352 s_IndexArray = (GLushort*)demo::Alloc(s_IndexArraySize);
353 if ( s_IndexArray == NULL )
354 {
355 NN_PANIC("FILE(%s), LINE(%d) : s_IndexArray is NULL.\n", __FILE__, __LINE__);
356 }
357 }
358
SetCube(void)359 void SetCube(void)
360 {
361 for (u32 index = 0; index < 3; index++)
362 {
363 s_CubeHalfEdge[index] = 0.5f;
364 }
365
366 for (u32 index = 0; index < 3; index++)
367 {
368 s_Position[index] = 0.0f;
369 s_Angle[index] = 0.0f;
370 }
371
372 SetCubePosition();
373 SetCubeColor(1.0f, 0.0f, 0.0f, 1.0f);
374 SetCubeNormal();
375 SetCubeIndex();
376 }
377
SetCubePosition(void)378 void SetCubePosition(void)
379 {
380 // POSITION : -Y face
381 u32 vertexIndex = 0;
382 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
383 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
384 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
385 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
386 vertexIndex++;
387
388 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
389 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
390 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
391 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
392 vertexIndex++;
393
394 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
395 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
396 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
397 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
398 vertexIndex++;
399
400 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
401 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
402 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
403 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
404 vertexIndex++;
405
406 // POSITION : +Y face
407 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
408 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
409 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
410 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
411 vertexIndex++;
412
413 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
414 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
415 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
416 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
417 vertexIndex++;
418
419 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
420 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
421 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
422 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
423 vertexIndex++;
424
425 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
426 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
427 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
428 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
429 vertexIndex++;
430
431 // POSITION : -Z face
432 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
433 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
434 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
435 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
436 vertexIndex++;
437
438 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
439 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
440 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
441 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
442 vertexIndex++;
443
444 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
445 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
446 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
447 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
448 vertexIndex++;
449
450 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
451 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
452 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
453 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
454 vertexIndex++;
455
456 // POSITION : +Z face
457 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
458 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
459 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
460 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
461 vertexIndex++;
462
463 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
464 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
465 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
466 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
467 vertexIndex++;
468
469 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
470 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
471 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
472 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
473 vertexIndex++;
474
475 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
476 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
477 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
478 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
479 vertexIndex++;
480
481 // POSITION : -X face
482 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
483 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
484 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
485 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
486 vertexIndex++;
487
488 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
489 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
490 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
491 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
492 vertexIndex++;
493
494 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
495 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
496 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
497 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
498 vertexIndex++;
499
500 s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]);
501 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
502 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
503 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
504 vertexIndex++;
505
506 // POSITION : +X face
507 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
508 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
509 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
510 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
511 vertexIndex++;
512
513 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
514 s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]);
515 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
516 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
517 vertexIndex++;
518
519 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
520 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
521 s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]);
522 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
523 vertexIndex++;
524
525 s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]);
526 s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]);
527 s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]);
528 s_PositionArray[4 * vertexIndex + 3] = 1.0f;
529 vertexIndex++;
530 }
531
SetCubeColor(const f32 & red,const f32 & green,const f32 & blue,const f32 & alpha)532 void SetCubeColor(const f32& red, const f32& green, const f32& blue, const f32& alpha)
533 {
534 for (u32 vertexIndex = 0; vertexIndex < s_VerticesNum; vertexIndex++)
535 {
536 s_ColorArray[4 * vertexIndex] = red;
537 s_ColorArray[4 * vertexIndex + 1] = green;
538 s_ColorArray[4 * vertexIndex + 2] = blue;
539 s_ColorArray[4 * vertexIndex + 3] = alpha;
540 }
541 }
542
SetCubeNormal(void)543 void SetCubeNormal(void)
544 {
545 u32 vertexIndex = 0;
546
547 // NORMAL : -Y face
548 for (u32 index = 0; index < 4; index++)
549 {
550 s_NormalArray[3 * vertexIndex] = 0.0f;
551 s_NormalArray[3 * vertexIndex + 1] = -1.0f;
552 s_NormalArray[3 * vertexIndex + 2] = 0.0f;
553 vertexIndex++;
554 }
555
556 // NORMAL : +Y face
557 for (u32 index = 0; index < 4; index++)
558 {
559 s_NormalArray[3 * vertexIndex] = 0.0f;
560 s_NormalArray[3 * vertexIndex + 1] = 1.0f;
561 s_NormalArray[3 * vertexIndex + 2] = 0.0f;
562 vertexIndex++;
563 }
564
565 // NORMAL : -Z face
566 for (u32 index = 0; index < 4; index++)
567 {
568 s_NormalArray[3 * vertexIndex] = 0.0f;
569 s_NormalArray[3 * vertexIndex + 1] = 0.0f;
570 s_NormalArray[3 * vertexIndex + 2] = -1.0f;
571 vertexIndex++;
572 }
573
574 // NORMAL : +Z face
575 for (u32 index = 0; index < 4; index++)
576 {
577 s_NormalArray[3 * vertexIndex] = 0.0f;
578 s_NormalArray[3 * vertexIndex + 1] = 0.0f;
579 s_NormalArray[3 * vertexIndex + 2] = 1.0f;
580 vertexIndex++;
581 }
582
583 // NORMAL : -X face
584 for (u32 index = 0; index < 4; index++)
585 {
586 s_NormalArray[3 * vertexIndex] = -1.0f;
587 s_NormalArray[3 * vertexIndex + 1] = 0.0f;
588 s_NormalArray[3 * vertexIndex + 2] = 1.0f;
589 vertexIndex++;
590 }
591
592 // NORMAL : +X face
593 for (u32 index = 0; index < 4; index++)
594 {
595 s_NormalArray[3 * vertexIndex] = 1.0f;
596 s_NormalArray[3 * vertexIndex + 1] = 0.0f;
597 s_NormalArray[3 * vertexIndex + 2] = 0.0f;
598 vertexIndex++;
599 }
600 }
601
SetCubeIndex(void)602 void SetCubeIndex(void)
603 {
604 u32 triangleIndex = 0;
605
606 // INDEX : -Y face
607 s_IndexArray[3 * triangleIndex] = 0;
608 s_IndexArray[3 * triangleIndex + 1] = 2;
609 s_IndexArray[3 * triangleIndex + 2] = 1;
610 triangleIndex++;
611 s_IndexArray[3 * triangleIndex] = 0;
612 s_IndexArray[3 * triangleIndex + 1] = 3;
613 s_IndexArray[3 * triangleIndex + 2] = 2;
614 triangleIndex++;
615
616 // INDEX : +Y face
617 s_IndexArray[3 * triangleIndex] = 4;
618 s_IndexArray[3 * triangleIndex + 1] = 6;
619 s_IndexArray[3 * triangleIndex + 2] = 5;
620 triangleIndex++;
621 s_IndexArray[3 * triangleIndex] = 4;
622 s_IndexArray[3 * triangleIndex + 1] = 7;
623 s_IndexArray[3 * triangleIndex + 2] = 6;
624 triangleIndex++;
625
626 // INDEX : -Z face
627 s_IndexArray[3 * triangleIndex] = 8;
628 s_IndexArray[3 * triangleIndex + 1] = 10;
629 s_IndexArray[3 * triangleIndex + 2] = 9;
630 triangleIndex++;
631 s_IndexArray[3 * triangleIndex] = 8;
632 s_IndexArray[3 * triangleIndex + 1] = 11;
633 s_IndexArray[3 * triangleIndex + 2] = 10;
634 triangleIndex++;
635
636 // INDEX : +Z face
637 s_IndexArray[3 * triangleIndex] = 12;
638 s_IndexArray[3 * triangleIndex + 1] = 14;
639 s_IndexArray[3 * triangleIndex + 2] = 13;
640 triangleIndex++;
641 s_IndexArray[3 * triangleIndex] = 12;
642 s_IndexArray[3 * triangleIndex + 1] = 15;
643 s_IndexArray[3 * triangleIndex + 2] = 14;
644 triangleIndex++;
645
646 // INDEX : -X face
647 s_IndexArray[3 * triangleIndex] = 16;
648 s_IndexArray[3 * triangleIndex + 1] = 18;
649 s_IndexArray[3 * triangleIndex + 2] = 17;
650 triangleIndex++;
651 s_IndexArray[3 * triangleIndex] = 16;
652 s_IndexArray[3 * triangleIndex + 1] = 19;
653 s_IndexArray[3 * triangleIndex + 2] = 18;
654 triangleIndex++;
655
656 // INDEX : +X face
657 s_IndexArray[3 * triangleIndex] = 20;
658 s_IndexArray[3 * triangleIndex + 1] = 22;
659 s_IndexArray[3 * triangleIndex + 2] = 21;
660 triangleIndex++;
661 s_IndexArray[3 * triangleIndex] = 20;
662 s_IndexArray[3 * triangleIndex + 1] = 23;
663 s_IndexArray[3 * triangleIndex + 2] = 22;
664 triangleIndex++;
665 }
666
UpdateCubeVBO(const bool & updatePosition,const bool & updateColor,const bool & updateNormal,const bool & updateIndex)667 void UpdateCubeVBO(const bool& updatePosition, const bool& updateColor, const bool& updateNormal,
668 const bool& updateIndex)
669 {
670 // POSITION : Update the vertex coordinates
671 if ( updatePosition )
672 {
673 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_POSITION_ATTRIBUTE_INDEX]);
674 glBufferSubData(GL_ARRAY_BUFFER, 0, s_PositionArraySize, s_PositionArray);
675 }
676
677 // COLOR Update the vertex color
678 if ( updateColor )
679 {
680 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_COLOR_ATTRIBUTE_INDEX]);
681 glBufferSubData(GL_ARRAY_BUFFER, 0, s_ColorArraySize, s_ColorArray);
682 }
683
684 // NORMAL : Update vertex normals
685 if ( updateNormal )
686 {
687 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_NORMAL_ATTRIBUTE_INDEX]);
688 glBufferSubData(GL_ARRAY_BUFFER, 0, s_NormalArraySize, s_NormalArray);
689 }
690
691 // INDEX : Update vertex indices
692 if ( updateIndex )
693 {
694 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferId);
695 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s_IndexArraySize, s_IndexArray);
696 }
697
698 DEMO_ASSERT_GL_ERROR();
699 }
700
Finalize(void)701 void Finalize(void)
702 {
703 FinalizeCube();
704
705 s_RenderSystem.Finalize();
706
707 s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
708 s_AppHeap.Finalize();
709 }
710
FinalizeCube(void)711 void FinalizeCube(void)
712 {
713 DeallocateCube();
714
715 if ( s_ArrayBufferIdArray[0] != 0 )
716 {
717 glDeleteBuffers(3, s_ArrayBufferIdArray);
718 for (u32 index = 0; index < 3; index++)
719 {
720 s_ArrayBufferIdArray[index] = 0;
721 }
722 }
723
724 if ( s_ElementArrayBufferId != 0 )
725 {
726 glDeleteBuffers(1, &s_ElementArrayBufferId);
727 s_ElementArrayBufferId = 0;
728 }
729 }
730
DeallocateCube(void)731 void DeallocateCube(void)
732 {
733 if ( s_PositionArray != NULL )
734 {
735 demo::Free((void*) s_PositionArray);
736 s_PositionArray = NULL;
737 }
738
739 if ( s_ColorArray != NULL )
740 {
741 demo::Free((void*) s_ColorArray);
742 s_ColorArray = NULL;
743 }
744
745 if ( s_NormalArray != NULL )
746 {
747 demo::Free((void*) s_NormalArray);
748 s_NormalArray = NULL;
749 }
750
751 if ( s_IndexArray != NULL )
752 {
753 demo::Free((void*) s_IndexArray);
754 s_IndexArray = NULL;
755 }
756 }
757
DrawFrame(void)758 bool DrawFrame(void)
759 {
760 UpdateCamera();
761
762 DrawDisplay0();
763 DrawDisplay1();
764
765 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
766
767 // Stops executing the command list.
768 nngxStopCmdlist();
769
770 return true;
771 }
772
UpdateCamera(void)773 void UpdateCamera(void)
774 {
775 nn::math::MTX34LookAt(&s_ViewMatrix, &s_CameraPosition, &s_CameraUp, &s_CameraTarget);
776 }
777
DrawDisplay0(void)778 void DrawDisplay0(void)
779 {
780 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
781 s_RenderSystem.Clear();
782 UseShader();
783 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
784 1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
785
786 UpdateCube();
787 DrawCube();
788
789 s_RenderSystem.SwapBuffers();
790 }
791
UseShader(void)792 void UseShader(void)
793 {
794 glUseProgram(s_ProgramId);
795
796 // Fragment uniform
797 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
798
799 // Fragment uniform : Texture samplerType
800 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE);
801 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
802 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
803 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
804
805 // Fragment uniform : Fragment lighting
806 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
807 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
808 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
809 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_Light0Ambient);
810 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_Light0Diffuse);
811 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION], 1, s_Light0Position);
812
813 // Fragment uniform : Material
814 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
815 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
816
817 // Fragment uniform : Texture combiner
818 // Modulate fragment primary color and vertex color.
819 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
820 GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PRIMARY_COLOR, GL_PREVIOUS);
821 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
822 GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS);
823 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
824 GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
825 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
826 GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
827 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
828 GL_MODULATE);
829 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
830 GL_MODULATE);
831 }
832
DrawDisplay1(void)833 void DrawDisplay1(void)
834 {
835 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
836 s_RenderSystem.Clear();
837
838 s_RenderSystem.SwapBuffers();
839 }
840
UpdateCube(void)841 void UpdateCube(void)
842 {
843 static u32 mode = 1;
844 static u32 counter = 0;
845 static const u32 maxCounter = 120;
846
847 s_Angle[1] += 1.0f;
848 if ( s_Angle[1] > 360.f )
849 {
850 s_Angle[1] -= 360.0f;
851 }
852
853 nn::math::Vector3 positionVector(s_Position[0], s_Position[1], s_Position[2]);
854 nn::math::MTX34 positionMatrix;
855 nn::math::MTX34Identity(&positionMatrix);
856 nn::math::MTX34Translate(&positionMatrix, &positionVector);
857 nn::math::MTX44 worldMatrix(positionMatrix);
858
859 nn::math::MTX44 worldRotMatrix;
860 nn::math::MTX44RotXYZDeg(&worldRotMatrix, s_Angle[0], s_Angle[1], s_Angle[2]);
861 nn::math::MTX44Mult(&s_WorldMatrix, &worldMatrix, &worldRotMatrix);
862
863 // Updates the vertex color periodically.
864 if ( counter > maxCounter )
865 {
866 if ( mode == 0 )
867 {
868 SetCubeColor(1.0f, 0.0f, 0.0f, 1.0f);
869 mode = 1;
870 }
871 else if ( mode == 1 )
872 {
873 SetCubeColor(0.0f, 1.0f, 0.0f, 1.0f);
874 mode = 2;
875 }
876 else if ( mode == 2 )
877 {
878 SetCubeColor(0.0f, 0.0f, 1.0f, 1.0f);
879 mode = 0;
880 }
881
882 // Updates the vertex buffer for vertex color
883 UpdateCubeVBO(false, true, false, false);
884 counter = 0;
885 }
886 else
887 {
888 counter++;
889 }
890 }
891
DrawCube(void)892 void DrawCube(void)
893 {
894 nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
895 nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &s_WorldMatrix);
896 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
897 1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
898
899 // POSITION
900 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_POSITION_ATTRIBUTE_INDEX]);
901 glEnableVertexAttribArray(VERTEX_POSITION_ATTRIBUTE_INDEX);
902 glVertexAttribPointer(VERTEX_POSITION_ATTRIBUTE_INDEX,
903 VERTEX_POSITION_ATTRIBUTE_SIZE,
904 GL_FLOAT, GL_FALSE, 0, 0);
905
906 // COLOR
907 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_COLOR_ATTRIBUTE_INDEX]);
908 glEnableVertexAttribArray(VERTEX_COLOR_ATTRIBUTE_INDEX);
909 glVertexAttribPointer(VERTEX_COLOR_ATTRIBUTE_INDEX,
910 VERTEX_COLOR_ATTRIBUTE_SIZE,
911 GL_FLOAT, GL_FALSE, 0, 0);
912
913 // NORMAL
914 glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_NORMAL_ATTRIBUTE_INDEX]);
915 glEnableVertexAttribArray(VERTEX_NORMAL_ATTRIBUTE_INDEX);
916 glVertexAttribPointer(VERTEX_NORMAL_ATTRIBUTE_INDEX,
917 VERTEX_NORMAL_ATTRIBUTE_SIZE,
918 GL_FLOAT, GL_FALSE, 0, 0);
919
920 for (u32 index = VERTEX_ATTRIBUTES_NUM; index < 8; index++)
921 {
922 glDisableVertexAttribArray(index);
923 }
924
925 glDrawElements(GL_TRIANGLES, s_TrianglesNum * 3, GL_UNSIGNED_SHORT, 0);
926 }
927
nnMain(void)928 void nnMain(void)
929 {
930 // Call only nn::applet::Enable to also allow execution from the HOME Menu
931 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
932 nn::applet::Enable();
933
934 Initialize();
935
936 bool flag = true;
937 while ( flag )
938 {
939 flag = DrawFrame();
940 }
941
942 Finalize();
943 }
944