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