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