1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     GasCessna.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 
33 #include "demo.h"
34 
35 #include "Util.h"
36 #include "Loader.h"
37 
38 #include <string.h>
39 #include <math.h>
40 
41 #include "Gas.h"
42 #include "Memory.h"
43 
44 extern GLfloat particleData[];
45 extern float gasColorTable[6][24];
46 #define NUM_COLOR_SAMPLE 6
47 
48 /* program id */
49 GLuint pGeoId;      /* for normal geometry */
50 GLuint pAccId;      /* for gas accumulation pass */
51 GLuint pPostId;     /* for gas shading/post synthesis pass */
52 
53 /* Standard object (triangles, not gaseous object) */
54 dat_t cessna;
55 struct gas_data gas;
56 
57 /* Standard object (triangles, not gaseous object) */
58 GLuint lutids[2];
59 
60 static struct tagParticeInfo
61 {
62     GLint       cnt;                /* particle count          */
63     GLfloat*    position;           /* particle position array */
64     GLfloat*    size;               /* particle size array     */
65     GLfloat*    density;            /* particle density array  */
66 } prtclinfo;
67 
68 /* ExpHeap for app. */
69 nn::fnd::ExpHeap s_AppHeap;
70 uptr s_HeapForGx;
71 uptr s_HeapForMalloc;
72 const u32 s_GxHeapSize = 0x400000;
73 const u32 s_HeapSize = 0x200000;
74 
75 demo::RenderSystem s_RenderSystem;
76 
77 /*=======================================================*/
78 /* Static function declaration                           */
79 /*=======================================================*/
80 static int DrawFrame(void);
81 
82 /*=======================================================*/
83 /* initialization                                        */
84 /*=======================================================*/
Initialize(void)85 static void Initialize(void)
86 {
87     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
88     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
89     /* Initialize display */
90     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
91 
92     /* Create heap for malloc*/
93     s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
94     setMemoryHeap(s_HeapForMalloc, s_HeapSize);
95 
96     /* Initialization for gas */
97     GLuint depthStencilBufferId = s_RenderSystem.GetRenderBufferObjectId(NN_GX_DISPLAY0, GL_DEPTH_STENCIL_ATTACHMENT);
98     GasInitialize(depthStencilBufferId);
99 }
100 
101 /*=======================================================*/
102 /* finalization                                          */
103 /*=======================================================*/
GasFinalize(void)104 void GasFinalize(void)
105 {
106     free(prtclinfo.position);
107     free(prtclinfo.size);
108     free(prtclinfo.density);
109 }
110 
UnloadObjects(void)111 static void UnloadObjects(void)
112 {
113     unloadDAT(&cessna);
114 
115     return;
116 }
117 
118 /*=======================================================*/
119 /* initialization of the geometry and gaseous object     */
120 /*=======================================================*/
SceneObjectInitialize(void)121 static void SceneObjectInitialize(void)
122 {
123     /* Load object (non-gaseous object) */
124     loadDAT("rom:/resources/cessna.dat", &cessna);
125 
126     /* Load Gaseous object */
127     DefaultGasObject(&gas, gasColorTable[0]);
128 
129     /* Define the gaseous object geometry */
130     /* A simple quad in this sample */
131     GLfloat* p = &particleData[1];
132     prtclinfo.cnt = (GLuint)particleData[0];
133     prtclinfo.position = (GLfloat*)malloc(sizeof(GLfloat) * prtclinfo.cnt * 4);
134     prtclinfo.size = (GLfloat*)malloc(sizeof(GLfloat) * prtclinfo.cnt);
135     prtclinfo.density = (GLfloat*)malloc(sizeof(GLfloat) * prtclinfo.cnt);
136     for (int i = 0; i < prtclinfo.cnt; i++)
137     {
138         prtclinfo.position[i*4+0] = *p++ / 1.0f;        /* x       */
139         prtclinfo.position[i*4+1] = *p++ / 1.0f;        /* y       */
140         prtclinfo.position[i*4+2] = *p++ / 1.0f;        /* z       */
141         prtclinfo.position[i*4+3] = 1.0f;               /* w       */
142         prtclinfo.size[i] = *p++ / 1.0f;                /* size    */
143         prtclinfo.density[i] = *p++  * 5.f;             /* density */
144 
145         /* Adjust particle size based on accumulation buffer size */
146         prtclinfo.size[i] *= GAS_ACC_HEIGHT * 2;
147     }
148 
149     glGenBuffers(1, &gas.gasgeo_center_ID);
150     glGenBuffers(1, &gas.gasgeo_density_ID);
151     glGenBuffers(1, &gas.gasgeo_size_ID);
152     glGenBuffers(1, &gas.gasgeo_ind_ID);
153 
154     glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_center_ID);
155     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * prtclinfo.cnt, &prtclinfo.position[0], GL_STATIC_DRAW);
156     gas.gasgeo_size = 6;
157 
158     glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_size_ID);
159     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 1 *prtclinfo.cnt , &prtclinfo.size[0], GL_STATIC_DRAW);
160 
161     glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_density_ID);
162     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 1 * prtclinfo.cnt, &prtclinfo.density[0], GL_STATIC_DRAW);
163 
164     gas.gasgeo_size = prtclinfo.cnt;
165 
166     SetGasAccumulationUniform();
167     SetGasShadingUniform();
168 }
169 
170 /*=======================================================*/
171 /* Initialize material used for the geometry      */
172 /*=======================================================*/
SetGeoMaterial(GLuint pgid)173 void SetGeoMaterial(GLuint pgid)
174 {
175     GLfloat lut[512];
176     int j;
177 
178     glGenTextures(2, lutids);
179     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
180 
181     memset(lut, 0, sizeof(lut));
182     for (j = 0; j < 256; j++)
183         lut[j] = pow((float)j/256.0f, 15.f);
184     for (j = 0; j < 255; j++)
185         lut[j + 256] = lut[j+1] - lut[j];
186     lut[255 + 256] = 1.f - lut[255];
187     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
188     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
189 
190     glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentMaterial.samplerD0"), 0);
191 
192     glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLighting.enabled"), GL_TRUE);
193     glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].enabled"), GL_TRUE);
194 
195     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.absLutInputD0"),   GL_TRUE);
196     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
197 
198     glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].geomFactor0"), GL_FALSE);
199     glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE);
200     glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].twoSideDiffuse"), GL_FALSE);
201     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE);
202     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.clampHighlights"), GL_FALSE);
203     glUniform1f(glGetUniformLocation(pgid, "dmp_LightEnv.lutScaleD0"), 1.f);
204     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG0_DMP);
205     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
206     glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.bumpMode"), GL_LIGHT_ENV_BUMP_NOT_USED_DMP);
207 
208 
209     GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f};
210     GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
211     GLfloat green[] = {0.2f, 0.7f, 0.4f, 1.0f};
212 
213     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.specular1"), 1, black);
214     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].diffuse"), 1, white);
215     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].specular0"), 1, white);
216     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].specular1"), 1, black);
217 
218     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.diffuse"), 1, green);
219     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.specular0"), 1,white);
220     glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.ambient"), 1, black);
221 
222 
223     glUniform1i(glGetUniformLocation(pgid, "dmp_Texture[0].samplerType"), GL_FALSE);
224     glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[0].combineRgb"), GL_ADD);
225     glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
226     glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
227     glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
228     glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT);
229 
230     glUniform1i(glGetUniformLocation(pgid, "dmp_Texture[1].samplerType"), GL_FALSE);
231     glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[1].combineRgb"), GL_REPLACE);
232     glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[1].combineAlpha"), GL_REPLACE);
233     glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[1].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
234     glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[1].srcRgb"), GL_PREVIOUS, GL_PREVIOUS, GL_PREVIOUS);
235 }
236 
237 /*=======================================================*/
238 /* Initialize shaders                            */
239 /*=======================================================*/
ShaderInitialize(void)240 int ShaderInitialize(void)
241 {
242     GLuint shaders[4] ;
243     shaders[0] = glCreateShader(GL_VERTEX_SHADER);
244     shaders[1] = glCreateShader(GL_VERTEX_SHADER);
245     shaders[2] = glCreateShader(GL_VERTEX_SHADER);
246     shaders[3] = glCreateShader(GL_GEOMETRY_SHADER_DMP);
247 
248     nn::fs::FileReader file(L"rom:/shader.shbin");
249     size_t fileSize = file.GetSize();
250     void* buf = s_AppHeap.Allocate(fileSize);
251 
252     s32 read = file.Read(buf, fileSize);
253     glShaderBinary(4, shaders, GL_PLATFORM_BINARY_DMP, buf, read);
254     file.Finalize();
255     s_AppHeap.Free(buf);
256 
257     pGeoId = glCreateProgram();
258     glAttachShader(pGeoId, shaders[0]);
259     glAttachShader(pGeoId, GL_DMP_FRAGMENT_SHADER_DMP);
260 
261     glBindAttribLocation(pGeoId, 0, "aPosition");
262     glBindAttribLocation(pGeoId, 1, "aNormal");
263 
264     glLinkProgram(pGeoId);
265     glValidateProgram(pGeoId);
266     glUseProgram(pGeoId);
267     SetGeoMaterial(pGeoId);
268 
269     pAccId = glCreateProgram();
270     glAttachShader(pAccId, shaders[1]);
271     glAttachShader(pAccId, shaders[3]);
272     glAttachShader(pAccId, GL_DMP_FRAGMENT_SHADER_DMP);
273 
274     glBindAttribLocation(pAccId, 0, "aPosition");
275     glBindAttribLocation(pAccId, 1, "aColor");
276     glBindAttribLocation(pAccId, 2, "aPointSize");
277 
278     glLinkProgram(pAccId);
279     glValidateProgram(pAccId);
280     glUseProgram(pAccId);
281 
282     pPostId = glCreateProgram();
283     glAttachShader(pPostId, shaders[2]);
284     glAttachShader(pPostId, GL_DMP_FRAGMENT_SHADER_DMP);
285     glBindAttribLocation(pPostId, 0, "aPosition");
286     glBindAttribLocation(pPostId, 1, "aTexCoord");
287     glBindAttribLocation(pPostId, 2, "aColor");
288     glLinkProgram(pPostId);
289     glValidateProgram(pPostId);
290     glUseProgram(pPostId);
291 
292     return 0;
293 }
294 
295 /*=======================================================*/
296 /* draw object                                           */
297 /*=======================================================*/
DrawObject(void)298 static void DrawObject(void)
299 {
300     /* This function draws only one quadrangle. */
301     glUseProgram(pGeoId);
302     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
303     glClearDepthf(1.f);
304 
305     /* Set fragment operation mode to GL_FRAGOP_MODE_GL_DMP */
306     glUniform1i(glGetUniformLocation(pGeoId, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GL_DMP);
307 
308     /*
309      * Miscellaneous settings
310     */
311     glDisable(GL_BLEND);
312     glEnable(GL_DEPTH_TEST);
313     glDepthMask(GL_TRUE);
314     glDepthFunc(GL_LEQUAL);
315 
316     glDisable(GL_CULL_FACE);
317     glFrontFace(GL_CCW);
318     glCullFace(GL_BACK);
319 
320     glEnableVertexAttribArray(0);   /* enable position */
321     glEnableVertexAttribArray(1);   /* disable texture coordinate */
322 
323     for (int i = 0; i < cessna.obj_num; i++)
324     {
325         glBindBuffer(GL_ARRAY_BUFFER, cessna.posVB);
326         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)cessna.obj[i].vtx_offset);
327         glBindBuffer(GL_ARRAY_BUFFER, cessna.normVB);
328         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)cessna.obj[i].nrm_offset);
329         for (unsigned j = cessna.obj[i].patch_offset; j < cessna.obj[i].patch_size + cessna.obj[i].patch_offset; j++)
330         {
331             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cessna.idxVB);
332             glDrawElements(GL_TRIANGLES, cessna.patch[j].elm_size,
333                 GL_UNSIGNED_SHORT, (GLvoid*)(cessna.patch[j].elm_offset + cessna.obj[i].elm_offset));
334         }
335     }
336 
337     /*
338      * Finalization
339     */
340     glDisableVertexAttribArray(0);
341     glDisableVertexAttribArray(1);
342 }
343 
344 /*=======================================================*/
345 /* draw frame                                            */
346 /*=======================================================*/
DrawFrame(void)347 static int DrawFrame(void)
348 {
349     static int f = 0;
350     static int gas_pattern = 0;
351     static const int step = 60;
352 
353     /* Clear display buffer */
354     glUseProgram(pGeoId);
355     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
356     glClearDepthf(1.f);
357 
358     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
359     s_RenderSystem.Clear();
360 
361     glUseProgram(pGeoId);
362 
363     nn::math::Matrix44 proj;
364     nn::math::MTX44Perspective(&proj, 65.0f, static_cast<f32>(nn::gx::DISPLAY0_WIDTH) / static_cast<f32>(nn::gx::DISPLAY0_HEIGHT), 1.0f, 200.f);
365 
366     nn::math::Matrix34 mv;
367     nn::math::VEC3 camPos(0.f, 1.f, 16.0f);
368     nn::math::VEC3 camUp(-1.f, 0.f, 0.f);
369     nn::math::VEC3 target(0.f, 0.f, 0.f);
370     nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
371 
372     if (f == 0)
373         SetGasColorTable(&gas,gasColorTable[gas_pattern]);
374 
375     /* Draw the Object */
376     glUseProgram(pGeoId);
377 
378     glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
379 
380     nn::math::Matrix34 mv_rot, tmp;
381     nn::math::MTX34RotXYZDeg(&tmp, 0.f, -90.f, 0.f);
382     nn::math::MTX34Mult(&mv_rot, &mv, &tmp);
383 
384     nn::math::Vector3 scale(0.1f, 0.1f, 0.1f);
385     nn::math::MTX34MultScale(&mv_rot, &mv_rot, &scale);
386 
387     nn::math::Vector3 trans(100.0f, 0.f, 0.f);
388     nn::math::MTX34MultTranslate(&mv_rot, &mv_rot, &trans);
389 
390     nn::math::Matrix44 tmp_m(mv_rot);
391 
392     glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(tmp_m));
393     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
394 
395     nn::math::Vector4 lpos0(0.57735f, 0.57735f, 0.57735f, 0.f);
396     glUniform4fv(glGetUniformLocation(pGeoId, "dmp_FragmentLightSource[0].position"), 1, static_cast<f32*>(lpos0));
397 
398     DrawObject();
399 
400     /* Gas accumulation pass */
401     glUseProgram(pAccId);
402     glDisable(GL_CULL_FACE);
403     glFrontFace(GL_CCW);
404     glCullFace(GL_BACK);
405 
406     glUniformMatrix4fv(glGetUniformLocation(pAccId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
407 
408     nn::math::Matrix34 mv_tr;
409     nn::math::Vector3 trans2(0.0f, -1.0f, static_cast<f32>(f - 20));
410     nn::math::MTX34MultTranslate(&mv_tr, &mv, &trans2);
411     nn::math::Matrix44 tmp_mv_tr(mv_tr);
412     glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(tmp_mv_tr));
413     GasAccumulation();
414 
415     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
416 
417     /* Gas shading pass */
418     GasShading();
419 
420     /* swap buffer */
421     glFinish();
422 
423     s_RenderSystem.SwapBuffers();
424 
425     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
426     s_RenderSystem.Clear();
427     s_RenderSystem.SwapBuffers();
428 
429     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
430 
431     if (++f == step)
432     {
433         gas_pattern = ++gas_pattern % 3;
434         f = 0;
435     }
436 
437     return !glGetError();
438 }
439 
440 /* ======================================================= */
441 /* main function                                           */
442 /* ======================================================= */
nnMain(void)443 void nnMain(void)
444 {
445     // Call only nn::applet::Enable to also allow execution from the HOME Menu
446     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
447     nn::applet::Enable();
448 
449     // fs initialization
450     nn::fs::Initialize();
451 
452     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
453     static char buffer[ROMFS_BUFFER_SIZE];
454     NN_UTIL_PANIC_IF_FAILED(
455         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
456 
457     /* Initialize the framebuffer and gas buffer*/
458     Initialize();
459 
460     /* Initialize shaders */
461     if (ShaderInitialize() >= 0)
462     {
463         /*Initialize standard and gaseous objects */
464         SceneObjectInitialize();
465 
466         while (1)
467         {
468             (void)DrawFrame();
469         }
470     }
471 
472     GasFinalize();
473     UnloadObjects();
474     /* shutdown_display */
475     s_RenderSystem.Finalize();
476     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
477     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
478     s_AppHeap.Finalize();
479 }
480 
481