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