1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     LightingMicrofacet.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 "Memory.h"
42 
43 #define APP_NAME "LightingMicrofacet"
44 
45 #define STATE_SETTINGS 0 /* 0 - simple Blinn-Phong, 1 - generalized Blinn-Phong, 2 - Cook-Torrance */
46 
47 static void State0(void);
48 
49 static void State1(void);
50 
51 static void State2(void);
52 
53 void (*render_state_func[])(void) =
54 {
55     State0, State1, State2,
56 };
57 
58 /* obj file loader class object */
59 dat_t robot;
60 
61 /* program id */
62 GLuint s_ProgramID;
63 
64 /* shader id */
65 GLuint s_ShaderID;
66 
67 /* ExpHeap for app. */
68 nn::fnd::ExpHeap s_AppHeap;
69 uptr s_HeapForGx;
70 uptr s_HeapForMalloc;
71 const u32 s_GxHeapSize = 0x400000;
72 const u32 s_HeapSize = 0x200000;
73 
74 demo::RenderSystem s_RenderSystem;
75 
State0(void)76 static void State0(void)
77 {
78     GLfloat ls0[] = {1.f, 1.f, 0.f, 1.f};
79     GLfloat ms[] = {1.f, 1.f, 1.f, 1.f};
80     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0);
81     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms);
82 
83     /* to ignore 2nd specular term, set 0 to ms2.
84     use of const reflection allows material specular2(ms2). */
85     GLfloat ms2[] = {0.f, 0.f, 0.f, 1.f};
86     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms2);
87     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE);
88 
89     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
90     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_TRUE);
91 
92     /* Because the 2nd specular term is not used, only the D0 table is used
93     in configuration 0. */
94     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG0_DMP);
95 
96     /* geometry factor is not considered. */
97     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE);
98 
99     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
100     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE);
101 
102     /* bind lookup table */
103     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 0);
104 
105     /* setup lookup table */
106     GLuint lutids[2];
107     glGenTextures(2, lutids);
108     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
109 
110     GLfloat lut[512];
111     int j;
112     memset(lut, 0, sizeof(lut));
113 
114     for (j = 0; j < 256; j++)
115         /* shininess is 10.0 */
116         lut[j] = powf((float)j/255.9375f, 10.f);
117         /* shininess is 1.0 */
118         /* lut[j] = powf((float)j/255.9375f, 1.f); */
119     for (j = 0; j < 255; j++)
120         lut[j + 256] = lut[j + 1] - lut[j];
121     lut[255 + 256] = 1.f - lut[255];
122 
123     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
124     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
125 
126     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
127     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
128     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
129     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
130     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
131     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
132 }
133 
134 /* Generalized Blinn-Phong reflection */
State1(void)135 static void State1(void)
136 {
137     GLfloat ls0[] = {0.f, 1.f, 0.f, 1.f};
138     GLfloat ms[] = {1.f, 1.f, 1.f, 1.f};
139     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0);
140     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms);
141 
142     GLfloat ls20[] = {1.f, 0.01f, 0.25f, 1.f};
143     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls20);
144     /* use of const reflection allows material specular2(ms2). */
145     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE);
146     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms);
147 
148     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1"), GL_LIGHT_ENV_NH_DMP);
149     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
150     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1"), GL_TRUE);
151     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_TRUE);
152 
153     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG2_DMP);
154 
155     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0"), GL_FALSE);
156     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE);
157     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
158     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1"), GL_TRUE);
159     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE);
160 
161     /* bind lookup table */
162     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 0);
163     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 1);
164 
165     /* setup lookup table */
166     GLuint lutids[3];
167     glGenTextures(3, lutids);
168     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
169 
170     GLfloat lut[512];
171     int j;
172     memset(lut, 0, sizeof(lut));
173 
174     /* set layer1 distribution function */
175     for (j = 0; j < 256; j++)
176         /* when s is equal to 2.0/m^2, highlight specular is similar between
177         power function and gaussian function.
178         when s is 90.0, m is 0.149, and when s is 2.0,
179         m is 1.0. */
180         /* lut[j] = powf((float)j/255.9375f, 90.f); */
181         lut[j] = gaussian((float)j/255.9375f, 0.149f);
182     for (j = 0; j < 255; j++)
183         lut[j + 256] = lut[j + 1] - lut[j];
184     lut[255 + 256] = 1.f - lut[255];
185 
186     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
187     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
188 
189     /* set layer2 distribution function */
190     memset(lut, 0, sizeof(lut));
191 
192     for (j = 0; j < 256; j++)
193         /* lut[j] = powf((float)j/255.9375f, 2.f); */
194         lut[j] = gaussian((float)j/255.9375f, 1.f);
195     for (j = 0; j < 255; j++)
196         lut[j + 256] = lut[j + 1] - lut[j];
197     lut[255 + 256] = 1.f - lut[255];
198 
199     glBindTexture(GL_LUT_TEXTURE1_DMP, lutids[2]);
200     glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
201 
202     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
203     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
204     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
205     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
206     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
207     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
208 }
209 
210 
211 /* Full-scope Cook-Torrance reflection */
State2(void)212 static void State2(void)
213 {
214     GLfloat ls0[] = {1.f, 1.f, 1.f, 1.f};
215     GLfloat disable[] = {0.f, 0.f, 0.f, 0.f};
216 
217     /* to ignore specular 1st term, set 0. */
218     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, disable);
219     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls0);
220 
221     /* to use Rr, Rg, Rb table */
222     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_TRUE);
223 
224     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRR"), GL_LIGHT_ENV_VH_DMP);
225     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRG"), GL_LIGHT_ENV_VH_DMP);
226     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRB"), GL_LIGHT_ENV_VH_DMP);
227     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP);
228     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1"), GL_LIGHT_ENV_NH_DMP);
229 
230     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRR"), GL_FALSE);
231     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRG"), GL_FALSE);
232     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRB"), GL_FALSE);
233     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_FALSE);
234     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1"), GL_FALSE);
235 
236     /* below we make bit shift after sampling table of Fresnel reflection
237     we have to do this because we do not have HDR(sky has high intensity) */
238     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRR"), 2.f);
239     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRG"), 2.f);
240     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRB"), 2.f);
241     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD0"), 2.f);
242     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD1"), 2.f);
243 
244     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG4_DMP);
245 
246     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE);
247     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1"), GL_TRUE);
248     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE);
249 
250     /* geometory factor is considered in Cook-Torrance model */
251     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0"), GL_TRUE);
252     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_TRUE);
253 
254     /* bind lookup table */
255     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRR"), 0);
256     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRG"), 1);
257     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRB"), 2);
258     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 3);
259     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 4);
260 
261     /* setup lookup table */
262     GLuint lutids[6];
263     glGenTextures(6, lutids);
264     glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]);
265 
266     GLfloat lut[512];
267     int j;
268     memset(lut, 0, sizeof(lut));
269     glBindTexture(GL_LUT_TEXTURE4_DMP, lutids[5]);
270     glTexImage1D(GL_LUT_TEXTURE4_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
271 
272     /* in this sample, gold is used as fresnel factor,
273     and real and imaginary part of refractive index of gold
274     is following.
275         n        k
276     ---------------------------------
277     0.183521, 2.959155  at 630 nm
278     0.516924, 2.276178  at 525 nm
279     1.464924, 1.860113  at 455 nm */
280     /* setup Rr table */
281     for (j = 0; j < 128; j++)
282         lut[j] = nk_fresnel((float)j/128.f, 0.183521f, 2.959155f);
283 
284     for (j = 0; j < 127; j++)
285         lut[j + 256] = lut[j+1] - lut[j];
286 
287     lut[127 + 256] = nk_fresnel(1.f, 0.183521f, 2.959155f) - lut[127];
288 
289     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]);
290     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
291 
292     /* setup Rg table */
293     memset(lut, 0, sizeof(lut));
294     for (j = 0; j < 128; j++)
295         lut[j] = nk_fresnel((float)j/128.f, 0.516924f, 2.276178f);
296 
297     for (j = 0; j < 127; j++)
298         lut[j + 256] = lut[j+1] - lut[j];
299 
300     lut[127 + 256] = nk_fresnel(1.f, 0.516924f, 2.276178f) - lut[127];
301 
302     glBindTexture(GL_LUT_TEXTURE1_DMP, lutids[2]);
303     glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
304 
305     /* setup Rb table */
306     memset(lut, 0, sizeof(lut));
307     for (j = 0; j < 128; j++)
308         lut[j] = nk_fresnel((float)j/128.f, 1.464924f, 1.860113f);
309 
310     for (j = 0; j < 127; j++)
311         lut[j + 256] = lut[j+1] - lut[j];
312 
313     lut[127 + 256] = nk_fresnel(1.f, 1.464924f, 1.860113f) - lut[127];
314 
315     glBindTexture(GL_LUT_TEXTURE2_DMP, lutids[3]);
316     glTexImage1D(GL_LUT_TEXTURE2_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
317 
318     /* don't use D0 table, so setup D1 table only */
319     memset(lut, 0, sizeof(lut));
320     /* Beckmann function is used in m=1.0 and m=0.5 */
321     for (j = 1; j < 128; j++)
322         lut[j] = beckmann((float)j/128.f, 1.f); /* m=1.0 */
323         /* lut[j] = beckmann((float)j/128.f, 0.5f); */ /* m=0.5 */
324 
325     for (j = 0; j < 127; j++)
326         lut[j + 256] = lut[j+1] - lut[j];
327     lut[127 + 256] = 1.f - lut[127];
328 
329     glBindTexture(GL_LUT_TEXTURE3_DMP, lutids[4]);
330     glTexImage1D(GL_LUT_TEXTURE3_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
331 
332     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
333     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
334     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
335     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
336     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
337     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
338 }
339 
340 /* generate simple object */
LoadObjects(void)341 static void LoadObjects(void)
342 {
343     /* load obj file geometory and diffuse texture */
344     loadDAT( "rom:/resources/robot1.dat", &robot);
345 }
346 
UnloadObjects(void)347 static void UnloadObjects(void)
348 {
349     unloadDAT(&robot);
350 
351     return;
352 }
353 
DrawFrame(void)354 int DrawFrame(void)
355 {
356     static int f = 0;
357 
358     nn::math::Matrix44 proj;
359     nn::math::Matrix34 mv, rot;
360 
361     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
362     s_RenderSystem.Clear();
363 
364     /* setup projection matrix */
365     nn::math::MTX44Frustum(&proj, -0.06f, 0.06f, -0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH,
366                  0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH, 0.2f, 200.f);
367     glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
368 
369     nn::math::Vector3 camPos(0.f, 0.f, 6.f);
370     nn::math::Vector3 camUp(0.f, 1.f, 0.f);
371     nn::math::Vector3 target(0.f, 0.f, 0.f);
372     nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f);
373     nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
374     nn::math::MTX34Mult(&mv, &rot, &mv);
375 
376     /* setup light direction */
377     nn::math::Vector4 lpos0(0.f, 1.f, 1.f, 0.f);
378     nn::math::Vector4 mv0(mv.m[0][0], mv.m[0][1], mv.m[0][2], mv.m[0][3]);
379     nn::math::Vector4 mv1(mv.m[1][0], mv.m[1][1], mv.m[1][2], mv.m[1][3]);
380     nn::math::Vector4 mv2(mv.m[2][0], mv.m[2][1], mv.m[2][2], mv.m[2][3]);
381     nn::math::Vector4 lpos(nn::math::VEC4Dot(&mv0, &lpos0), nn::math::VEC4Dot(&mv1, &lpos0), nn::math::VEC4Dot(&mv2, &lpos0), lpos0.w);
382     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].position"), 1, static_cast<f32*>(lpos));
383 
384     /* setup modelview matrix */
385     nn::math::MTX34RotXYZDeg(&rot, 0.f, static_cast<f32>(-f), 0.f);
386     nn::math::MTX34Mult(&mv, &mv, &rot);
387     nn::math::Matrix44 m(mv);
388     glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
389 
390     glEnableVertexAttribArray(0);
391     glEnableVertexAttribArray(1);
392 
393     /* draw objects */
394     for (int i = 0; i < robot.obj_num; i++)
395     {
396         glBindBuffer(GL_ARRAY_BUFFER, robot.posVB);
397         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)robot.obj[i].vtx_offset);
398         glBindBuffer(GL_ARRAY_BUFFER, robot.normVB);
399         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)robot.obj[i].nrm_offset);
400 
401         for (unsigned j = robot.obj[i].patch_offset; j < robot.obj[i].patch_size + robot.obj[i].patch_offset; j++)
402         {
403             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, robot.idxVB);
404             glDrawElements(GL_TRIANGLES, robot.patch[j].elm_size,
405                 GL_UNSIGNED_SHORT, (GLvoid*)(robot.patch[j].elm_offset + robot.obj[i].elm_offset));
406         }
407     }
408 
409     glFinish();
410 
411     s_RenderSystem.SwapBuffers();
412 
413     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
414     s_RenderSystem.Clear();
415     s_RenderSystem.SwapBuffers();
416 
417     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
418 
419     f++;
420 
421     return !glGetError();
422 }
423 
424 /* initialization */
Initialize(void)425 static int Initialize(void)
426 {
427     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
428     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
429     /* Initialize display */
430     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
431 
432     /* Create heap for malloc*/
433     s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
434     setMemoryHeap(s_HeapForMalloc, s_GxHeapSize);
435 
436     s_ProgramID = glCreateProgram();
437     s_ShaderID = glCreateShader(GL_VERTEX_SHADER);
438 
439     nn::fs::FileReader file(L"rom:/shader.shbin");
440     size_t fileSize = file.GetSize();
441     void* buf = s_AppHeap.Allocate(fileSize);
442 
443     s32 read = file.Read(buf, fileSize);
444     glShaderBinary(1, &s_ShaderID, GL_PLATFORM_BINARY_DMP, buf, read);
445     file.Finalize();
446     s_AppHeap.Free(buf);
447 
448     glAttachShader(s_ProgramID, s_ShaderID);
449     glAttachShader(s_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP);
450 
451     glBindAttribLocation(s_ProgramID, 0, "aPosition");
452     glBindAttribLocation(s_ProgramID, 1, "aNormal");
453 
454     glLinkProgram(s_ProgramID);
455     glValidateProgram(s_ProgramID);
456     glUseProgram(s_ProgramID);
457 
458     glClearColor(0.36f, 0.42f, 0.5f, 1.0f);
459     glClearDepthf(1.f);
460 
461     glEnable(GL_DEPTH_TEST);
462     glDepthFunc(GL_LESS);
463     glEnable(GL_CULL_FACE);
464     glFrontFace(GL_CCW);
465     glCullFace(GL_BACK);
466 
467     LoadObjects();
468 
469     /* set another render state */
470     (*render_state_func[STATE_SETTINGS])();
471 
472     /* enable DMP fragment lighting */
473     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE);
474     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE);
475 
476     return 0;
477 }
478 
nnMain(void)479 void nnMain(void)
480 {
481     // Call only nn::applet::Enable to also allow execution from the HOME Menu
482     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
483     nn::applet::Enable();
484 
485     // fs initialization
486     nn::fs::Initialize();
487 
488     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
489     static char buffer[ROMFS_BUFFER_SIZE];
490     NN_UTIL_PANIC_IF_FAILED(
491         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
492 
493     /* initialization */
494     if (Initialize() >= 0)
495     {
496         /* Enter loop */
497         while (1)
498         {
499             (void)DrawFrame();
500         }
501     }
502 
503     UnloadObjects();
504     /* shutdown_display */
505     s_RenderSystem.Finalize();
506     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
507     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
508     s_AppHeap.Finalize();
509 }
510