1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: gx_AlphaTest.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 Test for alpha test using fragment shader
18
19 About texture combiner input
20 srcRgb inputs the the color calculated by fragment lighting and srcAlpha inputs the alpha value set as a vertex attribute.
21
22 */
23
24 #include <nn/types.h>
25
26 #include <nn/os.h>
27 #include <nn/fnd.h>
28 #include <nn/gx.h>
29 #include <nn/math.h>
30 #include <nn/fs.h>
31 #include <nn/init.h>
32 #include <nn/applet.h>
33
34 #include "demo_Models.h"
35
36 #include "demo.h"
37
38 namespace
39 {
40 const f32 ALPHA_TEST_REF_VALUE = 0.510f; // Alpha test threshold
41 const int MODE_SWITCH_SPAN = 50; // Loop count interval that switches the alpha test mode
42
43 const int MAX_OBJ_NUM = 9;
44
45 u32 s_Count = 1;
46 u32 s_TestFuncMode = 0;
47
48 demo::CubeModel s_CubeObject[MAX_OBJ_NUM];
49
50 GLuint s_ProgramId;
51 GLuint s_ShaderId;
52
53 f32 s_AlphaArray[MAX_OBJ_NUM] =
54 {
55 1.0f, 0.85f, 0.70f,
56 0.55f, 0.51f, 0.501f,
57 0.4f, 0.25f, 0.1f
58 };
59
60 u32 s_AlphaTestFunc[] =
61 {
62 GL_ALWAYS, // Default
63 GL_NEVER,
64 GL_LESS,
65 GL_LEQUAL,
66 GL_EQUAL,
67 GL_GEQUAL,
68 GL_GREATER,
69 GL_NOTEQUAL,
70 };
71
72 char* s_AlphaTestFuncName[] =
73 {
74 "GL_ALWAYS", // Default
75 "GL_NEVER",
76 "GL_LESS",
77 "GL_LEQUAL",
78 "GL_EQUAL",
79 "GL_GEQUAL",
80 "GL_GREATER",
81 "GL_NOTEQUAL"
82 };
83
84 /* ExpHeap for app. */
85 nn::fnd::ExpHeap s_AppHeap;
86 uptr s_AddrForGxHeap;
87 const u32 s_GxHeapSize = 0x400000;
88
89 demo::RenderSystemDrawing s_RenderSystem;
90 }
91
92 #define ALPHA_TEST_FUNC_NUM (sizeof(s_AlphaTestFunc)/sizeof(u32))
93
SetUniforms(void)94 void SetUniforms(void)
95 {
96 // Enable alpha test
97 glUseProgram(s_ProgramId);
98 glUniform1i(glGetUniformLocation(s_ProgramId, "dmp_FragOperation.enableAlphaTest"), GL_TRUE);
99 glUniform1f(glGetUniformLocation(s_ProgramId, "dmp_FragOperation.alphaRefValue"), ALPHA_TEST_REF_VALUE);
100 glUniform1i(glGetUniformLocation(s_ProgramId, "dmp_FragOperation.alphaTestFunc"), s_AlphaTestFunc[s_TestFuncMode]);
101
102 // Texture combiner settings
103 glUniform1i(glGetUniformLocation(s_ProgramId, "dmp_TexEnv[2].combineRgb"), GL_REPLACE);
104 glUniform1i(glGetUniformLocation(s_ProgramId, "dmp_TexEnv[2].combineAlpha"), GL_REPLACE);
105 glUniform3i(glGetUniformLocation(s_ProgramId, "dmp_TexEnv[2].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
106 glUniform3i(glGetUniformLocation(s_ProgramId, "dmp_TexEnv[2].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
107 glUniform3i(glGetUniformLocation(s_ProgramId, "dmp_TexEnv[2].srcRgb"), GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PREVIOUS, GL_PREVIOUS);
108 glUniform3i(glGetUniformLocation(s_ProgramId, "dmp_TexEnv[2].srcAlpha"), GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS);
109
110 // Fragment light settings
111 glUniform1i(glGetUniformLocation(s_ProgramId, "dmp_FragmentLighting.enabled"), GL_TRUE);
112
113 f32 gAmb[] = { 0.3f, 0.3f, 0.3f, 1.0f}; // Global environment light color
114 glUniform4fv(glGetUniformLocation(s_ProgramId, "dmp_FragmentLighting.ambient"), 1, gAmb);
115
116 f32 lAmb[] = { 0.3f, 0.3f, 0.1f, 1.0f}; // Ambient light color for Light 0
117 f32 lDif[] = { 0.7f, 0.7f, 0.2f, 1.0f}; // Diffuse light color for Light 0
118 f32 lPos[] = {15.0f, 15.0f, 0.0f, 0.0f}; // Position in view coordinate system for Light 0
119 glUniform1i(glGetUniformLocation(s_ProgramId, "dmp_FragmentLightSource[0].enabled"), GL_TRUE);
120 glUniform4fv(glGetUniformLocation(s_ProgramId, "dmp_FragmentLightSource[0].ambient"), 1, lAmb);
121 glUniform4fv(glGetUniformLocation(s_ProgramId, "dmp_FragmentLightSource[0].diffuse"), 1, lDif);
122 glUniform4fv(glGetUniformLocation(s_ProgramId, "dmp_FragmentLightSource[0].position"), 1, lPos);
123
124 // Material color settings
125 f32 mAmb[] = {0.3f, 0.0f, 0.0f, 1.0f}; // Ambient light color for the material
126 f32 mDif[] = {0.7f, 0.0f, 0.0f, 1.0f}; // Diffuse light color for the material
127 glUniform4fv(glGetUniformLocation(s_ProgramId, "dmp_FragmentMaterial.ambient"), 1, mAmb);
128 glUniform4fv(glGetUniformLocation(s_ProgramId, "dmp_FragmentMaterial.diffuse"), 1, mDif);
129 }
130
PrintInfo(void)131 void PrintInfo(void)
132 {
133 s_RenderSystem.DrawText(0.0f, 0.0f,
134 "Count: %d", s_Count);
135 s_RenderSystem.DrawText(0.0f, 8.0f,
136 "MODE: %s", s_AlphaTestFuncName[s_TestFuncMode]);
137 s_RenderSystem.DrawText(0.0f, 16.0f,
138 "REF: %.4f", ALPHA_TEST_REF_VALUE);
139
140 for ( u32 j = 0; j<MAX_OBJ_NUM; ++j)
141 {
142 s32 ofs_sx = 300 - (j / 3) * 130;
143 s32 ofs_sy = nn::gx::DISPLAY0_WIDTH - (j % 3) * 80 - 16;
144 s_RenderSystem.DrawText(ofs_sx, ofs_sy,
145 "a = %.4f", s_AlphaArray[j]);
146 }
147 }
148
DrawFrame(void)149 int DrawFrame(void)
150 {
151 glEnable(GL_BLEND);
152 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
153
154 // Switch the alpha test conditions
155 if ((s_Count % MODE_SWITCH_SPAN) == 0)
156 {
157 s_TestFuncMode++;
158 if(s_TestFuncMode >= ALPHA_TEST_FUNC_NUM)
159 {
160 s_TestFuncMode = 0;
161 }
162 }
163
164 nn::math::Matrix44 proj;
165 nn::math::MTX44Perspective(&proj, 45.0f, static_cast<f32>(nn::gx::DISPLAY0_WIDTH)/static_cast<f32>(nn::gx::DISPLAY0_HEIGHT), 0.2f, 100.0f);
166
167 nn::math::Matrix34 mv, rot;
168 nn::math::Vector3 camPos(0.f, 0.f, 18.f);
169 nn::math::Vector3 camUp(0.f, 1.f, 0.f);
170 nn::math::Vector3 target(0.f, 0.f, 0.f);
171 nn::math::Vector3 axis(1.f, 1.f, 0.f);
172
173 nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target);
174 nn::math::MTX34RotAxisDeg(&rot, &axis, static_cast<f32>(s_Count));
175
176 SetUniforms();
177
178 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
179 s_RenderSystem.Clear();
180
181 for ( u32 i = 0; i<MAX_OBJ_NUM; i++)
182 {
183 f32 ofs_x = (i % 3) * 3.0f - 3.0f;
184 f32 ofs_y = (i / 3) * 4.5f - 4.5f;
185
186 nn::math::Matrix34 mvtmp;
187 nn::math::Vector3 trans(ofs_x, ofs_y, 0.f);
188
189 nn::math::MTX34MultTranslate(&mvtmp, &mv, &trans);
190 nn::math::MTX34Mult(&mvtmp, &mvtmp, &rot);
191
192 glUseProgram(s_ProgramId);
193 glUniformMatrix4fv(glGetUniformLocation(s_ProgramId, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
194
195 nn::math::Matrix44 m(mvtmp);
196 glUniformMatrix4fv(glGetUniformLocation(s_ProgramId, "uModelView"), 1, GL_TRUE, static_cast<f32*>(m));
197
198 s_CubeObject[i].Draw();
199 }
200
201 PrintInfo();
202
203 s_RenderSystem.SwapBuffers();
204
205 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
206 s_RenderSystem.Clear();
207 s_RenderSystem.SwapBuffers();
208
209 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
210
211 s_Count++;
212
213 return 1;
214 }
215
216 /* initialization */
Initialize(void)217 int Initialize(void)
218 {
219 nn::fs::Initialize();
220
221 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
222 static char buffer[ROMFS_BUFFER_SIZE];
223 NN_UTIL_PANIC_IF_FAILED(
224 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
225
226 /* Initialize display */
227 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
228 s_AddrForGxHeap = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
229 s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize);
230
231 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
232 glClearDepthf(1.f);
233
234 glEnable(GL_DEPTH_TEST);
235 glDepthFunc(GL_LESS);
236 glEnable(GL_CULL_FACE);
237 glFrontFace(GL_CCW);
238 glCullFace(GL_BACK);
239
240 s_ProgramId = glCreateProgram();
241 s_ShaderId = glCreateShader(GL_VERTEX_SHADER);
242
243 nn::fs::FileReader file(L"rom:/shader.shbin");
244 size_t fileSize = file.GetSize();
245 void* buf = s_AppHeap.Allocate(fileSize);
246
247 s32 read = file.Read(buf, fileSize);
248 glShaderBinary(1, &s_ShaderId, GL_PLATFORM_BINARY_DMP, buf, read);
249 file.Finalize();
250 s_AppHeap.Free(buf);
251
252 glAttachShader(s_ProgramId, s_ShaderId);
253 glAttachShader(s_ProgramId, GL_DMP_FRAGMENT_SHADER_DMP);
254 glBindAttribLocation(s_ProgramId, 0, "aPosition");
255
256 glBindAttribLocation(s_ProgramId, 1, "aNormal");
257 glBindAttribLocation(s_ProgramId, 2, "aColor");
258
259 glLinkProgram(s_ProgramId);
260 glValidateProgram(s_ProgramId);
261
262 for (int i=0; i<MAX_OBJ_NUM; ++i)
263 {
264 s_CubeObject[i].Initialize(demo::ATTR_POSITION | demo::ATTR_NORMAL | demo::ATTR_VERTEX_COLOR,
265 0.0f, 0.0f, 1.0f,
266 s_AlphaArray[i]);
267 }
268
269 s_RenderSystem.SetColor(1.0f, 1.0f, 1.0f, 1.0f);
270
271 return 0;
272 }
273
nnMain(void)274 void nnMain(void)
275 {
276 // Call only nn::applet::Enable to also allow execution from the HOME Menu
277 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
278 nn::applet::Enable();
279
280 /* initialization */
281 if (Initialize() >= 0)
282 {
283 /* Enter loop */
284 while (1)
285 {
286 (void)DrawFrame();
287 }
288 }
289
290 /* shutdown_display (never reached.) */
291 for (int i=0; i<MAX_OBJ_NUM; ++i)
292 {
293 s_CubeObject[i].Finalize();
294 }
295 s_RenderSystem.Finalize();
296 s_AppHeap.Free(reinterpret_cast<void*>(s_AddrForGxHeap));
297 s_AppHeap.Finalize();
298 }
299