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