1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     Fog.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 /*
27  * Comments
28  * --------
29  *
30  * Fog sample.
31  * This sample shows how to set up lookup tables for linear and exponential fog.
32  * The rendered display is split in 2 by the scissor test and is relevant for linear fog.
33  * In that case, the left side of the screen shows a quadrilateral with fog enabled.
34  * The right side shows three different quadrilaterals, corresponding to 3 regions:
35  * i) before the start of the fog, ii) between the start and end of the fog, and iii) after the end of the fog
36  */
37 
38 #include <math.h>
39 
40 #include <nn/gx.h>
41 #include <nn/math.h>
42 #include <nn/fs.h>
43 #include <nn/os.h>
44 #include <nn/init.h>
45 #include <nn/applet.h>
46 #include <nn/fnd/fnd_ExpHeap.h>
47 
48 #include "demo.h"
49 
50 /* program id */
51 GLuint s_PgID;
52 
53 /* shader id */
54 GLuint s_ShID;
55 
56 /* fog color */
57 GLfloat s_FogColor[4]={1.0f, 1.0f, 1.0f, 1.0f};
58 
59 /* fog LUT number */
60 #define FOG_LUT_NUM     (0)
61 
62 /* fog mode settings */
63 #define FOG_MODE            (FOG_MODE_LINEAR)   /* Selection of fog mode */
64 #define FOG_MODE_LINEAR     (0)                 /* GL_LINEAR mode in OpenGL ES1.1 compatible */
65 #define FOG_MODE_EXP        (1)                 /* GL_EXP mode in OpenGL ES1.1 compatible */
66 
67 float s_FogStart = 10.f;        /* GL_FOG_START in OpenGL ES1.1 compatible settings */
68 float s_FogEnd = 30.f;      /* GL_FOG_END in OpenGL ES1.1 compatible settings */
69 float s_FogDensity = 0.1f;  /* GL_FOG_DENSITY in OpenGL ES1.1 compatible settings */
70 
71 float s_FogAfter = 500.f;
72 
73 float s_Width = 1000.f;
74 float s_Height = 0.f;
75 
76 /* Buffer ids */
77 GLuint s_QuadFogIndexBufID;
78 GLuint s_QuadFogVertBufID;
79 GLuint s_QuadFogColBufID;
80 
81 GLuint s_QuadAllIndexBufID;
82 GLuint s_QuadAllVertBufID;
83 GLuint s_QuadAllColBufID;
84 
85 /* Vertex attribute related */
86 GLfloat s_VertexFog[12];
87 const GLushort s_QuadIndexAll[18] =
88 {
89     0, 1, 2, 0, 2, 3,
90     4, 5, 6, 4, 6, 7,
91     8, 9, 10, 8, 9, 11
92 };
93 const GLushort s_QuadIndexFog[6] = {0, 1, 2, 0, 2, 3};
94 
95 GLfloat s_VertexAll[36];
96 GLfloat s_VertexAllColor[48];
97 GLfloat s_VertexFogColor[48];
98 
99 GLuint s_FogLutID;
100 GLuint s_CollectionLUTID;
101 
102 /* ExpHeap for app. */
103 nn::fnd::ExpHeap s_AppHeap;
104 uptr s_HeapForGx;
105 const u32 s_GxHeapSize = 0x400000;
106 
107 demo::RenderSystem s_RenderSystem;
108 
109 /* This function returns fog coefficient for input value c */
FogCoef(float fog_c)110 float FogCoef(float fog_c)
111 {
112     /* GL_LINEAR compatible */
113     if (FOG_MODE == FOG_MODE_LINEAR)
114     {
115         if (fog_c < s_FogStart)
116             return 1.0f;
117         else if (fog_c > s_FogEnd)
118             return 0.0f;
119         else
120             return (s_FogEnd - fog_c) / (s_FogEnd - s_FogStart);
121     }
122     /* GL_EXP compatible */
123     else if (FOG_MODE == FOG_MODE_EXP)
124     {
125         return exp(-s_FogDensity * fog_c);
126     }
127     /* Error */
128     else
129         return -1.0;
130 }
131 
InitializeFogTable(nn::math::Matrix44 * MP)132 void InitializeFogTable(nn::math::Matrix44 *MP)
133 {
134     static float Fog_LUT[256];      /* Fog lut contents */
135     static float Fog_c[128 + 1];    /* c (distance from origin in eye coordinate */
136 
137     int i;
138     nn::math::Matrix44 invPM;
139     nn::math::Vector4 v_clip(0.0f, 0.0f, 0.0f, 1.0f);
140     nn::math::Vector4 v_eye;
141 
142     /* If projection matrix is DMPGL2.0 one, USE code following */
143     nn::math::MTX44Inverse(&invPM, MP);
144     nn::math::Vector4 v0(invPM.m[0]);
145     nn::math::Vector4 v1(invPM.m[1]);
146     nn::math::Vector4 v2(invPM.m[2]);
147     nn::math::Vector4 v3(invPM.m[3]);
148     for (i = 0; i <= 128; i++)
149     {
150         v_clip.z = -(static_cast<f32>(i)) / 128;
151         v_eye.x = nn::math::VEC4Dot(&v0, &v_clip);
152         v_eye.y = nn::math::VEC4Dot(&v1, &v_clip);
153         v_eye.z = nn::math::VEC4Dot(&v2, &v_clip);
154         v_eye.w = nn::math::VEC4Dot(&v3, &v_clip);
155         Fog_c[i] = -(v_eye.z / v_eye.w);
156     }
157 
158     for (i = 0; i < 128; i++)
159     {
160         Fog_LUT[i] = FogCoef(Fog_c[i]);
161         Fog_LUT[128 + i]= FogCoef(Fog_c[i + 1]) - FogCoef(Fog_c[i]);
162     }
163 
164     glBindTexture(GL_TEXTURE_COLLECTION_DMP, s_CollectionLUTID);
165     glBindTexture(GL_LUT_TEXTURE0_DMP + FOG_LUT_NUM, s_FogLutID);
166     glTexImage1D(GL_LUT_TEXTURE0_DMP + FOG_LUT_NUM, 0, GL_LUMINANCEF_DMP, 256, 0, GL_LUMINANCEF_DMP, GL_FLOAT, Fog_LUT);
167 }
168 
169 /* load objects */
LoadObjects(void)170 static void LoadObjects(void)
171 {
172     s_VertexAll[0] = -s_Width;
173     s_VertexAll[1] = s_Height;
174     s_VertexAll[2] = 0;
175 
176     s_VertexAll[3] = s_Width;
177     s_VertexAll[4] = s_Height;
178     s_VertexAll[5] = 0;
179 
180     s_VertexAll[6] = s_Width;
181     s_VertexAll[7] = s_Height;
182     s_VertexAll[8] = s_FogStart;
183 
184     s_VertexAll[9]  = -s_Width;
185     s_VertexAll[10] = s_Height;
186     s_VertexAll[11] = s_FogStart;
187 
188     for (int i = 0; i < 4; i++)
189     {
190         s_VertexAllColor[4 * i + 0] = 1.0f;
191         s_VertexAllColor[4 * i + 1] = 0.0f;
192         s_VertexAllColor[4 * i + 2] = 0.0f;
193         s_VertexAllColor[4 * i + 3] = 1.0f;
194     }
195 
196     s_VertexAll[12 + 0] = -s_Width;
197     s_VertexAll[12 + 1] = s_Height;
198     s_VertexAll[12 + 2] = s_FogStart;
199 
200     s_VertexAll[12 + 3] = s_Width;
201     s_VertexAll[12 + 4] = s_Height;
202     s_VertexAll[12 + 5] = s_FogStart;
203 
204     s_VertexAll[12 + 6] = s_Width;
205     s_VertexAll[12 + 7] = s_Height;
206     s_VertexAll[12 + 8] = s_FogEnd;
207 
208     s_VertexAll[12 + 9]  = -s_Width;
209     s_VertexAll[12 + 10] = s_Height;
210     s_VertexAll[12 + 11] = s_FogEnd;
211     for (int i = 0; i < 4; i++)
212     {
213         s_VertexAllColor[16 + 4 * i + 0] = 1.0f;
214         s_VertexAllColor[16 + 4 * i + 1] = 1.0f;
215         s_VertexAllColor[16 + 4 * i + 2] = 0.0f;
216         s_VertexAllColor[16 + 4 * i + 3] = 1.0f;
217     }
218 
219     s_VertexAll[24 + 0] = -s_Width;
220     s_VertexAll[24 + 1] = s_Height;
221     s_VertexAll[24 + 2] = s_FogEnd;
222 
223     s_VertexAll[24 + 3] = s_Width;
224     s_VertexAll[24 + 4] = s_Height;
225     s_VertexAll[24 + 5] = s_FogEnd;
226 
227     s_VertexAll[24 + 6] = s_Width;
228     s_VertexAll[24 + 7] = s_Height;
229     s_VertexAll[24 + 8] = s_FogEnd+s_FogAfter;
230 
231     s_VertexAll[24 + 9]  = -s_Width;
232     s_VertexAll[24 + 10] = s_Height;
233     s_VertexAll[24 + 11] = s_FogEnd+s_FogAfter;
234     for (int i = 0; i < 4; i++)
235     {
236         s_VertexAllColor[32 + 4 * i + 0] = 1.0f;
237         s_VertexAllColor[32 + 4 * i + 1] = 0.0f;
238         s_VertexAllColor[32 + 4 * i + 2] = 1.0f;
239         s_VertexAllColor[32 + 4 * i + 3] = 1.0f;
240     }
241 
242     s_VertexFog[0] = -s_Width;
243     s_VertexFog[1] = s_Height;
244     s_VertexFog[2] = 0;
245 
246     s_VertexFog[3] = s_Width;
247     s_VertexFog[4] = s_Height;
248     s_VertexFog[5] = 0;
249 
250     s_VertexFog[6] = s_Width;
251     s_VertexFog[7] = s_Height;
252     s_VertexFog[8] = s_FogEnd + s_FogAfter;
253 
254     s_VertexFog[9]  = -s_Width;
255     s_VertexFog[10] = s_Height;
256     s_VertexFog[11] = s_FogEnd + s_FogAfter;
257 
258     for (int i = 0; i < 4; i++)
259     {
260         s_VertexFogColor[4 * i + 0] = 0.0f;
261         s_VertexFogColor[4 * i + 1] = 0.0f;
262         s_VertexFogColor[4 * i + 2] = 1.0f;
263         s_VertexFogColor[4 * i + 3] = 1.0f;
264     }
265 
266     glGenBuffers(1, &s_QuadFogIndexBufID);
267     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_QuadFogIndexBufID);
268     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), &s_QuadIndexFog, GL_STATIC_DRAW);
269 
270     glGenBuffers(1, &s_QuadAllIndexBufID);
271     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_QuadAllIndexBufID);
272     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 18 * sizeof(GLushort), &s_QuadIndexAll, GL_STATIC_DRAW);
273 
274     glGenBuffers(1, &s_QuadFogVertBufID);
275     glBindBuffer(GL_ARRAY_BUFFER, s_QuadFogVertBufID);
276     glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), &s_VertexFog, GL_STATIC_DRAW);
277     glGenBuffers(1, &s_QuadFogColBufID);
278     glBindBuffer(GL_ARRAY_BUFFER, s_QuadFogColBufID);
279     glBufferData(GL_ARRAY_BUFFER, 16*sizeof(GLfloat), &s_VertexFogColor, GL_STATIC_DRAW);
280 
281     glGenBuffers(1, &s_QuadAllVertBufID);
282     glBindBuffer(GL_ARRAY_BUFFER, s_QuadAllVertBufID);
283     glBufferData(GL_ARRAY_BUFFER, 36 * sizeof(GLfloat), &s_VertexAll, GL_STATIC_DRAW);
284     glGenBuffers(1, &s_QuadAllColBufID);
285     glBindBuffer(GL_ARRAY_BUFFER, s_QuadAllColBufID);
286     glBufferData(GL_ARRAY_BUFFER, 48 * sizeof(GLfloat), &s_VertexAllColor, GL_STATIC_DRAW);
287 }
288 
DrawScene()289 void DrawScene()
290 {
291     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
292     glViewport(0, 0, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT);
293     s_RenderSystem.Clear();
294 
295     glDisable(GL_CULL_FACE);
296     glEnable(GL_SCISSOR_TEST);
297     glScissor(0, 0, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT / 2);
298 
299     glBindBuffer(GL_ARRAY_BUFFER, s_QuadAllVertBufID);
300     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
301 
302     glBindBuffer(GL_ARRAY_BUFFER, s_QuadAllColBufID);
303     glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
304 
305     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_QuadAllIndexBufID);
306     glDrawElements(GL_TRIANGLES, 18, GL_UNSIGNED_SHORT, 0);
307 
308     glScissor(0, nn::gx::DISPLAY0_HEIGHT / 2, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT / 2);
309     glUniform1i(glGetUniformLocation(s_PgID, "dmp_Fog.mode"), GL_FOG);
310 
311     glBindBuffer(GL_ARRAY_BUFFER, s_QuadFogVertBufID);
312     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
313 
314     glBindBuffer(GL_ARRAY_BUFFER, s_QuadFogColBufID);
315     glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
316 
317     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_QuadFogIndexBufID);
318     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,0);
319 
320     glUniform1i(glGetUniformLocation(s_PgID, "dmp_Fog.mode"), 0);
321 
322     glDisable(GL_SCISSOR_TEST);
323 
324     s_RenderSystem.SwapBuffers();
325 }
326 
DrawFrame(void)327 int DrawFrame(void)
328 {
329     static int f = 0;
330     static const int step = 128;
331 
332     /* fog_sampler 0 is exponential fog */
333     /* fog_sampler 1 is linear fog */
334     glUniform1i(glGetUniformLocation(s_PgID, "dmp_Fog.sampler"), FOG_LUT_NUM);
335     float dx = f * (1.0f / (float)(step - 1));
336     s_FogColor[0] = 0.2f + dx * (1.0f - 0.2f);
337     s_FogColor[1] = 0.4f + dx * (1.0f - 0.4f);
338     s_FogColor[2] = 0.6f + dx * (1.0f - 0.6f);
339     glUniform3fv(glGetUniformLocation(s_PgID, "dmp_Fog.color"), 1, s_FogColor);
340     DrawScene();
341 
342     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
343     s_RenderSystem.Clear();
344     s_RenderSystem.SwapBuffers();
345 
346     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
347 
348     if (f == step - 1)
349         f=0;
350     else
351         f++;
352 
353     return !glGetError();
354 }
355 
356 /* initialization */
Initialize(void)357 static int Initialize(void)
358 {
359     // fs initialization
360     nn::fs::Initialize();
361 
362     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
363     static char buffer[ROMFS_BUFFER_SIZE];
364     NN_UTIL_PANIC_IF_FAILED(
365         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
366 
367     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
368     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
369     /* Initialize display */
370     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
371 
372     glClearColor(0.2f, 0.4f, 0.6f, 1.0f);
373     glClearDepthf(1.f);
374 
375     glViewport(0, 0, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT);
376 
377     glEnable(GL_DEPTH_TEST);
378     glDepthFunc(GL_LESS);
379 
380     glEnable(GL_CULL_FACE);
381     glFrontFace(GL_CCW);
382     glCullFace(GL_BACK);
383 
384     /* create program and load & attach vertex shader */
385     s_PgID = glCreateProgram();
386     s_ShID = glCreateShader(GL_VERTEX_SHADER);
387 
388     nn::fs::FileReader file(L"rom:/shader.shbin");
389     size_t fileSize = file.GetSize();
390     void* buf = s_AppHeap.Allocate(fileSize);
391 
392     s32 read = file.Read(buf, fileSize);
393     glShaderBinary(1, &s_ShID, GL_PLATFORM_BINARY_DMP, buf, read);
394     file.Finalize();
395     s_AppHeap.Free(buf);
396 
397     glAttachShader(s_PgID, s_ShID);
398 
399     /* attach fixed-function fragment shader */
400     glAttachShader(s_PgID, GL_DMP_FRAGMENT_SHADER_DMP);
401 
402     glBindAttribLocation(s_PgID, 0, "aPosition");
403     glBindAttribLocation(s_PgID, 1, "aColor");
404 
405     glLinkProgram(s_PgID);
406     glValidateProgram(s_PgID);
407     /* set program as current one to enable setting its uniforms */
408     glUseProgram(s_PgID);
409 
410     LoadObjects();
411 
412     glEnableVertexAttribArray(0);
413     glEnableVertexAttribArray(1);
414 
415     glUniform3i(glGetUniformLocation(s_PgID, "dmp_TexEnv[0].srcRgb"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
416     glUniform3i(glGetUniformLocation(s_PgID, "dmp_TexEnv[0].srcAlpha"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
417 
418     nn::math::Matrix44 proj;
419     nn::math::MTX44Perspective(&proj, 65.0f, static_cast<f32>(nn::gx::DISPLAY0_WIDTH) / static_cast<f32>(nn::gx::DISPLAY0_HEIGHT), 1.0f, 500.0f);
420     glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
421 
422     nn::math::Matrix34 eye;
423     nn::math::Vector3 camPos(0.0f, 2.0f, 0.0f);
424     nn::math::Vector3 camUp(1.0f, 0.0f, 0.0f);
425     nn::math::Vector3 target(0.0f, 2.0f, 10.0f);
426 
427     nn::math::MTX34Identity(&eye);
428     nn::math::MTX34LookAt(&eye, &camPos, &camUp, &target);
429     nn::math::Matrix44 mv(eye);
430     glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(mv));
431 
432     glGenTextures(1, &s_CollectionLUTID);
433     glGenTextures(1, &s_FogLutID);
434 
435     InitializeFogTable(&proj);
436 
437     return 0;
438 }
439 
nnMain(void)440 void nnMain(void)
441 {
442     // Call only nn::applet::Enable to also allow execution from the HOME Menu
443     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
444     nn::applet::Enable();
445 
446     /* initialization */
447     if (Initialize() >= 0)
448     {
449         while (1)
450         {
451             (void)DrawFrame();
452         }
453     }
454     /* shutdown_display */
455     s_RenderSystem.Finalize();
456     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
457     s_AppHeap.Finalize();
458 }
459 
460