1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: lyt_Material.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: 25594 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/lyt/lyt_Common.h>
19 #include <nw/lyt/lyt_DrawInfo.h>
20 #include <nw/lyt/lyt_GraphicsResource.h>
21 #include <nw/lyt/lyt_Material.h>
22 #include <nw/lyt/lyt_Layout.h>
23 #include <nw/lyt/lyt_Resources.h>
24 #include <nw/lyt/lyt_Animation.h>
25 #include <nw/lyt/lyt_ResourceAccessor.h>
26 #include <nw/lyt/lyt_Stopwatch.h>
27 #include <nw/lyt/lyt_Util.h>
28
29 #define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
30
31 namespace nw
32 {
33 namespace lyt
34 {
35 namespace
36 {
37
38 const u32 DefaultBlackColor = 0x00000000;
39 const u32 DefaultWhiteColor = 0xffffffff;
40
41 void
InitTexSRT(TexSRT * texSRTs,u32 num)42 InitTexSRT(TexSRT* texSRTs, u32 num)
43 {
44 for (u32 i = 0; i < num; ++i)
45 {
46 texSRTs[i].translate = res::Vec2(0.f, 0.f);
47 texSRTs[i].rotate = 0.f;
48 texSRTs[i].scale = res::Vec2(1.f, 1.f);
49 }
50 }
51
52 u32
CalcOffsetTexSRTAry(const internal::MatMemNums & bitNums)53 CalcOffsetTexSRTAry(const internal::MatMemNums& bitNums)
54 {
55 return sizeof(TexMap) * bitNums.texMap;
56 }
57
58 u32
CalcOffsetTexCoordGenAry(const internal::MatMemNums & bitNums)59 CalcOffsetTexCoordGenAry(const internal::MatMemNums& bitNums)
60 {
61 return CalcOffsetTexSRTAry(bitNums) + sizeof(TexSRT) * bitNums.texSRT;
62 }
63
64 u32
CalcOffsetGetAlphaCompare(const internal::MatMemNums & bitNums)65 CalcOffsetGetAlphaCompare(const internal::MatMemNums& bitNums)
66 {
67 return CalcOffsetTexCoordGenAry(bitNums) + sizeof(TexCoordGen) * bitNums.texCoordGen;
68 }
69
70 u32
CalcOffsetBlendMode(const internal::MatMemNums & bitNums)71 CalcOffsetBlendMode(const internal::MatMemNums& bitNums)
72 {
73 return CalcOffsetGetAlphaCompare(bitNums) + sizeof(AlphaCompare) * bitNums.alpComp;
74 }
75
76 u32
CalcOffsetTevStageAry(const internal::MatMemNums & bitNums)77 CalcOffsetTevStageAry(const internal::MatMemNums& bitNums)
78 {
79 return CalcOffsetBlendMode(bitNums) + sizeof(BlendMode) * bitNums.blendMode;
80 }
81
82 #ifdef NW_LYT_DMPGL_ENABLED
83
84 static void
LoadTexCoordMatrix(GraphicsResource & graphicsResource,int texIdx,f32 (* v)[3])85 LoadTexCoordMatrix(GraphicsResource& graphicsResource, int texIdx, f32 (*v)[3])
86 {
87 NW_MINMAX_ASSERT(texIdx, 0, TexMapMax - 1);
88
89 GLuint program = graphicsResource.GetGlProgram();
90 // 2 x 4 行列をロード。
91 GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_uTexMtx0 + texIdx);
92 glUniform4f(loc + 0, v[0][0], v[0][1], 0.0f, v[0][2]);
93 glUniform4f(loc + 1, v[1][0], v[1][1], 0.0f, v[1][2]);
94 }
95
96 struct TexEnvSetting
97 {
98 u8 /*TevMode*/ m_ModeRgb;
99 u8 /*TevMode*/ m_ModeAlpha;
100 u8 /*TevSrc*/ m_SrcRgb0;
101 u8 /*TevSrc*/ m_SrcRgb1;
102 u8 /*TevSrc*/ m_SrcRgb2;
103 u8 /*TevSrc*/ m_SrcAlpha0;
104 u8 /*TevSrc*/ m_SrcAlpha1;
105 u8 /*TevSrc*/ m_SrcAlpha2;
106 u8 /*TevOpRgb*/ m_OpRgb0;
107 u8 /*TevOpRgb*/ m_OpRgb1;
108 u8 /*TevOpRgb*/ m_OpRgb2;
109 u8 /*TevOpAlp*/ m_OpAlpha0;
110 u8 /*TevOpAlp*/ m_OpAlpha1;
111 u8 /*TevOpAlp*/ m_OpAlpha2;
112 u8 /*TevScale*/ m_ScaleRgb;
113 u8 /*TevScale*/ m_ScaleAlpha;
114
SetTexEnvnw::lyt::__anond1402cc90111::TexEnvSetting115 void SetTexEnv(GraphicsResource& gres, int i) const
116 {
117 internal::GL::SetTevCombineRgb(gres, i, TevMode(m_ModeRgb));
118 internal::GL::SetTevCombineAlpha(gres, i, TevMode(m_ModeAlpha));
119 internal::GL::SetTevSrcRgb(
120 gres,
121 i,
122 TevSrc(m_SrcRgb0),
123 TevSrc(m_SrcRgb1),
124 TevSrc(m_SrcRgb2));
125 internal::GL::SetTevSrcAlpha(
126 gres,
127 i,
128 TevSrc(m_SrcAlpha0),
129 TevSrc(m_SrcAlpha1),
130 TevSrc(m_SrcAlpha2));
131 internal::GL::SetTevOperandRgb(
132 gres,
133 i,
134 TevOpRgb(m_OpRgb0),
135 TevOpRgb(m_OpRgb1),
136 TevOpRgb(m_OpRgb2));
137 internal::GL::SetTevOperandAlpha(
138 gres,
139 i,
140 TevOpAlp(m_OpAlpha0),
141 TevOpAlp(m_OpAlpha1),
142 TevOpAlp(m_OpAlpha2));
143 internal::GL::SetTevScaleRgb(gres, i, TevScale(m_ScaleRgb));
144 internal::GL::SetTevScaleAlpha(gres, i, TevScale(m_ScaleAlpha));
145 }
146 };
147
148 #endif // NW_LYT_DMPGL_ENABLED
149
150 } // namespace nw::lyt::{no-name}
151
Material()152 Material::Material()
153 {
154 Init();
155
156 std::memset(m_Name, 0, sizeof(m_Name));
157 }
158
Material(const res::Material * pRes,const ResBlockSet & resBlockSet)159 Material::Material(
160 const res::Material* pRes,
161 const ResBlockSet& resBlockSet
162 )
163 {
164 Init();
165
166 SetName(pRes->name);
167
168 // constant color
169 for (int i = 0; i < MatColorMax; ++i)
170 {
171 m_Colors[i] = pRes->colors[i];
172 }
173
174 u32 resOffs = sizeof(res::Material);
175
176 const res::TexMap *const pResTexMap = internal::ConvertOffsToPtr<res::TexMap>(pRes, resOffs);
177 resOffs += sizeof(res::TexMap) * pRes->resNum.GetTexMapNum();
178
179 const TexSRT *const pResTexSRTs = internal::ConvertOffsToPtr<TexSRT>(pRes, resOffs);
180 resOffs += sizeof(TexSRT) * pRes->resNum.GetTexSRTNum();
181
182 const TexCoordGen *const pResTexCoordGens = internal::ConvertOffsToPtr<TexCoordGen>(pRes, resOffs);
183 resOffs += sizeof(TexCoordGen) * pRes->resNum.GetTexCoordGenNum();
184
185 const TevStage *const pResTevStages = internal::ConvertOffsToPtr<TevStage>(pRes, resOffs);
186 resOffs += sizeof(TevStage) * pRes->resNum.GetTevStageNum();
187
188 const AlphaCompare *const pResAlphaCompare = internal::ConvertOffsToPtr<AlphaCompare>(pRes, resOffs);
189 resOffs += pRes->resNum.HasAlphaCompare()? sizeof(AlphaCompare) : 0;
190
191 const BlendMode *const pResBlendMode = internal::ConvertOffsToPtr<BlendMode>(pRes, resOffs);
192 resOffs += pRes->resNum.HasBlendMode()? sizeof(BlendMode) : 0;
193
194 const u8 texMapNum = ut::Min(pRes->resNum.GetTexMapNum(), u8(TexMapMax));
195 const u8 texSRTNum = ut::Min(pRes->resNum.GetTexSRTNum(), u8(TexMapMax));
196 const u8 texCoordGenNum = ut::Min(pRes->resNum.GetTexCoordGenNum(), u8(TexMapMax));
197 const u8 tevStageNum = ut::Min(pRes->resNum.GetTevStageNum(), u8(TevStageMax));
198 const bool allocAlpComp = pRes->resNum.HasAlphaCompare();
199 const bool allocBlendMode = pRes->resNum.HasBlendMode();
200
201 ReserveMem(
202 texMapNum,
203 texSRTNum,
204 texCoordGenNum,
205 tevStageNum,
206 allocAlpComp,
207 allocBlendMode);
208
209 this->SetTextureOnly(pRes->resNum.IsTextureOnly());
210
211 if (m_pMem)
212 {
213 // texmap
214 SetTexMapNum(texMapNum);
215 if (texMapNum > 0)
216 {
217 NW_NULL_ASSERT(resBlockSet.pTextureList);
218
219 const res::Texture *const pResTextures = internal::ConvertOffsToPtr<res::Texture>(resBlockSet.pTextureList, sizeof(*resBlockSet.pTextureList));
220 TexMap *const texMaps = GetTexMapAry();
221
222 u8 di = 0;
223 for (u8 si = 0; si < texMapNum; ++si)
224 {
225 int texIdx = pResTexMap[si].texIdx;
226 NW_ASSERT(texIdx < resBlockSet.pTextureList->texNum);
227 const char* fileName = internal::ConvertOffsToPtr<char>(pResTextures, pResTextures[pResTexMap[si].texIdx].nameStrOffset);
228
229 TextureInfo texInfo = resBlockSet.pResAccessor->GetTexture(fileName);
230 texMaps[di].Set(texInfo);
231 texMaps[di].SetWrapMode(pResTexMap[si].GetWarpModeS(), pResTexMap[si].GetWarpModeT());
232 texMaps[di].SetFilter(pResTexMap[si].GetMinFilter(), pResTexMap[si].GetMagFilter());
233 ++di;
234 }
235 }
236
237 // テクスチャSRT
238 TexSRT* texSRTs = GetTexSRTAry();
239 SetTexSRTNum(texSRTNum);
240 for (int i = 0; i < texSRTNum; ++i)
241 {
242 texSRTs[i].translate = pResTexSRTs[i].translate;
243 texSRTs[i].rotate = pResTexSRTs[i].rotate;
244 texSRTs[i].scale = pResTexSRTs[i].scale;
245 }
246
247 // テクスチャ座標生成
248 TexCoordGen* texCoordGens = GetTexCoordGenAry();
249 SetTexCoordGenNum(texCoordGenNum);
250 for (unsigned int i = 0; i < m_MemNum.texCoordGen; ++i)
251 {
252 texCoordGens[i] = pResTexCoordGens[i];
253 }
254
255 if (tevStageNum > 0)
256 {
257 SetTevStageNum(tevStageNum);
258 TevStage *const tevStages = GetTevStageAry();
259 for (int i = 0; i < tevStageNum; ++i)
260 {
261 tevStages[i] = pResTevStages[i];
262 }
263 }
264
265 if (allocAlpComp)
266 {
267 NW_ASSERT(IsAlphaCompareCap());
268 *GetAlphaComparePtr() = *pResAlphaCompare;
269 }
270
271 if (allocBlendMode)
272 {
273 NW_ASSERT(IsBlendModeCap());
274 *GetBlendModePtr() = *pResBlendMode;
275 }
276 }
277 }
278
279 void
Init()280 Material::Init()
281 {
282 m_Colors[INTERPOLATECOLOR_BLACK] = ut::Color8(DefaultBlackColor);
283 m_Colors[INTERPOLATECOLOR_WHITE] = ut::Color8(DefaultWhiteColor);
284 m_Colors[2] = DefaultWhiteColor;
285
286 InitMatMemNums(&m_MemCap);
287 InitMatMemNums(&m_MemNum);
288
289 m_Flag = 0;
290
291 m_pMem = 0;
292 }
293
~Material()294 Material::~Material()
295 {
296 // OSReport("Material::~Material()\n");
297
298 UnbindAllAnimation();
299
300 if (m_pMem)
301 {
302 Layout::FreeMemory(m_pMem);
303 m_pMem = 0;
304 }
305 }
306
307 void
InitMatMemNums(internal::MatMemNums * ptr)308 Material::InitMatMemNums(internal::MatMemNums* ptr)
309 {
310 ptr->texMap = 0;
311 ptr->texSRT = 0;
312 ptr->texCoordGen = 0;
313 ptr->tevStage = 0;
314 ptr->alpComp = 0;
315 ptr->blendMode = 0;
316 }
317
318 void
ReserveMem(u8 texMapNum,u8 texSRTNum,u8 texCoordGenNum,u8 tevStageNum,bool allocAlpComp,bool allocBlendMode)319 Material::ReserveMem(
320 u8 texMapNum,
321 u8 texSRTNum,
322 u8 texCoordGenNum,
323 u8 tevStageNum,
324 bool allocAlpComp,
325 bool allocBlendMode
326 )
327 {
328 NW_ASSERT(texMapNum <= TexMapMax);
329 NW_ASSERT(texSRTNum <= TexMapMax);
330 NW_ASSERT(texCoordGenNum <= TexMapMax);
331 NW_ASSERT(tevStageNum <= TevStageMax);
332
333 const unsigned int alpCompNum = allocAlpComp ? 1: 0;
334 const unsigned int blendModeNum = allocBlendMode ? 1: 0;
335
336 // いずれかが要求しているサイズのほうが大きい場合
337 if ( m_MemCap.texMap < texMapNum
338 || m_MemCap.texSRT < texSRTNum
339 || m_MemCap.texCoordGen < texCoordGenNum
340 || m_MemCap.tevStage < tevStageNum
341 || m_MemCap.alpComp < alpCompNum
342 || m_MemCap.blendMode < blendModeNum
343 )
344 {
345 if (m_pMem)
346 {
347 Layout::FreeMemory(m_pMem);
348 m_pMem = 0;
349
350 InitMatMemNums(&m_MemCap);
351 InitMatMemNums(&m_MemNum);
352 }
353
354 m_pMem = Layout::AllocMemory(
355 sizeof(TexMap) * texMapNum +
356 sizeof(TexSRT) * texSRTNum +
357 sizeof(TexCoordGen) * texCoordGenNum +
358 sizeof(AlphaCompare) * alpCompNum +
359 sizeof(BlendMode) * blendModeNum +
360 sizeof(TevStage) * tevStageNum);
361
362 if (m_pMem)
363 {
364 m_MemCap.texMap = texMapNum;
365 m_MemCap.texSRT = texSRTNum;
366 m_MemCap.texCoordGen = texCoordGenNum;
367 m_MemCap.tevStage = tevStageNum;
368 m_MemCap.alpComp = alpCompNum;
369 m_MemCap.blendMode = blendModeNum;
370
371 m_MemNum.texSRT = m_MemCap.texSRT;
372 InitTexSRT(GetTexSRTAry(), m_MemNum.texSRT);
373
374 m_MemNum.alpComp = m_MemCap.alpComp;
375 if (m_MemNum.alpComp)
376 {
377 *GetAlphaComparePtr() = AlphaCompare();
378 }
379
380 m_MemNum.blendMode = m_MemCap.blendMode;
381 if (m_MemNum.blendMode)
382 {
383 *GetBlendModePtr() = BlendMode();
384 }
385 }
386 }
387 }
388
389 const TexMap*
GetTexMapAry() const390 Material::GetTexMapAry() const
391 {
392 return internal::ConvertOffsToPtr<TexMap>(m_pMem, 0);
393 }
394
395 TexMap*
GetTexMapAry()396 Material::GetTexMapAry()
397 {
398 return internal::ConvertOffsToPtr<TexMap>(m_pMem, 0);
399 }
400
401 const TexSRT*
GetTexSRTAry() const402 Material::GetTexSRTAry() const
403 {
404 return internal::ConvertOffsToPtr<TexSRT>(m_pMem, CalcOffsetTexSRTAry(m_MemCap));
405 }
406
407 TexSRT*
GetTexSRTAry()408 Material::GetTexSRTAry()
409 {
410 return internal::ConvertOffsToPtr<TexSRT>(m_pMem, CalcOffsetTexSRTAry(m_MemCap));
411 }
412
413 const TexCoordGen*
GetTexCoordGenAry() const414 Material::GetTexCoordGenAry() const
415 {
416 return internal::ConvertOffsToPtr<TexCoordGen>(m_pMem, CalcOffsetTexCoordGenAry(m_MemCap));
417 }
418
419 TexCoordGen*
GetTexCoordGenAry()420 Material::GetTexCoordGenAry()
421 {
422 return internal::ConvertOffsToPtr<TexCoordGen>(m_pMem, CalcOffsetTexCoordGenAry(m_MemCap));
423 }
424
425 const AlphaCompare*
GetAlphaComparePtr() const426 Material::GetAlphaComparePtr() const
427 {
428 return internal::ConvertOffsToPtr<AlphaCompare>(m_pMem, CalcOffsetGetAlphaCompare(m_MemCap));
429 }
430
431 AlphaCompare*
GetAlphaComparePtr()432 Material::GetAlphaComparePtr()
433 {
434 return internal::ConvertOffsToPtr<AlphaCompare>(m_pMem, CalcOffsetGetAlphaCompare(m_MemCap));
435 }
436
437 const BlendMode*
GetBlendModePtr() const438 Material::GetBlendModePtr() const
439 {
440 return internal::ConvertOffsToPtr<BlendMode>(m_pMem, CalcOffsetBlendMode(m_MemCap));
441 }
442
443 BlendMode*
GetBlendModePtr()444 Material::GetBlendModePtr()
445 {
446 return internal::ConvertOffsToPtr<BlendMode>(m_pMem, CalcOffsetBlendMode(m_MemCap));
447 }
448
449 const TevStage*
GetTevStageAry() const450 Material::GetTevStageAry() const
451 {
452 return internal::ConvertOffsToPtr<TevStage>(m_pMem, CalcOffsetTevStageAry(m_MemCap));
453 }
454
455 TevStage*
GetTevStageAry()456 Material::GetTevStageAry()
457 {
458 return internal::ConvertOffsToPtr<TevStage>(m_pMem, CalcOffsetTevStageAry(m_MemCap));
459 }
460
461 void
SetName(const char * name)462 Material::SetName(const char* name)
463 {
464 ut::strcpy(m_Name, sizeof(m_Name), name);
465 }
466
467 void
SetTexMapNum(u8 num)468 Material::SetTexMapNum(u8 num)
469 {
470 NW_ASSERT(num <= m_MemCap.texMap);
471 if (num > 0)
472 {
473 NW_NULL_ASSERT(m_pMem);
474
475 TexMap *const texMaps = GetTexMapAry();
476 for (u32 i = m_MemNum.texMap; i < num; ++i)
477 {
478 new (&texMaps[i]) TexMap(); // コンストラクタ呼び出し
479 }
480 }
481
482 m_MemNum.texMap = num;
483
484 this->SetTextureDirty();
485 }
486
487 void
SetTexSRTNum(u8 num)488 Material::SetTexSRTNum(u8 num)
489 {
490 NW_ASSERT(num <= m_MemCap.texSRT);
491 if (num > 0)
492 {
493 NW_NULL_ASSERT(m_pMem);
494
495 TexSRT *const texSRTs = GetTexSRTAry();
496 for (u32 i = m_MemNum.texSRT; i < num; ++i)
497 {
498 new (&texSRTs[i]) TexSRT(); // コンストラクタ呼び出し
499 }
500 }
501
502 m_MemNum.texSRT = num;
503
504 this->SetTextureDirty();
505 }
506
507 void
SetTexCoordGenNum(u8 num)508 Material::SetTexCoordGenNum(u8 num)
509 {
510 NW_ASSERT(num <= m_MemCap.texCoordGen);
511 if (num > 0)
512 {
513 NW_NULL_ASSERT(m_pMem);
514
515 TexCoordGen *const texCoordGens = GetTexCoordGenAry();
516 for (u32 i = m_MemNum.texCoordGen; i < num; ++i)
517 {
518 new (&texCoordGens[i]) TexCoordGen(); // コンストラクタ呼び出し
519 }
520 }
521
522 m_MemNum.texCoordGen = num;
523
524 this->SetTextureDirty();
525 }
526
527 void
SetTevStageNum(u8 num)528 Material::SetTevStageNum(u8 num)
529 {
530 NW_ASSERT(num <= m_MemCap.tevStage);
531 if (num > 0)
532 {
533 NW_NULL_ASSERT(m_pMem);
534
535 TevStage *const tevStages = GetTevStageAry();
536 for (u32 i = m_MemNum.tevStage; i < num; ++i)
537 {
538 new (&tevStages[i]) TevStage(); // コンストラクタ呼び出し
539 }
540 }
541
542 m_MemNum.tevStage = num;
543 }
544
545 u8
GetColorElement(u32 colorType) const546 Material::GetColorElement(u32 colorType) const
547 {
548 NW_COMPILER_ASSERT(ANIMTARGET_MATCOLOR_MAX / 4 == MatColorMax);
549
550 if (colorType < ANIMTARGET_MATCOLOR_MAX)
551 {
552 const u32 idx = (colorType - ANIMTARGET_MATCOLOR_BUFFER_R) / 4;
553 switch ((colorType - ANIMTARGET_MATCOLOR_BUFFER_R) % 4)
554 {
555 case 0: return m_Colors[idx].r;
556 case 1: return m_Colors[idx].g;
557 case 2: return m_Colors[idx].b;
558 case 3: return m_Colors[idx].a;
559 }
560 }
561
562 return ut::Color8::ELEMENT_MAX;
563 }
564
565 void
SetColorElement(u32 colorType,u8 value)566 Material::SetColorElement(u32 colorType, u8 value)
567 {
568 if (colorType < ANIMTARGET_MATCOLOR_MAX)
569 {
570 NW_COMPILER_ASSERT(ANIMTARGET_MATCOLOR_MAX / 4 == MatColorMax);
571
572 const u32 idx = (colorType - ANIMTARGET_MATCOLOR_BUFFER_R) / 4;
573 switch ((colorType - ANIMTARGET_MATCOLOR_BUFFER_R) % 4)
574 {
575 case 0: m_Colors[idx].r = value; break;
576 case 1: m_Colors[idx].g = value; break;
577 case 2: m_Colors[idx].b = value; break;
578 case 3: m_Colors[idx].a = value; break;
579 }
580 }
581 }
582
583 #ifdef NW_LYT_DMPGL_ENABLED
584 void
SetupGraphics(const DrawInfo & drawInfo,u8 alpha,bool bInitFrameTransform)585 Material::SetupGraphics(
586 const DrawInfo& drawInfo,
587 u8 alpha,
588 bool bInitFrameTransform
589 )
590 {
591 NW_LYT_STOPWATCH_MEASURE(-210, "nw::lyt::Material::SetupGraphics");
592
593 NW_GL_ASSERT();
594
595 Layout* layout = drawInfo.GetLayout();
596 GraphicsResource& graphicsResource = *drawInfo.GetGraphicsResource();
597
598 if (!this->GetTextureOnly())
599 {
600 GLuint program = graphicsResource.GetGlProgram();
601
602 graphicsResource.UseProgram(program);
603 NW_GL_ASSERT();
604
605 // 頂点カラーを[0, 1]に正規化するためのスケールです。
606 f32 scale = 1.0f / 255.0f;
607
608 if (bInitFrameTransform)
609 {
610 GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_uFrameSpec);
611 glUniform4f(loc, (f32)TEXTUREFLIP_NONE, 0.0f, 0.0f, 0.0f);
612 NW_GL_ASSERT();
613 }
614
615 // 頂点カラーへ積算するカラーを設定します。
616 glUniform4f(
617 graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_uColor),
618 scale * 1.0f,
619 scale * 1.0f,
620 scale * 1.0f,
621 scale * scale * alpha);
622
623 if (m_MemNum.texCoordGen > 0)
624 {
625 u32 i = 0;
626 const u32 num = ut::Min(m_MemNum.texCoordGen, u32(TexMapMax));
627 for (; i < num; ++i)
628 {
629 const TexCoordGen& texCoordGen = this->GetTexCoordGen(i);
630 graphicsResource.SetTexCoordSrc(int(i), texCoordGen.GetTexGenSrc());
631 }
632 for (; i < TexMapMax; ++i)
633 {
634 graphicsResource.SetTexCoordSrc(int(i), -1);
635 }
636 }
637 NW_GL_ASSERT();
638 }
639
640 // テクスチャ行列
641 if (m_MemNum.texSRT > 0)
642 {
643 const u32 num = ut::Min(ut::Min(m_MemNum.texSRT, u32(this->GetTexMapNum())), u32(TexMapMax));
644 for (u32 i = 0; i < num; ++i)
645 {
646 const TexSRT& texSRT = this->GetTexSRT(i);
647 const TexMap& texMap = this->GetTexMap(i);
648
649 math::MTX23 texMtx;
650 lyt::CalcTextureMtx(&texMtx, texSRT, texMap);
651
652 LoadTexCoordMatrix(graphicsResource, i, texMtx.m);
653 }
654 }
655 NW_GL_ASSERT();
656
657 // テクスチャ
658 if (m_MemNum.texMap > 0)
659 {
660 static const GLint wrapMode[] =
661 {
662 GL_CLAMP_TO_EDGE,
663 GL_REPEAT,
664 GL_MIRRORED_REPEAT,
665 };
666 NW_COMPILER_ASSERT(ARRAY_LENGTH(wrapMode) == TEXWRAP_MAX);
667
668 u32 i = 0;
669 const u32 num = ut::Min(m_MemNum.texMap, u32(TexMapMax));
670 for (; i < num; ++i)
671 {
672 const TexMap& texMap = this->GetTexMap(i);
673
674 NW_ASSERTMSG(texMap.GetTextureObject() != TextureInfo::INVALID, "DMPGL texture-object is not created. Use Layout::SetLayoutDrawEnable(true)");
675
676 glActiveTexture(GL_TEXTURE0 + i);
677 glBindTexture(GL_TEXTURE_2D, texMap.GetTextureObject());
678 internal::GL::SetTextureSamplerType(graphicsResource, i, GL_TEXTURE_2D);
679 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode[texMap.GetWrapModeS()]);
680 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode[texMap.GetWrapModeT()]);
681 internal::GL::SetTexMinFilter(graphicsResource, texMap.GetMinFilter());
682 internal::GL::SetTexMagFilter(graphicsResource, texMap.GetMagFilter());
683
684 if (i == 0)
685 {
686 GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_uRcpTexSize0);
687 glUniform4f(loc, 1.0f / texMap.GetWidth(), 1.0f / texMap.GetHeight(), 0.0f, 0.0f);
688 NW_GL_ASSERT();
689 }
690
691 // 固定設定
692 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0f);
693 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, -1000);
694 NW_GL_ASSERT();
695 }
696
697 // 使わないテクスチャを無効化。
698 for (; i < internal::TexUnitMax; ++i)
699 {
700 internal::GL::SetTextureSamplerType(graphicsResource, i, GL_FALSE);
701 NW_GL_ASSERT();
702 }
703 }
704
705 // TEV
706 if (!this->GetTextureOnly())
707 {
708 // Buffer = Black
709 internal::GL::SetTevBufferColor(graphicsResource, this->GetColor(TEVKONSTSEL_BUFFER));
710
711 u32 i = 0;
712 if (m_MemNum.tevStage > 0)
713 {
714 graphicsResource.SetTexEnvAuto(false);
715
716 for (; i < ut::Min(m_MemNum.tevStage, (u32)internal::TexEnvUnitMax); ++i)
717 {
718 const TevStage& tevStage = this->GetTevStage(i);
719 internal::GL::SetTevCombineRgb(graphicsResource, i, tevStage.GetCombineRgb());
720 NW_GL_ASSERT();
721 internal::GL::SetTevCombineAlpha(graphicsResource, i, tevStage.GetCombineAlpha());
722 NW_GL_ASSERT();
723 internal::GL::SetTevSrcRgb(graphicsResource, i, tevStage.GetSrcRgb0(), tevStage.GetSrcRgb1(), tevStage.GetSrcRgb2());
724 NW_GL_ASSERT();
725 internal::GL::SetTevSrcAlpha(graphicsResource, i, tevStage.GetSrcAlpha0(), tevStage.GetSrcAlpha1(), tevStage.GetSrcAlpha2());
726 NW_GL_ASSERT();
727 internal::GL::SetTevOperandRgb(graphicsResource, i, tevStage.GetOperandRgb0(), tevStage.GetOperandRgb1(), tevStage.GetOperandRgb2());
728 NW_GL_ASSERT();
729 internal::GL::SetTevOperandAlpha(graphicsResource, i, tevStage.GetOperandAlpha0(), tevStage.GetOperandAlpha1(), tevStage.GetOperandAlpha2());
730 NW_GL_ASSERT();
731 internal::GL::SetTevScaleRgb(graphicsResource, i, tevStage.GetScaleRgb());
732 NW_GL_ASSERT();
733 internal::GL::SetTevScaleAlpha(graphicsResource, i, tevStage.GetScaleAlpha());
734 NW_GL_ASSERT();
735 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(tevStage.GetKonstSelRgb()), this->GetColor(tevStage.GetKonstSelAlpha()));
736 NW_GL_ASSERT();
737 if (0 < i && i <= 4)
738 {
739 internal::GL::SetTevBufferInput(graphicsResource, i, tevStage.GetSavePrevRgb(), tevStage.GetSavePrevAlpha());
740 }
741 }
742 }
743 else
744 {
745 // 以前の設定がそのまま使えるか調べる。
746 bool setTexEnv = !graphicsResource.GetTexEnvAuto() ||
747 graphicsResource.GetNumTexMap() != m_MemNum.texMap;
748
749 graphicsResource.SetTexEnvAuto(true, m_MemNum.texMap);
750
751 switch (m_MemNum.texMap)
752 {
753 case 0:
754 // 白補間とラスタライズカラー
755
756 // Constant_0 = White
757 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K0));
758 // Output_0 = Modulate(Constant, Primary)
759 if (setTexEnv)
760 {
761 static const TexEnvSetting setting =
762 {
763 TEVMODE_MODULATE,
764 TEVMODE_MODULATE,
765 TEVSRC_CONSTANT, TEVSRC_PRIMARY, TEVSRC_PRIMARY,
766 TEVSRC_CONSTANT, TEVSRC_PRIMARY, TEVSRC_PRIMARY,
767 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
768 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
769 TEVSCALE_1,
770 TEVSCALE_1,
771 };
772
773 setting.SetTexEnv(graphicsResource, i);
774 }
775
776 NW_GL_ASSERT();
777 ++i;
778 break;
779
780 case 1:
781 // テクスチャと白黒カラーによる補間
782 #ifdef NW_TARGET_CTR_GL_FINAL
783 // Output_0 = Replace(Texture_0)
784 if (setTexEnv)
785 {
786 static const TexEnvSetting setting =
787 {
788 TEVMODE_REPLACE,
789 TEVMODE_REPLACE,
790 TEVSRC_TEXTURE0, TEVSRC_TEXTURE0, TEVSRC_TEXTURE0,
791 TEVSRC_TEXTURE0, TEVSRC_TEXTURE0, TEVSRC_TEXTURE0,
792 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
793 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
794 TEVSCALE_1,
795 TEVSCALE_1,
796 };
797
798 setting.SetTexEnv(graphicsResource, i);
799 }
800
801 NW_GL_ASSERT();
802 ++i;
803
804 // Constant_1 = White
805 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K0));
806 NW_GL_ASSERT();
807 // Output_1 = Interpolate(Constant, PreviousBuffer, Previous)
808 if (setTexEnv)
809 {
810 static const TexEnvSetting setting =
811 {
812 TEVMODE_INTERPOLATE,
813 TEVMODE_INTERPOLATE,
814 TEVSRC_CONSTANT, TEVSRC_PREVIOUS_BUFFER, TEVSRC_PREVIOUS,
815 TEVSRC_CONSTANT, TEVSRC_PREVIOUS_BUFFER, TEVSRC_PREVIOUS,
816 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
817 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
818 TEVSCALE_1,
819 TEVSCALE_1,
820 };
821
822 setting.SetTexEnv(graphicsResource, i);
823 }
824
825 NW_GL_ASSERT();
826 ++i;
827
828 // Output_2 = Modulate(Primary, Previous)
829 if (setTexEnv)
830 {
831 static const TexEnvSetting setting =
832 {
833 TEVMODE_MODULATE,
834 TEVMODE_MODULATE,
835 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
836 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
837 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
838 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
839 TEVSCALE_1,
840 TEVSCALE_1,
841 };
842
843 setting.SetTexEnv(graphicsResource, i);
844 }
845 NW_GL_ASSERT();
846 ++i;
847
848 #else
849 // Constant_0 = White
850 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K0));
851 // Output_0 = Modulate(White, Texture0)
852 if (setTexEnv)
853 {
854 static const TexEnvSetting setting =
855 {
856 TEVMODE_MODULATE,
857 TEVMODE_MODULATE,
858 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_TEXTURE0,
859 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_TEXTURE0,
860 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
861 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
862 TEVSCALE_1,
863 TEVSCALE_1,
864 };
865
866 setting.SetTexEnv(graphicsResource, i);
867 }
868
869 NW_GL_ASSERT();
870 ++i;
871
872 // Constant_1 = Black
873 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_BUFFER));
874 // Output_1 = MultAdd(Constant, 1-Texture_0, Previous)
875 if (setTexEnv)
876 {
877 static const TexEnvSetting setting =
878 {
879 TEVMODE_MULT_ADD,
880 TEVMODE_MULT_ADD,
881 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_PREVIOUS,
882 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_PREVIOUS,
883 TEVOPRGB_RGB, TEVOPRGB_INV_RGB, TEVOPRGB_RGB,
884 TEVOPALP_ALPHA, TEVOPALP_INV_ALPHA, TEVOPALP_ALPHA,
885 TEVSCALE_1,
886 TEVSCALE_1,
887 };
888
889 setting.SetTexEnv(graphicsResource, i);
890 }
891
892 NW_GL_ASSERT();
893 ++i;
894
895 // Output_2 = Modulate(Primary, Previous)
896 if (setTexEnv)
897 {
898 static const TexEnvSetting setting =
899 {
900 TEVMODE_MODULATE,
901 TEVMODE_MODULATE,
902 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
903 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
904 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
905 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
906 TEVSCALE_1,
907 TEVSCALE_1,
908 };
909
910 setting.SetTexEnv(graphicsResource, i);
911 }
912
913 NW_GL_ASSERT();
914 ++i;
915 #endif
916 break;
917
918 case 2:
919 // テクスチャ2枚と白黒カラーによる補間
920 #ifdef NW_TARGET_CTR_GL_FINAL
921 // Constant_0 = Blend
922 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K5));
923 // Output_0 = Modulate(Constant_a, Texture_0)
924 if (setTexEnv)
925 {
926 static const TexEnvSetting setting =
927 {
928 TEVMODE_MODULATE,
929 TEVMODE_MODULATE,
930 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_CONSTANT,
931 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_CONSTANT,
932 TEVOPRGB_ALPHA, TEVOPRGB_RGB, TEVOPRGB_RGB,
933 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
934 TEVSCALE_1,
935 TEVSCALE_1,
936 };
937
938 setting.SetTexEnv(graphicsResource, i);
939 }
940
941 NW_GL_ASSERT();
942 ++i;
943
944 // Constant_1 = Blend
945 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K5));
946 // Output_1 = MultAdd(1 - Constant_a, Texture_1, Previous)
947 if (setTexEnv)
948 {
949 static const TexEnvSetting setting =
950 {
951 TEVMODE_MULT_ADD,
952 TEVMODE_MULT_ADD,
953 TEVSRC_CONSTANT, TEVSRC_TEXTURE1, TEVSRC_PREVIOUS,
954 TEVSRC_CONSTANT, TEVSRC_TEXTURE1, TEVSRC_PREVIOUS,
955 TEVOPRGB_INV_ALPHA, TEVOPRGB_RGB, TEVOPRGB_RGB,
956 TEVOPALP_INV_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
957 TEVSCALE_1,
958 TEVSCALE_1,
959 };
960
961 setting.SetTexEnv(graphicsResource, i);
962 internal::GL::SetTevBufferInput(graphicsResource, i, false, false);
963 }
964
965 NW_GL_ASSERT();
966 ++i;
967
968 // Constant_2 = White
969 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K0));
970 // Output_2 = Interpolate(Constant, PreviousBuffer, Previous)
971 if (setTexEnv)
972 {
973 static const TexEnvSetting setting =
974 {
975 TEVMODE_INTERPOLATE,
976 TEVMODE_INTERPOLATE,
977 TEVSRC_CONSTANT, TEVSRC_PREVIOUS_BUFFER, TEVSRC_PREVIOUS,
978 TEVSRC_CONSTANT, TEVSRC_PREVIOUS_BUFFER, TEVSRC_PREVIOUS,
979 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
980 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
981 TEVSCALE_1,
982 TEVSCALE_1,
983 };
984
985 setting.SetTexEnv(graphicsResource, i);
986 }
987
988 NW_GL_ASSERT();
989 ++i;
990
991 // Output_3 = Modulate(Primary, Previous)
992 if (setTexEnv)
993 {
994 static const TexEnvSetting setting =
995 {
996 TEVMODE_MODULATE,
997 TEVMODE_MODULATE,
998 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
999 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1000 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1001 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1002 TEVSCALE_1,
1003 TEVSCALE_1,
1004 };
1005
1006 setting.SetTexEnv(graphicsResource, i);
1007 }
1008
1009 NW_GL_ASSERT();
1010 ++i;
1011
1012 #else
1013 // Constant_0.a = Blend0
1014 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K5));
1015 // Output_0 = Interpolate(Texture_0, Texture_1, Constant.a)
1016 if (setTexEnv)
1017 {
1018 static const TexEnvSetting setting =
1019 {
1020 TEVMODE_INTERPOLATE,
1021 TEVMODE_INTERPOLATE,
1022 TEVSRC_TEXTURE0, TEVSRC_TEXTURE1, TEVSRC_CONSTANT,
1023 TEVSRC_TEXTURE0, TEVSRC_TEXTURE1, TEVSRC_CONSTANT,
1024 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_ALPHA,
1025 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1026 TEVSCALE_1,
1027 TEVSCALE_1,
1028 };
1029
1030 setting.SetTexEnv(graphicsResource, i);
1031 }
1032
1033 NW_GL_ASSERT();
1034 ++i;
1035
1036 // Constant_1 = White
1037 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K0));
1038 // Output_1 = Modulate(Constant, Previous)
1039 if (setTexEnv)
1040 {
1041 static const TexEnvSetting setting =
1042 {
1043 TEVMODE_MODULATE,
1044 TEVMODE_MODULATE,
1045 TEVSRC_CONSTANT, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1046 TEVSRC_CONSTANT, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1047 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1048 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1049 TEVSCALE_1,
1050 TEVSCALE_1,
1051 };
1052
1053 setting.SetTexEnv(graphicsResource, i);
1054 }
1055
1056 NW_GL_ASSERT();
1057 ++i;
1058
1059 // Output_2 = Modulate(Primary, Previous)
1060 if (setTexEnv)
1061 {
1062 static const TexEnvSetting setting =
1063 {
1064 TEVMODE_MODULATE,
1065 TEVMODE_MODULATE,
1066 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1067 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1068 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1069 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1070 TEVSCALE_1,
1071 TEVSCALE_1,
1072 };
1073
1074 setting.SetTexEnv(graphicsResource, i);
1075 }
1076
1077 NW_GL_ASSERT();
1078 ++i;
1079 #endif
1080 break;
1081
1082 case 3:
1083 #ifdef NW_TARGET_CTR_GL_FINAL
1084 // Constant_0 = Konst_5
1085 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K5));
1086 // Output_0 = Modulate(Constant_a, Texture_0)
1087 if (setTexEnv)
1088 {
1089 static const TexEnvSetting setting =
1090 {
1091 TEVMODE_MODULATE,
1092 TEVMODE_MODULATE,
1093 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_CONSTANT,
1094 TEVSRC_CONSTANT, TEVSRC_TEXTURE0, TEVSRC_CONSTANT,
1095 TEVOPRGB_ALPHA, TEVOPRGB_RGB, TEVOPRGB_RGB,
1096 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1097 TEVSCALE_1,
1098 TEVSCALE_1,
1099 };
1100
1101 setting.SetTexEnv(graphicsResource, i);
1102 }
1103
1104 NW_GL_ASSERT();
1105 ++i;
1106
1107 // Constant_1 = Konst_5
1108 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K5));
1109 // Output_1 = MultAdd(Constant_b, Texture_1, Previous)
1110 if (setTexEnv)
1111 {
1112 static const TexEnvSetting setting =
1113 {
1114 TEVMODE_MULT_ADD,
1115 TEVMODE_MULT_ADD,
1116 TEVSRC_CONSTANT, TEVSRC_TEXTURE1, TEVSRC_PREVIOUS,
1117 TEVSRC_CONSTANT, TEVSRC_TEXTURE1, TEVSRC_PREVIOUS,
1118 TEVOPRGB_BBB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1119 TEVOPALP_B, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1120 TEVSCALE_1,
1121 TEVSCALE_1,
1122 };
1123 setting.SetTexEnv(graphicsResource, i);
1124 internal::GL::SetTevBufferInput(graphicsResource, i, false, false);
1125 }
1126
1127 NW_GL_ASSERT();
1128 ++i;
1129
1130 // Constant_2 = Konst_5
1131 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K5));
1132 // Output_2 = MultAdd(Constant_g, Texture_2, Previous)
1133 if (setTexEnv)
1134 {
1135 static const TexEnvSetting setting =
1136 {
1137 TEVMODE_MULT_ADD,
1138 TEVMODE_MULT_ADD,
1139 TEVSRC_CONSTANT, TEVSRC_TEXTURE2, TEVSRC_PREVIOUS,
1140 TEVSRC_CONSTANT, TEVSRC_TEXTURE2, TEVSRC_PREVIOUS,
1141 TEVOPRGB_GGG, TEVOPRGB_RGB, TEVOPRGB_RGB,
1142 TEVOPALP_G, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1143 TEVSCALE_1,
1144 TEVSCALE_1,
1145 };
1146
1147 setting.SetTexEnv(graphicsResource, i);
1148 internal::GL::SetTevBufferInput(graphicsResource, i, false, false);
1149 }
1150 NW_GL_ASSERT();
1151 ++i;
1152
1153 // Constant_3 = White
1154 internal::GL::SetTevConstRgba(graphicsResource, i, this->GetColor(TEVKONSTSEL_K0));
1155 // Output_3 = Interpolate(Constant, PreviousBuffer, Previous)
1156 if (setTexEnv)
1157 {
1158 static const TexEnvSetting setting =
1159 {
1160 TEVMODE_INTERPOLATE,
1161 TEVMODE_INTERPOLATE,
1162 TEVSRC_CONSTANT, TEVSRC_PREVIOUS_BUFFER, TEVSRC_PREVIOUS,
1163 TEVSRC_CONSTANT, TEVSRC_PREVIOUS_BUFFER, TEVSRC_PREVIOUS,
1164 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1165 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1166 TEVSCALE_1,
1167 TEVSCALE_1,
1168 };
1169
1170 setting.SetTexEnv(graphicsResource, i);
1171 }
1172
1173 NW_GL_ASSERT();
1174 ++i;
1175
1176 // Output_4 = Modulate(Primary, Previous)
1177 if (setTexEnv)
1178 {
1179 static const TexEnvSetting setting =
1180 {
1181 TEVMODE_MODULATE,
1182 TEVMODE_MODULATE,
1183 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1184 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1185 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1186 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1187 TEVSCALE_1,
1188 TEVSCALE_1,
1189 };
1190
1191 setting.SetTexEnv(graphicsResource, i);
1192 }
1193
1194 NW_GL_ASSERT();
1195 ++i;
1196
1197 #else
1198 if (setTexEnv)
1199 {
1200 // Constant.a ← 1/2
1201 internal::GL::SetTevConstRgba(graphicsResource, i, ut::Color8(0, 0, 0, 255 / 2));
1202 // Output0 = Interpolate(Texture0, Texture1, 1/2)
1203 static const TexEnvSetting setting =
1204 {
1205 TEVMODE_INTERPOLATE,
1206 TEVMODE_INTERPOLATE,
1207 TEVSRC_TEXTURE0, TEVSRC_TEXTURE1, TEVSRC_CONSTANT,
1208 TEVSRC_TEXTURE0, TEVSRC_TEXTURE1, TEVSRC_CONSTANT,
1209 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_ALPHA,
1210 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1211 TEVSCALE_1,
1212 TEVSCALE_1,
1213 };
1214
1215 setting.SetTexEnv(graphicsResource, i);
1216 }
1217
1218 NW_GL_ASSERT();
1219 ++i;
1220
1221 if (setTexEnv)
1222 {
1223 // Constant.a ← 1/3
1224 internal::GL::SetTevConstRgba(graphicsResource, i, ut::Color8(0, 0, 0, 255 / 3));
1225 // Output1 = Interpolate(Texture2, Previous, 1/3)
1226 static const TexEnvSetting setting =
1227 {
1228 TEVMODE_INTERPOLATE,
1229 TEVMODE_INTERPOLATE,
1230 TEVSRC_TEXTURE2, TEVSRC_PREVIOUS, TEVSRC_CONSTANT,
1231 TEVSRC_TEXTURE2, TEVSRC_PREVIOUS, TEVSRC_CONSTANT,
1232 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_ALPHA,
1233 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1234 TEVSCALE_1,
1235 TEVSCALE_1,
1236 };
1237
1238 setting.SetTexEnv(graphicsResource, i);
1239 }
1240
1241 NW_GL_ASSERT();
1242 ++i;
1243
1244 // Output2 = Modulate(Primary, Previous)
1245 if (setTexEnv)
1246 {
1247 static const TexEnvSetting setting =
1248 {
1249 TEVMODE_MODULATE,
1250 TEVMODE_MODULATE,
1251 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1252 TEVSRC_PRIMARY, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS,
1253 TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB,
1254 TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA,
1255 TEVSCALE_1,
1256 TEVSCALE_1,
1257 };
1258
1259 setting.SetTexEnv(graphicsResource, i);
1260 }
1261
1262 NW_GL_ASSERT();
1263 ++i;
1264 #endif
1265 break;
1266 }
1267 }
1268
1269 // 使わないTexEnvはスルーに設定。
1270 const u32 numPrevTexEnv = graphicsResource.GetNumTexEnv();
1271 graphicsResource.SetNumTexEnv(i);
1272
1273 for (; i < numPrevTexEnv; ++i)
1274 {
1275 internal::GL::SetTevCombineRgb(graphicsResource, i, TEVMODE_REPLACE);
1276 internal::GL::SetTevCombineAlpha(graphicsResource, i, TEVMODE_REPLACE);
1277 internal::GL::SetTevSrcRgb(graphicsResource, i, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS);
1278 internal::GL::SetTevSrcAlpha(graphicsResource, i, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS, TEVSRC_PREVIOUS);
1279 internal::GL::SetTevOperandRgb(graphicsResource, i, TEVOPRGB_RGB, TEVOPRGB_RGB, TEVOPRGB_RGB);
1280 internal::GL::SetTevOperandAlpha(graphicsResource, i, TEVOPALP_ALPHA, TEVOPALP_ALPHA, TEVOPALP_ALPHA);
1281 internal::GL::SetTevScaleRgb(graphicsResource, i, TEVSCALE_1);
1282 internal::GL::SetTevScaleAlpha(graphicsResource, i, TEVSCALE_1);
1283 NW_GL_ASSERT();
1284 }
1285 }
1286
1287 // アルファコンペア
1288 if (IsAlphaCompareCap())
1289 {
1290 const AlphaCompare& alphaCompare = this->GetAlphaCompare();
1291 internal::GL::SetEnableAlphaTest(graphicsResource, true);
1292 internal::GL::SetAlphaRefValue(graphicsResource, alphaCompare.GetRef());
1293 internal::GL::SetAlphaTestFunc(graphicsResource, alphaCompare.GetFunc());
1294 NW_GL_ASSERT();
1295 }
1296 else
1297 {
1298 internal::GL::SetEnableAlphaTest(graphicsResource, false);
1299 NW_GL_ASSERT();
1300 }
1301
1302 if (!this->GetTextureOnly())
1303 {
1304 // ピクセル処理
1305 if (IsBlendModeCap())
1306 {
1307 static const GLint blendOp[] =
1308 {
1309 0, // DISABLE
1310 GL_FUNC_ADD,
1311 GL_FUNC_SUBTRACT,
1312 GL_FUNC_REVERSE_SUBTRACT,
1313 };
1314 NW_COMPILER_ASSERT(ARRAY_LENGTH(blendOp) == BLENDOP_MAX);
1315
1316 static const GLint srcFactor[] =
1317 {
1318 GL_ZERO,
1319 GL_ONE,
1320 GL_DST_COLOR,
1321 GL_ONE_MINUS_DST_COLOR,
1322 GL_SRC_ALPHA,
1323 GL_ONE_MINUS_SRC_ALPHA,
1324 GL_DST_ALPHA,
1325 GL_ONE_MINUS_DST_ALPHA,
1326 };
1327 NW_COMPILER_ASSERT(ARRAY_LENGTH(srcFactor) == BLENDFACTORSRC_MAX);
1328
1329 static const GLint dstFactor[] =
1330 {
1331 GL_ZERO,
1332 GL_ONE,
1333 GL_SRC_COLOR,
1334 GL_ONE_MINUS_SRC_COLOR,
1335 GL_SRC_ALPHA,
1336 GL_ONE_MINUS_SRC_ALPHA,
1337 GL_DST_ALPHA,
1338 GL_ONE_MINUS_DST_ALPHA,
1339 };
1340 NW_COMPILER_ASSERT(ARRAY_LENGTH(dstFactor) == BLENDFACTORDST_MAX);
1341
1342 static const GLint logicOp[] =
1343 {
1344 0 , // DISABLE
1345 GL_NOOP,
1346 GL_CLEAR,
1347 GL_SET,
1348 GL_COPY,
1349 GL_COPY_INVERTED,
1350 GL_INVERT,
1351 GL_AND,
1352 GL_NAND,
1353 GL_OR,
1354 GL_NOR,
1355 GL_XOR,
1356 GL_EQUIV,
1357 GL_AND_REVERSE,
1358 GL_AND_INVERTED,
1359 GL_OR_REVERSE,
1360 GL_OR_INVERTED,
1361 };
1362 NW_COMPILER_ASSERT(ARRAY_LENGTH(logicOp) == LOGICOP_MAX);
1363
1364 const BlendMode& blendMode = this->GetBlendMode();
1365
1366 if (blendMode.GetBlendOp() == BLENDOP_DISABLE)
1367 {
1368 glDisable(GL_BLEND);
1369 NW_GL_ASSERT();
1370 }
1371 else
1372 {
1373 glEnable(GL_BLEND);
1374 glBlendFunc(srcFactor[blendMode.GetSrcFactor()], dstFactor[blendMode.GetDstFactor()]);
1375 glBlendEquation(blendOp[blendMode.GetBlendOp()]);
1376 NW_GL_ASSERT();
1377 }
1378
1379 if (blendMode.GetLogicOp() == LOGICOP_DISABLE)
1380 {
1381 glDisable(GL_COLOR_LOGIC_OP);
1382 NW_GL_ASSERT();
1383 }
1384 else
1385 {
1386 glEnable(GL_COLOR_LOGIC_OP);
1387 glLogicOp(logicOp[blendMode.GetLogicOp()]);
1388 NW_GL_ASSERT();
1389 }
1390 }
1391 else
1392 {
1393 // ソースアルファでブレンド
1394 glEnable(GL_BLEND);
1395 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1396
1397 // 論理演算はしない
1398 glDisable(GL_COLOR_LOGIC_OP);
1399 NW_GL_ASSERT();
1400 }
1401 }
1402 }
1403 #endif
1404
1405 void
BindAnimation(AnimTransform * pAnimTrans)1406 Material::BindAnimation(AnimTransform* pAnimTrans)
1407 {
1408 pAnimTrans->Bind(this);
1409 }
1410
1411 void
UnbindAnimation(AnimTransform * pAnimTrans)1412 Material::UnbindAnimation(AnimTransform* pAnimTrans)
1413 {
1414 internal::UnbindAnimationLink(&m_AnimList, pAnimTrans);
1415 }
1416
1417 void
UnbindAllAnimation()1418 Material::UnbindAllAnimation()
1419 {
1420 UnbindAnimation(0);
1421 }
1422
1423 void
Animate()1424 Material::Animate()
1425 {
1426 for (AnimationList::Iterator it = m_AnimList.GetBeginIter(); it != m_AnimList.GetEndIter(); ++it)
1427 {
1428 if (it->IsEnable())
1429 {
1430 AnimTransform* animTrans = it->GetAnimTransform();
1431 animTrans->Animate(it->GetIndex(), this);
1432 }
1433 }
1434 }
1435
1436 void
AddAnimationLink(AnimationLink * pAnimationLink)1437 Material::AddAnimationLink(AnimationLink* pAnimationLink)
1438 {
1439 m_AnimList.PushBack(pAnimationLink);
1440 }
1441
1442 AnimationLink*
FindAnimationLink(AnimTransform * pAnimTrans)1443 Material::FindAnimationLink(AnimTransform* pAnimTrans)
1444 {
1445 return internal::FindAnimationLink(&m_AnimList, pAnimTrans);
1446 }
1447
1448 AnimationLink*
FindAnimationLink(const AnimResource & animRes)1449 Material::FindAnimationLink(const AnimResource& animRes)
1450 {
1451 return internal::FindAnimationLink(&m_AnimList, animRes);
1452 }
1453
1454 void
SetAnimationEnable(AnimTransform * pAnimTrans,bool bEnable)1455 Material::SetAnimationEnable(
1456 AnimTransform* pAnimTrans,
1457 bool bEnable
1458 )
1459 {
1460 if (AnimationLink* pAnimLink= FindAnimationLink(pAnimTrans))
1461 {
1462 pAnimLink->SetEnable(bEnable);
1463 }
1464 }
1465
1466 void
SetAnimationEnable(const AnimResource & animRes,bool bEnable)1467 Material::SetAnimationEnable(
1468 const AnimResource& animRes,
1469 bool bEnable
1470 )
1471 {
1472 if (AnimationLink* pAnimLink= FindAnimationLink(animRes))
1473 {
1474 pAnimLink->SetEnable(bEnable);
1475 }
1476 }
1477
1478 } // namespace nw::lyt
1479 } // namespace nw
1480