1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     GrRenderer.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: $
16  *---------------------------------------------------------------------------*/
17 
18 #define NW_DEBUG_CHECK_MEMORY_LEAK
19 
20 #include "GrRenderer.h"
21 
22 //----------------------------------------------------------
23 void
Initialize(const nn::math::VEC3 & halfEdges)24 PrimitiveBox::Initialize(const nn::math::VEC3& halfEdges)
25 {
26     // 頂点ストリーム(Position)
27     static const f32 s_BoxVtxStreamPosition[PrimitiveBox::VERTEX_NUM * 3] =
28     {
29         -0.5f,  0.5f,  0.5f,   -0.5f,  0.5f, -0.5f,   -0.5f, -0.5f, -0.5f,
30         -0.5f, -0.5f,  0.5f,   -0.5f,  0.5f,  0.5f,   -0.5f, -0.5f, -0.5f,
31          0.5f,  0.5f,  0.5f,   -0.5f,  0.5f,  0.5f,   -0.5f, -0.5f,  0.5f,
32          0.5f, -0.5f,  0.5f,    0.5f,  0.5f,  0.5f,   -0.5f, -0.5f,  0.5f,
33          0.5f,  0.5f, -0.5f,    0.5f,  0.5f,  0.5f,    0.5f, -0.5f, -0.5f,
34          0.5f, -0.5f, -0.5f,    0.5f,  0.5f,  0.5f,    0.5f, -0.5f,  0.5f,
35         -0.5f,  0.5f, -0.5f,    0.5f,  0.5f, -0.5f,   -0.5f, -0.5f, -0.5f,
36          0.5f,  0.5f, -0.5f,    0.5f, -0.5f, -0.5f,   -0.5f, -0.5f, -0.5f,
37         -0.5f, -0.5f, -0.5f,    0.5f, -0.5f, -0.5f,   -0.5f, -0.5f,  0.5f,
38         -0.5f, -0.5f,  0.5f,    0.5f, -0.5f, -0.5f,    0.5f, -0.5f,  0.5f,
39         -0.5f,  0.5f, -0.5f,   -0.5f,  0.5f,  0.5f,    0.5f,  0.5f, -0.5f,
40         -0.5f,  0.5f,  0.5f,    0.5f,  0.5f,  0.5f,    0.5f,  0.5f, -0.5f,
41     };
42 
43     // 頂点ストリーム (Normal)
44     static const f32 s_BoxVtxStreamNormal[PrimitiveBox::VERTEX_NUM * 3] =
45     {
46         -1.f,  0.f,  0.f,  -1.f,  0.f,  0.f,  -1.f,  0.f,  0.f,
47         -1.f,  0.f,  0.f,  -1.f,  0.f,  0.f,  -1.f,  0.f,  0.f,
48          0.f,  0.f,  1.f,   0.f,  0.f,  1.f,   0.f,  0.f,  1.f,
49          0.f,  0.f,  1.f,   0.f,  0.f,  1.f,   0.f,  0.f,  1.f,
50          1.f,  0.f,  0.f,   1.f,  0.f,  0.f,   1.f,  0.f,  0.f,
51          1.f,  0.f,  0.f,   1.f,  0.f,  0.f,   1.f,  0.f,  0.f,
52          0.f,  0.f, -1.f,   0.f,  0.f, -1.f,   0.f,  0.f, -1.f,
53          0.f,  0.f, -1.f,   0.f,  0.f, -1.f,   0.f,  0.f, -1.f,
54          0.f, -1.f,  0.f,   0.f, -1.f,  0.f,   0.f, -1.f,  0.f,
55          0.f, -1.f,  0.f,   0.f, -1.f,  0.f,   0.f, -1.f,  0.f,
56          0.f,  1.f,  0.f,   0.f,  1.f,  0.f,   0.f,  1.f,  0.f,
57          0.f,  1.f,  0.f,   0.f,  1.f,  0.f,   0.f,  1.f,  0.f,
58     };
59 
60     // 頂点ストリーム(Color)
61     static const f32 s_BoxVtxStreamColor[PrimitiveBox::VERTEX_NUM * 4] =
62     {
63         1.0f, 0.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f, 0.0f,
64         1.0f, 0.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f, 0.0f,
65         0.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 1.0f,
66         0.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 1.0f,
67         0.0f, 0.0f, 1.0f, 1.0f,  0.0f, 0.0f, 1.0f, 1.0f,  0.0f, 0.0f, 1.0f, 1.0f,
68         0.0f, 0.0f, 1.0f, 1.0f,  0.0f, 0.0f, 1.0f, 1.0f,  0.0f, 0.0f, 1.0f, 1.0f,
69         1.0f, 1.0f, 0.0f, 0.0f,  1.0f, 1.0f, 0.0f, 0.0f,  1.0f, 1.0f, 0.0f, 0.0f,
70         1.0f, 1.0f, 0.0f, 0.0f,  1.0f, 1.0f, 0.0f, 0.0f,  1.0f, 1.0f, 0.0f, 0.0f,
71         0.0f, 1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f, 1.0f,
72         0.0f, 1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f, 1.0f,
73         1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 1.0f,
74         1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 1.0f
75     } ;
76 
77     // 6 面体の頂点インデックス
78     static const u16 s_BoxVtxStreamIndex[PrimitiveBox::VERTEX_NUM * 1] =
79     {
80         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
81         12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
82         24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
83     };
84 
85     std::memcpy(m_StreamPosition, s_BoxVtxStreamPosition, sizeof(s_BoxVtxStreamPosition));
86 
87 
88     for (u32 index = 0; index < PrimitiveBox::VERTEX_NUM; index++)
89     {
90         m_StreamPosition[3 * index    ] *= halfEdges.x;
91         m_StreamPosition[3 * index + 1] *= halfEdges.y;
92         m_StreamPosition[3 * index + 2] *= halfEdges.z;
93     }
94 
95     std::memcpy(m_StreamNormal, s_BoxVtxStreamNormal, sizeof(s_BoxVtxStreamNormal));
96     std::memcpy(m_StreamColor, s_BoxVtxStreamColor, sizeof(s_BoxVtxStreamColor));
97     std::memcpy(m_StreamIndex, s_BoxVtxStreamIndex, sizeof(s_BoxVtxStreamIndex));
98 
99     nngxUpdateBuffer(this, sizeof(PrimitiveBox));
100 }
101 
102 //----------------------------------------------------------
103 void
Initialize(nw::demo::DemoAllocator * deviceAllocator,const wchar_t * shaderFilePath)104 GrPrimitiveRenderer::Initialize(
105     nw::demo::DemoAllocator* deviceAllocator,
106     const wchar_t* shaderFilePath
107 )
108 {
109     NW_NULL_ASSERT(deviceAllocator);
110     m_DeviceAllocator = deviceAllocator;
111 
112     InitializeShader(shaderFilePath);
113 
114     InitializePrimitive();
115 
116     InitializeEnvironments();
117 }
118 
119 //----------------------------------------------------------
120 void
Finalize()121 GrPrimitiveRenderer::Finalize()
122 {
123     m_VertexBox.DisableAll();
124 
125     m_DeviceAllocator->Free(m_PrimitiveBox);
126     m_DeviceAllocator->Free(m_ShaderBinary);
127 }
128 
129 //----------------------------------------------------------
130 void
InitializeShader(const wchar_t * shaderFilePath)131 GrPrimitiveRenderer::InitializeShader(const wchar_t* shaderFilePath)
132 {
133     bool isSuccess = false;
134     NW_UNUSED_VARIABLE(isSuccess);
135 
136     // シェーダーの初期化
137     nw::ut::MoveArray<u8> shaderFile =
138         nw::demo::Utility::LoadFile(m_DeviceAllocator, shaderFilePath );
139     m_ShaderBinary = shaderFile.release();
140 
141     // シェーダーバイナリを指定して初期化
142     // 0番目の実行イメージを頂点シェーダーとして有効化
143     m_Shader.SetupBinary(m_ShaderBinary, 0, -1);
144 
145     // 文字列で、Uniform を検索
146     isSuccess = m_Shader.SearchBindSymbol(&m_BindSymbolWorldMtx, "world");
147     NW_ASSERT(isSuccess);
148 
149     isSuccess = m_Shader.SearchBindSymbol(&m_BindSymbolProjMtx, "proj");
150     NW_ASSERT(isSuccess);
151 
152     isSuccess = m_Shader.SearchBindSymbol(&m_BindSymbolViewMtx, "view");
153     NW_ASSERT(isSuccess);
154 }
155 
156 //----------------------------------------------------------
157 void
InitializePrimitive()158 GrPrimitiveRenderer::InitializePrimitive()
159 {
160     bool isSuccess = false;
161     NW_UNUSED_VARIABLE(isSuccess);
162 
163     uptr physicalAddr = 0;
164 
165     nn::gr::CTR::BindSymbolVSInput symbolPosition;
166     nn::gr::CTR::BindSymbolVSInput symbolColor;
167     nn::gr::CTR::BindSymbolVSInput symbolNormal;
168 
169     m_PrimitiveBox =
170         static_cast<PrimitiveBox*>(m_DeviceAllocator->Alloc(sizeof(PrimitiveBox), 128));
171     NW_ASSERT(m_PrimitiveBox);
172 
173     const nn::math::VEC3 halfEdges(10.0f, 10.0f, 10.0f);
174 
175     m_PrimitiveBox->Initialize(halfEdges);
176 
177     // 文字列による location の検索
178     isSuccess = m_Shader.SearchBindSymbol(&symbolPosition, "Position");
179     NW_ASSERT(isSuccess);
180 
181     isSuccess = m_Shader.SearchBindSymbol(&symbolColor, "Color");
182     NW_ASSERT(isSuccess);
183 
184     isSuccess = m_Shader.SearchBindSymbol(&symbolNormal, "Normal");
185     NW_ASSERT(isSuccess);
186 
187     // 頂点ストリーム(Position)の設定
188     physicalAddr = nngxGetPhysicalAddr(reinterpret_cast<uptr>(m_PrimitiveBox->m_StreamPosition));
189     m_VertexBox.EnableAttrAsArray(symbolPosition, physicalAddr, PICA_DATA_SIZE_3_FLOAT);
190 
191     // 頂点ストリーム(Color)の設定
192     physicalAddr = nngxGetPhysicalAddr(reinterpret_cast<uptr>(m_PrimitiveBox->m_StreamColor));
193     m_VertexBox.EnableAttrAsArray(symbolColor, physicalAddr, PICA_DATA_SIZE_4_FLOAT);
194 
195     // 頂点ストリーム(Normal)の設定
196     physicalAddr = nngxGetPhysicalAddr(reinterpret_cast<uptr>(m_PrimitiveBox->m_StreamNormal));
197     m_VertexBox.EnableAttrAsArray(symbolNormal, physicalAddr, PICA_DATA_SIZE_3_FLOAT);
198 
199     // インデックスの設定
200     m_IndexStreamBox.physicalAddr = nngxGetPhysicalAddr(reinterpret_cast<uptr>(m_PrimitiveBox->m_StreamIndex));
201     m_IndexStreamBox.drawVtxNum = m_PrimitiveBox->VERTEX_NUM;
202 
203     // インデックスを u16 で定義している
204     m_IndexStreamBox.isUnsignedByte = false;
205 }
206 
207 //----------------------------------------------------------
208 void
InitializeEnvironments()209 GrPrimitiveRenderer::InitializeEnvironments()
210 {
211     m_Viewport.Set(0, 0, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT);
212     m_Scissor.Set(0, 0, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT);
213 }
214 
215 //----------------------------------------------------------
216 bit32*
MakeSceneBeginCommand(bit32 * command)217 GrPrimitiveRenderer::MakeSceneBeginCommand(bit32* command)
218 {
219     command = nn::gr::CTR::MakeDisableAllCommand(command);
220 
221     // ビューポート設定.
222     command = m_Viewport.MakeCommand(command);
223 
224     // シザー設定.
225     command = m_Scissor.MakeCommand(command);
226 
227     // シェーダバイナリの設定 ( glUseProgram() )
228     command = m_Shader.MakeFullCommand(command);
229 
230     // レンダーステートの設定
231     // Cull, Depth, Stencil, AlphaTest, Blend, etc.
232     nn::gr::RenderState render_state;
233     command = render_state.MakeCommand(command);
234 
235     // テクスチャの設定
236     nn::gr::Texture texture;
237     texture.unit0.texType = PICA_DATA_TEXTURE0_SAMPLER_TYPE_FALSE;
238     texture.unit1.texType = PICA_DATA_TEXTURE1_SAMPLER_TYPE_FALSE;
239     texture.unit2.texType = PICA_DATA_TEXTURE2_SAMPLER_TYPE_FALSE;
240     texture.unit3.texType = PICA_DATA_TEXTURE3_SAMPLER_TYPE_FALSE;
241 
242     command = texture.MakeCommand(command);
243 
244     //テクスチャコンバイナの設定
245     nn::gr::Combiner combiner;
246 
247     // テクスチャコンバイナの設定の変更
248     // プライマリカラーで置換
249     combiner.stage[0].rgb.combine       = PICA_DATA_TEX_ENV_COMBINE_REPLACE;
250     combiner.stage[0].rgb.source[0]     = PICA_DATA_TEX_ENV_SRC_RGBA_PRIMARY_COLOR;
251     combiner.stage[0].rgb.source[1]     = PICA_DATA_TEX_ENV_SRC_RGBA_FRAGMENT_SECONDARY_COLOR_DMP;
252     command = combiner.MakeCommand(command);
253 
254     // 頂点を使用し始める前に、全ての頂点属性を無効化
255     command = nn::gr::Vertex::MakeDisableCommand(command);
256 
257     return command;
258 }
259 
260 //----------------------------------------------------------
261 bit32*
MakeDrawBoxCommand(bit32 * command,const nn::math::MTX34 & worldMatrix)262 GrPrimitiveRenderer::MakeDrawBoxCommand(bit32* command, const nn::math::MTX34& worldMatrix)
263 {
264     nn::gr::Vertex*              pVertex      = &m_VertexBox;
265     nn::gr::Vertex::IndexStream* pIndexStream = &m_IndexStreamBox;
266 
267     // モデル行列の設定
268     command = m_BindSymbolWorldMtx.MakeUniformCommand(command, worldMatrix);
269 
270     // Box プリミティブを描画
271 
272     // glBindBuffer( GL_ARRAY_BUFFER )
273     command = pVertex->MakeEnableAttrCommand(command);
274 
275     // glBindBuffer( GL_ELEMENT_ARRAY_BUFFER ) + glDrawElements()
276     command = pVertex->MakeDrawCommand(command, *pIndexStream);
277 
278     return command;
279 }
280