1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: gx_CommandListDouble.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 #define USE_COMMAND_LIST_DOUBLE
27
28 namespace
29 {
30 GLuint s_ProgramId = 0;
31 GLuint s_ShaderId = 0;
32
33 nn::fnd::ExpHeap s_AppHeap;
34 uptr s_AddrForGxHeap;
35 const u32 s_GxHeapSize = 0x400000;
36
37 nn::os::Tick s_FrameStartTick;
38 nn::os::Tick s_FrameEndTick;
39 nn::os::Tick s_StoreTick;
40 nn::os::Tick s_RenderTick;
41
42 nn::math::Vector3 s_CameraPosition(0.0f, 1.0f, 5.0f);
43 nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
44 nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
45
46 nn::math::Matrix34 s_ViewMatrix;
47 nn::math::Matrix44 s_Display0ProjectionMatrix;
48 nn::math::Matrix44 s_Display1ProjectionMatrix;
49
50 f32 s_GlobalAmbientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f};
51 f32 s_Light0Ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f};
52 f32 s_Light0Diffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f};
53 f32 s_Light0Position[] = {10.0f, 10.0f, 10.0f, 0.0f};
54
55 f32 s_MaterialAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f};
56 f32 s_MaterialDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
57
58 const u32 s_RowCubeNum = 20;
59 const u32 s_ColumnCubeNum = 10;
60 demo::Cube s_Cube[s_RowCubeNum][s_ColumnCubeNum];
61
62 const u32 s_MaxCount = 120;
63 }
64
65 namespace demo
66 {
67 //
68 // Class that double buffers the render command list
69 //
70 class RenderSystemDouble : public demo::RenderSystem
71 {
72 public:
73 RenderSystemDouble(void);
74 virtual ~RenderSystemDouble();
75
76 public:
77 virtual void Initialize(const uptr fcramAddress, const size_t memorySize,
78 const u32 commandBufferSize = 0x40000, const u32 requestNum = 128,
79 const bool serialRunMode = true,
80 const demo::DisplayBuffersDescription& displayBuffers0Desc = DisplayBuffersDescription::GetDefaultDisplay0Description(),
81 const demo::DisplayBuffersDescription& displayBuffers1Desc = DisplayBuffersDescription::GetDefaultDisplay1Description(),
82 const demo::FrameBufferDescription& frameBuffer0Desc = FrameBufferDescription::GetDefaultDisplay0FrameBufferDescription(),
83 const demo::DisplayBuffersDescription& displayBuffers0ExtDesc = DisplayBuffersDescription::GetDefaultDisplay0ExtDescription() );
84 virtual void Finalize(void);
85
86 protected:
87 void CreateCommandListDouble(GLsizei bufSize, GLsizei reqCountNum);
88 void RunCommandListDouble(void);
89
90 public:
91 virtual void SwapBuffers(void);
92 protected:
93 virtual void SwapBuffers0(void);
94 virtual void SwapBuffers1(void);
95
96 protected:
97 GLuint m_CurrentDisplay0BufferIndex;
98 GLuint m_CurrentDisplay1BufferIndex;
99
100 GLuint m_Display0BufferIdArray[2];
101 GLuint m_Display1BufferIdArray[2];
102
103 GLuint m_CurrentCommandListIndex;
104 GLuint m_CommandListIdArray[2];
105 };
106
RenderSystemDouble()107 RenderSystemDouble::RenderSystemDouble() :
108 demo::RenderSystem(),
109 m_CurrentDisplay0BufferIndex(0), m_CurrentDisplay1BufferIndex(0),
110 m_CurrentCommandListIndex(0)
111 {
112 for (u32 index = 0; index < 2; index++)
113 {
114 m_Display0BufferIdArray[index] = 0;
115 m_Display1BufferIdArray[index] = 0;
116
117 m_CommandListIdArray[index] = 0;
118 }
119 }
120
~RenderSystemDouble()121 RenderSystemDouble::~RenderSystemDouble()
122 {
123 }
124
Initialize(const uptr fcramAddress,const size_t memorySize,const u32 commandBufferSize,const u32 requestNum,const bool serialRunMode,const demo::DisplayBuffersDescription & displayBuffers0Desc,const demo::DisplayBuffersDescription & displayBuffers1Desc,const demo::FrameBufferDescription & frameBuffer0Desc,const demo::DisplayBuffersDescription & displayBuffers0ExtDesc)125 void RenderSystemDouble::Initialize(const uptr fcramAddress, const size_t memorySize,
126 const u32 commandBufferSize, const u32 requestNum,
127 const bool serialRunMode,
128 const demo::DisplayBuffersDescription& displayBuffers0Desc,
129 const demo::DisplayBuffersDescription& displayBuffers1Desc,
130 const demo::FrameBufferDescription& frameBuffer0Desc,
131 const demo::DisplayBuffersDescription& displayBuffers0ExtDesc)
132 {
133 NN_UNUSED_VAR(serialRunMode);
134 NN_UNUSED_VAR(displayBuffers0ExtDesc);
135
136 #ifdef USE_COMMAND_LIST_DOUBLE
137 demo::InitializeMemoryManager(fcramAddress, memorySize);
138 if ( nngxInitialize(demo::GetAllocator, demo::GetDeallocator) == GL_FALSE )
139 {
140 NN_TPANIC_("nngxInitialize() failed.\n");
141 }
142
143 // Double buffer the command list
144 CreateCommandListDouble(commandBufferSize, requestNum);
145
146 DisplayBuffers::Create(displayBuffers0Desc, m_DisplayBuffers0);
147 DEMO_ASSERT_GL_ERROR();
148
149 DisplayBuffers::Create(displayBuffers1Desc, m_DisplayBuffers1);
150 DEMO_ASSERT_GL_ERROR();
151
152 m_CurrentDisplay0BufferIndex = 0;
153 m_CurrentDisplay1BufferIndex = 0;
154
155 for (u32 index = 0; index < 2; index++)
156 {
157 m_Display0BufferIdArray[index] = m_DisplayBuffers0.GetDisplayBufferId(index);
158 m_Display1BufferIdArray[index] = m_DisplayBuffers1.GetDisplayBufferId(index);
159 }
160
161 FrameBuffer::Create(frameBuffer0Desc, m_FrameBuffer0);
162 DEMO_ASSERT_GL_ERROR();
163
164 m_InitializeFlag = true;
165
166 InitializeLcdDisplay();
167
168 DEMO_ASSERT_GL_ERROR();
169 #else
170
171 RenderSystem::Initialize(fcramAddress, memorySize,
172 commandBufferSize, requestNum, serialRunMode,
173 displayBuffers0Desc, displayBuffers1Desc, frameBuffer0Desc);
174 #endif
175 }
176
CreateCommandListDouble(GLsizei bufSize,GLsizei reqCountNum)177 void RenderSystemDouble::CreateCommandListDouble(GLsizei bufSize, GLsizei reqCountNum)
178 {
179 nngxGenCmdlists(2, &m_CommandListIdArray[0]);
180 for (u32 index = 0; index < 2; index++)
181 {
182 nngxBindCmdlist(m_CommandListIdArray[index]);
183 nngxCmdlistStorage(bufSize, reqCountNum);
184 nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN);
185 nngxClearCmdlist();
186 }
187
188 m_CurrentCommandListIndex = 0;
189 nngxBindCmdlist( m_CommandListIdArray[m_CurrentCommandListIndex] );
190 }
191
Finalize(void)192 void RenderSystemDouble::Finalize(void)
193 {
194 #ifdef USE_COMMAND_LIST_DOUBLE
195 nngxDeleteCmdlists(2, &m_CommandListIdArray[0]);
196 #endif
197
198 RenderSystem::Finalize();
199 }
200
SwapBuffers(void)201 void RenderSystemDouble::SwapBuffers(void)
202 {
203 #ifdef USE_COMMAND_LIST_DOUBLE
204 if ( m_TargetDisplay == NN_GX_DISPLAY0 )
205 {
206 SwapBuffers0();
207 }
208 else if ( m_TargetDisplay == NN_GX_DISPLAY1 )
209 {
210 SwapBuffers1();
211 }
212 else
213 {
214 NN_TPANIC_("Invalid display.\n");
215 }
216 #else
217 RenderSystem::SwapBuffers();
218 s_RenderTick = nn::os::Tick::GetSystemCurrent();
219 #endif
220
221 }
222
SwapBuffers0(void)223 void RenderSystemDouble::SwapBuffers0(void)
224 {
225 if (! m_InitializeFlag )
226 {
227 return;
228 }
229
230 // Sends the color buffer contents for each screen to display buffers.
231 nngxTransferRenderImage(m_Display0BufferIdArray[m_CurrentDisplay0BufferIndex],
232 NN_GX_ANTIALIASE_NOT_USED, GL_FALSE, 0, 0);
233
234 // Binds the display buffers to each display
235 // However, the buffers for the previous screens are bound
236 nngxActiveDisplay(NN_GX_DISPLAY0);
237 m_CurrentDisplay0BufferIndex = 1 - m_CurrentDisplay0BufferIndex;
238 nngxBindDisplaybuffer(m_Display0BufferIdArray[m_CurrentDisplay0BufferIndex]);
239
240 // Waits for the color buffer to finish sending.
241 RunCommandListDouble();
242
243 // Measures the time it takes to finish rendering to the upper screen
244 s_RenderTick = nn::os::Tick::GetSystemCurrent();
245
246 nngxSwapBuffers(m_TargetDisplay);
247
248 // Binds the accumulated command list and executes it
249 nngxBindCmdlist( m_CommandListIdArray[m_CurrentCommandListIndex] );
250 nngxRunCmdlist();
251
252 // Switches the command list to start accumulating
253 m_CurrentCommandListIndex = 1 - m_CurrentCommandListIndex;
254
255 // Binds the command list to start accumulating
256 nngxBindCmdlist( m_CommandListIdArray[m_CurrentCommandListIndex] );
257 }
258
SwapBuffers1(void)259 void RenderSystemDouble::SwapBuffers1(void)
260 {
261 if (! m_InitializeFlag )
262 {
263 return;
264 }
265
266 // Sends the color buffer contents for each screen to display buffers.
267 nngxTransferRenderImage(m_Display1BufferIdArray[m_CurrentDisplay1BufferIndex],
268 NN_GX_ANTIALIASE_NOT_USED, GL_FALSE, 0, 0);
269
270 // Binds the display buffers to each display
271 // However, the buffers for the previous screens are bound
272 nngxActiveDisplay(NN_GX_DISPLAY1);
273 m_CurrentDisplay0BufferIndex = 1 - m_CurrentDisplay1BufferIndex;
274 nngxBindDisplaybuffer(m_Display1BufferIdArray[m_CurrentDisplay1BufferIndex]);
275
276 // Waits for the color buffer to finish sending.
277 RunCommandListDouble();
278
279 s_RenderTick = nn::os::Tick::GetSystemCurrent();
280
281 nngxSwapBuffers(m_TargetDisplay);
282
283 // Binds the accumulated command list and executes it
284 nngxBindCmdlist( m_CommandListIdArray[m_CurrentCommandListIndex] );
285 nngxRunCmdlist();
286
287 // Switches the command list to start accumulating
288 m_CurrentCommandListIndex = 1 - m_CurrentCommandListIndex;
289
290 // Binds the command list to start accumulating
291 nngxBindCmdlist( m_CommandListIdArray[m_CurrentCommandListIndex] );
292 }
293
RunCommandListDouble(void)294 void RenderSystemDouble::RunCommandListDouble(void)
295 {
296 // Splits the 3D command buffer of the accumulating command list
297 nngxSplitDrawCmdlist();
298
299 // Waits for the executing command list to finish
300 nngxBindCmdlist( m_CommandListIdArray[1 - m_CurrentCommandListIndex] );
301 nngxWaitCmdlistDone();
302
303 // Clears the command list that has finished execution
304 nngxClearCmdlist();
305
306 // Binds the accumulating command list
307 nngxBindCmdlist( m_CommandListIdArray[m_CurrentCommandListIndex] );
308 }
309 }
310
311 namespace
312 {
313 demo::RenderSystemDouble s_RenderSystem;
314 }
315
316 void InitializeGraphics(void);
317 void InitializeShader(void);
318
319 void UseShader(void);
320 void UpdateCamera(void);
321 void DrawDisplay0(void);
322 void DrawDisplay1(void);
323 void DrawBody(demo::Body& body);
324
Initialize(void)325 void Initialize(void)
326 {
327 // fs initialization
328 nn::fs::Initialize();
329
330 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
331 static char buffer[ROMFS_BUFFER_SIZE];
332 NN_UTIL_PANIC_IF_FAILED(
333 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
334
335 InitializeGraphics();
336 }
337
InitializeGraphics(void)338 void InitializeGraphics(void)
339 {
340 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
341 s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
342 s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
343
344 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
345 glClearDepthf(1.0f);
346
347 glEnable(GL_DEPTH_TEST);
348 glDepthFunc(GL_LESS);
349
350 glEnable(GL_CULL_FACE);
351 glFrontFace(GL_CCW);
352 glCullFace(GL_BACK);
353
354 InitializeShader();
355
356 // Initialize projection matrix
357 nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f,
358 demo::DISPLAY0_ASPECT, 0.2f, 100.0f,
359 nn::math::PIVOT_UPSIDE_TO_TOP);
360
361 nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f,
362 demo::DISPLAY1_ASPECT, 0.2f, 100.0f,
363 nn::math::PIVOT_UPSIDE_TO_TOP);
364
365 // Initialize cubes
366 u32 vertexAttributes = demo::VERTEX_POSITION_ATTRIBUTE |
367 demo::VERTEX_COLOR_ATTRIBUTE |
368 demo::VERTEX_NORMAL_ATTRIBUTE;
369
370 f32 s_CubeHalfEdges[3];
371 s_CubeHalfEdges[0] = 0.1f;
372 s_CubeHalfEdges[1] = 0.1f;
373 s_CubeHalfEdges[2] = 0.1f;
374
375 f32 s_CubeOffsetSpace = 0.025f;
376 f32 s_CubeOffsetX = - (s_CubeHalfEdges[0] + s_CubeOffsetSpace) * s_RowCubeNum;
377 f32 s_CubeOffsetY = - (s_CubeHalfEdges[1] + s_CubeOffsetSpace) * s_ColumnCubeNum;
378
379 f32 z = 0.0f;
380 for (u32 j = 0; j < s_ColumnCubeNum; j++)
381 {
382 f32 y = s_CubeOffsetY + 2.0f * (s_CubeHalfEdges[1] + s_CubeOffsetSpace) * j;
383 for (u32 i = 0; i < s_RowCubeNum; i++)
384 {
385 f32 x = s_CubeOffsetX + 2.0f * (s_CubeHalfEdges[0] + s_CubeOffsetSpace) * i;
386 s_Cube[i][j].InitializeCube(vertexAttributes, s_CubeHalfEdges[0], s_CubeHalfEdges[1], s_CubeHalfEdges[2]);
387 s_Cube[i][j].SetWorldPosition(x, y, z);
388
389 f32 color[3];
390 demo::GetRandomColor(color[0], color[1], color[2]);
391 s_Cube[i][j].SetColor(color[0], color[1], color[2]);
392 }
393 }
394
395 #ifdef USE_COMMAND_LIST_DOUBLE
396 NN_LOG("Use double-buffered command list\n");
397 #else
398 NN_LOG("Use single command list\n");
399 #endif
400 NN_LOG(" Total number of cubes = %d\n", s_ColumnCubeNum * s_RowCubeNum);
401 NN_LOG(" Total number of vertices to draw = %d\n", s_ColumnCubeNum * s_RowCubeNum * 24);
402 NN_LOG(" Total number of triangles to draw = %d\n", s_ColumnCubeNum * s_RowCubeNum * 12);
403 }
404
InitializeShader(void)405 void InitializeShader(void)
406 {
407 s_ProgramId = glCreateProgram();
408
409 s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
410 nn::fs::FileReader file(L"rom:/shader.shbin");
411 size_t fileSize = file.GetSize();
412 void* buf = s_AppHeap.Allocate(fileSize);
413 s32 read = file.Read(buf, fileSize);
414 glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
415 file.Finalize();
416 s_AppHeap.Free(buf);
417
418 glAttachShader(s_ProgramId, s_ShaderId);
419
420 glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
421 glBindAttribLocation(s_ProgramId, 0, "aPosition");
422 glBindAttribLocation(s_ProgramId, 1, "aColor");
423 glBindAttribLocation(s_ProgramId, 2, "aNormal");
424
425 glLinkProgram(s_ProgramId);
426 glValidateProgram(s_ProgramId);
427
428 demo::InitializeUniforms(s_ProgramId);
429 }
430
Finalize(void)431 void Finalize(void)
432 {
433 for (u32 j = 0; j < s_ColumnCubeNum; j++)
434 {
435 for (u32 i = 0; i < s_RowCubeNum; i++)
436 {
437 s_Cube[i][j].Finalize();
438 }
439 }
440
441 s_RenderSystem.Finalize();
442
443 s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
444 s_AppHeap.Finalize();
445 }
446
DrawFrame(void)447 bool DrawFrame(void)
448 {
449 static f32 totalStoreTime = 0.0f;
450 static f32 totalRenderTime = 0.0f;
451 static f32 totalFrameTime = 0.0f;
452 static u32 count = 0;
453
454 s_FrameStartTick = nn::os::Tick::GetSystemCurrent();
455
456 UpdateCamera();
457 DrawDisplay0();
458 DrawDisplay1();
459
460 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
461
462 s_FrameEndTick = nn::os::Tick::GetSystemCurrent();
463
464 nn::fnd::TimeSpan storeTimeSpan = s_StoreTick - s_FrameStartTick;
465 totalStoreTime += storeTimeSpan.GetMicroSeconds();
466
467 nn::fnd::TimeSpan renderTimeSpan = s_RenderTick - s_StoreTick;
468 totalRenderTime += renderTimeSpan.GetMicroSeconds();
469
470 nn::fnd::TimeSpan frameTimeSpan = s_FrameEndTick - s_FrameStartTick;
471 totalFrameTime += frameTimeSpan.GetMicroSeconds();
472
473 if ( count >= s_MaxCount )
474 {
475 NN_UNUSED_VAR(totalStoreTime);
476 NN_UNUSED_VAR(totalRenderTime);
477 NN_UNUSED_VAR(totalFrameTime);
478
479 f32 storeTime = totalStoreTime / static_cast<f32>( s_MaxCount );
480 f32 renderTime = totalRenderTime / static_cast<f32>( s_MaxCount );
481 f32 frameTime = totalFrameTime / static_cast<f32>( s_MaxCount );
482
483 NN_UNUSED_VAR(storeTime);
484 NN_UNUSED_VAR(renderTime);
485 NN_UNUSED_VAR(frameTime);
486
487 NN_LOG("\n");
488 NN_LOG("Average storeTime = %f (usec)\n", storeTime);
489 NN_LOG("Average renderTime = %f (usec)\n", renderTime);
490 NN_LOG("Average frameTime = %f (usec)\n", frameTime);
491
492 count = 0;
493
494 totalStoreTime = 0.0f;
495 totalRenderTime = 0.0f;
496 totalFrameTime = 0.0f;
497 }
498 else
499 {
500 count += 1;
501 }
502
503 return true;
504 }
505
UseShader(void)506 void UseShader(void)
507 {
508 glUseProgram(s_ProgramId);
509
510 // Fragment uniform
511 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
512
513 // Fragment uniform : Texture samplerType
514 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE);
515 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
516 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
517 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
518
519 // Fragment uniform : Fragment lighting
520 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
521 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
522 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
523 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_Light0Ambient);
524 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_Light0Diffuse);
525 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION], 1, s_Light0Position);
526
527 // Fragment uniform : Material
528 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
529 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
530
531 // Fragment uniform : Texture combiner
532 // Modulate fragment primary color and vertex color.
533 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
534 GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PRIMARY_COLOR, GL_PREVIOUS);
535 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
536 GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS);
537 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
538 GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
539 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
540 GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
541 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
542 GL_MODULATE);
543 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
544 GL_MODULATE);
545 }
546
UpdateCamera(void)547 void UpdateCamera(void)
548 {
549 nn::math::MTX34LookAt(&s_ViewMatrix, &s_CameraPosition, &s_CameraUp, &s_CameraTarget);
550 }
551
DrawDisplay0(void)552 void DrawDisplay0(void)
553 {
554 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
555 s_RenderSystem.Clear();
556
557 UseShader();
558
559 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
560 1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
561
562 for (u32 i = 0; i < s_RowCubeNum; i++)
563 {
564 for (u32 j = 0; j < s_ColumnCubeNum; j++)
565 {
566 DrawBody(s_Cube[i][j]);
567 }
568 }
569
570 s_StoreTick = nn::os::Tick::GetSystemCurrent();
571
572 s_RenderSystem.SwapBuffers();
573 }
574
DrawDisplay1(void)575 void DrawDisplay1(void)
576 {
577 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
578 s_RenderSystem.Clear();
579
580 s_RenderSystem.SwapBuffers();
581 }
582
DrawBody(demo::Body & body)583 void DrawBody(demo::Body& body)
584 {
585 nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
586 nn::math::Matrix44 worldMatrix = body.GetWorldMatrix();
587 nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix);
588 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
589 1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
590
591 body.Draw();
592 }
593
nnMain(void)594 void nnMain(void)
595 {
596 // Call only nn::applet::Enable to also allow execution from the HOME Menu
597 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
598 nn::applet::Enable();
599
600 Initialize();
601
602 bool flag = true;
603 while ( flag )
604 {
605 flag = DrawFrame();
606 }
607
608 Finalize();
609 }
610