1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: LightingSss.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 * Comments
27 * --------
28 *
29 * This example is the rendering translucent materials in Maestro. See Subsurface-Scattering Model
30 * section of "ILLUMINATION MODELS IN MAESTRO" for details.
31 * The following papers can help you understand the LUT settings.
32 * Jensen,H., Marschner,S., Levoy,H., and Hanrahan,P., A Practical Model for Subsurface Light Transport
33 * Jensen,H. and Buhler,J., A Rapid Hierarchical Rendering Technique for Translucent Materials
34 * Kolchin,K., Curvature-Based Shading of Translucent Materials ,such as Human Skin
35 */
36
37 #include <nn/gx.h>
38 #include <nn/fs.h>
39 #include <nn/math.h>
40 #include <nn/init.h>
41 #include <nn/os.h>
42 #include <nn/applet.h>
43
44 #include "demo.h"
45
46 #include "Util.h"
47 #include "Loader.h"
48
49 #include <string.h>
50 #include <math.h>
51
52 #include "Memory.h"
53
54 #define APP_NAME "LightingSSS"
55
56 #define DMP_PI (3.1415926f)
57 #define REV_PI (1.0f/DMP_PI)
58
59 /* env texture name */
60 GLuint s_EnvTexName;
61
62 /* obj file loader class object */
63 dat_t hand;
64
65 /* program name */
66 GLuint s_ProgramID;
67
68 /* shader name */
69 GLuint s_ShaderID;
70
71 /* texture collection name */
72 GLuint s_TexColl;
73
74 /* ExpHeap for app. */
75 nn::fnd::ExpHeap s_AppHeap;
76 uptr s_HeapForGx;
77 uptr s_HeapForMalloc;
78 const u32 s_GxHeapSize = 0x400000;
79 const u32 s_HeapSize = 0x200000;
80
81 demo::RenderSystem s_RenderSystem;
82
SetLutTable(void)83 static void SetLutTable(void)
84 {
85 struct
86 {
87 float albedo[3];
88 float dif_refl[4];
89 float beta[3];
90 float beta_prime[3];
91 float zr[3];
92 float Bi;
93 float F_dr;
94 float refi;
95 float m;
96 float i0[3];
97 float i1[3];
98 } mat;
99
100 GLfloat qlut[3][512], lut[512];
101 int j, co;
102
103 GLuint lutids[6];
104 glGenTextures(6, lutids);
105
106 for (co = 0; co < 3; co++)
107 memset(qlut[co], 0, sizeof(qlut[0]));
108 memset(lut, 0, sizeof(lut));
109
110 GLfloat A, refi, sigma_s_prim[3], sigma_a[3], sigma_t_prim[3], geom_scale = 0.24f;
111 refi = 1.4f;
112 #if 0 /* face */
113 sigma_s_prim[0] = 1.09f;
114 sigma_s_prim[1] = 1.59f;
115 sigma_s_prim[2] = 1.79f;
116 sigma_a[0] = 0.013f;
117 sigma_a[1] = 0.070f; /* 0.085; */ /* <-- use these values for more sun-tanned skin */
118 sigma_a[2] = 0.145f; /* 0.180; */
119 #else /* hand */
120 sigma_s_prim[0] = 1.09f;
121 sigma_s_prim[1] = 1.39f;
122 sigma_s_prim[2] = 1.3f;
123 sigma_a[0] = 0.013f;
124 sigma_a[1] = 0.120f;
125 sigma_a[2] = 0.295f;
126 #endif
127
128 mat.F_dr = - 1.440f / (refi * refi) + 0.71f / refi + 0.668f + 0.0636f * refi;
129 A = (1.0f + mat.F_dr) / (1.0f - mat.F_dr);
130 mat.Bi = 1.0f + (4.0f / 3.0f) * A;
131 mat.refi = refi;
132 for (co = 0; co < 3; co++)
133 {
134 sigma_t_prim[co] = sigma_s_prim[co] + sigma_a[co];
135 mat.zr[co] = geom_scale / sigma_t_prim[co];
136 mat.albedo[co] = sigma_s_prim[co] / sigma_t_prim[co];
137 mat.beta[co] = sqrt(3.0f * (1.0f - mat.albedo[co]));
138 mat.beta_prime[co] = mat.beta[co] * mat.Bi;
139 mat.dif_refl[co] = 0.5f * mat.albedo[co] * (exp(-mat.beta[co]) + exp(-mat.beta_prime[co]));
140 mat.i0[co] = exp(-mat.beta[co]) * sqrt(2.0f * DMP_PI / mat.beta[co]) +
141 mat.Bi * exp(-mat.beta_prime[co]) * sqrt(2.0f * DMP_PI / mat.beta_prime[co]);
142 mat.i1[co] = DMP_PI * (exp(-mat.beta[co]) + exp(-mat.beta_prime[co])) / mat.i0[co];
143 }
144
145 float gamma, LN, h, kappa, display_gamma = 0.47f;
146 for (j = 0; j < 128; j++)
147 {
148 LN = (float)j/128.f;
149 kappa = 1.0f - LN * LN;
150 for (co = 0; co < 3; co++)
151 {
152 /* R(LN) is sum of lambertian term(linear term)and wrapping term(non-linear term). */
153 if (LN > 0.f)
154 qlut[co][j] = mat.dif_refl[co] * LN;
155 gamma = mat.zr[co] * sqrt(kappa);
156 h = fabsf(LN) / gamma;
157 qlut[co][j] += mat.i0[co] * (1.0f / (1.0f + mat.i1[co] * h)) * gamma * mat.albedo[co] * 0.25f * REV_PI;
158 qlut[co][j] = pow(qlut[co][j], display_gamma);
159 }
160 }
161
162 for (j = 128; j < 256; j++)
163 {
164 LN = (float)(j - 256) /128.f;
165 kappa = 1.0f - LN * LN;
166 for (co = 0; co < 3; co++)
167 {
168 if (LN > 0.f)
169 qlut[co][j] = mat.dif_refl[co] * LN;
170 gamma = mat.zr[co] * sqrt(kappa);
171 h = fabsf(LN) / gamma;
172 qlut[co][j] += mat.i0[co] * (1.0f / (1.0f + mat.i1[co] * h)) *
173 gamma * mat.albedo[co] * 0.25f * REV_PI;
174 qlut[co][j] = pow(qlut[co][j], display_gamma);
175 }
176 }
177
178 for (j = 0; j < 127; j++)
179 for (co = 0; co < 3; co++)
180 qlut[co][j + 256] = qlut[co][j + 1] - qlut[co][j];
181
182 for (co = 0; co < 3; co++)
183 qlut[co][127 + 256] = pow(mat.dif_refl[co], display_gamma) - qlut[co][127];
184
185 for (j = 128; j < 255; j++)
186 for (co = 0; co < 3; co++)
187 qlut[co][j + 256] = qlut[co][j + 1] - qlut[co][j];
188
189 for (co = 0; co < 3; co++)
190 qlut[co][255 + 256] = qlut[co][0] - qlut[co][255];
191
192 glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[0]);
193 glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, qlut[0]);
194 glBindTexture(GL_LUT_TEXTURE1_DMP, lutids[1]);
195 glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, qlut[1]);
196 glBindTexture(GL_LUT_TEXTURE2_DMP, lutids[2]);
197 glTexImage1D(GL_LUT_TEXTURE2_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, qlut[2]);
198
199 /* T(NV) term setting */
200 for (j = 0; j < 256; j++)
201 {
202 lut[j] = 1.f - r_fresnel((float)j / 255.9375f, 1.7f, 0.36f, 0.f);
203 lut[j] = pow(lut[j], display_gamma);
204 }
205 for (j = 0; j < 255; j++)
206 lut[j + 256] = lut[j + 1] - lut[j];
207 lut[255 + 256] = pow((1.f - r_fresnel(1.f, 1.7f, 0.36f, 0.f)), display_gamma) - lut[255];
208
209 glBindTexture(GL_LUT_TEXTURE3_DMP, lutids[3]);
210 glTexImage1D(GL_LUT_TEXTURE3_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
211
212 /* distribution function of specular setting */
213 /* beckmann function is used. */
214 memset(lut, 0, sizeof(lut));
215 for (j = 0; j < 128; j++)
216 lut[j] = beckmann((float)j / 128.f, 0.5f);
217 for (j = 128; j < 256; j++)
218 lut[j] = 0.f;
219
220 for (j = 0; j < 127; j++)
221 lut[j + 256] = lut[j + 1] - lut[j];
222 lut[127 + 256] = 1.f - lut[127];
223 for (j = 128; j < 256; j++)
224 lut[j + 256] = 0;
225
226 glBindTexture(GL_LUT_TEXTURE4_DMP, lutids[4]);
227 glTexImage1D(GL_LUT_TEXTURE4_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
228
229 /* fresnel function is used for environment illumination. is is looked up by
230 dot product NV. */
231 memset(lut, 0, sizeof(lut));
232 for (j = 0; j < 256; j++)
233 /*lut[j] = 0.6f * r_fresnel((float)j / 255.9375f, 2.f, 0.35f, 0.f);*/
234 lut[j] = r_fresnel((float)j / 255.9375f, 2.f, 0.35f, 0.f);
235
236 for (j = 0; j < 255; j++)
237 lut[j + 256] = lut[j + 1] - lut[j];
238
239 /*lut[255 + 256] = 0.6f * r_fresnel(1.f, 2.f, 0.35f, 0.f) - lut[255];*/
240 lut[255 + 256] = r_fresnel(1.f, 2.f, 0.35f, 0.f) - lut[255];
241
242 glBindTexture(GL_LUT_TEXTURE5_DMP, lutids[5]);
243 glTexImage1D(GL_LUT_TEXTURE5_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
244 }
245
246 /* load objects */
LoadObjects(void)247 static void LoadObjects(void)
248 {
249 /* load obj file geometory and diffuse texture */
250 loadDAT( "rom:/resources/hand.dat", &hand);
251
252 /* load env texture */
253 char *env_tex[] =
254 {
255 "rom:/resources/bright1.tga",
256 "rom:/resources/bright1.tga",
257 "rom:/resources/bright1.tga",
258 "rom:/resources/bright1.tga",
259 "rom:/resources/bright1.tga",
260 "rom:/resources/bright1.tga",
261 };
262 glGenTextures(1, &s_EnvTexName);
263 glActiveTexture(GL_TEXTURE0);
264 glBindTexture(GL_TEXTURE_CUBE_MAP, s_EnvTexName);
265 for (int face = 0; face < 6; face++)
266 {
267 bool use_alpha;
268 loadTexture(env_tex[face], GL_TEXTURE_CUBE_MAP_POSITIVE_X+face, 0, use_alpha, true, 0, GL_RGBA);
269 }
270 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
271 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
272 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
273 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
274 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_LOD, 0);
275 }
276
UnloadObjects(void)277 static void UnloadObjects(void)
278 {
279 unloadDAT(&hand);
280
281 return;
282 }
283
284 /* set lighting render state */
SetRenderState(void)285 static void SetRenderState(void)
286 {
287 GLfloat ld0[] = {1.f, 1.f, 1.f, 1.f}; /* light0 diffuse */
288 GLfloat ls0[] = {0.35f, 0.35f, 0.35f, 1.f}; /* light0 specular */
289 GLfloat ls1[] = {0.28f, 0.28f, 0.28f, 1.f}; /* light0 specular2 */
290
291 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].diffuse"), 1, ld0);
292 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0);
293 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls1);
294
295 GLfloat ms2[] = {0.28f, 0.28f, 0.28f, 1.f};
296 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms2);
297
298 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0" ), GL_FALSE);
299 /* We use GL_TRUE below to make negative NV non-zero because negative NV values happen on silhouettes */
300 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1" ), GL_TRUE);
301 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputSP" ), GL_FALSE);
302 /* We use GL_TRUE below to make negative NV non-zero because negative NV values happen on silhouettes */
303 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputFR" ), GL_TRUE);
304 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRB" ), GL_FALSE);
305 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRG" ), GL_FALSE);
306 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRR" ), GL_FALSE);
307
308 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRB" ), GL_LIGHT_ENV_LN_DMP);
309 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRG" ), GL_LIGHT_ENV_LN_DMP);
310 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRR" ), GL_LIGHT_ENV_LN_DMP);
311 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1" ), GL_LIGHT_ENV_NV_DMP);
312 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0" ), GL_LIGHT_ENV_NH_DMP);
313 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputFR" ), GL_LIGHT_ENV_NV_DMP);
314
315 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0" ), GL_FALSE);
316 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1" ), GL_FALSE);
317
318 /* all light setting */
319 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRR" ), 2.f);
320 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRG" ), 2.f);
321 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRB" ), 2.f);
322 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD0" ), 2.f);
323 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD1" ), 2.f);
324 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleSP" ), 2.f);
325 glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleFR" ), 2.f);
326
327 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl" ), GL_TRUE);
328
329 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config" ), GL_LIGHT_ENV_LAYER_CONFIG7_DMP);
330 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.fresnelSelector" ), GL_LIGHT_ENV_PRI_SEC_ALPHA_FRESNEL_DMP);
331 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights" ), GL_FALSE);
332
333 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0" ), GL_TRUE);
334 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1" ), GL_TRUE);
335
336 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRR"), 0);
337 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRG"), 1);
338 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRB"), 2);
339 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 3);
340 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 4);
341 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerFR"), 5);
342
343 SetLutTable();
344
345 /* setup texture combine */
346 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_Texture[0].samplerType" ), GL_TEXTURE_CUBE_MAP);
347 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_ADD);
348 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
349 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
350 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
351 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT);
352 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
353
354 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[1].combineRgb"), GL_MULT_ADD_DMP);
355 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[1].combineAlpha"), GL_REPLACE);
356 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[1].operandRgb"), GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_COLOR);
357 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[1].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
358 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[1].srcRgb"), GL_TEXTURE0, GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PREVIOUS);
359 glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[1].srcAlpha"), GL_PREVIOUS, GL_PREVIOUS, GL_PREVIOUS);
360 }
361
DrawFrame(void)362 int DrawFrame(void)
363 {
364 static int f = 0;
365 nn::math::Matrix44 proj, world;
366 nn::math::Matrix34 mv, rot;
367
368 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
369 s_RenderSystem.Clear();
370
371 /* setup projection matrix */
372 nn::math::MTX44Frustum(&proj, -0.06f, 0.06f, -0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH,
373 0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH, 0.2f, 200.f);
374 glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
375
376 nn::math::Vector3 camPos(0.f, 0.f, 2.f);
377 nn::math::Vector3 camUp(0.f, 1.f, 0.f);
378 nn::math::Vector3 target(0.f, 0.f, 0.f);
379 nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f);
380 nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
381 nn::math::MTX34Mult(&mv, &rot, &mv);
382
383 /* setup light direction */
384 nn::math::Vector4 lpos0(-30.f, 0.4f, 18.5f, 1.f);
385 nn::math::Vector4 mv0(mv.m[0][0], mv.m[0][1], mv.m[0][2], mv.m[0][3]);
386 nn::math::Vector4 mv1(mv.m[1][0], mv.m[1][1], mv.m[1][2], mv.m[1][3]);
387 nn::math::Vector4 mv2(mv.m[2][0], mv.m[2][1], mv.m[2][2], mv.m[2][3]);
388 nn::math::Vector4 lpos(nn::math::VEC4Dot(&mv0, &lpos0), nn::math::VEC4Dot(&mv1, &lpos0), nn::math::VEC4Dot(&mv2, &lpos0), lpos0.w);
389
390 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].position"), 1, static_cast<f32*>(lpos));
391
392 /* setup modelview matrix */
393 nn::math::MTX34RotXYZDeg(&rot, 0.f, static_cast<f32>(-f), 0.f);
394 nn::math::MTX34Mult(&mv, &mv, &rot);
395 nn::math::Matrix44 m(mv);
396 glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
397
398 /* for calculation of reflection vector */
399 nn::math::MTX44Identity(&world);
400 glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uWorld"), 1, GL_FALSE, static_cast<f32*>(world));
401
402 glEnableVertexAttribArray(0);
403 glEnableVertexAttribArray(1);
404
405 /* draw objects */
406 for (int i = 0; i < hand.obj_num; i++)
407 {
408 glBindBuffer(GL_ARRAY_BUFFER, hand.posVB);
409 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)hand.obj[i].vtx_offset);
410 glBindBuffer(GL_ARRAY_BUFFER, hand.normVB);
411 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)hand.obj[i].nrm_offset);
412
413 for (unsigned j = hand.obj[i].patch_offset; j < hand.obj[i].patch_size + hand.obj[i].patch_offset; j++)
414 {
415 GLfloat ma[4] = {0.f, 0.f, 0.f, 1.f};
416 GLfloat md[4] = {0.f, 0.f, 0.f, 1.f};
417 GLfloat ms[4] = {0.f, 0.f, 0.f, 1.f};
418 for (int col = 0; col < 3; col++)
419 {
420 ma[col] = hand.patch[j].ambient[col];
421 md[col] = hand.patch[j].diffuse[col];
422 ms[col] = hand.patch[j].specular[col];
423 }
424 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.diffuse"), 1, md);
425 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms);
426 glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.ambient"), 1, ma);
427
428 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hand.idxVB);
429 glDrawElements(GL_TRIANGLES, hand.patch[j].elm_size,
430 GL_UNSIGNED_SHORT, (GLvoid*)(hand.patch[j].elm_offset + hand.obj[i].elm_offset));
431 }
432 }
433
434 glFinish();
435
436 s_RenderSystem.SwapBuffers();
437
438 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
439 s_RenderSystem.Clear();
440 s_RenderSystem.SwapBuffers();
441
442 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
443
444 f++;
445
446 return !glGetError();
447 }
448
449 /* initialization */
Initialize(void)450 static int Initialize(void)
451 {
452 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
453 s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
454
455 /* Initialize display */
456 s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
457
458 /* Create heap for malloc*/
459 s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
460 setMemoryHeap(s_HeapForMalloc, s_HeapSize);
461
462 s_ProgramID = glCreateProgram();
463 s_ShaderID = glCreateShader(GL_VERTEX_SHADER);
464
465 nn::fs::FileReader file(L"rom:/shader.shbin");
466 size_t fileSize = file.GetSize();
467 void* buf = s_AppHeap.Allocate(fileSize);
468
469 s32 read = file.Read(buf, fileSize);
470 glShaderBinary(1, &s_ShaderID, GL_PLATFORM_BINARY_DMP, buf, read);
471 file.Finalize();
472 s_AppHeap.Free(buf);
473
474 glAttachShader(s_ProgramID, s_ShaderID);
475 glAttachShader(s_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP);
476
477 glBindAttribLocation(s_ProgramID, 0, "aPosition");
478 glBindAttribLocation(s_ProgramID, 1, "aNormal");
479
480 glLinkProgram(s_ProgramID);
481 glValidateProgram(s_ProgramID);
482 glUseProgram(s_ProgramID);
483
484 glClearColor(0.36f, 0.42f, 0.5f, 1.0f);
485 glClearDepthf(1.f);
486
487 glEnable(GL_DEPTH_TEST);
488 glDepthFunc(GL_LESS);
489
490 glEnable(GL_CULL_FACE);
491 glFrontFace(GL_CCW);
492 glCullFace(GL_BACK);
493
494 /* create and bind texture collection object to capture subsequent modifications in the texture state
495 both lookup table-related one and ordinary (2d, cube) textures */
496 glGenTextures(1, &s_TexColl);
497 glBindTexture(GL_TEXTURE_COLLECTION_DMP, s_TexColl);
498
499 LoadObjects();
500
501 /* set another render state */
502 SetRenderState();
503
504 /* enable DMP fragment lighting */
505 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE);
506 glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE);
507
508 return 0;
509 }
510
nnMain(void)511 void nnMain(void)
512 {
513 // Call only nn::applet::Enable to also allow execution from the HOME Menu
514 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
515 nn::applet::Enable();
516
517 // fs initialization
518 nn::fs::Initialize();
519
520 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
521 static char buffer[ROMFS_BUFFER_SIZE];
522 NN_UTIL_PANIC_IF_FAILED(
523 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
524
525 /* initialization */
526 if (Initialize() >= 0)
527 {
528 /* Enter loop */
529 while (1)
530 {
531 (void)DrawFrame();
532 }
533 }
534
535 UnloadObjects();
536 /* shutdown_display */
537 s_RenderSystem.Finalize();
538 s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
539 s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
540 s_AppHeap.Finalize();
541 }
542