1 /*
2  *------------------------------------------------------------
3  * Copyright(c) 2009-2010 by Digital Media Professionals Inc.
4  * All rights reserved.
5  *------------------------------------------------------------
6  * This source code is the confidential and proprietary
7  * of Digital Media Professionals Inc.
8  *------------------------------------------------------------
9  */
10 
11 #include <nn/gx.h>
12 #include <nn/fs.h>
13 #include <nn/math.h>
14 #include <nn/init.h>
15 #include <nn/os.h>
16 #include <nn/applet.h>
17 #include "Util.h"
18 #include "Loader.h"
19 #include "Gas.h"
20 #include "Memory.h"
21 
22 #include "demo.h"
23 
24 /* program id */
25 GLuint pAccId;
26 GLuint pPostId;
27 
28 /* shader id */
29 GLuint s_Shaders[2];
30 
31 /* Standard object (triangles, not gaseous object) */
32 struct gas_data gas;
33 dat_t plane;
34 
35 /* ExpHeap for app. */
36 nn::fnd::ExpHeap s_AppHeap;
37 uptr s_HeapForGx;
38 uptr s_HeapForMalloc;
39 const u32 s_GxHeapSize = 0x400000;
40 const u32 s_HeapSize = 0x200000;
41 
42 demo::RenderSystem s_RenderSystem;
43 
44 /*=======================================================*/
45 /* Static function declaration                           */
46 /*=======================================================*/
47 static int DrawFrame(void);
48 
49 /*=======================================================*/
50 /* initialization                                        */
51 /*=======================================================*/
52 
Initialize(void)53 static void Initialize(void)
54 {
55     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
56     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
57     /* Initialize display */
58     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
59 
60     /* Create heap for malloc*/
61     s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
62     setMemoryHeap(s_HeapForMalloc, s_HeapSize);
63 
64     /* Initialization for gas */
65     GasInitialize();
66 }
67 
SceneObjectInitialize(void)68 static void SceneObjectInitialize(void)
69 {
70     /* Load object (non-gaseous object) */
71     loadDAT( "rom:/resources/planeXY3.dat", &plane);
72 
73     /* Load Gaseous object */
74     float tr_flame[24] =
75     {
76         0.0f,   0.00f,  0.0f,   /* 0 */
77         0.2f,   0.15f,  0.05f,  /* 1 */
78         0.6f,   0.25f,  0.15f,  /* 2 */
79         0.9f,   0.35f,  0.2f,   /* 3 */
80         0.92f,  0.6f,   0.15f,  /* 4 */
81         0.95f,  0.85f,  0.05f,  /* 5 */
82         1.0f,   0.95f,  0.0f,   /* 6 */
83         1.0f,   1.0f,   1.0f    /* 7 */
84     };
85     DefaultGasObject(&gas, tr_flame);
86 
87     /* Define the gaseous object geometry */
88     /* A simple quad in this sample */
89     float cx = 0.0;
90     float cy = 0.0;
91     float rd = 8.0;
92     float _vertex[16]=
93     {
94         cx - rd, cy - rd, 0.0f, 1.0f,
95         cx - rd, cy + rd, 0.0f, 1.0f,
96         cx + rd, cy + rd, 0.0f, 1.0f,
97         cx + rd, cy - rd, 0.0f, 1.0f
98     };
99 
100     float density = 1.0;
101     float _color[4]= {density, density, density, density };
102 
103     float t0 = 0.0f, t1 = 1.0f;
104     float _texture[8]=
105     {
106         t0, t0,
107         t1, t0,
108         t1, t1,
109         t0, t1
110     };
111 
112     glGenBuffers(1, &gas.gasgeo_center_ID);
113     glGenBuffers(1, &gas.gasgeo_density_ID);
114     glGenBuffers(1, &gas.gasgeo_tx0_ID);
115     glGenBuffers(1, &gas.gasgeo_tri_ID);
116 
117     glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_center_ID);
118     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, &_vertex[0], GL_STATIC_DRAW);
119     gas.gasgeo_size = 6;
120 
121     glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_tx0_ID);
122     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, &_texture[0], GL_STATIC_DRAW);
123 
124     glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_density_ID);
125     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, &_color[0], GL_STATIC_DRAW);
126 
127     GLushort idxs[6] = {0, 1, 2, 0, 2,  3};
128     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gas.gasgeo_tri_ID);
129     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*sizeof(GLushort), idxs, GL_STATIC_DRAW);
130 }
131 
132 /*=======================================================*/
133 /* finalization                                          */
134 /*=======================================================*/
UnloadObjects(void)135 static void UnloadObjects(void)
136 {
137     unloadDAT(&plane);
138 
139     return;
140 }
141 
142 /*=======================================================*/
143 /* Initialization  of s_Shaders                            */
144 /*=======================================================*/
ShaderInitialize(void)145 int ShaderInitialize(void)
146 {
147     s_Shaders[0] = glCreateShader(GL_VERTEX_SHADER);
148     s_Shaders[1] = glCreateShader(GL_VERTEX_SHADER);
149 
150     nn::fs::FileReader file(L"rom:/shader.shbin");
151     size_t fileSize = file.GetSize();
152     void* buf = s_AppHeap.Allocate(fileSize);
153 
154     s32 read = file.Read(buf, fileSize);
155     glShaderBinary(2, s_Shaders, GL_PLATFORM_BINARY_DMP, buf, read);
156     file.Finalize();
157     s_AppHeap.Free(buf);
158 
159     pAccId = glCreateProgram();
160     glAttachShader(pAccId, s_Shaders[0]);
161     glAttachShader(pAccId, GL_DMP_FRAGMENT_SHADER_DMP);
162     glBindAttribLocation(pAccId, 0, "aPosition");
163     glBindAttribLocation(pAccId, 1, "aTexCoord");
164     glBindAttribLocation(pAccId, 2, "aColor");
165 
166     glLinkProgram(pAccId);
167     glValidateProgram(pAccId);
168     glUseProgram(pAccId);
169 
170     pPostId = glCreateProgram();
171     glAttachShader(pPostId, s_Shaders[1]);
172     glAttachShader(pPostId, GL_DMP_FRAGMENT_SHADER_DMP);
173     glBindAttribLocation(pPostId, 0, "aPosition");
174     glBindAttribLocation(pPostId, 1, "aTexCoord");
175     glBindAttribLocation(pPostId, 2, "aColor");
176 
177     glLinkProgram(pPostId);
178     glValidateProgram(pPostId);
179     glUseProgram(pPostId);
180 
181     return 0;
182 }
183 
184 /*=======================================================*/
185 /* draw object                                           */
186 /*=======================================================*/
DrawObject(void)187 static void DrawObject(void)
188 {
189     /* This function draws only one quadrangle. */
190     glUseProgram(pAccId);
191     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
192     glClearDepthf(1.f);
193 
194     /* Set fragment operation mode to GL_FRAGOP_MODE_GL_DMP */
195     glUniform1i(glGetUniformLocation(pAccId, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GL_DMP);
196 
197     /*
198      * Setup texture and blending unit
199      * The color of the object is defined as a constant color from blending unit 0
200     */
201     glUniform1i(glGetUniformLocation(pAccId, "dmp_Texture[0].samplerType"), GL_FALSE);
202     glUniform1i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
203     glUniform1i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
204     glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
205     glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
206     glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].srcRgb"), GL_CONSTANT, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
207     glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
208 
209     float almostblack[4] = {0.15f, 0.15f, 0.15f, 0.0f};
210     glUniform4fv(glGetUniformLocation(pAccId, "dmp_TexEnv[0].constRgba"), 1, almostblack);
211 
212     /*
213      * Miscellaneous settings
214     */
215     glDisable(GL_BLEND);
216     glEnable(GL_DEPTH_TEST);
217     glDepthMask(GL_TRUE);
218     glDepthFunc(GL_LEQUAL);
219 
220     glDisable(GL_CULL_FACE);
221     glFrontFace(GL_CCW);
222     glCullFace(GL_BACK);
223 
224     glEnableVertexAttribArray(0);   /* enable position */
225     glDisableVertexAttribArray(1);  /* disable texture coordinate */
226     glDisableVertexAttribArray(2);  /* disable color */
227 
228     for (int i = 0; i < plane.obj_num; i++)
229     {
230         glBindBuffer(GL_ARRAY_BUFFER, plane.posVB);
231         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)plane.obj[i].vtx_offset);
232         for (unsigned j = plane.obj[i].patch_offset; j < plane.obj[i].patch_size + plane.obj[i].patch_offset; j++)
233         {
234             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane.idxVB);
235             glDrawElements(GL_TRIANGLES, plane.patch[j].elm_size,
236                 GL_UNSIGNED_SHORT, (GLvoid*)(plane.patch[j].elm_offset + plane.obj[i].elm_offset));
237         }
238     }
239 
240     /*
241      * Finalization
242     */
243     glDisableVertexAttribArray(0);
244 }
245 
246 /*=======================================================*/
247 /* draw frame                                            */
248 /*=======================================================*/
DrawFrame(void)249 static int DrawFrame(void)
250 {
251     static int f = 0;
252     static const int step = 60;
253 
254     /* Clear display buffer */
255     glBindFramebuffer(GL_FRAMEBUFFER, DISPLAY_BUFFER);
256     glClearColor(0.2f, 0.4f, 0.7f, 1.0f);
257     glClearDepthf(1.f);
258 
259     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
260     s_RenderSystem.Clear();
261 
262     glUseProgram(pAccId);
263 
264     nn::math::Matrix44 proj, m;
265     nn::math::MTX44Perspective(&proj, 45.0f, static_cast<f32>(DISPLAY_WIDTH) / static_cast<f32>(DISPLAY_HEIGHT), 1.0f, 200.f);
266     glUniformMatrix4fv(glGetUniformLocation(pAccId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
267 
268     nn::math::Matrix34 mv, rot;
269     nn::math::Vector3 camPos(0.f, 0.f, 80.0f);
270     nn::math::Vector3 camUp(0.f, 1.f, 0.f);
271     nn::math::Vector3 target(0.f, 0.f, 0.f);
272 
273     nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
274     nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f);
275     nn::math::MTX34Mult(&mv, &mv, &rot);
276 
277     {
278         /* Draw the Object */
279         nn::math::Matrix34 mv_rot;
280         nn::math::MTX34RotXYZDeg(&mv_rot, 0.f, 45.0f, 0.f);
281         nn::math::MTX34Mult(&mv_rot, &mv, &mv_rot);
282         m = nn::math::Matrix44(mv_rot);
283         glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
284         DrawObject();
285     }
286 
287     /* Draw Z buffer for accumulation */
288     GasRenderAccumulationZBuffer(DrawObject);
289 
290     {
291         /* Gas accumulation pass */
292         nn::math::Matrix34 mv_tr;
293         nn::math::Vector3 trans(static_cast<f32>(f - 20), 0.f, 0.f);
294         nn::math::MTX34MultTranslate(&mv_tr, &mv, &trans);
295         m = nn::math::Matrix44(mv_tr);
296         glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
297         GasAccumulation();
298     }
299 
300     /* Gas shading pass */
301     GasShading();
302 
303     /* Blend shading result to color buffer */
304     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
305     GasBlendShadingResult();
306 
307     /* swap buffer */
308     glFinish();
309     s_RenderSystem.SwapBuffers();
310 
311 
312     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
313     s_RenderSystem.Clear();
314     s_RenderSystem.SwapBuffers();
315 
316     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
317 
318     if (++f == step)
319         f = 0;
320 
321     return !glGetError();
322 }
323 
324 /*=======================================================*/
325 /* main function                                         */
326 /*=======================================================*/
nnMain(void)327 void nnMain(void)
328 {
329     // Call only nn::applet::Enable to also allow execution from the HOME Menu
330     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
331     nn::applet::Enable();
332 
333     // fs initialization
334     nn::fs::Initialize();
335 
336     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
337     static char buffer[ROMFS_BUFFER_SIZE];
338     NN_UTIL_PANIC_IF_FAILED(
339         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
340 
341     /* Initialize the framebuffer and gas buffer*/
342     Initialize();
343 
344     /* Initialization  of s_Shaders */
345     if (ShaderInitialize() >= 0)
346     {
347         /*Initialize standard and gaseous objects */
348         SceneObjectInitialize();
349 
350         /* Enter loop */
351         while (1)
352         {
353             (void)DrawFrame();
354         }
355     }
356 
357     UnloadObjects();
358     /* shutdown_display */
359     s_RenderSystem.Finalize();
360     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
361     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
362     s_AppHeap.Finalize();
363 }
364 
365