1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: graphics.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: 46365 $
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.h>
27 #include <nn/math.h>
28 #include <nn/fs.h>
29 #include <nn/ulcd.h>
30 #include "graphics.h"
31 #include "snd.h"
32
33 #include "demo.h"
34
35 /* program id */
36 GLuint s_PgID;
37
38 /* shader id */
39 GLuint s_ShID;
40
41 /* OpenGLES1.1 vertex lighting specular shininess */
42 #define SPEC_SHININESS 32.f
43 #define STEP 6.f
44
45 /* object names */
46 enum {
47 OBJECT_SPHERE, /* sphere */
48 OBJECT_PLANE, /* plane */
49 OBJECT_COUNT /* object count */
50 };
51
52 /* buffer object ID */
53 static struct tagObject
54 {
55 GLuint id[OBJECT_COUNT];
56 GLuint idxId[OBJECT_COUNT];
57 } s_Object;
58
59 /* buffer object information */
60 static struct tagObjectInfo
61 {
62 GLushort idxcnt[OBJECT_COUNT];
63 GLushort vtxcnt[OBJECT_COUNT];
64 } s_ObjectInfo;
65
66
67 #define ROW_NUM (50) /* NUM in ROW */
68 #define COL_NUM (50) /* NUM in COLUMN */
69 #define deltaROW (DMP_PI / (ROW_NUM - 1))
70 #define deltaCOL (2 * DMP_PI / (COL_NUM - 1))
71
72 struct tagVertex{
73 GLfloat pos[ROW_NUM * COL_NUM][3];
74 GLfloat nor[ROW_NUM * COL_NUM][3];
75 } s_Vtx;
76 GLushort s_Idx[COL_NUM * (ROW_NUM - 1) * 2];
77
78 /* ExpHeap for app. */
79 extern nn::fnd::ExpHeap s_AppHeap;
80 uptr s_HeapForGx;
81 const u32 s_GxHeapSize = 0x800000;
82
83 /* Render system */
84 demo::RenderSystemExt s_RenderSystem;
85 void* s_pShader;
86
87 /* 3D view */
88 nn::ulcd::CTR::StereoCamera s_StereoCamera;
89 const f32 DEMO2_3D_DEPTH_LEVEL = 10.0f;
90 const f32 DEMO2_3D_FACTOR = 1.0f;
91
92
93 /* load sphere object */
LoadSphere(void)94 static void LoadSphere(void)
95 {
96 /* vertex array */
97 for(int row = 0; row < ROW_NUM; row++)
98 {
99 for(int col = 0; col < COL_NUM; col++)
100 {
101 /* position */
102 s_Vtx.pos[row * COL_NUM + col][0] =0.5f * (GLfloat)nn::math::SinRad(deltaROW * row) * nn::math::CosRad(deltaCOL * col);
103 s_Vtx.pos[row * COL_NUM + col][1] =0.5f * (GLfloat)nn::math::CosRad(deltaROW * row);
104 s_Vtx.pos[row * COL_NUM + col][2] =0.5f * (GLfloat)nn::math::SinRad(deltaROW * row) * nn::math::SinRad(deltaCOL * col);
105 /* normal */
106 s_Vtx.nor[row * COL_NUM + col][0] =0.5f * (GLfloat)nn::math::SinRad(deltaROW * row) * nn::math::CosRad(deltaCOL * col);
107 s_Vtx.nor[row * COL_NUM + col][1] =0.5f * (GLfloat)nn::math::CosRad(deltaROW * row);
108 s_Vtx.nor[row * COL_NUM + col][2] =0.5f * (GLfloat)nn::math::SinRad(deltaROW * row) * nn::math::SinRad(deltaCOL * col);
109 }
110 }
111
112 /* index array */
113 for(int i = 0, row = 0; row < ROW_NUM - 1; row++)
114 {
115 #define __INDEX(ROW, COL) ((ROW) * COL_NUM + (COL))
116 for(int col = 0; col < COL_NUM; col++)
117 {
118 s_Idx[i++] = __INDEX(row + 1, col);
119 s_Idx[i++] = __INDEX(row, col);
120 }
121 #undef __INDEX
122 }
123 /* count */
124 s_ObjectInfo.idxcnt[OBJECT_SPHERE] = COL_NUM * (ROW_NUM - 1) * 2;
125 s_ObjectInfo.vtxcnt[OBJECT_SPHERE] = ROW_NUM * COL_NUM;
126
127 /* load vertex array and index array */
128 glBindBuffer(GL_ARRAY_BUFFER, s_Object.id[OBJECT_SPHERE]);
129 glBufferData(GL_ARRAY_BUFFER, sizeof(s_Vtx), &s_Vtx, GL_STATIC_DRAW);
130 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_Object.idxId[OBJECT_SPHERE]);
131 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s_Idx), s_Idx, GL_STATIC_DRAW);
132
133
134 #undef LONG_NUM
135 #undef LATI_NUM
136 #undef deltaROW
137 #undef deltaCOL
138 }
139
140 /* load plane object */
LoadPlane(void)141 static void LoadPlane(void)
142 {
143 struct tagVertex{
144 GLfloat pos[4][3];
145 GLfloat nor[4][3];
146 } vtx;
147 GLushort idx[4] ={0, 1, 2, 3};
148
149 /* vertex array */
150 vtx.pos[0][0] = +4.0f;
151 vtx.pos[0][1] = 0.f;
152 vtx.pos[0][2] = +4.0f;
153
154 vtx.pos[1][0] = +4.0f;
155 vtx.pos[1][1] = 0.f;
156 vtx.pos[1][2] = -4.0f;
157
158 vtx.pos[2][0] = -4.0f;
159 vtx.pos[2][1] = 0.f;
160 vtx.pos[2][2] = +4.0f;
161
162 vtx.pos[3][0] = -4.0f;
163 vtx.pos[3][1] = 0.f;
164 vtx.pos[3][2] = -4.0f;
165
166 for(int i = 0; i < 4; i++)
167 {
168 vtx.nor[i][0] = 0.f;
169 vtx.nor[i][1] = 1.f;
170 vtx.nor[i][2] = 0.f;
171 }
172
173 /* count */
174 s_ObjectInfo.idxcnt[OBJECT_PLANE] = 4;
175 s_ObjectInfo.vtxcnt[OBJECT_PLANE] = 4;
176
177 /* load vertex array and index array */
178 glBindBuffer(GL_ARRAY_BUFFER, s_Object.id[OBJECT_PLANE]);
179 glBufferData(GL_ARRAY_BUFFER, sizeof(vtx), vtx.pos[0], GL_STATIC_DRAW);
180 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_Object.idxId[OBJECT_PLANE]);
181 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idx), idx, GL_STATIC_DRAW);
182 }
183
184 /* load objects */
LoadObjects(void)185 static void LoadObjects(void)
186 {
187 glGenBuffers(OBJECT_COUNT * 2, (GLuint*)&s_Object);
188
189 LoadSphere();
190 LoadPlane();
191 }
192
UpdateParams(nn::math::VEC3 * v_pos,nn::math::VEC2 * v_degSphere,nn::math::VEC2 * v_deg,const nn::math::VEC3 v_cam,const nn::math::VEC3 v_focus,const nn::math::VEC2 v_acc,const u8 loudness)193 static void UpdateParams(
194 nn::math::VEC3* v_pos, // Sphere position (output)
195 nn::math::VEC2* v_degSphere, // Slope of plane when sphere is on a plane (output)
196 nn::math::VEC2* v_deg, // Plane slope (output)
197 const nn::math::VEC3 v_cam, // Camera position
198 const nn::math::VEC3 v_focus, // Focus position
199 const nn::math::VEC2 v_acc, // Accelerometer
200 const u8 loudness) // Mic volume
201 {
202 /*
203 * About Coordinates (initial position)
204 * x: To the right direction on the horizontal plane
205 * y: Up in the vertical direction
206 * z: Down direction on the horizontal plane
207 */
208 const f32 SPEED = 0.05f; // Parameters for moving speed of the sphere
209 static nn::math::VEC3 v_v(0, 0, 0); // Sphere speed
210 nn::math::VEC3 v_g(v_acc.x, -1.f, v_acc.y); // Gravitational acceleration
211
212 // Calculate the plane's incline
213 if(v_g.x > 1.f) v_g.x = 1.f;
214 else if(v_g.x < -1.f) v_g.x = -1.f;
215 if(v_g.z > 1.f) v_g.z = 1.f;
216 else if(v_g.z < -1.f) v_g.z = -1.f;
217 v_deg->x = nn::math::AsinDeg(v_g.x); // Incline of x-axis
218 v_deg->y = nn::math::AsinDeg(v_g.z); // Incline of z-axis
219
220 // Calculate acceleration with the microphone
221 const f32 MIC_STRENGTH = 0.25f; // Parameter for the effect from the microphone volume
222 f32 micAcc = loudness * MIC_STRENGTH;
223 nn::math::VEC3 v_f(v_focus - v_cam); // Focus vector from camera
224 nn::math::VEC3 v_s(*v_pos - v_cam); // Vector from camera to sphere
225 if( nn::math::VEC3Dot(&v_f, &v_s) > 0 )
226 {
227 // When the direction from the camera to the focus and to the sphere are the same
228 // Vector normalization
229 nn::math::VEC3Normalize(&v_f, &v_f);
230 nn::math::VEC3Normalize(&v_s, &v_s);
231 // Calculate effect on sphere by microphone
232 micAcc *= nn::math::VEC3Dot(&v_f, &v_s) / nn::math::VEC3Len(*v_pos - v_cam);
233 nn::math::VEC3Scale(&v_s, &v_s, micAcc);
234 }
235 else
236 {
237 // When the direction from the camera to the focus and to the sphere are the opposite
238 nn::math::VEC3Scale(&v_s, &v_s, 0);
239 }
240
241 if(v_pos->x > -4.f && v_pos->x < 4.f && v_pos->z > -4.f && v_pos->z < 4.f)
242 {
243 // When the sphere is on the plane, ignore speed in y-axis direction
244 //
245 v_g.y = 0;
246 v_s.y = 0;
247 v_v += (v_g + v_s) * SPEED;
248 *v_pos += v_v;
249 v_degSphere->x = v_deg->x;
250 v_degSphere->y = v_deg->y;
251 }
252 else if( v_pos->y > -50.f )
253 {
254 // When the sphere is falling
255 v_v.y += v_g.y * SPEED;
256 *v_pos += v_v;
257
258 PlaySound();
259 }
260 else
261 {
262 // Reset sphere position
263 v_pos->x = 0.f;
264 v_pos->y = 0.f;
265 v_pos->z = 0.f;
266 v_v.x = 0.f;
267 v_v.y = 0.f;
268 v_v.z = 0.f;
269
270 StopSound();
271 }
272 }
273
DrawObjects(const nn::math::Matrix44 & proj,const nn::math::Matrix34 & view,const nn::math::VEC3 v_pos,const nn::math::VEC2 v_degSphere,const nn::math::VEC2 v_deg,f32 posYforSphere)274 void DrawObjects(
275 const nn::math::Matrix44& proj,
276 const nn::math::Matrix34& view,
277 const nn::math::VEC3 v_pos,
278 const nn::math::VEC2 v_degSphere,
279 const nn::math::VEC2 v_deg,
280 f32 posYforSphere
281 )
282 {
283 glUseProgram(s_PgID);
284 glBindAttribLocation(s_PgID, 0, "aPosition");
285 glBindAttribLocation(s_PgID, 1, "aNormal");
286
287 glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uProjection"), 1, GL_TRUE, static_cast<const f32*>(proj));
288
289 /* set light position */
290 GLfloat lpos[] = {3.f, 3.f, 0.f, 1.f}; /* Light position */
291 /* constant light position is transformed from object-space to eye-space */
292 /* Lighting calculations in the vertex shader assume view coordinates system.
293 * For this reason, the light position is converted to view coordinates system. The shader does not perform conversion.
294 * This is because common values are used for lights in all vertex processing.
295 * mv is the view matrix, and multiplication by this matrix converts to view coordinates system.*/
296 nn::math::Vector4 p(lpos);
297 nn::math::Vector4 mvv0(view.m[0]);
298 nn::math::Vector4 mvv1(view.m[1]);
299 nn::math::Vector4 mvv2(view.m[2]);
300 nn::math::Vector4 lpos2( VEC4Dot(&mvv0, &p), VEC4Dot(&mvv1, &p), VEC4Dot(&mvv2, &p), 1.f);
301
302 glUniform4fv(glGetUniformLocation(s_PgID, "uLightPos"), 1, static_cast<f32*>(lpos2));
303
304 /* draw objects */
305 for (int i = 0; i < OBJECT_COUNT; i++)
306 {
307 glBindBuffer(GL_ARRAY_BUFFER, s_Object.id[i]);
308 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
309 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(sizeof(GLfloat) * 3 * s_ObjectInfo.vtxcnt[i]));
310 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_Object.idxId[i]);
311
312 if (i == OBJECT_SPHERE) /* for sphere */
313 {
314 nn::math::Matrix34 arr[3];
315 nn::math::Matrix34 mv2;
316 nn::math::Vector3 trans(v_pos.x, posYforSphere, v_pos.z);
317 nn::math::Vector3 fall(0.f, v_pos.y, 0.f);
318 nn::math::MTX34Translate(&arr[0], &trans);
319 nn::math::MTX34RotXYZDeg(&arr[1], v_degSphere.y, 0.f, -v_degSphere.x);
320 nn::math::MTX34Translate(&arr[2], &fall);
321 nn::math::MTX34Mult(&mv2, &view, &arr[2]);
322 nn::math::MTX34Mult(&mv2, &mv2, &arr[1]);
323 nn::math::MTX34Mult(&mv2, &mv2, &arr[0]);
324 nn::math::Matrix44 tmp2(mv2);
325 glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(tmp2));
326 }
327 else if(i == OBJECT_PLANE) /* for plane */
328 {
329 nn::math::Matrix34 arr;
330 nn::math::Matrix34 mv2;
331 nn::math::MTX34RotXYZDeg(&arr, v_deg.y, 0.f, -v_deg.x);
332 nn::math::MTX34Mult(&mv2, &view, &arr);
333 nn::math::Matrix44 tmp2(mv2);
334 glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(tmp2));
335 }
336
337 glDrawElements(GL_TRIANGLE_STRIP, s_ObjectInfo.idxcnt[i], GL_UNSIGNED_SHORT,(GLvoid*)0);
338 }
339 glFinish();
340 }
341
DrawFrame(nn::math::VEC3 v_cam,nn::math::VEC3 v_focus,nn::math::VEC2 v_acc,u8 loudness)342 int DrawFrame(nn::math::VEC3 v_cam, nn::math::VEC3 v_focus, nn::math::VEC2 v_acc, u8 loudness)
343 {
344 /*
345 * About Coordinates (initial position)
346 * x: To the right direction on the horizontal plane
347 * y: Up in the vertical direction
348 * z: Down direction on the horizontal plane
349 */
350 const f32 posYforSphere = 0.5f; // Sphere y-axis position correction parameter
351 static nn::math::VEC3 v_pos(0, 0, 0); // Sphere position
352 static nn::math::VEC2 v_degSphere(0, 0); // Slope of plane when sphere is on a plane
353 nn::math::VEC2 v_deg(0, 0); // Plane slope
354
355 // Update render parameters
356 UpdateParams(&v_pos, &v_degSphere, &v_deg, v_cam, v_focus, v_acc, loudness);
357
358
359 // Lower screen display
360 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
361 s_RenderSystem.Clear();
362
363 // Display current time
364 nn::fnd::DateTime now = nn::fnd::DateTime::GetNow();
365 s_RenderSystem.SetColor(1.0f, 1.0f, 1.0f, 1.0f);
366 s_RenderSystem.DrawText(0, 0, "CTR demo2");
367 s_RenderSystem.DrawText(0, 16, "%04d/%02d/%02d %02d:%02d:%02d", now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond());
368
369 s_RenderSystem.Transfer();
370 s_RenderSystem.SwapBuffers();
371
372
373 /* Projection settings */
374 s_StereoCamera.SetBaseFrustum(-0.07f * HEIGHT / WIDTH, 0.07f * HEIGHT / WIDTH, -0.07f, 0.07f, 0.2f, 200.f);
375
376 /* modelview setting */
377 /* mv indicates the view matrix.*/
378 nn::math::Matrix34 cam;
379 nn::math::Vector3 camUp(0.f, 1.f, 0.f);
380 nn::math::MTX34LookAt(&cam, &v_cam, &camUp, &v_focus);
381
382 // Calculate the view matrix and projection matrix for rendering the image that corresponds to the left and right parallax
383 nn::math::Matrix44 projL, projR;
384 nn::math::Matrix34 viewL, viewR;
385
386 s_StereoCamera.SetBaseCamera(&cam);
387 s_StereoCamera.CalculateMatrices(
388 &projL, &viewL, &projR, &viewR,
389 DEMO2_3D_DEPTH_LEVEL,
390 DEMO2_3D_FACTOR,
391 nn::math::PIVOT_UPSIDE_TO_TOP
392 );
393
394 // Display upper screen (left)
395 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
396 s_RenderSystem.Clear();
397
398 DrawObjects(projL, viewL, v_pos, v_degSphere, v_deg, posYforSphere);
399 s_RenderSystem.Transfer();
400
401 // Display upper screen (right)
402 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0_EXT);
403 s_RenderSystem.Clear();
404
405 DrawObjects(projR, viewR, v_pos, v_degSphere, v_deg, posYforSphere);
406 s_RenderSystem.Transfer();
407
408 s_RenderSystem.SwapBuffers();
409
410 /* it is possible to save the content of the buffer */
411 /*
412 char fname[256];
413 sprintf(fname, "frame-%04d.tga", f);
414 outputImage(WIDTH, HEIGHT, fname);
415 */
416
417 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
418
419 return !glGetError();
420 }
421
422 /* initialization */
InitializeGraphics(void)423 int InitializeGraphics(void)
424 {
425 s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
426
427 /* Initialize display */
428 s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
429
430 s_StereoCamera.Initialize();
431
432 /* setup vertex shader */
433 /* The shader setup process with DMPGL2.0 uses the same mechanism as OpenGLES2.0.
434 *
435 * Because only the vertex shader can be created as user-defined with DMPGL2.0, only one shader object is created.
436 * */
437 s_PgID = glCreateProgram();
438 s_ShID = glCreateShader(GL_VERTEX_SHADER);
439
440 // Load shader binary with file system
441 nn::fs::FileReader shaderReader(L"rom:/shader.shbin");
442 size_t size = shaderReader.GetSize();
443 s_pShader = s_AppHeap.Allocate(size);
444 s32 read = shaderReader.Read(s_pShader, size);
445 NN_ASSERT(read == size);
446 glShaderBinary(1, &s_ShID, GL_PLATFORM_BINARY_DMP, s_pShader, read);
447
448 glAttachShader(s_PgID, s_ShID);
449 /* The GL_DMP_FRAGMENT_SHADER_DMP shader object is the shader object of the fragment shader reserved with DMPGL2.0.
450 * */
451 glAttachShader(s_PgID, GL_DMP_FRAGMENT_SHADER_DMP);
452
453 /* Because the shader program performs coordinate conversions and lighting calculations, vertex coordinates and normals are required as vertex attributes, and the vertex coordinates are allocated to attribute0 and the normals are allocated to attribute1.
454 *
455 * */
456 glBindAttribLocation(s_PgID, 0, "aPosition");
457 glBindAttribLocation(s_PgID, 1, "aNormal");
458
459 /* Links the vertex shader and fragment shader.*/
460 glLinkProgram(s_PgID);
461
462 glValidateProgram(s_PgID);
463 glUseProgram(s_PgID);
464
465 s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0.36f, 0.42f, 0.5f, 1.0f);
466 s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0.f, 0.f, 0.f, 1.0f);
467
468 glClearDepthf(1.f);
469
470 glEnableVertexAttribArray(0);
471 glEnableVertexAttribArray(1);
472
473 glEnable(GL_DEPTH_TEST);
474 glDepthFunc(GL_LESS);
475
476 glEnable(GL_CULL_FACE);
477 glFrontFace(GL_CCW);
478 glCullFace(GL_BACK);
479
480 LoadObjects();
481
482 /* The following parameters are the same as the OpenGLES1.1 vertex lighting parameters.
483 *
484 * Note that product of multiplying the same components of lights and materials is set in the shader Uniform.
485 * */
486 GLfloat ldif[] = {1.f, 1.f, 1.f, 1.f}; /* light diffuse */
487 GLfloat lspc[] = {1.f, 1.f, 1.f, 1.f}; /* light specular */
488 GLfloat lamb[] = {0.f, 0.f, 0.f, 1.f}; /* light ambient */
489 GLfloat lmamb[] = {0.2f, 0.2f, 0.f, 1.f}; /* light model ambient */
490
491 GLfloat mspc[] = {1.f, 1.f, 1.f, 1.f}; /* material specular */
492 GLfloat mdif[] = {0.8f, 0.8f, 0.f, 1.f}; /* material diffuse */
493 GLfloat mamb[] = {0.8f, 0.f, 0.f, 1.f}; /* material ambient */
494
495 /* Set the sum of the light ambient and global ambient as ambient.
496 * */
497 nn::math::Vector4 amb;
498 nn::math::Vector4 lamb_mamb = nn::math::VEC4(lamb[0]*mamb[0], lamb[1]*mamb[1], lamb[2]*mamb[2], lamb[3]*mamb[3]);
499 nn::math::Vector4 lmamb_mamb = nn::math::VEC4(lmamb[0]*mamb[0], lmamb[1]*mamb[1], lmamb[2]*mamb[2], lmamb[3]*mamb[3]);
500 nn::math::VEC4Add(&amb, &lamb_mamb, &lmamb_mamb);
501
502 nn::math::Vector4 dif = nn::math::VEC4(ldif[0]*mdif[0], ldif[1]*mdif[1], ldif[2]*mdif[2], ldif[3]*mdif[3]);
503 nn::math::Vector4 spc = nn::math::VEC4(lspc[0]*mspc[0], lspc[1]*mspc[1], lspc[2]*mspc[2], lspc[3]*mspc[3]);
504 GLfloat a[] = {amb.x, amb.y, amb.z, amb.w};
505 GLfloat d[] = {dif.x, dif.y, dif.z, dif.w};
506 GLfloat s[] = {spc.x, spc.y, spc.z, spc.w};
507
508 glUniform4fv(glGetUniformLocation(s_PgID, "uDiff"), 1, d);
509 glUniform4fv(glGetUniformLocation(s_PgID, "uAmb"), 1, a);
510 glUniform4fv(glGetUniformLocation(s_PgID, "uSpec"), 1, s);
511 glUniform1f(glGetUniformLocation(s_PgID, "uMatShiniess"), SPEC_SHININESS);
512
513 glUniform3i(glGetUniformLocation(s_PgID, "dmp_TexEnv[0].srcRgb"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
514 glUniform3i(glGetUniformLocation(s_PgID, "dmp_TexEnv[0].srcAlpha"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
515
516 s_RenderSystem.SetLcdMode(NN_GX_DISPLAYMODE_STEREO);
517
518 return 0;
519 }
520
FinalizeGraphics(void)521 int FinalizeGraphics(void)
522 {
523 /* shutdown_display */
524 s_RenderSystem.Finalize();
525 s_AppHeap.Free(s_pShader);
526 s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
527
528 return 0;
529 }
530
531 /*---------------------------------------------------------------------------*
532 End of file
533 *---------------------------------------------------------------------------*/
534