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