1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gx_FragmentLightingSimple.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 #include <nn/os.h>
18 #include <nn/fnd.h>
19 #include <nn/gx.h>
20 #include <nn/math.h>
21 #include <nn/fs.h>
22 #include <nn/init.h>
23 #include <nn/applet.h>
24 
25 #include "demo.h"
26 
27 namespace
28 {
29     GLuint s_ProgramId = 0;
30     GLuint s_ShaderId = 0;
31 
32     nn::fnd::ExpHeap s_AppHeap;
33     uptr s_AddrForGxHeap;
34     const u32 s_GxHeapSize = 0x400000;
35 
36     demo::RenderSystem s_RenderSystem;
37 
38     nn::math::Vector3 s_CameraPosition(0.0f, 4.0f, 6.0f);
39     nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
40     nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
41 
42     nn::math::Matrix34 s_ViewMatrix;
43     nn::math::Matrix44 s_Display0ProjectionMatrix;
44     nn::math::Matrix44 s_Display1ProjectionMatrix;
45 
46     const u32 MAX_LIGHT_NUM = 4;
47     f32 s_GlobalAmbientLight[] = { 0.4f,  0.4f,  0.4f, 1.0f};
48 
49     demo::Light s_LightArray[MAX_LIGHT_NUM];
50 
51     f32 s_LightPhi[MAX_LIGHT_NUM];
52     f32 s_LightRadius = 3.0f;
53     f32 s_LightDeltaPhi = 1.0f;
54 
55     f32 s_MaterialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
56     f32 s_MaterialDiffuse[] = {0.6f, 0.6f, 0.6f, 1.0f};
57     f32 s_MaterialSpecular0[] = {1.0f, 1.0f, 1.0f, 1.0f};
58     f32 s_MaterialSpecular1[] = {0.0f, 0.0f, 0.0f, 1.0f};
59     u32 s_MaterialShininess = 8;
60 
61     demo::Cube s_Cube;
62 
63     const u32 MAX_SPHERE_NUM = MAX_LIGHT_NUM;
64     demo::Sphere s_LightSphereArray[MAX_SPHERE_NUM];
65 
66     GLuint s_D0LutTextureId = 0;
67 }
68 
69 void InitializeGraphics(void);
70 void InitializeLights(void);
71 void InitializeShader(void);
72 void InitializeD0Lut(const u32& materialShininess);
73 
74 void UseShader(void);
75 void UpdateCamera(void);
76 void UpdateLights(void);
77 
78 void DrawDisplay0(void);
79 void DrawDisplay1(void);
80 
81 void UseShader(void);
82 void UpdateBody(demo::Body& body);
83 void DrawBody(demo::Body& body);
84 
85 void SetLightUniform(void);
86 void DrawLights(void);
87 
Initialize(void)88 void Initialize(void)
89 {
90     // fs initialization
91     nn::fs::Initialize();
92 
93     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
94     static char buffer[ROMFS_BUFFER_SIZE];
95     NN_UTIL_PANIC_IF_FAILED(
96         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
97 
98     InitializeGraphics();
99 }
100 
InitializeGraphics(void)101 void InitializeGraphics(void)
102 {
103     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
104         nn::os::GetDeviceMemorySize() );
105     s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
106 
107     s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
108 
109     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
110     glClearDepthf(1.0f);
111 
112     glEnable(GL_DEPTH_TEST);
113     glDepthFunc(GL_LESS);
114 
115     glEnable(GL_CULL_FACE);
116     glFrontFace(GL_CCW);
117     glCullFace(GL_BACK);
118 
119     InitializeLights();
120 
121     InitializeShader();
122 
123     // Initialize projection matrix
124     nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f,
125         demo::DISPLAY0_ASPECT, 0.1f, 20.0f,
126         nn::math::PIVOT_UPSIDE_TO_TOP);
127 
128     nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f,
129         demo::DISPLAY1_ASPECT, 0.1f, 20.0f,
130         nn::math::PIVOT_UPSIDE_TO_TOP);
131 
132     // Initialize cube
133     u32 vertexAttributes = demo::VERTEX_POSITION_ATTRIBUTE |
134         demo::VERTEX_COLOR_ATTRIBUTE |
135         demo::VERTEX_NORMAL_ATTRIBUTE;
136     s_Cube.InitializeCube(vertexAttributes, 1.5f, 1.5f, 1.5f);
137     s_Cube.SetColor(1.0f, 0.0f, 0.0f);
138     s_Cube.SetWorldPosition(0.0f, 0.0f, 0.0f);
139     s_Cube.SetWorldAngle(0.0f, 0.0f, 0.0f);
140 
141     // Initialize sphere
142     for (u32 sphereIndex = 0; sphereIndex < MAX_SPHERE_NUM; sphereIndex++)
143     {
144         s_LightSphereArray[sphereIndex].InitializeSphere(vertexAttributes, 0.2, 4);
145         s_LightSphereArray[sphereIndex].SetWorldPosition(0.0f, 0.0f, 0.0f);
146         s_LightSphereArray[sphereIndex].SetWorldAngle(0.0f, 0.0f, 0.0f);
147     }
148 
149     u32 sphereIndex = 0;
150     s_LightSphereArray[sphereIndex].SetColor(1.0f, 0.0f, 0.0f);
151 
152     sphereIndex = 1;
153     s_LightSphereArray[sphereIndex].SetColor(0.0f, 1.0f, 0.0f);
154 
155     sphereIndex = 2;
156     s_LightSphereArray[sphereIndex].SetColor(0.0f, 0.0f, 1.0f);
157 
158     sphereIndex = 3;
159     s_LightSphereArray[sphereIndex].SetColor(1.0f, 1.0f, 0.0f);
160 }
161 
InitializeLights(void)162 void InitializeLights(void)
163 {
164     for (u32 lightIndex = 0; lightIndex < MAX_LIGHT_NUM; lightIndex++)
165     {
166         s_LightArray[lightIndex].Initialize();
167     }
168 
169     s_LightPhi[0] = 0.0f;
170     s_LightPhi[1] = 180.0f;
171     s_LightPhi[2] = 270.0f;
172     s_LightPhi[3] = 0.0f;
173 
174     // Light0 (Red)
175     u32 lightIndex = 0;
176     s_LightArray[lightIndex].m_Ambient[0] = 0.0f;
177     s_LightArray[lightIndex].m_Ambient[1] = 0.0f;
178     s_LightArray[lightIndex].m_Ambient[2] = 0.0f;
179     s_LightArray[lightIndex].m_Ambient[3] = 1.0f;
180     s_LightArray[lightIndex].m_Diffuse[0] = 1.0f;
181     s_LightArray[lightIndex].m_Diffuse[1] = 0.0f;
182     s_LightArray[lightIndex].m_Diffuse[2] = 0.0f;
183     s_LightArray[lightIndex].m_Diffuse[3] = 1.0f;
184     s_LightArray[lightIndex].m_Specular0[0] = 1.0f;
185     s_LightArray[lightIndex].m_Specular0[1] = 1.0f;
186     s_LightArray[lightIndex].m_Specular0[2] = 1.0f;
187     s_LightArray[lightIndex].m_Specular0[3] = 1.0f;
188 
189     // Light1 (Green)
190     lightIndex = 1;
191     s_LightArray[lightIndex].m_Ambient[0] = 0.0f;
192     s_LightArray[lightIndex].m_Ambient[1] = 0.0f;
193     s_LightArray[lightIndex].m_Ambient[2] = 0.0f;
194     s_LightArray[lightIndex].m_Ambient[3] = 1.0f;
195     s_LightArray[lightIndex].m_Diffuse[0] = 0.0f;
196     s_LightArray[lightIndex].m_Diffuse[1] = 1.0f;
197     s_LightArray[lightIndex].m_Diffuse[2] = 0.0f;
198     s_LightArray[lightIndex].m_Diffuse[3] = 1.0f;
199     s_LightArray[lightIndex].m_Specular0[0] = 1.0f;
200     s_LightArray[lightIndex].m_Specular0[1] = 1.0f;
201     s_LightArray[lightIndex].m_Specular0[2] = 1.0f;
202     s_LightArray[lightIndex].m_Specular0[3] = 1.0f;
203 
204     // Light2 (Blue)
205     lightIndex = 2;
206     s_LightArray[lightIndex].m_Ambient[0] = 0.0f;
207     s_LightArray[lightIndex].m_Ambient[1] = 0.0f;
208     s_LightArray[lightIndex].m_Ambient[2] = 0.0f;
209     s_LightArray[lightIndex].m_Ambient[3] = 1.0f;
210     s_LightArray[lightIndex].m_Diffuse[0] = 0.0f;
211     s_LightArray[lightIndex].m_Diffuse[1] = 0.0f;
212     s_LightArray[lightIndex].m_Diffuse[2] = 1.0f;
213     s_LightArray[lightIndex].m_Diffuse[3] = 1.0f;
214     s_LightArray[lightIndex].m_Specular0[0] = 1.0f;
215     s_LightArray[lightIndex].m_Specular0[1] = 1.0f;
216     s_LightArray[lightIndex].m_Specular0[2] = 1.0f;
217     s_LightArray[lightIndex].m_Specular0[3] = 1.0f;
218 
219     // Light3 (Yellow)
220     lightIndex = 3;
221     s_LightArray[lightIndex].m_Ambient[0] = 0.0f;
222     s_LightArray[lightIndex].m_Ambient[1] = 0.0f;
223     s_LightArray[lightIndex].m_Ambient[2] = 0.0f;
224     s_LightArray[lightIndex].m_Ambient[3] = 1.0f;
225     s_LightArray[lightIndex].m_Diffuse[0] = 1.0f;
226     s_LightArray[lightIndex].m_Diffuse[1] = 1.0f;
227     s_LightArray[lightIndex].m_Diffuse[2] = 0.0f;
228     s_LightArray[lightIndex].m_Diffuse[3] = 1.0f;
229     s_LightArray[lightIndex].m_Specular0[0] = 1.0f;
230     s_LightArray[lightIndex].m_Specular0[1] = 1.0f;
231     s_LightArray[lightIndex].m_Specular0[2] = 1.0f;
232     s_LightArray[lightIndex].m_Specular0[3] = 1.0f;
233 }
234 
InitializeShader(void)235 void InitializeShader(void)
236 {
237     s_ProgramId = glCreateProgram();
238 
239     // Load vertex shader
240     s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
241     nn::fs::FileReader file(L"rom:/shader.shbin");
242     size_t fileSize = file.GetSize();
243     void* buf = s_AppHeap.Allocate(fileSize);
244     s32 read = file.Read(buf, fileSize);
245     glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
246     file.Finalize();
247     s_AppHeap.Free(buf);
248 
249     glAttachShader(s_ProgramId, s_ShaderId);
250     glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
251 
252     glBindAttribLocation(s_ProgramId, 0, "aPosition");
253     glBindAttribLocation(s_ProgramId, 1, "aColor");
254     glBindAttribLocation(s_ProgramId, 2, "aNormal");
255 
256     glLinkProgram(s_ProgramId);
257     glValidateProgram(s_ProgramId);
258 
259     demo::InitializeUniforms(s_ProgramId);
260 
261     InitializeD0Lut(s_MaterialShininess);
262 }
263 
InitializeD0Lut(const u32 & materialShininess)264 void InitializeD0Lut(const u32& materialShininess)
265 {
266     const u32 LUT_TABLE_SIZE = 512;
267     const u32 LUT_TABLE_HALF_SIZE = LUT_TABLE_SIZE / 2;
268     GLfloat lutArray[LUT_TABLE_SIZE];
269     for (u32 index = 0; index < LUT_TABLE_SIZE; index++)
270     {
271         lutArray[index] = 0.0f;
272     }
273 
274     for (u32 j = 0; j < LUT_TABLE_HALF_SIZE; j++)
275     {
276         f32 value = 1.0f;
277         for (u32 count = 0; count < materialShininess; count++)
278         {
279             value *= (j / 255.0f);
280         }
281         lutArray[j] = value;
282     }
283 
284     for (u32 j = 0; j < (LUT_TABLE_HALF_SIZE - 1); j++)
285     {
286         lutArray[j + LUT_TABLE_HALF_SIZE] = lutArray[j + 1] - lutArray[j];
287     }
288     lutArray[(LUT_TABLE_HALF_SIZE - 1) + LUT_TABLE_HALF_SIZE] =
289         1.0f - lutArray[LUT_TABLE_HALF_SIZE - 1];
290 
291     glGenTextures(1, &s_D0LutTextureId);
292     glBindTexture(GL_LUT_TEXTURE0_DMP, s_D0LutTextureId);
293     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, LUT_TABLE_SIZE,
294         0, GL_LUMINANCEF_DMP, GL_FLOAT, lutArray);
295 }
296 
Finalize(void)297 void Finalize(void)
298 {
299     s_Cube.Finalize();
300     for (u32 sphereIndex = 0; sphereIndex < MAX_SPHERE_NUM; sphereIndex++)
301     {
302         s_LightSphereArray[sphereIndex].Finalize();
303     }
304 
305     glDeleteTextures(1, &s_D0LutTextureId);
306 
307     s_RenderSystem.Finalize();
308 
309     s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
310     s_AppHeap.Finalize();
311 }
312 
DrawFrame(void)313 bool DrawFrame(void)
314 {
315     UpdateCamera();
316     UpdateLights();
317 
318     DrawDisplay0();
319     DrawDisplay1();
320 
321     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
322 
323     return true;
324 }
325 
UpdateCamera(void)326 void UpdateCamera(void)
327 {
328     nn::math::MTX34LookAt(&s_ViewMatrix, s_CameraPosition, s_CameraUp, s_CameraTarget);
329 }
330 
UpdateLights(void)331 void UpdateLights(void)
332 {
333     // Light0 (Red)
334     u32 lightIndex = 0;
335     f32 sinPhi = 0.0f;
336     f32 cosPhi = 0.0f;
337     nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[0]);
338     s_LightArray[lightIndex].m_Position[0] = 0.0f;
339     s_LightArray[lightIndex].m_Position[1] = s_LightRadius * cosPhi;
340     s_LightArray[lightIndex].m_Position[2] = s_LightRadius * sinPhi;
341 
342     // Light1 (Green)
343     lightIndex = 1;
344     nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[1]);
345     s_LightArray[lightIndex].m_Position[0] = s_LightRadius * cosPhi;
346     s_LightArray[lightIndex].m_Position[1] = 0.0f;
347     s_LightArray[lightIndex].m_Position[2] = s_LightRadius * sinPhi;
348 
349     // Light2 (Blue)
350     lightIndex = 2;
351     nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[2]);
352     s_LightArray[lightIndex].m_Position[0] = s_LightRadius * cosPhi;
353     s_LightArray[lightIndex].m_Position[1] = s_LightRadius * sinPhi;
354     s_LightArray[lightIndex].m_Position[2] = 0.0f;
355 
356     // Light3 (Yellow)
357     lightIndex = 3;
358     nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[3]);
359     s_LightArray[lightIndex].m_Position[0] = s_LightRadius * cosPhi;
360     s_LightArray[lightIndex].m_Position[1] = 0.0f;
361     s_LightArray[lightIndex].m_Position[2] = s_LightRadius * sinPhi;
362 
363     for (u32 index = 0; index < MAX_LIGHT_NUM; index++)
364     {
365         s_LightSphereArray[index].SetWorldPosition(s_LightArray[index].m_Position[0],
366             s_LightArray[index].m_Position[1], s_LightArray[index].m_Position[2]);
367 
368         s_LightPhi[index] += s_LightDeltaPhi;
369         if ( s_LightPhi[index] > 360.0f )
370         {
371             s_LightPhi[index] -= 360.0f;
372         }
373     }
374 }
375 
DrawDisplay0(void)376 void DrawDisplay0(void)
377 {
378     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
379     s_RenderSystem.Clear();
380 
381     UseShader();
382     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
383         1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
384     UpdateBody(s_Cube);
385     DrawBody(s_Cube);
386 
387     SetLightUniform();
388     DrawLights();
389 
390     s_RenderSystem.SwapBuffers();
391 }
392 
UseShader(void)393 void UseShader(void)
394 {
395     glUseProgram(s_ProgramId);
396 
397     // Fragment uniform
398     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
399 
400     // Fragment uniform : Texture samplerType
401     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE);
402     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
403     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
404     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
405 
406     // LightEnv
407     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_CONFIG], GL_LIGHT_ENV_LAYER_CONFIG0_DMP);
408     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_ENABLED_REFL], GL_FALSE);
409     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_CLAMP_HIGHLIGHTS], GL_TRUE);
410 
411     // D0
412     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_ENABLED_D0], GL_TRUE);
413     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_ABS_LUT_INPUT_D0], GL_TRUE);
414     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_INPUT_D0], GL_LIGHT_ENV_NH_DMP);
415     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SAMPLER_D0], 0);
416 
417     // Fragment uniform : Fragment lighting
418     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
419     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
420 
421     // Light0 (Red)
422     u32 lightIndex = 0;
423     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
424     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient);
425     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse);
426     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0);
427     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1);
428     // Compute Light0 view matrix
429     nn::math::MTX34 s_LightWorldMatrix;
430     nn::math::MTX34Identity(&s_LightWorldMatrix);
431     nn::math::VEC3 position(s_LightArray[lightIndex].m_Position[0], s_LightArray[lightIndex].m_Position[1], s_LightArray[lightIndex].m_Position[2]);
432     nn::math::MTX34Translate(&s_LightWorldMatrix, &position);
433     nn::math::Matrix34 lightViewMatrix;
434     nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix);
435     glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION],
436         lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3],
437         1.0f);
438     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR1], GL_FALSE);
439     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR0], GL_FALSE);
440     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_TWO_SIDE_DIFFUSE], GL_FALSE);
441 
442     // Light1 (Green)
443     lightIndex = 1;
444     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_ENABLED], GL_TRUE);
445     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient);
446     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse);
447     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0);
448     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1);
449     // Compute Light1 view matrix
450     nn::math::MTX34Identity(&s_LightWorldMatrix);
451     position.x = s_LightArray[lightIndex].m_Position[0];
452     position.y = s_LightArray[lightIndex].m_Position[1];
453     position.z = s_LightArray[lightIndex].m_Position[2];
454     nn::math::MTX34Translate(&s_LightWorldMatrix, &position);
455     nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix);
456     glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_POSITION],
457         lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3],
458         1.0f);
459     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_GEOM_FACTOR1], GL_FALSE);
460     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_GEOM_FACTOR0], GL_FALSE);
461     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_TWO_SIDE_DIFFUSE], GL_FALSE);
462 
463     // Light2 (Blue)
464     lightIndex = 2;
465     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_ENABLED], GL_TRUE);
466     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient);
467     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse);
468     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0);
469     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1);
470     // Compute Light2 view matrix
471     nn::math::MTX34Identity(&s_LightWorldMatrix);
472     position.x = s_LightArray[lightIndex].m_Position[0];
473     position.y = s_LightArray[lightIndex].m_Position[1];
474     position.z = s_LightArray[lightIndex].m_Position[2];
475     nn::math::MTX34Translate(&s_LightWorldMatrix, &position);
476     nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix);
477     glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_POSITION],
478         lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3],
479         1.0f);
480     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_GEOM_FACTOR1], GL_FALSE);
481     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_GEOM_FACTOR0], GL_FALSE);
482     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_TWO_SIDE_DIFFUSE], GL_FALSE);
483 
484     // Light3 (Yellow)
485     lightIndex = 3;
486     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_ENABLED], GL_TRUE);
487     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient);
488     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse);
489     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0);
490     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1);
491     // Compute Light3 view matrix
492     nn::math::MTX34Identity(&s_LightWorldMatrix);
493     position.x = s_LightArray[lightIndex].m_Position[0];
494     position.y = s_LightArray[lightIndex].m_Position[1];
495     position.z = s_LightArray[lightIndex].m_Position[2];
496     nn::math::MTX34Translate(&s_LightWorldMatrix, &position);
497     nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix);
498     glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_POSITION],
499         lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3],
500         1.0f);
501     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_GEOM_FACTOR1], GL_FALSE);
502     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_GEOM_FACTOR0], GL_FALSE);
503     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_TWO_SIDE_DIFFUSE], GL_FALSE);
504 
505     // Fragment uniform : Material
506     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
507     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
508     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR0], 1, s_MaterialSpecular0);
509     glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR1], 1, s_MaterialSpecular1);
510 
511     // Fragment uniform : Texture combiner
512     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
513         GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS);
514     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
515         GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS);
516 
517     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
518         GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
519     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
520         GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
521     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
522         GL_ADD);
523     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
524         GL_ADD);
525 }
526 
DrawDisplay1(void)527 void DrawDisplay1(void)
528 {
529     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
530     s_RenderSystem.Clear();
531 
532     s_RenderSystem.SwapBuffers();
533 }
534 
UpdateBody(demo::Body & body)535 void UpdateBody(demo::Body& body)
536 {
537     f32 worldAngle[3];
538     body.GetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
539     worldAngle[1] += 1.0f;
540     if ( worldAngle[1] > 360.0f )
541     {
542         worldAngle[1] = 0.0f;
543     }
544     body.SetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
545 }
546 
DrawBody(demo::Body & body)547 void DrawBody(demo::Body& body)
548 {
549     nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
550     nn::math::Matrix44 worldMatrix = body.GetWorldMatrix();
551     nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix);
552     glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
553         1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
554     body.Draw();
555 }
556 
SetLightUniform(void)557 void SetLightUniform(void)
558 {
559     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_FALSE);
560 
561     // Fragment uniform : Texture combiner
562     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
563         GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS);
564     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
565         GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS);
566     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
567         GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
568     glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
569         GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
570     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
571         GL_REPLACE);
572     glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
573         GL_REPLACE);
574 }
575 
DrawLights(void)576 void DrawLights(void)
577 {
578     for (u32 lightIndex = 0; lightIndex < MAX_LIGHT_NUM; lightIndex++)
579     {
580         DrawBody(s_LightSphereArray[lightIndex]);
581     }
582 }
583 
nnMain(void)584 void nnMain(void)
585 {
586     // Call only nn::applet::Enable to also allow execution from the HOME Menu
587     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
588     nn::applet::Enable();
589 
590     Initialize();
591 
592     bool flag = true;
593     while ( flag )
594     {
595         flag = DrawFrame();
596     }
597 
598     Finalize();
599 }
600