1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: SmPrimitive.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 #include <nn/os.h>
18 #include <nn/fs.h>
19
20 #include <nw/types.h>
21 //#include <nw/demo.h>
22 #include <nw/dev.h>
23 #include <nw/gfx.h>
24 #include <nw/ut.h>
25
26 #include "../include/SmDef.h"
27 #include "../include/SmPrimitive.h"
28
29
30 // Singleton
31 SmOgl* s_SmOgl = NULL;
32
33
34 namespace
35 {
36
37 //----------------------------------------
38 // SmOgl の初期化
InitializeSmOgl(const wchar_t * shaderName)39 SmOgl* SmOgl::InitializeSmOgl( const wchar_t* shaderName )
40 {
41 if ( s_SmOgl )
42 {
43 NW_FATAL_ERROR("SmOgl instance is exsit.\n");
44 }
45
46 s_SmOgl = new SmOgl( shaderName );
47 NW_NULL_ASSERT( s_SmOgl );
48
49 return s_SmOgl;
50 }
51
52
53 //----------------------------------------
54 // SmOgl の終了
TerminateSmOgl()55 void SmOgl::TerminateSmOgl()
56 {
57 if ( !s_SmOgl )
58 {
59 NW_FATAL_ERROR("SmOgl instance is not exsit.\n");
60 }
61
62 delete s_SmOgl;
63 s_SmOgl = NULL;
64 }
65
66
67
68 //----------------------------------------
69 // コンストラクタ
SmOgl(const wchar_t * shaderName)70 SmOgl::SmOgl( const wchar_t* shaderName )
71 : m_ProgramID( 0 ),
72 m_ShaderID( 0 )
73 {
74 NW_NULL_ASSERT( shaderName );
75
76 m_ProjectionMatrix.Identity();
77 m_ViewMatrix.Identity();
78
79 if ( s_SmOgl )
80 {
81 NW_FATAL_ERROR("SmOgl instance is exsit.\n");
82 }
83
84 // シェーダファイルをロード
85 if ( !m_ShaderFile.Read( shaderName, m_Allocator ) )
86 {
87 NW_FATAL_ERROR("can not read shader file.");
88 }
89
90 if ( m_ProgramID == 0 )
91 {
92 m_ProgramID = glCreateProgram();
93 }
94
95 if ( m_ShaderID == 0 )
96 {
97 m_ShaderID = glCreateShader( GL_VERTEX_SHADER );
98 }
99
100 glShaderBinary( 1, &m_ShaderID, GL_PLATFORM_BINARY_DMP, m_ShaderFile.Buffer(), m_ShaderFile.Size() );
101 NW_GL_ASSERT();
102
103 glAttachShader( m_ProgramID, m_ShaderID );
104 glAttachShader( m_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP );
105
106 glBindAttribLocation(m_ProgramID, SMP_ATTR_POSITION, "aPosition");
107 glBindAttribLocation(m_ProgramID, SMP_ATTR_COLOR, "aColor");
108 glBindAttribLocation(m_ProgramID, SMP_ATTR_OFFSET, "aOffset");
109
110 glLinkProgram(m_ProgramID);
111 glUseProgram(m_ProgramID);
112
113 glEnableVertexAttribArray( SMP_ATTR_POSITION );
114 glDisableVertexAttribArray( SMP_ATTR_COLOR );
115 glDisableVertexAttribArray( SMP_ATTR_TEXCOORD0 );
116 NW_GL_ASSERT();
117
118 // todo:understand
119 SetupMaterial();
120 SetupTexEnv();
121
122 // インスタンスを登録
123 s_SmOgl = this;
124
125 // 正射影マトリクスの生成
126 {
127 nw::math::MTX44OrthoPivot( &m_ProjectionMatrix, 0.f,
128 SM_LOWER_SCREEN_SIZE_W, SM_LOWER_SCREEN_SIZE_H, 0.f, -100.f, 100.f, nw::math::PIVOT_UPSIDE_TO_TOP);
129 }
130
131 // ビューマトリクス
132 {
133 const nw::math::VEC3 camPos(0.0f, 0.0f, 1.0f);
134 const nw::math::VEC3 aimPos(0.0f, 0.0f, 0.0f);
135 const nw::math::VEC3 camUp(0.0f, 1.0f, 0.0f);
136 nw::math::MTX34LookAt( reinterpret_cast<nw::math::MTX34*>(&m_ViewMatrix), &camPos, &camUp, &aimPos );
137 }
138 }
139
140
141 //----------------------------------------
142 // デストラクタ
~SmOgl()143 SmOgl::~SmOgl()
144 {
145 s_SmOgl = NULL;
146
147 // メモリを解放
148 m_ShaderFile.Release();
149
150 SmStaticCommandCache::DestroyCopiedCmdCache( m_CopiedCmdCache );
151 // todo:glDeleteProgoram 等
152 }
153
154
155 //--------------------------------------------------------------------------
156 void
SetupMaterial()157 SmOgl::SetupMaterial()
158 {
159 glDisable(GL_CULL_FACE);
160 glDisable(GL_DEPTH_TEST);
161 glDisable(GL_STENCIL_TEST);
162 glDisable(GL_BLEND);
163 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
164 }
165
166
167 //--------------------------------------------------------------------------
168 void
SetupTexEnv()169 SmOgl::SetupTexEnv()
170 {
171 glUniform3i(glGetUniformLocation(m_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
172 glUniform3i(glGetUniformLocation(m_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
173 }
174
175
176 //----------------------------------------
177 // 2D エントリ開始
SetBegin2D()178 void SmOgl::SetBegin2D()
179 {
180 if ( !m_CopiedCmdCache.IsCopied() )
181 {
182 // まずはキャッシュを生成
183 SmStaticCommandCache::StartStaticCmdCache( m_SetBeginCmd );
184 {
185 // シェーダプログラム変更
186 glUseProgram(m_ProgramID);
187
188 // ビューやプロジェクションの変更
189 {
190 GLint location;
191
192 location = glGetUniformLocation( m_ProgramID, "uProjection" );
193 glUniform4fv( location, 4, m_ProjectionMatrix );
194
195 location = glGetUniformLocation( m_ProgramID, "uModelView" );
196 glUniform4fv( location, 4, m_ViewMatrix );
197 NW_GL_ASSERT();
198 }
199
200 glDisable(GL_CULL_FACE);
201 glDisable(GL_DEPTH_TEST);
202 glDisable(GL_STENCIL_TEST);
203 glDisable(GL_BLEND);
204 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
205 }
206 SmStaticCommandCache::EndStaticCmdCache( m_SetBeginCmd );
207
208 // キャッシュのコピーを生成
209 SmStaticCommandCache::CreateCopiedCmdCache( m_CopiedCmdCache );
210 }
211
212 // todo:キャッシュに入れると、処理バーが描画されない
213 {
214 // バッファの整理
215 glBindBuffer(GL_ARRAY_BUFFER, 0);
216 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
217
218 // 有効/無効
219 glEnableVertexAttribArray( SmOgl::SMP_ATTR_POSITION );
220 glEnableVertexAttribArray( SmOgl::SMP_ATTR_COLOR );
221 glDisableVertexAttribArray( SmOgl::SMP_ATTR_TEXCOORD0 );
222 }
223
224 // コマンドキャッシュを利用してセット
225 if ( m_CopiedCmdCache.IsCopied() )
226 {
227 SmStaticCommandCache::UseCopiedCmdCache( m_CopiedCmdCache );
228 }
229 }
230
231
232
233
234
235
236
237
238 //----------------------------------------
239 // コンストラクタ
Sm2DPrimPC(uint vertexCnt)240 Sm2DPrimPC::Sm2DPrimPC( uint vertexCnt )
241 : m_pVertex( NULL ),
242 m_VertexCnt( vertexCnt ),
243 m_VertexUpdate( false )
244 {
245 // ASSERT:m_VertexCnt != 0
246 NW_NULL_ASSERT( m_Allocator );
247
248 m_CopiedCmdCache.Init();
249
250 m_pVertex = static_cast<SmVertexPC*>(m_Allocator->Alloc( sizeof( SmVertexPC ) * m_VertexCnt ));
251 NW_NULL_ASSERT( m_pVertex );
252 }
253
254
255 //----------------------------------------
256 // デストラクタ
~Sm2DPrimPC()257 Sm2DPrimPC::~Sm2DPrimPC()
258 {
259 SmStaticCommandCache::DestroyCopiedCmdCache( m_CopiedCmdCache );
260 nw::os::SafeFree( m_pVertex, m_Allocator );
261 }
262
263
264 //----------------------------------------
265 // 現在積まれている頂点で更新する
Update()266 void Sm2DPrimPC::Update()
267 {
268
269 }
270
271
272 //----------------------------------------
273 // 描画
Render(GLenum entryMode,f32 posX,f32 posY)274 void Sm2DPrimPC::Render( GLenum entryMode, f32 posX, f32 posY )
275 {
276 // オフセット位置
277 {
278 nw::math::VEC4 offset;
279 offset.x = posX;
280 offset.y = posY;
281 offset.z = 0.f;
282 offset.w = 0.f;
283 glVertexAttrib4fv( SmOgl::SMP_ATTR_OFFSET, offset );
284 }
285
286 // コマンドキャッシュコピーを生成する
287 if ( m_VertexUpdate )
288 {
289 // まずはキャッシュを生成
290 SmStaticCommandCache::StartStaticCmdCache( m_CmdCache );
291 {
292 RenderSub( entryMode );
293 }
294 SmStaticCommandCache::EndStaticCmdCache( m_CmdCache );
295
296 // 生成済みがあれば破棄
297 if ( m_CopiedCmdCache.IsCopied() )
298 {
299 SmStaticCommandCache::DestroyCopiedCmdCache( m_CopiedCmdCache );
300 }
301
302 // キャッシュのコピーを生成
303 SmStaticCommandCache::CreateCopiedCmdCache( m_CopiedCmdCache );
304
305 m_VertexUpdate = false;
306 }
307
308 // コマンドキャッシュを利用して描画
309 if ( m_CopiedCmdCache.IsCopied() )
310 {
311 SmStaticCommandCache::UseCopiedCmdCache( m_CopiedCmdCache );
312 }
313 else
314 {
315 RenderSub( entryMode );
316 }
317
318 NW_GL_ASSERT();
319 }
320
321
322 //----------------------------------------
323 // 描画 下請け
RenderSub(GLenum entryMode)324 void Sm2DPrimPC::RenderSub( GLenum entryMode )
325 {
326 // 基準のアドレス
327 const u8* basePtr = reinterpret_cast<u8*>(m_pVertex);
328
329 // position
330 glVertexAttribPointer( SmOgl::SMP_ATTR_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(SmVertexPC), basePtr );
331
332 // color
333 glVertexAttribPointer( SmOgl::SMP_ATTR_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(SmVertexPC), basePtr + offsetof(SmVertexPC, color) );
334
335 // draw
336 glDrawArrays( entryMode, 0, m_VertexCnt );
337
338 NW_GL_ASSERT();
339 }
340
341
342 //----------------------------------------
343 // 頂点を登録する
SetVertex(uint vertexIdx,f32 x,f32 y,nw::ut::Color8 color)344 void Sm2DPrimPC::SetVertex( uint vertexIdx, f32 x, f32 y, nw::ut::Color8 color )
345 {
346 NW_ASSERT( m_VertexCnt > vertexIdx );
347
348 m_pVertex[vertexIdx].position.x = x;
349 m_pVertex[vertexIdx].position.y = y;
350
351 m_pVertex[vertexIdx].color = color;
352 }
353
354 //----------------------------------------
355 // 頂点カラーを登録する
SetVertexColor(nw::ut::Color8 color)356 void Sm2DPrimPC::SetVertexColor( nw::ut::Color8 color )
357 {
358 uint i = 0;
359
360 for ( i = 0; i < m_VertexCnt; i ++ )
361 {
362 m_pVertex[i].color = color;
363 }
364 }
365
366
367
368
369 //----------------------------------------
370 // コンストラクタ
Sm2DDynamicPrimPC()371 Sm2DDynamicPrimPC::Sm2DDynamicPrimPC()
372 : m_pPrimitive( NULL ),
373 m_VertexCnt( 0 ),
374 m_EntryCnt( 0 ),
375 m_EntryMode( 0 ),
376 m_OffsetX( 0.f ),
377 m_OffsetY( 0.f ){}
378
379
380 //----------------------------------------
381 // エントリ開始
Begin(uint vertexCnt,GLenum entryMode,f32 posX,f32 posY)382 bool Sm2DDynamicPrimPC::Begin( uint vertexCnt,
383 GLenum entryMode,
384 f32 posX,
385 f32 posY )
386 {
387 if ( m_pPrimitive ) return false;
388 if ( vertexCnt == 0 ) return false;
389
390 m_pPrimitive = new Sm2DPrimPC( vertexCnt );
391 NW_NULL_ASSERT( m_pPrimitive );
392
393 m_EntryCnt = 0;
394 m_VertexCnt = vertexCnt;
395 m_EntryMode = entryMode;
396 m_OffsetX = posX;
397 m_OffsetY = posY;
398
399 return true;
400 }
401
402
403 //----------------------------------------
404 // 頂点を登録する
SetVertex(f32 x,f32 y,nw::ut::Color8 color)405 void Sm2DDynamicPrimPC::SetVertex( f32 x, f32 y, nw::ut::Color8 color )
406 {
407 m_pPrimitive->SetVertex( m_EntryCnt, x, y, color );
408 m_EntryCnt++;
409 }
410
411
412 //----------------------------------------
413 // エントリ終了
End()414 void Sm2DDynamicPrimPC::End()
415 {
416 if ( m_VertexCnt != m_EntryCnt ) return;
417
418 m_pPrimitive->Render( m_EntryMode, m_OffsetX, m_OffsetY );
419
420 delete m_pPrimitive;
421 m_pPrimitive = NULL;
422 }
423
424 } // namespace
425
426
427