1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: gx_Draw3d.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 #include <nn/os.h>
17 #include <nn/fnd.h>
18 #include <nn/gx.h>
19 #include <nn/math.h>
20 #include <nn/fs.h>
21 #include <nn/init.h>
22 #include <nn/applet.h>
23
24 #include "demo.h"
25
26 namespace
27 {
28 GLuint s_ProgramId = 0;
29 GLuint s_ShaderId = 0;
30
31 nn::fnd::ExpHeap s_AppHeap;
32 uptr s_AddrForGxHeap;
33 const u32 s_GxHeapSize = 0x400000;
34
35 demo::RenderSystem s_RenderSystem;
36
37 nn::math::Vector3 s_CameraPosition(0.0f, 2.0f, 2.0f);
38 nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f);
39 nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f);
40
41 nn::math::Matrix34 s_ViewMatrix;
42 nn::math::Matrix44 s_Display0ProjectionMatrix;
43 nn::math::Matrix44 s_Display1ProjectionMatrix;
44
45 f32 s_GlobalAmbientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f};
46 f32 s_Light0Ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f};
47 f32 s_Light0Diffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f};
48 f32 s_Light0Position[] = {15.0f, 15.0f, 15.0f, 1.0f};
49
50 f32 s_MaterialAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f};
51 f32 s_MaterialDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
52
53 demo::Cube s_Cube;
54 demo::Sphere s_Sphere;
55 demo::Cylinder s_Cylinder;
56 }
57
58 void InitializeGraphics(void);
59 void InitializeShader(void);
60
61 void UseShader(void);
62 void UpdateCamera(void);
63 void DrawDisplay0(void);
64 void DrawDisplay1(void);
65
66 void UpdateBody(demo::Body& body);
67 void DrawBody(demo::Body& body);
68
Initialize(void)69 void Initialize(void)
70 {
71 // fs initialization
72 nn::fs::Initialize();
73
74 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
75 static char buffer[ROMFS_BUFFER_SIZE];
76 NN_UTIL_PANIC_IF_FAILED(
77 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
78
79 InitializeGraphics();
80 }
81
InitializeGraphics(void)82 void InitializeGraphics(void)
83 {
84 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
85 nn::os::GetDeviceMemorySize() );
86 s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
87
88 s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
89
90 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
91 glClearDepthf(1.f);
92
93 glEnable(GL_DEPTH_TEST);
94 glDepthFunc(GL_LESS);
95
96 glEnable(GL_CULL_FACE);
97 glFrontFace(GL_CCW);
98 glCullFace(GL_BACK);
99
100 InitializeShader();
101
102 // Initialize projection matrix
103 nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f,
104 demo::DISPLAY0_ASPECT, 0.2f, 100.0f,
105 nn::math::PIVOT_UPSIDE_TO_TOP);
106
107 nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f,
108 demo::DISPLAY1_ASPECT, 0.2f, 100.0f,
109 nn::math::PIVOT_UPSIDE_TO_TOP);
110
111 // Initialize cube
112 u32 vertexAttributes = demo::VERTEX_POSITION_ATTRIBUTE |
113 demo::VERTEX_COLOR_ATTRIBUTE | demo::VERTEX_NORMAL_ATTRIBUTE;
114 s_Cube.InitializeCube(vertexAttributes, 0.4f, 0.4f, 0.4f);
115 s_Cube.SetColor(1.0f, 0.0f, 0.0f);
116 s_Cube.SetWorldPosition(-1.1f, 0.0f, 0.0f);
117 s_Cube.SetWorldAngle(0.0f, 0.0f, 0.0f);
118
119 // Initialize sphere
120 s_Sphere.InitializeSphere(vertexAttributes, 0.4, 8);
121 s_Sphere.SetColor(0.0f, 1.0f, 0.0f);
122 s_Sphere.SetWorldPosition(0.0f, 0.0f, 0.0f);
123 s_Sphere.SetWorldAngle(0.0f, 0.0f, 0.0f);
124
125 // Initialize cylinder
126 s_Cylinder.InitializeCylinder(vertexAttributes, 0.4f, 1.0f, 8);
127 s_Cylinder.SetColor(0.0f, 0.0f, 1.0f);
128 s_Cylinder.SetWorldPosition(1.1f, 0.0f, 0.0f);
129 s_Cylinder.SetWorldAngle(0.0f, 0.0f, 0.0f);
130 }
131
InitializeShader(void)132 void InitializeShader(void)
133 {
134 s_ProgramId = glCreateProgram();
135
136 // Load vertex shader
137 s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
138 nn::fs::FileReader file(L"rom:/shader.shbin");
139 size_t fileSize = file.GetSize();
140 void* buf = s_AppHeap.Allocate(fileSize);
141 s32 read = file.Read(buf, fileSize);
142 glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
143 file.Finalize();
144 s_AppHeap.Free(buf);
145
146 glAttachShader(s_ProgramId, s_ShaderId);
147 glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
148
149 glBindAttribLocation(s_ProgramId, 0, "aPosition");
150 glBindAttribLocation(s_ProgramId, 1, "aColor");
151 glBindAttribLocation(s_ProgramId, 2, "aNormal");
152
153 glLinkProgram(s_ProgramId);
154 glValidateProgram(s_ProgramId);
155
156 demo::InitializeUniforms(s_ProgramId);
157 }
158
Finalize(void)159 void Finalize(void)
160 {
161 s_Cube.Finalize();
162 s_Cylinder.Finalize();
163 s_Sphere.Finalize();
164
165 s_RenderSystem.Finalize();
166
167 s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
168 s_AppHeap.Finalize();
169 }
170
DrawFrame(void)171 bool DrawFrame(void)
172 {
173 UpdateCamera();
174
175 DrawDisplay0();
176 DrawDisplay1();
177
178 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
179
180 return true;
181 }
182
UpdateCamera(void)183 void UpdateCamera(void)
184 {
185 nn::math::MTX34LookAt(&s_ViewMatrix, &s_CameraPosition, &s_CameraUp, &s_CameraTarget);
186 }
187
DrawDisplay0(void)188 void DrawDisplay0(void)
189 {
190 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
191 s_RenderSystem.Clear();
192
193 UseShader();
194
195 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
196 1, GL_TRUE, static_cast<f32*>(s_Display0ProjectionMatrix));
197
198 UpdateBody(s_Cube);
199 DrawBody(s_Cube);
200
201 UpdateBody(s_Sphere);
202 DrawBody(s_Sphere);
203
204 UpdateBody(s_Cylinder);
205 DrawBody(s_Cylinder);
206
207 s_RenderSystem.SwapBuffers();
208 }
209
UseShader(void)210 void UseShader(void)
211 {
212 glUseProgram(s_ProgramId);
213
214 // Fragment uniform
215 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE);
216
217 // Fragment uniform : Texture samplerType
218 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE);
219 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE);
220 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE);
221 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE);
222
223 // Fragment uniform : Fragment lighting
224 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE);
225 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight);
226 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE);
227 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_Light0Ambient);
228 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_Light0Diffuse);
229 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION], 1, s_Light0Position);
230
231 // Fragment uniform : Material
232 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient);
233 glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse);
234
235 // Fragment uniform : Texture combiner
236 // Modulate fragment primary color and vertex color.
237 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB],
238 GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PRIMARY_COLOR, GL_PREVIOUS);
239 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA],
240 GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS);
241 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB],
242 GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
243 glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA],
244 GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
245 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB],
246 GL_MODULATE);
247 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA],
248 GL_MODULATE);
249 }
250
DrawDisplay1(void)251 void DrawDisplay1(void)
252 {
253 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
254 s_RenderSystem.Clear();
255
256 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION],
257 1, GL_TRUE, static_cast<f32*>(s_Display1ProjectionMatrix));
258
259 s_RenderSystem.SwapBuffers();
260 }
261
UpdateBody(demo::Body & body)262 void UpdateBody(demo::Body& body)
263 {
264 f32 worldAngle[3];
265 body.GetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
266
267 worldAngle[0] += 1.0f;
268 if ( worldAngle[0] > 360.0f )
269 {
270 worldAngle[0] = 0.0f;
271 }
272
273 body.SetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]);
274 }
275
DrawBody(demo::Body & body)276 void DrawBody(demo::Body& body)
277 {
278 nn::math::MTX44 modelViewMatrix(s_ViewMatrix);
279 nn::math::Matrix44 worldMatrix = body.GetWorldMatrix();
280 nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix);
281 glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW],
282 1, GL_TRUE, static_cast<f32*>(modelViewMatrix));
283
284 body.Draw();
285 }
286
nnMain(void)287 void nnMain(void)
288 {
289 // Call only nn::applet::Enable to also allow execution from the HOME Menu
290 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
291 nn::applet::Enable();
292
293 Initialize();
294
295 bool flag = true;
296 while ( flag )
297 {
298 flag = DrawFrame();
299 }
300
301 Finalize();
302 }
303