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