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