1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     LightingDistanceAtte.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 #include <nn/gx.h>
27 #include <nn/fs.h>
28 #include <nn/math.h>
29 #include <nn/init.h>
30 #include <nn/os.h>
31 #include <nn/applet.h>
32 
33 #include "demo.h"
34 
35 #include "Util.h"
36 #include "Loader.h"
37 
38 #include <string.h>
39 #include <math.h>
40 
41 #include "Memory.h"
42 #include "s.h"
43 
44 #define APP_NAME "LightingDistanceAtte"
45 
46 #define DMP_PI	(3.1415926f)
47 #define REV_PI	(1.0f/DMP_PI)
48 
49 /* buffer id */
50 GLuint s_ArrayBufferID;
51 GLuint s_ElementArrayBufferID;
52 
53 /* program id */
54 GLuint s_ProgramID;
55 
56 /* shader id */
57 GLuint s_ShaderID;
58 
59 /* sphere object */
60 sphere *obj = 0;
61 
62 /* ExpHeap for app. */
63 nn::fnd::ExpHeap s_AppHeap;
64 uptr s_HeapForGx;
65 uptr s_HeapForMalloc;
66 const u32 s_GxHeapSize = 0x400000;
67 const u32 s_HeapSize = 0x400000;
68 
69 demo::RenderSystem s_RenderSystem;
70 
SetRenderState(void)71 static void SetRenderState(void)
72 {
73     GLfloat la[] = {1.f, 1.f, 1.f, 1.f};
74     GLfloat ld[] = {1.f, 1.f, 1.f, 1.f};
75     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].ambient"), 1, la);
76     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].diffuse"), 1, ld);
77 
78     /* setup lookup table */
79     GLuint lutids[1];
80     glGenTextures(1, lutids);
81 
82     GLfloat lut[512];
83     int j;
84 
85     /* In this sample, the distance attenuation lookup table uses the distribution expressed by the function y=1-x
86         */
87     memset(lut, 0, sizeof(lut));
88     for (j = 0; j < 256; j++)
89     {
90         float x = (float)j / 255.f;
91         float y = 1 - x;
92         lut[j] = y;
93     }
94     for (j = 0; j < 255; j++)
95         lut[j + 256] = lut[j + 1] - lut[j];
96     lut[255 + 256] = 0.f - lut[255];
97 
98     glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[0]);
99     glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut);
100     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].samplerDA"), 0);
101     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].distanceAttenuationEnabled"), GL_TRUE );
102     /* Regarding scale and bias for the lookup table input values, typically, if "start" is used as the attenuation start distance and "end" is used as the attenuation end distance, and if scale is set to "1.0/(end - start)" and bias is set to "-start/(end - start)" then "start" and "end" would be mapped to input values of 0.0 and 1.0.
103 
104 
105 
106        However, in this sample, those values may not always be used. */
107     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].distanceAttenuationScale"), 0.07f );
108     glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].distanceAttenuationBias"), 0.f );
109 }
110 
111 /* generate simple object */
LoadObjects(void)112 static void LoadObjects(void)
113 {
114     obj = new sphere(20, 20, 1.f);
115 
116     glGenBuffers(1, &s_ArrayBufferID);
117     glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferID);
118     glBufferData(GL_ARRAY_BUFFER, obj->get_index_count()*3*sizeof(float)*2, 0, GL_STATIC_DRAW);
119     glBufferSubData(GL_ARRAY_BUFFER, 0, obj->get_index_count()*3*sizeof(float), obj->get_vertex());
120     glBufferSubData(GL_ARRAY_BUFFER, obj->get_index_count()*3*sizeof(float), obj->get_index_count()*3*sizeof(float), obj->get_normal());
121 
122     glGenBuffers(1, &s_ElementArrayBufferID);
123     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferID);
124     glBufferData(GL_ELEMENT_ARRAY_BUFFER, obj->get_index_count()*sizeof(unsigned short), obj->get_index(), GL_STATIC_DRAW);
125 
126     glEnableVertexAttribArray(0);
127     glEnableVertexAttribArray(1);
128 
129     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
130     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(obj->get_index_count()*3*sizeof(float)));
131 }
132 
UnloadObjects(void)133 static void UnloadObjects(void)
134 {
135     glDeleteBuffers(1, &s_ArrayBufferID);
136     glDeleteBuffers(1, &s_ElementArrayBufferID);
137 
138     delete obj;
139 
140     return;
141 }
142 
DrawSphere()143 void DrawSphere()
144 {
145     glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferID);
146     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferID);
147 
148     glDrawElements(GL_TRIANGLES, obj->get_index_count(), GL_UNSIGNED_SHORT, 0);
149 }
150 
DrawFrame(void)151 int DrawFrame(void)
152 {
153     static int f = 0;
154 
155     nn::math::Matrix34 mv, rot;
156 
157     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
158     s_RenderSystem.Clear();
159 
160     /* setup projection matrix */
161     nn::math::Matrix44 proj;
162     nn::math::MTX44Frustum(&proj, -0.06f, 0.06f, -0.06f*nn::gx::DISPLAY0_HEIGHT/nn::gx::DISPLAY0_WIDTH,
163                            0.06f*nn::gx::DISPLAY0_HEIGHT/nn::gx::DISPLAY0_WIDTH, 0.2f, 200.f);
164     glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
165 
166     nn::math::Vector3 camPos(0.f, 15.f, 20.f);
167     nn::math::Vector3 camUp(0.f, 1.f, 0.f);
168     nn::math::Vector3 target(0.f, 0.f, 0.f);
169     nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f);
170     nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
171     nn::math::MTX34Mult(&mv, &rot, &mv);
172 
173     /* setup light direction */
174     nn::math::Vector4 lpos0(0.f, 0.f, 0.f, 1.f);
175     lpos0.y = 5.f * cosf(2.f * f / 60.f) + 7.f;
176     nn::math::Vector4 mv0(mv.m[0][0], mv.m[0][1], mv.m[0][2], mv.m[0][3]);
177     nn::math::Vector4 mv1(mv.m[1][0], mv.m[1][1], mv.m[1][2], mv.m[1][3]);
178     nn::math::Vector4 mv2(mv.m[2][0], mv.m[2][1], mv.m[2][2], mv.m[2][3]);
179     nn::math::Vector4 lpos(VEC4Dot(&mv0, &lpos0), VEC4Dot(&mv1, &lpos0), VEC4Dot(&mv2, &lpos0), lpos0.w);
180     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].position"), 1, static_cast<f32*>(lpos));
181 
182     GLfloat sphere_a[] = {0.f, 0.f, 0.f, 1.f};
183     GLfloat sphere_d[] = {1.f, 1.f, 0.f, 1.f};
184     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.ambient"), 1, sphere_a);
185     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.diffuse"), 1, sphere_d);
186 
187     #define N ( 3 )
188     for (unsigned k = 0; k < N*2+1; k++)
189     {
190         for (unsigned j = 0; j < N*2+1; j++)
191         {
192             float x = -3.f*N + (float)k*N;
193             float z = -3.f*N + (float)j*N;
194             nn::math::Vector3 trans(x, 0.0f, z);
195             nn::math::Matrix34 mv_tr, tmp;
196             nn::math::MTX34Translate(&tmp, &trans);
197             MTX34Mult(&mv_tr, &mv, &tmp);
198             nn::math::Matrix44 m(mv_tr);
199             glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
200             DrawSphere();
201         }
202     }
203 
204     /* draw light object */
205     GLfloat light_a[] = {1.f, 0.f, 0.f, 1.f};
206     GLfloat light_d[] = {0.f, 0.f, 0.f, 1.f};
207     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.ambient"), 1, light_a);
208     glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.diffuse"), 1, light_d);
209 
210     {
211         nn::math::Matrix34 mv_tr, tmp[2];
212         nn::math::Vector3 trans(lpos0.x, lpos0.y, lpos0.z);
213         nn::math::Vector3 scale(0.3f, 0.3f, 0.3f);
214         nn::math::MTX34Translate(&tmp[0], &trans);
215         nn::math::MTX34Scale(&tmp[1], &scale);
216         nn::math::MTX34Mult(&mv_tr, &mv, &tmp[0]);
217         nn::math::MTX34Mult(&mv_tr, &mv_tr, &tmp[1]);
218         nn::math::Matrix44 m(mv_tr);
219         glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
220         DrawSphere();
221     }
222 
223     glFinish();
224     s_RenderSystem.SwapBuffers();
225 
226     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
227     s_RenderSystem.Clear();
228     s_RenderSystem.SwapBuffers();
229 
230     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
231 
232     f++;
233 
234     return !glGetError();
235 }
236 
237 /* initialization */
Initialize(void)238 static int Initialize(void)
239 {
240     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
241     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
242     /* Initialize display */
243     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
244 
245     /* Create heap for malloc*/
246     s_HeapForMalloc = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_HeapSize));
247     setMemoryHeap(s_HeapForMalloc, s_HeapSize);
248 
249     s_ProgramID = glCreateProgram();
250     s_ShaderID = glCreateShader(GL_VERTEX_SHADER);
251 
252     nn::fs::FileReader file(L"rom:/shader.shbin");
253     size_t fileSize = file.GetSize();
254     void* buf = s_AppHeap.Allocate(fileSize);
255 
256     s32 read = file.Read(buf, fileSize);
257     glShaderBinary(1, &s_ShaderID, GL_PLATFORM_BINARY_DMP, buf, read);
258     file.Finalize();
259     s_AppHeap.Free(buf);
260 
261     glAttachShader(s_ProgramID, s_ShaderID);
262     glAttachShader(s_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP);
263 
264     glBindAttribLocation(s_ProgramID, 0, "aPosition");
265     glBindAttribLocation(s_ProgramID, 1, "aNormal");
266 
267     glLinkProgram(s_ProgramID);
268     glValidateProgram(s_ProgramID);
269     glUseProgram(s_ProgramID);
270 
271     glClearColor(0.36f, 0.42f, 0.5f, 1.0f);
272     glClearDepthf(1.f);
273 
274     glEnable(GL_DEPTH_TEST);
275     glDepthFunc(GL_LESS);
276     glEnable(GL_CULL_FACE);
277     glFrontFace(GL_CCW);
278     glCullFace(GL_BACK);
279 
280     LoadObjects();
281 
282     /* set another render state */
283     SetRenderState();
284 
285     /* enable DMP fragment lighting */
286     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE);
287     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE);
288 
289     /* this sample use only fragment primary color */
290     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
291     glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
292     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
293     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
294     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT);
295     glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT);
296 
297     return 0;
298 }
299 
nnMain(void)300 void nnMain(void)
301 {
302     // Call only nn::applet::Enable to also allow execution from the HOME Menu
303     // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
304     nn::applet::Enable();
305 
306     // fs initialization
307     nn::fs::Initialize();
308 
309     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
310     static char buffer[ROMFS_BUFFER_SIZE];
311     NN_UTIL_PANIC_IF_FAILED(
312         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
313 
314     /* initialization */
315     if (Initialize() >= 0)
316     {
317         /* Enter loop */
318         while (1)
319         {
320             (void)DrawFrame();
321         }
322     }
323 
324     UnloadObjects();
325     /* shutdown_display */
326     s_RenderSystem.Finalize();
327     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForMalloc));
328     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
329     s_AppHeap.Finalize();
330 }
331