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