1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     PartsysGas.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 /*
17  *------------------------------------------------------------
18  * Copyright(c) 2009-2010 by Digital Media Professionals Inc.
19  * All rights reserved.
20  *------------------------------------------------------------
21  * This source code is the confidential and proprietary
22  * of Digital Media Professionals Inc.
23  *------------------------------------------------------------
24  */
25 
26 #include <nn/gx.h>
27 #include <nn/fs.h>
28 #include <nn/math.h>
29 #include <nn/init.h>
30 #include <nn/os.h>
31 #include <nn/applet.h>
32 #include "Util.h"
33 #include "Loader.h"
34 #include "Gas.h"
35 
36 #include <string.h>
37 
38 #include "Memory.h"
39 
40 #include "demo.h"
41 
42 /* program id */
43 GLuint pGeoId;      /* for normal geometry */
44 GLuint pAccId;      /* for gas accumulation pass */
45 GLuint pPostId;     /* for gas shading/post synthesis pass */
46 
47 /* Standard object (triangles, not gaseous object) */
48 dat_t plane;
49 struct gas_data gas;
50 
51 /* ExpHeap for app. */
52 nn::fnd::ExpHeap s_AppHeap;
53 uptr s_HeapForGx;
54 uptr s_HeapForMalloc;
55 const u32 s_GxHeapSize = 0x400000;
56 const u32 s_HeapSize = 0x200000;
57 
58 demo::RenderSystem s_RenderSystem;
59 
60 /*=======================================================*/
61 /* Sample specific. Different color variation for gas    */
62 /*=======================================================*/
63 #define NUM_COLOR_SAMPLE  6
64 static float gasColorTable[NUM_COLOR_SAMPLE][24]=
65 {
66     {   /* red flame */
67         0.0f,   0.0f,   0.0f,
68         0.2f,   0.15f,  0.05f,
69         0.6f,   0.25f,  0.15f,
70         0.9f,   0.35f,  0.2f,
71         0.92f,  0.6f,   0.15f,
72         0.95f,  0.85f,  0.05f,
73         1.0f,   0.95f,  0.0f,
74         1.0f,   1.0f,   1.0f
75     },
76     {   /* blue flame */
77         0.00f,  0.00f,  0.00f,
78         0.05f,  0.15f,  0.20f,
79         0.15f,  0.25f,  0.60f,
80         0.20f,  0.35f,  0.90f,
81         0.15f,  0.60f,  0.92f,
82         0.05f,  0.85f,  0.95f,
83         0.00f,  0.95f,  1.00f,
84         1.00f,  1.00f,  1.00f
85     },
86     {   /* Grey Gradient */
87         0.000000f,   0.000000f, 0.000000f,
88         0.140000f,   0.140000f, 0.140000f,
89         0.280000f,   0.280000f, 0.280000f,
90         0.420000f,   0.420000f, 0.420000f,
91         0.560000f,   0.560000f, 0.560000f,
92         0.700000f,   0.700000f, 0.700000f,
93         0.840000f,   0.840000f, 0.840000f,
94         1.000000f,   1.000000f, 1.000000f
95     },
96     {   /* Pastel color */
97         255.0f/255.0f,      191.0f/255.0f,  191.0f/255.0f,
98         255.0f/255.0f,      238.0f/255.0f,  191.0f/255.0f,
99         222.0f/255.0f,      255.0f/255.0f,  191.0f/255.0f,
100         191.0f/255.0f,      255.0f/255.0f,  207.0f/255.0f,
101         191.0f/255.0f,      254.0f/255.0f,  255.0f/255.0f,
102         191.0f/255.0f,      206.0f/255.0f,  255.0f/255.0f,
103         223.0f/255.0f,      191.0f/255.0f,  255.0f/255.0f,
104         255.0f/255.0f,      191.0f/255.0f,  238.0f/255.0f
105     },
106     {   /* Greenish */
107         125.0f/255.0f,  255.0f/255.0f,  1.0f/255.0f,
108         173.0f/255.0f,  255.0f/255.0f,  35.0f/255.0f,
109         189.0f/255.0f,  255.0f/255.0f,  46.0f/255.0f,
110         204.0f/255.0f,  255.0f/255.0f,  57.0f/255.0f,
111         219.0f/255.0f,  255.0f/255.0f,  68.0f/255.0f,
112         229.0f/255.0f,  247.0f/255.0f,  65.0f/255.0f,
113         234.0f/255.0f,  230.0f/255.0f,  53.0f/255.0f,
114         239.0f/255.0f,  212.0f/255.0f,  40.0f/255.0f
115     },
116     {   /* Red strips */
117          0.000000f,     0.000000f,   0.000000f,
118          1.000000f,     0.500000f,   0.000000f,
119          0.500000f,     0.000000f,   0.000000f,
120          1.000000f,     0.500000f,   0.000000f,
121          0.500000f,     0.000000f,   0.000000f,
122          1.000000f,     0.50000f,    0.000000f,
123          0.500000f,     0.000000f,   0.000000f,
124          1.000000f,     0.200000f,   0.300000f
125     }
126 };
127 
128 /*=======================================================*/
129 /* Static function declaration                           */
130 /*=======================================================*/
131 static int DrawFrame(void);
132 
133 /*=======================================================*/
134 /* initialization                                        */
135 /*=======================================================*/
136 
Initialize(void)137 static void Initialize(void)
138 {
139     /* Initialize display */
140     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
141     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
142     /* Initialize display */
143     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
144 
145     /* Create heap for malloc*/
146     s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
147     setMemoryHeap(s_HeapForMalloc, s_HeapSize);
148 
149     /* Initialization for gas */
150     GasInitialize();
151 }
152 
LoadParticleSystem1(struct _particleSys * pp)153 static void LoadParticleSystem1(struct _particleSys *pp)
154 {
155     GLfloat vertex[4] = {0.0f, 1.0f, 2.0f, 3.0f};
156 
157     glGenBuffers(1, &pp->m_pSysPositionID) ;
158     glBindBuffer(GL_ARRAY_BUFFER, pp->m_pSysPositionID);
159     glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat), &vertex[0], GL_STATIC_DRAW);
160 
161     /*------------------------------------------------------------------------------------*/
162     /*--------Definition of the 4 control point positions---------------------------------*/
163     /*------------------------------------------------------------------------------------*/
164     /*-----------Control Point 1---------------------Control Point 2----------------------*/
165     pp->m_partsys_center.m[0][0] = 0.0f;      /*|*/   pp->m_partsys_center.m[1][0] = -5.0f;
166     pp->m_partsys_center.m[0][1] = -20.0f;    /*|*/   pp->m_partsys_center.m[1][1] = -20.0f;
167     pp->m_partsys_center.m[0][2] = 0.0f;      /*|*/   pp->m_partsys_center.m[1][2] = 0.0f;
168     pp->m_partsys_center.m[0][3] = 1.0f;      /*|*/   pp->m_partsys_center.m[1][3] = 1.0f;
169     /*-----------Control Point 3---------------------Control Point 4----------------------*/
170     pp->m_partsys_center.m[2][0] = 5.0f;      /*|*/   pp->m_partsys_center.m[3][0] = 0.0f;
171     pp->m_partsys_center.m[2][1] = 5.0f;      /*|*/   pp->m_partsys_center.m[3][1] = 15.0f;
172     pp->m_partsys_center.m[2][2] = 0.0f;      /*|*/   pp->m_partsys_center.m[3][2] = 0.0f;
173     pp->m_partsys_center.m[2][3] = 1.0f;      /*|*/   pp->m_partsys_center.m[3][3] = 1.0f;
174     /*------------------------------------------------------------------------------------*/
175     /*------------------------------------------------------------------------------------*/
176 
177     /*------------------------------------------------------------------------------------*/
178     /*--------Definition of the 4 control point colors------------------------------------*/
179     /*------------------------------------------------------------------------------------*/
180     /*Color is not used in this sample.                                                   */
181     /*To modify the alpha value, please use pp->m_partsys_aspect[k][3]                    */
182     /*-----------Control Point 1---------------------Control Point 2----------------------*/
183     pp->m_partsys_color.m[0][0] = 0.0f;       /*|*/   pp->m_partsys_color.m[1][0] = 1.0f;
184     pp->m_partsys_color.m[0][1] = 0.0f;       /*|*/   pp->m_partsys_color.m[1][1] = 0.0f;
185     pp->m_partsys_color.m[0][2] = 0.0f;       /*|*/   pp->m_partsys_color.m[1][2] = 0.0f;
186     pp->m_partsys_color.m[0][3] = 1.0f;       /*|*/   pp->m_partsys_color.m[1][3] = 1.0f;
187     /*-----------Control Point 3---------------------Control Point 4----------------------*/
188     pp->m_partsys_color.m[2][0] = 0.0f;       /*|*/   pp->m_partsys_color.m[3][0] = 0.0f;
189     pp->m_partsys_color.m[2][1] = 1.0f;       /*|*/   pp->m_partsys_color.m[3][1] = 0.0f;
190     pp->m_partsys_color.m[2][2] = 0.0f;       /*|*/   pp->m_partsys_color.m[3][2] = 1.0f;
191     pp->m_partsys_color.m[2][3] = 0.5f;       /*|*/   pp->m_partsys_color.m[3][3] = 0.0f;
192     /*------------------------------------------------------------------------------------*/
193     /*------------------------------------------------------------------------------------*/
194 
195     /*------------------------------------------------------------------------------------*/
196     /*--------Definition of the 4 bounding boxes------------------------------------------*/
197     /*--------Radii in X, Y and Z direction. W not used ----------------------------------*/
198     /*------------------------------------------------------------------------------------*/
199     /*-----------Control Point 1---------------------Control Point 2----------------------*/
200     pp->m_partsys_radius.m[0][0] = 0.0f;      /*|*/   pp->m_partsys_radius.m[1][0] = 0.2f;
201     pp->m_partsys_radius.m[0][1] = 0.0f;      /*|*/   pp->m_partsys_radius.m[1][1] = 2.0f;
202     pp->m_partsys_radius.m[0][2] = 0.0f;      /*|*/   pp->m_partsys_radius.m[1][2] = 0.2f;
203     pp->m_partsys_radius.m[0][3] = 1.0f;      /*|*/   pp->m_partsys_radius.m[1][3] = 1.0f;
204     /*-----------Control Point 3---------------------Control Point 4----------------------*/
205     pp->m_partsys_radius.m[2][0] = 1.0f;      /*|*/   pp->m_partsys_radius.m[3][0] = 5.0f;
206     pp->m_partsys_radius.m[2][1] = 10.0f;     /*|*/   pp->m_partsys_radius.m[3][1] = 0.0f;
207     pp->m_partsys_radius.m[2][2] = 1.0f;      /*|*/   pp->m_partsys_radius.m[3][2] = 5.0f;
208     pp->m_partsys_radius.m[2][3] = 1.0f;      /*|*/   pp->m_partsys_radius.m[3][3] = 1.0f;
209     /*------------------------------------------------------------------------------------*/
210     /*------------------------------------------------------------------------------------*/
211 
212     /*------------------------------------------------------------------------------------*/
213     /*--------Definition of the particle aspect-------------------------------------------*/
214     /*--------Particle size, texture coordinates !!!??TBD   ------------------------------*/
215     /*------------------------------------------------------------------------------------*/
216     /*Rotation disabled: Size, unused,unused,unused/alpha                                 */
217     /*Rotation Enabled:  Size,  Angle, Radius, unused/alpha                                */
218     /*-----------Control Point 1---------------------Control Point 2----------------------*/
219     pp->m_partsys_aspect.m[0][0] = 0.0f;      /*|*/   pp->m_partsys_aspect.m[1][0] = 4.0f;
220     pp->m_partsys_aspect.m[0][1] = 0.0f;      /*|*/   pp->m_partsys_aspect.m[1][1] = 0.0f;
221     pp->m_partsys_aspect.m[0][2] = 0.9f;      /*|*/   pp->m_partsys_aspect.m[1][2] = 0.9f;
222     pp->m_partsys_aspect.m[0][3] = 1.0f;      /*|*/   pp->m_partsys_aspect.m[1][3] = 1.0f;
223     /*-----------Control Point 3---------------------Control Point 4----------------------*/
224     pp->m_partsys_aspect.m[2][0] = 6.0f;      /*|*/   pp->m_partsys_aspect.m[3][0] = 30.0f;
225     pp->m_partsys_aspect.m[2][1] = 0.0f;      /*|*/   pp->m_partsys_aspect.m[3][1] = 0.0f;
226     pp->m_partsys_aspect.m[2][2] = 0.9f;      /*|*/   pp->m_partsys_aspect.m[3][2] = 0.9f;
227     pp->m_partsys_aspect.m[2][3] = 0.0f;      /*|*/   pp->m_partsys_aspect.m[3][3] = 0.0f;
228     /*------------------------------------------------------------------------------------*/
229     /*------------------------------------------------------------------------------------*/
230     pp->m_size_min_max[0] = 1.0f;
231     pp->m_size_min_max[1] = static_cast<GLfloat>(NN_GX_DISPLAY0_HEIGHT) / 2.0f;
232 
233     pp->m_random_seed[0] = 45.0f;
234     pp->m_random_seed[1] = 2.564f + pp->m_random_seed[0];
235     pp->m_random_seed[2] = 1.15f + pp->m_random_seed[0];
236     pp->m_random_seed[3] = 0.9875f + pp->m_random_seed[0];
237 
238     /* Core value for random
239      Algorithm is based on pseudo-random number generators: X(n+1) = (a*Xn+b) mod m
240      Expected values for uniform are
241      [0] = a, [1] = b, [2] = m, [3] = 1/m
242     */
243     pp->m_prng[0] = 17.0f;                  /* a */
244     pp->m_prng[1] = 37.0f;                  /* b */
245     pp->m_prng[2] = 65535.0f;               /* m */
246     pp->m_prng[3] = 1.0f / (pp->m_prng[2]); /* 1/m */
247 
248     pp->m_speed = 1.0f;             /*  emitter->particle_speed  */
249     pp->m_particleCountMax = 60.0f; /*  particle number          */
250 
251     /* Application only */
252     pp->simulationTime = 2.0f;
253     pp->NFrame = 512;
254     pp->dTime = pp->simulationTime / pp->NFrame;
255 }
256 
SceneObjectInitialize(void)257 static void SceneObjectInitialize(void)
258 {
259     /* Load object (non-gaseous object) */
260     loadDAT( "rom:/resources/planeXY3.dat", &plane);
261 
262     /* Load Gaseous object */
263     DefaultGasObject(&gas, gasColorTable[0]);
264 
265     /* Define the gaseous object geometry as a particle system */
266     LoadParticleSystem1(&gas.pSys);
267 }
268 
UnloadObjects(void)269 static void UnloadObjects(void)
270 {
271     unloadDAT(&plane);
272 
273     return;
274 }
275 
276 /*=======================================================*/
277 /* Initialization of shaders                            */
278 /*=======================================================*/
ShaderInitialize(void)279 int ShaderInitialize(void)
280 {
281     GLuint shaders[4] ;
282     shaders[0] = glCreateShader(GL_VERTEX_SHADER);
283     shaders[1] = glCreateShader(GL_VERTEX_SHADER);
284     shaders[2] = glCreateShader(GL_VERTEX_SHADER);
285     shaders[3] = glCreateShader(GL_GEOMETRY_SHADER_DMP);
286 
287     nn::fs::FileReader file(L"rom:/shader.shbin");
288     size_t fileSize = file.GetSize();
289     void* buf = s_AppHeap.Allocate(fileSize);
290 
291     s32 read = file.Read(buf, fileSize);
292     glShaderBinary(4, shaders, GL_PLATFORM_BINARY_DMP, buf, read);
293     file.Finalize();
294     s_AppHeap.Free(buf);
295 
296     /* for normal geometry */
297     pGeoId = glCreateProgram();
298     glAttachShader(pGeoId, shaders[0]);
299     glAttachShader(pGeoId, GL_DMP_FRAGMENT_SHADER_DMP);
300 
301     glBindAttribLocation(pGeoId, 0, "aPosition");
302 
303     glLinkProgram(pGeoId);
304     glValidateProgram(pGeoId);
305     glUseProgram(pGeoId);
306 
307     /* for gas accumulation pass */
308     pAccId = glCreateProgram();
309     glAttachShader(pAccId, shaders[1]);
310     glAttachShader(pAccId, shaders[3]);
311     glAttachShader(pAccId, GL_DMP_FRAGMENT_SHADER_DMP);
312 
313     glBindAttribLocation(pAccId, 0, "attrCtrPointIndex");
314 
315     glLinkProgram(pAccId);
316     glValidateProgram(pAccId);
317     glUseProgram(pAccId);
318 
319     /* for gas shading/pos synthesis pass */
320     pPostId = glCreateProgram();
321     glAttachShader(pPostId, shaders[2]);
322     glAttachShader(pPostId, GL_DMP_FRAGMENT_SHADER_DMP);
323     glBindAttribLocation(pPostId, 0, "aPosition");
324     glBindAttribLocation(pPostId, 1, "aTexCoord");
325     glBindAttribLocation(pPostId, 2, "aColor");
326     glLinkProgram(pPostId);
327     glValidateProgram(pPostId);
328     glUseProgram(pPostId);
329 
330     return 0;
331 }
332 
333 /*=======================================================*/
334 /* draw object                                           */
335 /*=======================================================*/
DrawObject(void)336 static void DrawObject(void)
337 {
338     /* This function draws only one quadrangle. */
339     glUseProgram(pGeoId);
340     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
341     glClearDepthf(1.f);
342 
343     /* Set fragment operation mode to GL_FRAGOP_MODE_GL_DMP */
344     glUniform1i(glGetUniformLocation(pGeoId, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GL_DMP);
345 
346     /*
347      * Setup texture and blending unit
348      * The color of the object is defined as a constant color from blending unit 0
349     */
350     glUniform1i(glGetUniformLocation(pGeoId, "dmp_Texture[0].samplerType"), GL_FALSE);
351     glUniform1i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
352     glUniform1i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
353     glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
354     glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
355     glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].srcRgb"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
356     glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
357 
358     float almostblack[4] = {0.15f, 0.15f, 0.15f, 0.0f};
359     glUniform4fv(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].constRgba"), 1, almostblack);
360 
361     /*
362      * Miscellaneous settings
363     */
364     glDisable(GL_BLEND);
365     glEnable(GL_DEPTH_TEST);
366     glDepthMask(GL_TRUE);
367     glDepthFunc(GL_LEQUAL);
368 
369     glDisable(GL_CULL_FACE);
370     glFrontFace(GL_CCW);
371     glCullFace(GL_BACK);
372 
373     glEnableVertexAttribArray(0);   /* enable position */
374     glDisableVertexAttribArray(1);  /* disable texture coordinate */
375     glDisableVertexAttribArray(2);  /* disable color */
376 
377     for (int i = 0; i < plane.obj_num; i++)
378     {
379         glBindBuffer(GL_ARRAY_BUFFER, plane.posVB);
380         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)plane.obj[i].vtx_offset);
381         for (unsigned j = plane.obj[i].patch_offset; j < plane.obj[i].patch_size + plane.obj[i].patch_offset; j++)
382         {
383             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane.idxVB);
384             glDrawElements(GL_TRIANGLES, plane.patch[j].elm_size,
385                 GL_UNSIGNED_SHORT, (GLvoid*)(plane.patch[j].elm_offset + plane.obj[i].elm_offset));
386         }
387     }
388 
389     /*
390      * Finalization
391     */
392     glDisableVertexAttribArray(0);
393 }
394 
395 /*=======================================================*/
396 /* draw frame                                            */
397 /*=======================================================*/
DrawFrame(void)398 static int DrawFrame(void)
399 {
400     static int f = 0;
401     static int pattern = 0;
402 
403     /* Clear display buffer */
404     glUseProgram(pGeoId);
405     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
406     glClearDepthf(1.f);
407 
408     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
409     s_RenderSystem.Clear();
410 
411     glUseProgram(pGeoId);
412     nn::math::Matrix44 proj, m;
413     nn::math::MTX44Perspective(&proj, 35.0f, static_cast<f32>(nn::gx::DISPLAY0_WIDTH) / static_cast<f32>(nn::gx::DISPLAY0_HEIGHT), 1.0f, 200.f);
414 
415     nn::math::Matrix34 mv;
416     nn::math::Vector3 camPos(0.f, 0.f, 80.0f);
417     nn::math::Vector3 camUp(0.f, 1.f, 0.f);
418     nn::math::Vector3 target(0.f, 0.f, 0.f);
419     nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
420 
421     if (f == 0)
422     {
423         /* set next gas table */
424         SetGasColorTable(&gas,gasColorTable[pattern % NUM_COLOR_SAMPLE]);
425         gas.pSys.simulationTime = 0.f;
426         pattern++;
427     }
428 
429     glUseProgram(pGeoId);
430     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
431     glClearDepthf(1.f);
432 
433     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
434     s_RenderSystem.Clear();
435 
436     {
437         /* Draw the Object */
438         glUseProgram(pGeoId);
439         glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
440         nn::math::Matrix34 mv_rot, tmp;
441         nn::math::MTX34RotXYZDeg(&tmp, 0.f, 45.0f, 0.f);
442         nn::math::MTX34Mult(&mv_rot, &mv, &tmp);
443 
444         nn::math::Vector3 scale(0.5f, 0.5f, 0.5f);
445         nn::math::MTX34MultScale(&mv_rot, &mv_rot, &scale);
446 
447         m = nn::math::Matrix44(mv_rot);
448         glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
449         DrawObject();
450     }
451 
452     {
453         /* Gas accumulation pass */
454         glUseProgram(pAccId);
455 
456         glDisable(GL_CULL_FACE);
457         glFrontFace(GL_CCW);
458         glCullFace(GL_BACK);
459 
460         glUniformMatrix4fv(glGetUniformLocation(pAccId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
461 
462         m = nn::math::Matrix44(mv);
463         glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
464         GasAccumulation();
465     }
466 
467     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
468 
469     /* Gas shading pass */
470     GasShading();
471 
472     gas.pSys.simulationTime += gas.pSys.dTime;
473     /* swap buffer */
474     glFinish();
475 
476     s_RenderSystem.SwapBuffers();
477 
478     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
479     s_RenderSystem.Clear();
480     s_RenderSystem.SwapBuffers();
481 
482     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
483 
484     if (++f == gas.pSys.NFrame)
485         f = 0;  /* go to next gas pattern */
486 
487     /* return 0 when 16 frames done */
488     return !glGetError();
489 }
490 
491 /* ======================================================= */
492 /* main function                                           */
493 /* ======================================================= */
nnMain(void)494 void nnMain(void)
495 {
496     // Call only nn::applet::Enable to also allow execution from the HOME Menu
497     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
498     nn::applet::Enable();
499 
500     // fs initialization
501     nn::fs::Initialize();
502 
503     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
504     static char buffer[ROMFS_BUFFER_SIZE];
505     NN_UTIL_PANIC_IF_FAILED(
506         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
507 
508     /* Initialize the framebuffer and gas buffer*/
509     Initialize();
510 
511     /* Initialization of shaders */
512     if (ShaderInitialize() >= 0)
513     {
514         /*Initialize standard and gaseous objects */
515         SceneObjectInitialize();
516 
517         /* Enter loop */
518         while (1)
519         {
520             DrawFrame();
521         }
522     }
523 
524     UnloadObjects();
525     /* shutdown_display */
526     s_RenderSystem.Finalize();
527     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
528     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
529     s_AppHeap.Finalize();
530 }
531 
532