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