1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gx_RenderToTexture.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     GLuint s_ProgramId = 0;
29     GLuint s_ShaderId = 0;
30 
31     nn::fnd::ExpHeap s_AppHeap;
32     uptr s_AddrForGxHeap;
33     const u32 s_GxHeapSize = 0x400000;
34 
35     demo::RenderSystem s_RenderSystem;
36 
37     nn::math::Vector3 s_CameraPosition(0.0f, 4.0f, 6.0f);
38     nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
39     nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
40 
41     nn::math::Matrix34 s_ViewMatrix;
42     nn::math::Matrix44 s_Display0ProjectionMatrix;
43     nn::math::Matrix44 s_Display1ProjectionMatrix;
44     nn::math::Matrix44 s_RenderTextureProjectionMatrix;
45 
46     const u32 MAX_LIGHT_NUM = 1;
47     f32 s_GlobalAmbientLight[] = { 0.4f,  0.4f,  0.4f, 1.0f};
48     demo::Light s_LightArray[MAX_LIGHT_NUM];
49 
50     f32 s_MaterialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
51     f32 s_MaterialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
52     f32 s_MaterialSpecular0[] = {1.0f, 1.0f, 1.0f, 1.0f};
53     f32 s_MaterialSpecular1[] = {0.0f, 0.0f, 0.0f, 1.0f};
54 
55     demo::Cube s_Cube;
56 
57     GLuint s_FrameBufferId = 0;
58     GLuint s_RenderColorTextureId = 0;
59     GLsizei s_RenderTextureWidth = 256;
60     GLsizei s_RenderTextureHeight = 256;
61 
62     GLuint s_DepthBufferId = 0;
63 
64     const nn::math::Vector3 s_InitialPosition(0.0f, -3.0f, 0.0f);
65     const nn::math::Vector3 s_InitialVelocity(0.0f, 1.0f, 0.0f);
66     const nn::math::Vector3 s_Gravity(0.0f, -0.1f, 0.0f);
67 
68     const f32 s_DeltaTime = 0.1f;
69     const u32 MAX_PARTICLE_NUM = 64;
70     demo::Particle s_ParticleArray[MAX_PARTICLE_NUM];
71 }
72 
73 void InitializeGraphics(void);
74 void InitializeParticles(void);
75 void InitializeLights(void);
76 void InitializeShader(void);
77 void InitializeRenderTexture(void);
78 
79 void Finalize(void);
80 
81 void UseShader(void);
82 void UpdateCamera(void);
83 void UpdateLights(void);
84 void UpdateParticles(void);
85 
86 void RenderTexture(void);
87 void DrawDisplay0(void);
88 void DrawDisplay1(void);
89 
90 void UseShaderParticle(void);
91 void DrawParticles(void);
92 
93 void UseShaderTexture(void);
94 void UpdateBody(demo::Body& body);
95 void DrawBody(demo::Body& body);
96 
Initialize(void)97 void Initialize(void)
98 {
99     // fs initialization
100     nn::fs::Initialize();
101 
102     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
103     static char buffer[ROMFS_BUFFER_SIZE];
104     NN_UTIL_PANIC_IF_FAILED(
105         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
106 
107     InitializeGraphics();
108     InitializeParticles();
109 }
110 
InitializeGraphics(void)111 void InitializeGraphics(void)
112 {
113     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
114         nn::os::GetDeviceMemorySize() );
115     s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
116 
117     s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
118 
119     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
120     glClearDepthf(1.0f);
121 
122     glEnable(GL_DEPTH_TEST);
123     glDepthFunc(GL_LESS);
124 
125     glEnable(GL_CULL_FACE);
126     glFrontFace(GL_CCW);
127     glCullFace(GL_BACK);
128 
129     InitializeLights();
130     InitializeShader();
131     InitializeRenderTexture();
132 
133     // Initialize projection matrix
134     nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f,
135         demo::DISPLAY0_ASPECT, 0.1f, 20.0f,
136         nn::math::PIVOT_UPSIDE_TO_TOP);
137 
138     nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f,
139         demo::DISPLAY1_ASPECT, 0.1f, 20.0f,
140         nn::math::PIVOT_UPSIDE_TO_TOP);
141 
142     nn::math::MTX44PerspectivePivotDeg(&s_RenderTextureProjectionMatrix, 45.0f,
143         1.0f, 0.1f, 20.0f,
144         nn::math::PIVOT_NONE);
145 
146     // Initialize cube
147     u32 vertexAttributes = demo::VERTEX_POSITION_ATTRIBUTE |
148         demo::VERTEX_COLOR_ATTRIBUTE |
149         demo::VERTEX_NORMAL_ATTRIBUTE |
150         demo::VERTEX_TEXCOORD_ATTRIBUTE;
151     s_Cube.InitializeCube(vertexAttributes, 1.6f, 1.6f, 1.6f);
152     s_Cube.SetColor(1.0f, 0.0f, 0.0f);
153     s_Cube.SetWorldPosition(0.0f, 0.0f, 0.0f);
154     s_Cube.SetWorldAngle(0.0f, 0.0f, 0.0f);
155 }
156 
InitializeLights(void)157 void InitializeLights(void)
158 {
159     for (u32 lightIndex = 0; lightIndex < MAX_LIGHT_NUM; lightIndex++)
160     {
161         s_LightArray[lightIndex].Initialize();
162     }
163 
164     // Light0
165     u32 lightIndex = 0;
166     s_LightArray[lightIndex].m_Ambient[0] = 0.0f;
167     s_LightArray[lightIndex].m_Ambient[1] = 0.0f;
168     s_LightArray[lightIndex].m_Ambient[2] = 0.0f;
169     s_LightArray[lightIndex].m_Ambient[3] = 1.0f;
170     s_LightArray[lightIndex].m_Diffuse[0] = 0.9f;
171     s_LightArray[lightIndex].m_Diffuse[1] = 0.9f;
172     s_LightArray[lightIndex].m_Diffuse[2] = 0.9f;
173     s_LightArray[lightIndex].m_Diffuse[3] = 1.0f;
174     s_LightArray[lightIndex].m_Specular0[0] = 0.0f;
175     s_LightArray[lightIndex].m_Specular0[1] = 0.0f;
176     s_LightArray[lightIndex].m_Specular0[2] = 0.0f;
177     s_LightArray[lightIndex].m_Specular0[3] = 0.0f;
178 }
179 
InitializeRenderTexture(void)180 void InitializeRenderTexture(void)
181 {
182     glGenFramebuffers(1, &s_FrameBufferId);
183 
184     glGenTextures(1, &s_RenderColorTextureId);
185     glBindTexture(GL_TEXTURE_2D, s_RenderColorTextureId);
186 
187     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
188         s_RenderTextureWidth, s_RenderTextureHeight, 0,
189         GL_RGBA, GL_UNSIGNED_BYTE, NULL);
190 
191     GLfloat bcolor[] = {0.0f, 1.0f, 0.0f, 1.0f};
192     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bcolor);
193     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
194     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
195     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
196     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
197 
198     glGenRenderbuffers(1, &s_DepthBufferId);
199     glBindRenderbuffer(GL_RENDERBUFFER, s_DepthBufferId);
200     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_EXT,
201         s_RenderTextureWidth, s_RenderTextureHeight);
202 
203     glBindFramebuffer(GL_FRAMEBUFFER, s_FrameBufferId);
204     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
205         GL_TEXTURE_2D, s_RenderColorTextureId, 0);
206 
207     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
208         GL_RENDERBUFFER, s_DepthBufferId);
209 }
210 
InitializeShader(void)211 void InitializeShader(void)
212 {
213     s_ProgramId = glCreateProgram();
214 
215     // Load vertex shader
216     s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
217     nn::fs::FileReader file(L"rom:/shader.shbin");
218     size_t fileSize = file.GetSize();
219     void* buf = s_AppHeap.Allocate(fileSize);
220     s32 read = file.Read(buf, fileSize);
221     glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
222     file.Finalize();
223     s_AppHeap.Free(buf);
224 
225     glAttachShader(s_ProgramId, s_ShaderId);
226     glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
227 
228     glBindAttribLocation(s_ProgramId, 0, "aPosition");
229     glBindAttribLocation(s_ProgramId, 1, "aColor");
230     glBindAttribLocation(s_ProgramId, 2, "aTexcoord");
231     glBindAttribLocation(s_ProgramId, 3, "aNormal");
232 
233     glLinkProgram(s_ProgramId);
234     glValidateProgram(s_ProgramId);
235 
236     demo::InitializeUniforms(s_ProgramId);
237 }
238 
InitializeParticles(void)239 void InitializeParticles(void)
240 {
241     demo::Particle::s_InitialPosition = ::s_InitialPosition;
242     demo::Particle::s_InitialVelocity = ::s_InitialVelocity;
243     demo::Particle::s_Gravity = ::s_Gravity;
244 
245     for (u32 particleIndex = 0; particleIndex < MAX_PARTICLE_NUM; particleIndex++)
246     {
247         s_ParticleArray[particleIndex].Initialize();
248     }
249 }
250 
Finalize(void)251 void Finalize(void)
252 {
253     s_Cube.Finalize();
254 
255     for (u32 particleIndex = 0; particleIndex < MAX_PARTICLE_NUM; particleIndex++)
256     {
257         s_ParticleArray[particleIndex].Finalize();
258     }
259 
260     glDeleteTextures(1, &s_RenderColorTextureId);
261     glDeleteRenderbuffers(1, &s_DepthBufferId);
262 
263     s_RenderSystem.Finalize();
264 
265     s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
266     s_AppHeap.Finalize();
267 }
268 
DrawFrame(void)269 bool DrawFrame(void)
270 {
271     UpdateCamera();
272     UpdateParticles();
273 
274     RenderTexture();
275 
276     DrawDisplay0();
277     DrawDisplay1();
278 
279     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
280 
281     return true;
282 }
283 
UpdateCamera(void)284 void UpdateCamera(void)
285 {
286     nn::math::MTX34LookAt(&s_ViewMatrix, s_CameraPosition, s_CameraUp, s_CameraTarget);
287 }
288 
UpdateParticles(void)289 void UpdateParticles(void)
290 {
291     for (u32 particleIndex = 0; particleIndex < MAX_PARTICLE_NUM; particleIndex++)
292     {
293         s_ParticleArray[particleIndex].Update(s_DeltaTime);
294     }
295 }
296 
RenderTexture(void)297 void RenderTexture(void)
298 {
299     glBindFramebuffer(GL_FRAMEBUFFER, s_FrameBufferId);
300 
301     glViewport(0, 0, s_RenderTextureWidth, s_RenderTextureHeight);
302     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
303     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
304 
305     UseShaderParticle();
306     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
307         1, GL_TRUE, static_cast<f32*>(s_RenderTextureProjectionMatrix));
308 
309     DrawParticles();
310 }
311 
UseShaderParticle(void)312 void UseShaderParticle(void)
313 {
314     glUseProgram(s_ProgramId);
315 
316     // Fragment uniform
317     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
318 
319     // Fragment uniform : Texture samplerType
320     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE);
321     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
322     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
323     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
324 
325     // Fragment uniform : Fragment lighting
326     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_FALSE);
327 
328     // Fragment uniform : Texture combiner
329     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
330         GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS);
331     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
332         GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS);
333     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
334         GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
335     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
336         GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
337     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
338         GL_REPLACE);
339     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
340         GL_REPLACE);
341 }
342 
DrawDisplay0(void)343 void DrawDisplay0(void)
344 {
345     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
346     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
347     s_RenderSystem.Clear();
348 
349     UseShaderTexture();
350     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
351         1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
352     UpdateBody(s_Cube);
353 
354     DrawBody(s_Cube);
355 
356     s_RenderSystem.SwapBuffers();
357 }
358 
UseShaderTexture(void)359 void UseShaderTexture(void)
360 {
361     glUseProgram(s_ProgramId);
362 
363     glActiveTexture(GL_TEXTURE0);
364     glBindTexture(GL_TEXTURE_2D, s_RenderColorTextureId);
365 
366     // Fragment uniform
367     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
368 
369     // Fragment uniform : Texture samplerType
370     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_TEXTURE_2D);
371     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
372     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
373     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
374 
375     // Fragment uniform : Fragment lighting
376     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
377     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
378 
379     // Light0
380     u32 lightIndex = 0;
381     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
382     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient);
383     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse);
384     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0);
385     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1);
386 
387     // Compute Light0 view matrix
388     nn::math::MTX34 s_LightWorldMatrix;
389     nn::math::MTX34Identity(&s_LightWorldMatrix);
390     nn::math::VEC3 position(0.0f, 10.0f, 10.0f);
391     nn::math::MTX34Translate(&s_LightWorldMatrix, &position);
392     nn::math::Matrix34 lightViewMatrix;
393     nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix);
394     glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION],
395         lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3],
396         1.0f);
397 
398     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR1], GL_FALSE);
399     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR0], GL_FALSE);
400     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_TWO_SIDE_DIFFUSE], GL_FALSE);
401 
402     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_ENABLED], GL_FALSE);
403     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_ENABLED], GL_FALSE);
404     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_ENABLED], GL_FALSE);
405 
406     // Fragment uniform : Material
407     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
408     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
409     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR0], 1, s_MaterialSpecular0);
410     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR1], 1, s_MaterialSpecular1);
411 
412     // Fragment uniform : Texture combiner
413     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
414         GL_TEXTURE0, GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PREVIOUS);
415     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
416         GL_TEXTURE0, GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PREVIOUS);
417 
418     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
419         GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
420     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
421         GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
422     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
423         GL_MODULATE);
424     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
425         GL_MODULATE);
426 }
427 
DrawParticles(void)428 void DrawParticles(void)
429 {
430     for (u32 particleIndex = 0; particleIndex < MAX_PARTICLE_NUM; particleIndex++)
431     {
432         DrawBody(s_ParticleArray[particleIndex]);
433     }
434 }
435 
DrawDisplay1(void)436 void DrawDisplay1(void)
437 {
438     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
439     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
440     s_RenderSystem.Clear();
441 
442     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
443         1, GL_TRUE, static_cast<f32*>(s_Display1ProjectionMatrix));
444 
445     UseShaderParticle();
446     DrawParticles();
447 
448     s_RenderSystem.SwapBuffers();
449 }
450 
UpdateBody(demo::Body & body)451 void UpdateBody(demo::Body& body)
452 {
453     f32 worldAngle[3];
454     body.GetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
455     worldAngle[1] += 1.0f;
456     if ( worldAngle[1] > 360.0f )
457     {
458         worldAngle[1] = 0.0f;
459     }
460     body.SetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
461 }
462 
DrawBody(demo::Body & body)463 void DrawBody(demo::Body& body)
464 {
465     nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
466     nn::math::Matrix44 worldMatrix = body.GetWorldMatrix();
467     nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix);
468     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
469         1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
470     body.Draw();
471 }
472 
nnMain(void)473 void nnMain(void)
474 {
475     // Call only nn::applet::Enable to also allow execution from the HOME Menu
476     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
477     nn::applet::Enable();
478 
479     Initialize();
480 
481     bool flag = true;
482     while ( flag )
483     {
484         flag = DrawFrame();
485     }
486 
487     Finalize();
488 }
489