1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     demo_RenderSystemDrawing.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 46365 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "demo/Render/demo_RenderSystemDrawing.h"
17 
18 namespace demo
19 {
20 
RenderSystemDrawing(void)21     RenderSystemDrawing::RenderSystemDrawing(void) :
22     RenderSystem(),
23     m_InitializeTexturedTriangles(false), m_UseDecalTextureProgram(false),
24     m_MaxTexturedTrianglesNum(demo::MAX_TEXTURED_TRIANGLES_NUM)
25     {
26         for (u32 textureArrayIndex = 0; textureArrayIndex < demo::MAX_TEXTURES_NUM;
27             textureArrayIndex++)
28         {
29             m_TextureIdArray[textureArrayIndex] = 0;
30             m_TotalTexturedTrianglesNumArray[textureArrayIndex] = 0;
31         }
32 
33         for (u32 displayIndex = 0; displayIndex < 3; displayIndex++)
34         {
35             for (u32 index = 0; index < 4; index++)
36             {
37                 m_ClearColorArray[displayIndex][index] = 0.0f;
38             }
39         }
40     }
41 
~RenderSystemDrawing(void)42     RenderSystemDrawing::~RenderSystemDrawing(void)
43     {
44         Finalize();
45     }
46 
Initialize(const uptr fcramAddress,const size_t memorySize,const u32 commandBufferSize,const u32 requestNum,const bool serialRunMode,const DisplayBuffersDescription & displayBuffers0Desc,const DisplayBuffersDescription & displayBuffers1Desc,const FrameBufferDescription & frameBuffer0Desc,const DisplayBuffersDescription & displayBuffers0ExtDesc,const bool isFillBlackLCD)47     void RenderSystemDrawing::Initialize(const uptr fcramAddress, const size_t memorySize,
48         const u32 commandBufferSize, const u32 requestNum,
49         const bool serialRunMode,
50         const DisplayBuffersDescription& displayBuffers0Desc,
51         const DisplayBuffersDescription& displayBuffers1Desc,
52         const FrameBufferDescription& frameBuffer0Desc,
53         const DisplayBuffersDescription& displayBuffers0ExtDesc,
54         const bool isFillBlackLCD)
55     {
56 
57         RenderSystem::Initialize(fcramAddress, memorySize,
58             commandBufferSize, requestNum, serialRunMode,
59             displayBuffers0Desc, displayBuffers1Desc,
60             frameBuffer0Desc, displayBuffers0ExtDesc, isFillBlackLCD);
61 
62         m_InitializeTexturedTriangles = false;
63         m_UseDecalTextureProgram = false;
64 
65         // Note: nngxInitialize() must be called in advance. It is called from within RenderSystem::Initialize().
66         m_GraphicsDrawing.Initialize();
67     }
68 
InitializeTexturedTriangles(const u32 maxTrianglesNum)69     void RenderSystemDrawing::InitializeTexturedTriangles(const u32 maxTrianglesNum)
70     {
71         if ( m_InitializeTexturedTriangles )
72         {
73             return;
74         }
75 
76         u32 vertexAttributes = m_GraphicsDrawing.m_ShaderManager.GetVertexAttributes(demo::DECAL_TEXTURE_SHADER);
77         u32 maxVerticesNum = 3 * maxTrianglesNum;
78         m_MaxTexturedTrianglesNum  = maxTrianglesNum;
79 
80         for (u32 textureArrayIndex = 0; textureArrayIndex < demo::MAX_TEXTURES_NUM; textureArrayIndex++)
81         {
82             m_TotalTexturedTrianglesNumArray[textureArrayIndex] = 0;
83 
84             m_TexturedTrianglesRenderDataArray[textureArrayIndex].Initialize();
85             m_TexturedTrianglesRenderDataArray[textureArrayIndex].InitializeVertexBuffers(vertexAttributes,
86                 GL_TRIANGLES, maxVerticesNum, m_MaxTexturedTrianglesNum);
87         }
88 
89         for (u32 textureArrayIndex = 0; textureArrayIndex < demo::MAX_TEXTURES_NUM; textureArrayIndex++)
90         {
91             m_TextureIdArray[textureArrayIndex] = 0;
92         }
93 
94         m_InitializeTexturedTriangles = true;
95 
96         DEMO_ASSERT_GL_ERROR();
97     }
98 
InitializeTriangles(const u32 maxTrianglesNum)99     void RenderSystemDrawing::InitializeTriangles(const u32 maxTrianglesNum)
100     {
101         m_GraphicsDrawing.InitializeTriangles(maxTrianglesNum);
102     }
103 
InitializeSquares(const u32 maxSquaresNum)104     void RenderSystemDrawing::InitializeSquares(const u32 maxSquaresNum)
105     {
106         m_GraphicsDrawing.InitializeSquares(maxSquaresNum);
107     }
108 
InitializeTexts(const u32 maxLength)109     void RenderSystemDrawing::InitializeTexts(const u32 maxLength)
110     {
111         m_GraphicsDrawing.InitializeTexts(maxLength);
112     }
113 
Finalize(void)114     void RenderSystemDrawing::Finalize(void)
115     {
116         for (u32 textureArrayIndex = 0; textureArrayIndex < MAX_TEXTURES_NUM; textureArrayIndex++)
117         {
118             m_TotalTexturedTrianglesNumArray[textureArrayIndex] = 0;
119             m_TexturedTrianglesRenderDataArray[textureArrayIndex].Finalize();
120         }
121         m_InitializeTexturedTriangles = false;
122 
123         for (u32 textureArrayIndex = 0; textureArrayIndex < MAX_TEXTURES_NUM; textureArrayIndex++)
124         {
125             GLuint textureId = m_TextureIdArray[textureArrayIndex];
126             if ( textureId != 0 )
127             {
128                 glDeleteTextures(1, &textureId);
129                 m_TextureIdArray[textureArrayIndex] = 0;
130             }
131         }
132 
133         m_GraphicsDrawing.Finalize();
134         RenderSystem::Finalize();
135 
136         DEMO_ASSERT_GL_ERROR();
137     }
138 
SetViewport(const GLint x,const GLint y,const GLsizei width,const GLsizei height)139     void RenderSystemDrawing::SetViewport(const GLint x, const GLint y, const GLsizei width, const GLsizei height)
140     {
141         NN_UNUSED_VAR(x);
142         NN_UNUSED_VAR(y);
143 
144         m_GraphicsDrawing.SetWindowSize(width, height);
145 
146         for (u32 textureArrayIndex = 0; textureArrayIndex < MAX_TEXTURES_NUM; textureArrayIndex++)
147         {
148             m_TexturedTrianglesRenderDataArray[textureArrayIndex].SetWindowSize(width, height);
149         }
150 
151         RenderSystem::SetViewport(x, y, width, height);
152     }
153 
SetClearColor(const s32 display,const f32 red,const f32 green,const f32 blue,const f32 alpha)154     void RenderSystemDrawing::SetClearColor(const s32 display,
155         const f32 red, const f32 green, const f32 blue, const f32 alpha)
156     {
157         if (display == NN_GX_DISPLAY0 || display == NN_GX_DISPLAY_BOTH)
158         {
159             m_ClearColorArray[0][0] = red;
160             m_ClearColorArray[0][1] = green;
161             m_ClearColorArray[0][2] = blue;
162             m_ClearColorArray[0][3] = alpha;
163         }
164 
165         if (display == NN_GX_DISPLAY1 || display == NN_GX_DISPLAY_BOTH)
166         {
167             m_ClearColorArray[1][0] = red;
168             m_ClearColorArray[1][1] = green;
169             m_ClearColorArray[1][2] = blue;
170             m_ClearColorArray[1][3] = alpha;
171         }
172     }
173 
Clear(const GLbitfield mask)174     void RenderSystemDrawing::Clear(const GLbitfield mask)
175     {
176         u32 displayIndex = 0;
177         if ( m_TargetDisplay == NN_GX_DISPLAY0 )
178         {
179             displayIndex = 0;
180         }
181         else if ( m_TargetDisplay == NN_GX_DISPLAY1 )
182         {
183             displayIndex = 1;
184         }
185         glClearColor(m_ClearColorArray[displayIndex][0], m_ClearColorArray[displayIndex][1],
186                 m_ClearColorArray[displayIndex][2], m_ClearColorArray[displayIndex][3]);
187 
188         RenderSystem::Clear(mask);
189     }
190 
SetColor(const f32 red,const f32 green,const f32 blue,const f32 alpha)191     void RenderSystemDrawing::SetColor(const f32 red, const f32 green, const f32 blue, const f32 alpha)
192     {
193         m_GraphicsDrawing.SetColor(red, green, blue, alpha);
194     }
195 
SetColor(const f32 red,const f32 green,const f32 blue)196     void RenderSystemDrawing::SetColor(const f32 red, const f32 green, const f32 blue)
197     {
198         m_GraphicsDrawing.SetColor(red, green, blue);
199     }
200 
SetDepth(const f32 depth)201     void RenderSystemDrawing::SetDepth(const f32 depth)
202     {
203         m_GraphicsDrawing.SetDepth(depth);
204     }
205 
SetAutoDepth(const bool enableAutoDepth)206     void RenderSystemDrawing::SetAutoDepth(const bool enableAutoDepth)
207     {
208         m_GraphicsDrawing.SetAutoDepth(enableAutoDepth);
209     }
210 
SetPointSize(const f32 pointSize)211     void RenderSystemDrawing::SetPointSize(const f32 pointSize)
212     {
213         m_GraphicsDrawing.SetPointSize(pointSize);
214     }
215 
DrawPoint(const f32 windowCoordinateX,const f32 windowCoordinateY)216     void RenderSystemDrawing::DrawPoint(const f32 windowCoordinateX, const f32 windowCoordinateY)
217     {
218         m_GraphicsDrawing.DrawPoint(windowCoordinateX, windowCoordinateY);
219     }
220 
SetLineWidth(const f32 lineWidth)221     void RenderSystemDrawing::SetLineWidth(const f32 lineWidth)
222     {
223         m_GraphicsDrawing.SetLineWidth(lineWidth);
224     }
225 
DrawLine(const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 windowCoordinateX1,const f32 windowCoordinateY1)226     void RenderSystemDrawing::DrawLine(const f32 windowCoordinateX0, const f32 windowCoordinateY0,
227         const f32 windowCoordinateX1, const f32 windowCoordinateY1)
228     {
229         CheckRenderTarget();
230         m_GraphicsDrawing.DrawLine(windowCoordinateX0, windowCoordinateY0,
231             windowCoordinateX1, windowCoordinateY1);
232     }
233 
FillSquare(const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 windowCoordinateX1,const f32 windowCoordinateY1,const f32 windowCoordinateX2,const f32 windowCoordinateY2,const f32 windowCoordinateX3,const f32 windowCoordinateY3)234     void RenderSystemDrawing::FillSquare(const f32 windowCoordinateX0, const f32 windowCoordinateY0,
235         const f32 windowCoordinateX1, const f32 windowCoordinateY1,
236         const f32 windowCoordinateX2, const f32 windowCoordinateY2,
237         const f32 windowCoordinateX3, const f32 windowCoordinateY3)
238     {
239         CheckRenderTarget();
240         m_GraphicsDrawing.FillSquare(windowCoordinateX0, windowCoordinateY0,
241             windowCoordinateX1, windowCoordinateY1,
242             windowCoordinateX2, windowCoordinateY2,
243             windowCoordinateX3, windowCoordinateY3);
244     }
245 
FillRectangle(const f32 windowCoordinateX,const f32 windowCoordinateY,const f32 width,const f32 height)246     void RenderSystemDrawing::FillRectangle(const f32 windowCoordinateX,
247         const f32 windowCoordinateY, const f32 width, const f32 height)
248     {
249         CheckRenderTarget();
250         m_GraphicsDrawing.FillRectangle(windowCoordinateX, windowCoordinateY,
251             width, height);
252     }
253 
FillTriangle(const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 windowCoordinateX1,const f32 windowCoordinateY1,const f32 windowCoordinateX2,const f32 windowCoordinateY2)254     void RenderSystemDrawing::FillTriangle(const f32 windowCoordinateX0, const f32 windowCoordinateY0,
255         const f32 windowCoordinateX1, const f32 windowCoordinateY1,
256         const f32 windowCoordinateX2, const f32 windowCoordinateY2)
257     {
258         CheckRenderTarget();
259         m_GraphicsDrawing.FillTriangle(windowCoordinateX0, windowCoordinateY0,
260             windowCoordinateX1, windowCoordinateY1,
261             windowCoordinateX2, windowCoordinateY2);
262     }
263 
SetFontSize(const f32 fontSize)264     void RenderSystemDrawing::SetFontSize(const f32 fontSize)
265     {
266         m_GraphicsDrawing.SetFontSize(fontSize);
267     }
268 
DrawText(const f32 windowCoordinateX,const f32 windowCoordinateY,const char * format,...)269     void RenderSystemDrawing::DrawText(const f32 windowCoordinateX, const f32 windowCoordinateY, const char* format, ...)
270     {
271         CheckRenderTarget();
272 
273         static const u32 tmpBufferSize = 1024;
274         static char textBuffer[tmpBufferSize];
275 
276         va_list va;
277         va_start(va, format);
278         vsnprintf(textBuffer, tmpBufferSize, format, va);
279         va_end(va);
280 
281         m_GraphicsDrawing.DrawTextBuffer(windowCoordinateX, windowCoordinateY, textBuffer);
282     }
283 
HasTexture(const GLuint textureId)284     bool RenderSystemDrawing::HasTexture(const GLuint textureId)
285     {
286         if (! m_InitializeFlag )
287         {
288             NN_TPANIC_("Initialize() is not called.\n");
289         }
290 
291         if (! m_InitializeTexturedTriangles )
292         {
293             InitializeTexturedTriangles();
294         }
295 
296         u32 arrayIndex = 0;
297         return FindTextureArrayIndex(textureId, arrayIndex);
298     }
299 
GenerateTexture(const GLenum target,const GLenum internalFormat,const GLsizei width,const GLsizei height,const GLenum format,const GLenum type,void * pixels,GLuint & textureId)300     bool RenderSystemDrawing::GenerateTexture(const GLenum target,
301         const GLenum internalFormat,
302         const GLsizei width, const GLsizei height,
303         const GLenum format, const GLenum type, void* pixels,
304         GLuint& textureId)
305     {
306         if (! m_InitializeFlag )
307         {
308             NN_TPANIC_("Initialize() is not called.\n");
309         }
310 
311         if (! m_InitializeTexturedTriangles )
312         {
313             InitializeTexturedTriangles();
314         }
315 
316         u32 emptyTextureId = 0;
317         u32 textureArrayIndex = 0;
318 
319         if (! FindTextureArrayIndex(emptyTextureId, textureArrayIndex) )
320         {
321             NN_TPANIC_("Max loadable textures numbers is %d.\n", demo::MAX_TEXTURES_NUM);
322 
323             return false;
324         }
325 
326         glActiveTexture(GL_TEXTURE0);
327         glGenTextures(1, &textureId);
328         DEMO_ASSERT_GL_ERROR();
329 
330         glBindTexture(GL_TEXTURE_2D, textureId);
331         glTexImage2D(target, 0, internalFormat,
332             width, height, 0,
333             format, type, pixels);
334         DEMO_ASSERT_GL_ERROR();
335 
336         m_TextureIdArray[textureArrayIndex] = textureId;
337 
338         return true;
339     }
340 
DeleteTexture(const GLuint textureId)341     bool RenderSystemDrawing::DeleteTexture(const GLuint textureId)
342     {
343         if (! m_InitializeFlag )
344         {
345             NN_TPANIC_("Initialize() is not called.\n");
346         }
347 
348         if (! m_InitializeTexturedTriangles )
349         {
350             InitializeTexturedTriangles();
351         }
352 
353         if ( textureId == 0 )
354         {
355             return false;
356         }
357 
358         u32 textureArrayIndex = 0;
359         if ( FindTextureArrayIndex(textureId, textureArrayIndex) )
360         {
361             glDeleteTextures(1, &textureId);
362             DEMO_ASSERT_GL_ERROR();
363 
364             m_TextureIdArray[textureArrayIndex] = 0;
365 
366             return true;
367         }
368         else
369         {
370             return false;
371         }
372     }
373 
FindTextureArrayIndex(const GLuint textureId,u32 & arrayIndex)374     bool RenderSystemDrawing::FindTextureArrayIndex(const GLuint textureId, u32& arrayIndex)
375     {
376         if (! m_InitializeFlag )
377         {
378             NN_TPANIC_("Initialize() is not called.\n");
379         }
380 
381         for (u32 textureArrayIndex = 0; textureArrayIndex < demo::MAX_TEXTURES_NUM;
382             textureArrayIndex++)
383         {
384             if ( textureId == m_TextureIdArray[textureArrayIndex] )
385             {
386                 arrayIndex = textureArrayIndex;
387 
388                 return true;
389             }
390         }
391 
392         return false;
393     }
394 
FillTexturedRectangle(const GLuint textureId,const f32 windowCoordinateX,const f32 windowCoordinateY,const f32 rectangleWidth,const f32 rectangleHeight,const f32 imageWidth,const f32 imageHeight,const f32 textureWidth,const f32 textureHeight)395     void RenderSystemDrawing::FillTexturedRectangle(const GLuint textureId,
396                                                   const f32 windowCoordinateX, const f32 windowCoordinateY,
397                                                   const f32 rectangleWidth, const f32 rectangleHeight,
398                                                   const f32 imageWidth, const f32 imageHeight,
399                                                   const f32 textureWidth, const f32 textureHeight)
400     {
401         CheckRenderTarget();
402 
403         if ( (textureId == 0 ) || (! HasTexture(textureId) ) )
404         {
405             NN_TPANIC_("Invalid textureId %d.\n", textureId);
406             return;
407         }
408 
409         f32 windowCoordinateX1 = windowCoordinateX + rectangleWidth;
410         f32 windowCoordinateY1 = windowCoordinateY + rectangleHeight;
411 
412         f32 texcoordS0 = 0.0f;
413         f32 texcoordT0 = 0.0f;
414         f32 texcoordS1 = static_cast<f32>(imageWidth) / static_cast<f32>(textureWidth);
415         f32 texcoordT1 = static_cast<f32>(imageHeight) / static_cast<f32>(textureHeight);
416 
417         FillTexturedTriangle(textureId,
418             windowCoordinateX, windowCoordinateY,
419             texcoordS0, texcoordT1,
420             windowCoordinateX, windowCoordinateY1,
421             texcoordS0, texcoordT0,
422             windowCoordinateX1, windowCoordinateY1,
423             texcoordS1, texcoordT0);
424 
425         FillTexturedTriangle(textureId,
426             windowCoordinateX, windowCoordinateY,
427             texcoordS0, texcoordT1,
428             windowCoordinateX1, windowCoordinateY1,
429             texcoordS1, texcoordT0,
430             windowCoordinateX1, windowCoordinateY,
431             texcoordS1, texcoordT1);
432     }
433 
FillTexturedTriangle(const GLuint textureId,const f32 windowCoordinateX0,const f32 windowCoordinateY0,const f32 texcoordS0,const f32 texcoordT0,const f32 windowCoordinateX1,const f32 windowCoordinateY1,const f32 texcoordS1,const f32 texcoordT1,const f32 windowCoordinateX2,const f32 windowCoordinateY2,const f32 texcoordS2,const f32 texcoordT2)434     void RenderSystemDrawing::FillTexturedTriangle(const GLuint textureId,
435                                                const f32 windowCoordinateX0, const f32 windowCoordinateY0,
436                                                const f32 texcoordS0, const f32 texcoordT0,
437                                                const f32 windowCoordinateX1, const f32 windowCoordinateY1,
438                                                const f32 texcoordS1, const f32 texcoordT1,
439                                                const f32 windowCoordinateX2, const f32 windowCoordinateY2,
440                                                const f32 texcoordS2, const f32 texcoordT2)
441     {
442         CheckRenderTarget();
443 
444         if (! m_InitializeTexturedTriangles )
445         {
446             InitializeTexturedTriangles();
447         }
448 
449         u32 textureArrayIndex = 0;
450         if ( ( textureId == 0 ) || (! FindTextureArrayIndex(textureId, textureArrayIndex) ) )
451         {
452             NN_TPANIC_("Invalid textureId %d.\n", textureId);
453             return;
454         }
455 
456         if ( m_TotalTexturedTrianglesNumArray[textureArrayIndex] >= m_MaxTexturedTrianglesNum )
457         {
458             NN_TLOG_("RenderSystemDrawing::FillTexturedTriangle() maxTriangles limit\n");
459             NN_TLOG_("  trianglesIndex = %d, maxTrianglesNum = %d\n",
460                 m_TotalTexturedTrianglesNumArray[textureArrayIndex], m_MaxTexturedTrianglesNum);
461             return;
462         }
463 
464         m_UseDecalTextureProgram = true;
465 
466         demo::TrianglesRenderData& renderData = m_TexturedTrianglesRenderDataArray[textureArrayIndex];
467         u32 triangleIndex = renderData.GetPackedTrianglesNum();
468 
469         f32 s_Depth = m_GraphicsDrawing.m_Depth;
470 
471         // POSITION0
472         f32 normalizedDeviceCoordinateX = 0.0f;
473         f32 normalizedDeviceCoordinateY = 0.0f;
474         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX0, windowCoordinateY0,
475             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
476         renderData.SetPosition(3 * triangleIndex,
477             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, s_Depth, 1.0f);
478 
479         // POSITION1
480         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX1, windowCoordinateY1,
481             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
482         renderData.SetPosition(3 * triangleIndex + 1,
483             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, s_Depth, 1.0f);
484 
485         // POSITION2
486         renderData.GetNormalizedDeviceCoordinateXY(windowCoordinateX2, windowCoordinateY2,
487             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY);
488         renderData.SetPosition(3 * triangleIndex + 2,
489             normalizedDeviceCoordinateX, normalizedDeviceCoordinateY, s_Depth, 1.0f);
490 
491         m_GraphicsDrawing.DecrementDepth();
492 
493         // TEXCOORD0-2
494         renderData.SetTexcoord(3 * triangleIndex, texcoordS0, texcoordT0);
495         renderData.SetTexcoord(3 * triangleIndex + 1, texcoordS1, texcoordT1);
496         renderData.SetTexcoord(3 * triangleIndex + 2, texcoordS2, texcoordT2);
497 
498         // INDEX
499         renderData.SetIndex(triangleIndex,
500             3 * triangleIndex, 3 * triangleIndex + 1, 3 * triangleIndex + 2);
501 
502         renderData.AddPackedVerticesNum(3);
503         renderData.AddPackedTrianglesNum(1);
504 
505         m_TotalTexturedTrianglesNumArray[textureArrayIndex] += 1;
506     }
507 
SwapBuffers(void)508     void RenderSystemDrawing::SwapBuffers(void)
509     {
510         CheckRenderTarget();
511 
512         RenderSystemDrawing::Flush();
513         RenderSystem::SwapBuffers();
514     }
515 
Flush(void)516     void RenderSystemDrawing::Flush(void)
517     {
518         FlushTexturedPrimitives();
519         m_GraphicsDrawing.Flush();
520     }
521 
FlushTexturedPrimitives(void)522     void RenderSystemDrawing::FlushTexturedPrimitives(void)
523     {
524         if (! m_UseDecalTextureProgram )
525         {
526             return;
527         }
528 
529         demo::ProgramObject* shaderProgramPtr = m_GraphicsDrawing.m_ShaderManager.GetShaderProgram(demo::DECAL_TEXTURE_SHADER);
530         shaderProgramPtr->SetUse3d(false);
531         shaderProgramPtr->Begin();
532         shaderProgramPtr->Use();
533 
534         for (u32 textureArrayIndex = 0; textureArrayIndex < demo::MAX_TEXTURES_NUM; textureArrayIndex++)
535         {
536             if ( m_TextureIdArray[textureArrayIndex] != 0 )
537             {
538                 demo::TrianglesRenderData& renderData = m_TexturedTrianglesRenderDataArray[textureArrayIndex];
539                 u32 packedTrianglesNum = renderData.GetPackedTrianglesNum();
540                 if ( packedTrianglesNum != 0 )
541                 {
542                     GLuint textureId = m_TextureIdArray[textureArrayIndex];
543                     if ( textureId != 0 )
544                     {
545                         shaderProgramPtr->SetTextureId(textureId);
546                         shaderProgramPtr->Update();
547                         renderData.DrawPackedTriangles();
548                     }
549                 }
550 
551                 m_TotalTexturedTrianglesNumArray[textureArrayIndex] = 0;
552             }
553         }
554 
555         shaderProgramPtr->End();
556 
557         m_UseDecalTextureProgram = false;
558     }
559 
560 }
561