1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     CommandBufferJump.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 <nn/gx/CTR/gx_CommandAccess.h>
33 
34 #include "demo.h"
35 
36 #include "Util.h"
37 #include "Loader.h"
38 
39 #include <string.h>
40 #include <math.h>
41 
42 #include "Memory.h"
43 
44 #define APP_NAME "CommandBufferJump"
45 
46 #define STATE_SETTINGS 0 /* 0 - simple Blinn-Phong, 1 - generalized Blinn-Phong, 2 - Cook-Torrance */
47 
48 static void State0(void);
49 
50 static void State1(void);
51 
52 static void State2(void);
53 
54 void (*render_state_func[])(void) =
55 {
56     State0, State1, State2,
57 };
58 
59 /* obj file loader class object */
60 dat_t robot;
61 
62 /* program id */
63 GLuint s_ProgramID;
64 
65 /* program ids */
66 GLuint s_ProgramIDs[3];
67 
68 /* shader id */
69 GLuint s_ShaderID;
70 
71 /* texture id */
72 GLuint s_TextureID[3];
73 
74 /* command list id */
75 GLuint s_CmdlistID[4];
76 
77 #define NUM_OBJ 18
78 unsigned* s_SubrCommand[NUM_OBJ];
79 
80 struct CmdlistInfo
81 {
82     GLvoid* bufferaddr;
83     GLsizei buffersize;
84 } s_CmdlistInfo[4];
85 
86 /* ExpHeap for app. */
87 nn::fnd::ExpHeap s_AppHeap;
88 uptr s_HeapForGx;
89 uptr s_HeapForMalloc;
90 const u32 s_GxHeapSize = 0x400000;
91 const u32 s_HeapSize = 0x200000;
92 
93 demo::RenderSystem s_RenderSystem;
94 
State0(void)95 static void State0(void)
96 {
97     GLfloat ls0[] = {1.f, 1.f, 0.f, 1.f};
98     GLfloat ms[] = {1.f, 1.f, 1.f, 1.f};
99     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0);
100     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms);
101 
102     /* to ignore 2nd specular term, set 0 to ms2.
103     use of const reflection allows material specular2(ms2). */
104     GLfloat ms2[] = {0.f, 0.f, 0.f, 1.f};
105     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms2);
106     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE);
107 
108     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
109     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_TRUE);
110 
111     /* Because the 2nd specular term is not used, only the D0 table is used
112     in configuration 0. */
113     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG0_DMP);
114 
115     /* geometry factor is not considered. */
116     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE);
117 
118     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
119     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE);
120 
121     /* bind lookup table */
122     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 0);
123 
124     /* setup lookup table */
125     GLuint lutids[2];
126     glGenTextures(2, lutids);
127     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
128 
129     GLfloat lut[512];
130     int j;
131     memset(lut, 0, sizeof(lut));
132 
133     for (j = 0; j < 256; j++)
134         /* shininess is 10.0 */
135         lut[j] = powf((float)j/255.9375f, 10.f);
136         /* shininess is 1.0 */
137         /* lut[j] = powf((float)j/255.9375f, 1.f); */
138     for (j = 0; j < 255; j++)
139         lut[j + 256] = lut[j + 1] - lut[j];
140     lut[255 + 256] = 1.f - lut[255];
141 
142     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
143     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
144 
145     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
146     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
147     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
148     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
149     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
150     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
151 }
152 
153 /* Generalized Blinn-Phong reflection */
State1(void)154 static void State1(void)
155 {
156     GLfloat ls0[] = {0.f, 1.f, 0.f, 1.f};
157     GLfloat ms[] = {1.f, 1.f, 1.f, 1.f};
158     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0);
159     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms);
160 
161     GLfloat ls20[] = {1.f, 0.01f, 0.25f, 1.f};
162     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls20);
163     /* use of const reflection allows material specular2(ms2). */
164     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE);
165     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms);
166 
167     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1"), GL_LIGHT_ENV_NH_DMP);
168     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
169     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1"), GL_TRUE);
170     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_TRUE);
171 
172     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG2_DMP);
173 
174     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0"), GL_FALSE);
175     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE);
176     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
177     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1"), GL_TRUE);
178     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE);
179 
180     /* bind lookup table */
181     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 0);
182     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 1);
183 
184     /* setup lookup table */
185     GLuint lutids[3];
186     glGenTextures(3, lutids);
187     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
188 
189     GLfloat lut[512];
190     int j;
191     memset(lut, 0, sizeof(lut));
192 
193     /* set layer1 distribution function */
194     for (j = 0; j < 256; j++)
195         /* when s is equal to 2.0/m^2, highlight specular is similar between
196         power function and gaussian function.
197         when s is 90.0, m is 0.149, and when s is 2.0,
198         m is 1.0. */
199         /* lut[j] = powf((float)j/255.9375f, 90.f); */
200         lut[j] = gaussian((float)j/255.9375f, 0.149f);
201     for (j = 0; j < 255; j++)
202         lut[j + 256] = lut[j + 1] - lut[j];
203     lut[255 + 256] = 1.f - lut[255];
204 
205     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
206     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
207 
208     /* set layer2 distribution function */
209     memset(lut, 0, sizeof(lut));
210 
211     for (j = 0; j < 256; j++)
212         /* lut[j] = powf((float)j/255.9375f, 2.f); */
213         lut[j] = gaussian((float)j/255.9375f, 1.f);
214     for (j = 0; j < 255; j++)
215         lut[j + 256] = lut[j + 1] - lut[j];
216     lut[255 + 256] = 1.f - lut[255];
217 
218     glBindTexture(GL_LUT_TEXTURE1_DMP, lutids[2]);
219     glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
220 
221     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
222     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
223     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
224     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
225     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
226     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
227 }
228 
229 
230 /* Full-scope Cook-Torrance reflection */
State2(void)231 static void State2(void)
232 {
233     GLfloat ls0[] = {1.f, 1.f, 1.f, 1.f};
234     GLfloat disable[] = {0.f, 0.f, 0.f, 0.f};
235 
236     /* to ignore specular 1st term, set 0. */
237     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, disable);
238     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls0);
239 
240     /* to use Rr, Rg, Rb table */
241     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_TRUE);
242 
243     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRR"), GL_LIGHT_ENV_VH_DMP);
244     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRG"), GL_LIGHT_ENV_VH_DMP);
245     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRB"), GL_LIGHT_ENV_VH_DMP);
246     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
247     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1"), GL_LIGHT_ENV_NH_DMP);
248 
249     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRR"), GL_FALSE);
250     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRG"), GL_FALSE);
251     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRB"), GL_FALSE);
252     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_FALSE);
253     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1"), GL_FALSE);
254 
255     /* below we make bit shift after sampling table of Fresnel reflection
256     we have to do this because we do not have HDR(sky has high intensity) */
257     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRR"), 2.f);
258     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRG"), 2.f);
259     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRB"), 2.f);
260     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD0"), 2.f);
261     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD1"), 2.f);
262 
263     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG4_DMP);
264 
265     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
266     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1"), GL_TRUE);
267     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE);
268 
269     /* geometory factor is considered in Cook-Torrance model */
270     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0"), GL_TRUE);
271     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_TRUE);
272 
273     /* bind lookup table */
274     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRR"), 0);
275     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRG"), 1);
276     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRB"), 2);
277     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 3);
278     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 4);
279 
280     /* setup lookup table */
281     GLuint lutids[6];
282     glGenTextures(6, lutids);
283     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
284 
285     GLfloat lut[512];
286     int j;
287     memset(lut, 0, sizeof(lut));
288     glBindTexture(GL_LUT_TEXTURE4_DMP, lutids[5]);
289     glTexImage1D(GL_LUT_TEXTURE4_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
290 
291     /* in this sample, gold is used as fresnel factor,
292     and real and imaginary part of refractive index of gold
293     is following.
294         n        k
295     ---------------------------------
296     0.183521, 2.959155  at 630 nm
297     0.516924, 2.276178  at 525 nm
298     1.464924, 1.860113  at 455 nm */
299     /* setup Rr table */
300     for (j = 0; j < 128; j++)
301         lut[j] = nk_fresnel((float)j/128.f, 0.183521f, 2.959155f);
302 
303     for (j = 0; j < 127; j++)
304         lut[j + 256] = lut[j+1] - lut[j];
305 
306     lut[127 + 256] = nk_fresnel(1.f, 0.183521f, 2.959155f) - lut[127];
307 
308     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
309     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
310 
311     /* setup Rg table */
312     memset(lut, 0, sizeof(lut));
313     for (j = 0; j < 128; j++)
314         lut[j] = nk_fresnel((float)j/128.f, 0.516924f, 2.276178f);
315 
316     for (j = 0; j < 127; j++)
317         lut[j + 256] = lut[j+1] - lut[j];
318 
319     lut[127 + 256] = nk_fresnel(1.f, 0.516924f, 2.276178f) - lut[127];
320 
321     glBindTexture(GL_LUT_TEXTURE1_DMP, lutids[2]);
322     glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
323 
324     /* setup Rb table */
325     memset(lut, 0, sizeof(lut));
326     for (j = 0; j < 128; j++)
327         lut[j] = nk_fresnel((float)j/128.f, 1.464924f, 1.860113f);
328 
329     for (j = 0; j < 127; j++)
330         lut[j + 256] = lut[j+1] - lut[j];
331 
332     lut[127 + 256] = nk_fresnel(1.f, 1.464924f, 1.860113f) - lut[127];
333 
334     glBindTexture(GL_LUT_TEXTURE2_DMP, lutids[3]);
335     glTexImage1D(GL_LUT_TEXTURE2_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
336 
337     /* don't use D0 table, so setup D1 table only */
338     memset(lut, 0, sizeof(lut));
339     /* Beckmann function is used in m=1.0 and m=0.5 */
340     for (j = 1; j < 128; j++)
341         lut[j] = beckmann((float)j/128.f, 1.f); /* m=1.0 */
342         /* lut[j] = beckmann((float)j/128.f, 0.5f); */ /* m=0.5 */
343 
344     for (j = 0; j < 127; j++)
345         lut[j + 256] = lut[j+1] - lut[j];
346     lut[127 + 256] = 1.f - lut[127];
347 
348     glBindTexture(GL_LUT_TEXTURE3_DMP, lutids[4]);
349     glTexImage1D(GL_LUT_TEXTURE3_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
350 
351     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
352     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
353     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
354     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
355     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
356     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
357 }
358 
359 /* generate simple object */
LoadObjects(void)360 static void LoadObjects(void)
361 {
362     /* load obj file geometry and diffuse texture */
363     loadDAT( "rom:/resources/robot1.dat", &robot);
364 }
365 
UnloadObjects(void)366 static void UnloadObjects(void)
367 {
368     unloadDAT(&robot);
369 
370     return;
371 }
372 
CreateCommand()373 static void CreateCommand()
374 {
375     nn::math::Matrix44 proj;
376     nn::math::Matrix34 mv, rot;
377 
378     // Different material setting commands each configured by State0(), State1(), and State2() are stored in s_CmdlistID[0], s_CmdlistID[1], and s_CmdlistID[2], respectively.
379     //
380     //
381 
382     // A command for drawing is stored at the front in s_CmdlistID[3].
383     //
384 
385     GLuint currentCmdlist;
386     nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, (GLint*)&currentCmdlist);
387 
388     for (int prog = 0; prog < 3; prog++)
389     {
390         s_ProgramID = s_ProgramIDs[prog];
391         nngxBindCmdlist(s_CmdlistID[prog]);
392 
393         glUseProgram(s_ProgramID);
394         glBindTexture(GL_TEXTURE_COLLECTION_DMP, s_TextureID[prog]);
395 
396         /* setup projection matrix */
397         nn::math::MTX44Frustum(&proj, -0.06f, 0.06f, -0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH,
398                      0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH, 0.2f, 200.f);
399         glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
400 
401         nn::math::Vector3 camPos(0.f, 0.f, 6.f);
402         nn::math::Vector3 camUp(0.f, 1.f, 0.f);
403         nn::math::Vector3 target(0.f, 0.f, 0.f);
404         nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f);
405         nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
406         nn::math::MTX34Mult(&mv, &rot, &mv);
407 
408         /* setup light direction */
409         nn::math::Vector4 lpos0(0.f, 1.f, 1.f, 0.f);
410         nn::math::Vector4 mv0(mv.m[0][0], mv.m[0][1], mv.m[0][2], mv.m[0][3]);
411         nn::math::Vector4 mv1(mv.m[1][0], mv.m[1][1], mv.m[1][2], mv.m[1][3]);
412         nn::math::Vector4 mv2(mv.m[2][0], mv.m[2][1], mv.m[2][2], mv.m[2][3]);
413         nn::math::Vector4 lpos(nn::math::VEC4Dot(&mv0, &lpos0), nn::math::VEC4Dot(&mv1, &lpos0), nn::math::VEC4Dot(&mv2, &lpos0), lpos0.w);
414         glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].position"), 1, static_cast<f32*>(lpos));
415 
416         // Create a material setting comment
417         nngxUpdateState(NN_GX_STATE_ALL);
418         nngxValidateState(NN_GX_STATE_ALL, GL_TRUE);
419 
420         // Add a Channel 1 kick command
421         // Pad with dummy commands as necessary
422         unsigned retCmd[2] = {0x00000001, 0x000f023d};
423         unsigned emptyCmd[2] = {0x00000000, 0x00000200};
424         GLsizei buffersize;
425         nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&buffersize);
426         if ((buffersize & 8) == 0)
427             nngxAdd3DCommand(emptyCmd, sizeof(emptyCmd), GL_TRUE);
428         nngxAdd3DCommand(retCmd, sizeof(retCmd), GL_TRUE);
429 
430         // Save the sub-routine used for setting materials in s_CmdlistInfo[0-2].
431         nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&s_CmdlistInfo[prog].buffersize);
432         nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&s_CmdlistInfo[prog].bufferaddr);
433         nngxUpdateBuffer(s_CmdlistInfo[prog].bufferaddr, s_CmdlistInfo[prog].buffersize);
434 
435         glEnableVertexAttribArray(0);
436         glEnableVertexAttribArray(1);
437 
438         if (prog == 0)
439         {
440             // Create a command for drawing in s_CmdlistID[3].
441             nngxBindCmdlist(s_CmdlistID[3]);
442 
443             /* draw objects */
444             for (int i = 0; i < robot.obj_num; i++)
445             {
446                 glBindBuffer(GL_ARRAY_BUFFER, robot.posVB);
447                 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)robot.obj[i].vtx_offset);
448                 glBindBuffer(GL_ARRAY_BUFFER, robot.normVB);
449                 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)robot.obj[i].nrm_offset);
450 
451                 for (unsigned j = robot.obj[i].patch_offset; j < robot.obj[i].patch_size + robot.obj[i].patch_offset; j++)
452                 {
453                     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, robot.idxVB);
454                     glDrawElements(GL_TRIANGLES, robot.patch[j].elm_size,
455                         GL_UNSIGNED_SHORT, (GLvoid*)(robot.patch[j].elm_offset + robot.obj[i].elm_offset));
456                 }
457             }
458 
459             // Add a Channel 1 kick command
460             // Pad with dummy commands as necessary
461             nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&buffersize);
462             if ((buffersize & 8) == 0)
463                 nngxAdd3DCommand(emptyCmd, sizeof(emptyCmd), GL_TRUE);
464             nngxAdd3DCommand(retCmd, sizeof(retCmd), GL_TRUE);
465 
466             // Save a sub-routine for the drawing command in s_CmdlistInfo[3].
467             nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&s_CmdlistInfo[3].buffersize);
468             nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&s_CmdlistInfo[3].bufferaddr);
469             nngxUpdateBuffer(s_CmdlistInfo[3].bufferaddr, s_CmdlistInfo[3].buffersize);
470         }
471     }
472 
473     nngxBindCmdlist(currentCmdlist);
474 
475 }
476 
DrawFrame(void)477 int DrawFrame(void)
478 {
479     static int f = 0;
480 
481     nn::math::Matrix44 proj;
482     nn::math::Matrix34 mv, rot, trans, scale;
483 
484     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
485     s_RenderSystem.Clear();
486 
487     if (f == 0)
488         CreateCommand();
489 
490     int num_obj = (f / 60) % NUM_OBJ + 1;
491 
492     // Draw the number of models given by num_obj.
493     for (int obj = 0; obj < num_obj; obj++)
494     {
495         unsigned* modelViewCommand = s_SubrCommand[obj];
496 
497         // Create model view command
498         nn::math::Vector3 camPos(0.f, 0.f, 6.f);
499         nn::math::Vector3 camUp(0.f, 1.f, 0.f);
500         nn::math::Vector3 target(0.f, 0.f, 0.f);
501         nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f);
502         nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
503         nn::math::MTX34Mult(&mv, &rot, &mv);
504         nn::math::MTX34RotXYZDeg(&rot, 0.f, static_cast<f32>((float)(360.f / NUM_OBJ * obj) - f), 0.f);
505         nn::math::MTX34Mult(&mv, &mv, &rot);
506         nn::math::Vector3 Trans(2.0f, 0.f, 0.f);
507         nn::math::MTX34Translate(&trans, &Trans);
508         nn::math::MTX34Mult(&mv, &mv, &trans);
509         nn::math::Vector3 Scale(0.25f, 0.25f, 0.25f);
510         nn::math::MTX34Scale(&scale, &Scale);
511         nn::math::MTX34Mult(&mv, &mv, &scale);
512 
513         nn::math::Matrix44 m(mv);
514 
515         // Create a sub-routine for configuring the model view
516         int index = 0;
517         modelViewCommand[index++] = 0x80000004;
518         modelViewCommand[index++] = 0x000f02c0;
519 
520         for (int i = 0; i < 4; i++)
521         for (int j = 0; j < 4; j++)
522         {
523             float v = m.m[i][3 - j];
524             modelViewCommand[index++] = *(unsigned*)&v;
525             if (i == 0 && j == 0)
526                 modelViewCommand[index++] = 0x00ff02c1;
527         }
528         modelViewCommand[index++] = 0x00000000;     // Pad the last four bytes of the burst.
529         if ((index & 2) == 0)
530         {
531             // Padding for 16-byte alignment
532             modelViewCommand[index++] = 0x00000000;
533             modelViewCommand[index++] = 0x00000200;
534         }
535         // Channel 1 kick command
536         modelViewCommand[index++] = 0x00000001;
537         modelViewCommand[index++] = 0x000f023d;
538 
539         // Clear the cache
540         nngxUpdateBuffer(modelViewCommand, sizeof(unsigned) * index);
541 
542 
543 
544         // Apply the sub-routine for configuring materials
545         nngxAddSubroutineCommand(s_CmdlistInfo[obj % 3].bufferaddr, s_CmdlistInfo[obj % 3].buffersize);
546 
547         // Apply the sub-routine for configuring the model view
548         nngxAddSubroutineCommand(modelViewCommand, sizeof(unsigned) * index);
549 
550         // Apply the sub-routine for the draw command
551         nngxAddSubroutineCommand(s_CmdlistInfo[3].bufferaddr, s_CmdlistInfo[3].buffersize);
552     }
553 
554     s_RenderSystem.SwapBuffers();
555 
556     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
557     s_RenderSystem.Clear();
558     s_RenderSystem.SwapBuffers();
559 
560     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
561 
562     f++;
563 
564     return !glGetError();
565 }
566 
567 /* initialization */
Initialize(void)568 static int Initialize(void)
569 {
570     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
571     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
572     /* Initialize display */
573     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
574 
575     /* Create heap for malloc*/
576     s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
577     setMemoryHeap(s_HeapForMalloc, s_GxHeapSize);
578 
579     for (int i = 0; i < 3; i++)
580         s_ProgramIDs[i] = glCreateProgram();
581     s_ShaderID = glCreateShader(GL_VERTEX_SHADER);
582 
583     nn::fs::FileReader file(L"rom:/shader.shbin");
584     size_t fileSize = file.GetSize();
585     void* buf = s_AppHeap.Allocate(fileSize);
586 
587     s32 read = file.Read(buf, fileSize);
588     glShaderBinary(1, &s_ShaderID, GL_PLATFORM_BINARY_DMP, buf, read);
589     file.Finalize();
590     s_AppHeap.Free(buf);
591 
592     GLuint currentCmdlist;
593     nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, (GLint*)&currentCmdlist);
594 
595     for (int i = 0; i < 3; i++)
596     {
597         s_ProgramID = s_ProgramIDs[i];
598 
599         nngxGenCmdlists(1, &s_CmdlistID[i]);
600         nngxBindCmdlist(s_CmdlistID[i]);
601         nngxCmdlistStorage(0x8000, 16);
602 
603         glAttachShader(s_ProgramID, s_ShaderID);
604         glAttachShader(s_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP);
605 
606         glBindAttribLocation(s_ProgramID, 0, "aPosition");
607         glBindAttribLocation(s_ProgramID, 1, "aNormal");
608 
609         glLinkProgram(s_ProgramID);
610         glValidateProgram(s_ProgramID);
611         glUseProgram(s_ProgramID);
612     }
613 
614     nngxGenCmdlists(1, &s_CmdlistID[3]);
615     nngxBindCmdlist(s_CmdlistID[3]);
616     nngxCmdlistStorage(0x10000, 16);
617     GLint SubrCommandStart;
618     nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&SubrCommandStart);
619 
620     // s_SubrCommand stores a subroutine for configuring the model view for each object.
621     for (int i = 0; i < NUM_OBJ; i++)
622         s_SubrCommand[i] = (unsigned*)(SubrCommandStart + 0x2000 + 0x100 * i);
623 
624     nngxBindCmdlist(currentCmdlist);
625 
626     glClearColor(0.36f, 0.42f, 0.5f, 1.0f);
627     glClearDepthf(1.f);
628 
629     glEnable(GL_DEPTH_TEST);
630     glDepthFunc(GL_LESS);
631     glEnable(GL_CULL_FACE);
632     glFrontFace(GL_CCW);
633     glCullFace(GL_BACK);
634 
635     LoadObjects();
636 
637     /* set another render state */
638     for (int i = 0; i < 3; i++)
639     {
640         s_ProgramID = s_ProgramIDs[i];
641 
642         glUseProgram(s_ProgramID);
643 
644         (*render_state_func[i])();
645 
646         /* enable DMP fragment lighting */
647         glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE);
648         glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE);
649 
650         glGetIntegerv(GL_TEXTURE_COLLECTION_BINDING_DMP, (GLint*)&s_TextureID[i]);
651     }
652 
653     return 0;
654 }
655 
nnMain(void)656 void nnMain(void)
657 {
658     // Call only the nn::applet::Enable function to also allow execution from the HOME Menu
659     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
660     nn::applet::Enable();
661 
662     // fs initialization
663     nn::fs::Initialize();
664 
665     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
666     static char buffer[ROMFS_BUFFER_SIZE];
667     NN_UTIL_PANIC_IF_FAILED(
668         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
669 
670     /* initialization */
671     if (Initialize() >= 0)
672     {
673         /* Enter loop */
674         while (1)
675         {
676             (void)DrawFrame();
677         }
678     }
679 
680     UnloadObjects();
681     /* shutdown_display */
682     s_RenderSystem.Finalize();
683     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
684     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
685     s_AppHeap.Finalize();
686 }
687