1 // Copyright (C) 2017 Michael Zeilfelder
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in Irrlicht.h
\r
5 #include "CWebGL1Driver.h"
\r
7 #ifdef _IRR_COMPILE_WITH_WEBGL1_
\r
9 #include "COpenGLCoreTexture.h"
\r
10 #include "COpenGLCoreRenderTarget.h"
\r
11 #include "COpenGLCoreCacheHandler.h"
\r
12 #include "EVertexAttributes.h"
\r
19 CWebGL1Driver::CWebGL1Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager) :
\r
20 COGLES2Driver(params, io, contextManager)
\r
21 , MBTriangleFanSize4(0), MBLinesSize2(0), MBPointsSize1(0)
\r
24 setDebugName("CWebGL1Driver");
\r
27 // NPOT are not allowed for WebGL in most cases.
\r
28 // One can use them when:
\r
29 // - The TEXTURE_MIN_FILTER is linear or nearest
\r
30 // - no mipmapping is used
\r
31 // - no texture wrapping is used (so all texture_wraps have to be CLAMP_TO_EDGE)
\r
32 // So users could still enable them for specific cases (usually GUI), but in general better to have it off.
\r
33 disableFeature(EVDF_TEXTURE_NPOT);
\r
35 MBLinesSize2 = createSimpleMeshBuffer(2, scene::EPT_LINES);
\r
36 MBTriangleFanSize4 = createSimpleMeshBuffer(4, scene::EPT_TRIANGLE_FAN);
\r
37 MBPointsSize1 = createSimpleMeshBuffer(1, scene::EPT_POINTS);
\r
40 CWebGL1Driver::~CWebGL1Driver()
\r
42 if ( MBTriangleFanSize4 )
\r
43 MBTriangleFanSize4->drop();
\r
45 MBLinesSize2->drop();
\r
46 if ( MBPointsSize1 )
\r
47 MBPointsSize1->drop();
\r
50 //! Returns type of video driver
\r
51 E_DRIVER_TYPE CWebGL1Driver::getDriverType() const
\r
56 //! draws a vertex primitive list
\r
57 void CWebGL1Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
\r
58 const void* indexList, u32 primitiveCount,
\r
59 E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
\r
63 COGLES2Driver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
\r
67 static bool first = true;
\r
71 os::Printer::log("WebGL driver does not support drawVertexPrimitiveList calls without a VBO", ELL_WARNING);
\r
72 os::Printer::log(__FILE__, irr::core::stringc(__LINE__).c_str(), ELL_WARNING);
\r
77 //! Draws a mesh buffer
\r
78 void CWebGL1Driver::drawMeshBuffer(const scene::IMeshBuffer* mb)
\r
82 // OK - this is bad and I hope I can find a better solution.
\r
83 // Basically casting away a const which shouldn't be cast away.
\r
84 // Not a nice surprise for users to see their mesh changes I guess :-(
\r
85 scene::IMeshBuffer* mbUglyHack = const_cast<scene::IMeshBuffer*>(mb);
\r
87 // We can't allow any buffers which are not bound to some VBO.
\r
88 if ( mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER)
\r
89 mbUglyHack->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_VERTEX);
\r
90 if ( mb->getHardwareMappingHint_Index() == scene::EHM_NEVER)
\r
91 mbUglyHack->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_INDEX);
\r
93 COGLES2Driver::drawMeshBuffer(mb);
\r
97 void CWebGL1Driver::draw2DImage(const video::ITexture* texture,
\r
98 const core::position2d<s32>& destPos,const core::rect<s32>& sourceRect,
\r
99 const core::rect<s32>* clipRect, SColor color, bool useAlphaChannelOfTexture)
\r
104 if (!sourceRect.isValid())
\r
107 core::position2d<s32> targetPos(destPos);
\r
108 core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner);
\r
109 core::dimension2d<s32> sourceSize(sourceRect.getSize());
\r
112 if (targetPos.X < clipRect->UpperLeftCorner.X)
\r
114 sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
\r
115 if (sourceSize.Width <= 0)
\r
118 sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
\r
119 targetPos.X = clipRect->UpperLeftCorner.X;
\r
122 if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)
\r
124 sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
\r
125 if (sourceSize.Width <= 0)
\r
129 if (targetPos.Y < clipRect->UpperLeftCorner.Y)
\r
131 sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
132 if (sourceSize.Height <= 0)
\r
135 sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
136 targetPos.Y = clipRect->UpperLeftCorner.Y;
\r
139 if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)
\r
141 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
\r
142 if (sourceSize.Height <= 0)
\r
147 // clip these coordinates
\r
149 if (targetPos.X < 0)
\r
151 sourceSize.Width += targetPos.X;
\r
152 if (sourceSize.Width <= 0)
\r
155 sourcePos.X -= targetPos.X;
\r
159 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
161 if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
\r
163 sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
\r
164 if (sourceSize.Width <= 0)
\r
168 if (targetPos.Y < 0)
\r
170 sourceSize.Height += targetPos.Y;
\r
171 if (sourceSize.Height <= 0)
\r
174 sourcePos.Y -= targetPos.Y;
\r
178 if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
\r
180 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
\r
181 if (sourceSize.Height <= 0)
\r
185 // ok, we've clipped everything.
\r
188 // texcoords need to be flipped horizontally for RTTs
\r
189 const bool isRTT = texture->isRenderTarget();
\r
190 const core::dimension2d<u32>& ss = texture->getOriginalSize();
\r
191 const f32 invW = 1.f / static_cast<f32>(ss.Width);
\r
192 const f32 invH = 1.f / static_cast<f32>(ss.Height);
\r
193 const core::rect<f32> tcoords(
\r
194 sourcePos.X * invW,
\r
195 (isRTT ? (sourcePos.Y + sourceSize.Height) : sourcePos.Y) * invH,
\r
196 (sourcePos.X + sourceSize.Width) * invW,
\r
197 (isRTT ? sourcePos.Y : (sourcePos.Y + sourceSize.Height)) * invH);
\r
199 const core::rect<s32> poss(targetPos, sourceSize);
\r
201 chooseMaterial2D();
\r
202 if ( !setMaterialTexture(0, texture) )
\r
205 setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);
\r
206 lockRenderStateMode();
\r
208 f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
209 f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
210 f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
211 f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
213 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
\r
214 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
\r
215 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
\r
216 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
\r
217 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
219 drawMeshBuffer(MBTriangleFanSize4);
\r
221 unlockRenderStateMode();
\r
224 void CWebGL1Driver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
\r
225 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
\r
226 const video::SColor* const colors, bool useAlphaChannelOfTexture)
\r
231 // texcoords need to be flipped horizontally for RTTs
\r
232 const bool isRTT = texture->isRenderTarget();
\r
233 const core::dimension2du& ss = texture->getOriginalSize();
\r
234 const f32 invW = 1.f / static_cast<f32>(ss.Width);
\r
235 const f32 invH = 1.f / static_cast<f32>(ss.Height);
\r
236 const core::rect<f32> tcoords(
\r
237 sourceRect.UpperLeftCorner.X * invW,
\r
238 (isRTT ? sourceRect.LowerRightCorner.Y : sourceRect.UpperLeftCorner.Y) * invH,
\r
239 sourceRect.LowerRightCorner.X * invW,
\r
240 (isRTT ? sourceRect.UpperLeftCorner.Y : sourceRect.LowerRightCorner.Y) *invH);
\r
242 const video::SColor temp[4] =
\r
250 const video::SColor* const useColor = colors ? colors : temp;
\r
252 chooseMaterial2D();
\r
253 if ( !setMaterialTexture(0, texture) )
\r
256 setRenderStates2DMode(useColor[0].getAlpha() < 255 || useColor[1].getAlpha() < 255 ||
\r
257 useColor[2].getAlpha() < 255 || useColor[3].getAlpha() < 255,
\r
258 true, useAlphaChannelOfTexture);
\r
259 lockRenderStateMode();
\r
261 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
263 bool useScissorTest = false;
\r
264 if (clipRect && clipRect->isValid())
\r
266 useScissorTest = true;
\r
267 glEnable(GL_SCISSOR_TEST);
\r
268 glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
\r
269 clipRect->getWidth(), clipRect->getHeight());
\r
272 f32 left = (f32)destRect.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
273 f32 right = (f32)destRect.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
274 f32 down = 2.f - (f32)destRect.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
275 f32 top = 2.f - (f32)destRect.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
277 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
\r
278 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
\r
279 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
\r
280 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
\r
281 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
283 drawMeshBuffer(MBTriangleFanSize4);
\r
285 if (useScissorTest)
\r
286 glDisable(GL_SCISSOR_TEST);
\r
288 unlockRenderStateMode();
\r
293 void CWebGL1Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)
\r
298 chooseMaterial2D();
\r
299 if ( !setMaterialTexture(0, texture) )
\r
302 setRenderStates2DMode(false, true, true);
\r
303 lockRenderStateMode();
\r
305 MBTriangleFanSize4->Vertices[0].Pos = core::vector3df(-1.f, 1.f, 0.f);
\r
306 MBTriangleFanSize4->Vertices[1].Pos = core::vector3df(1.f, 1.f, 0.f);
\r
307 MBTriangleFanSize4->Vertices[2].Pos = core::vector3df(1.f, -1.f, 0.f);
\r
308 MBTriangleFanSize4->Vertices[3].Pos = core::vector3df(-1.f, -1.f, 0.f);
\r
310 f32 modificator = (flip) ? 1.f : 0.f;
\r
312 MBTriangleFanSize4->Vertices[0].TCoords = core::vector2df(0.f, 0.f + modificator);
\r
313 MBTriangleFanSize4->Vertices[1].TCoords = core::vector2df(1.f, 0.f + modificator);
\r
314 MBTriangleFanSize4->Vertices[2].TCoords = core::vector2df(1.f, 1.f - modificator);
\r
315 MBTriangleFanSize4->Vertices[3].TCoords = core::vector2df(0.f, 1.f - modificator);
\r
317 MBTriangleFanSize4->Vertices[0].Color = SColor(0xFFFFFFFF);
\r
318 MBTriangleFanSize4->Vertices[1].Color = SColor(0xFFFFFFFF);
\r
319 MBTriangleFanSize4->Vertices[2].Color = SColor(0xFFFFFFFF);
\r
320 MBTriangleFanSize4->Vertices[3].Color = SColor(0xFFFFFFFF);
\r
322 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
324 drawMeshBuffer(MBTriangleFanSize4);
\r
326 unlockRenderStateMode();
\r
329 void CWebGL1Driver::draw2DImageBatch(const video::ITexture* texture,
\r
330 const core::position2d<s32>& pos,
\r
331 const core::array<core::rect<s32> >& sourceRects,
\r
332 const core::array<s32>& indices, s32 kerningWidth,
\r
333 const core::rect<s32>* clipRect,
\r
334 SColor color, bool useAlphaChannelOfTexture)
\r
339 chooseMaterial2D();
\r
340 if ( !setMaterialTexture(0, texture) )
\r
343 setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);
\r
344 lockRenderStateMode();
\r
346 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
348 bool useScissorTest = false;
\r
349 if (clipRect && clipRect->isValid())
\r
351 useScissorTest = true;
\r
352 glEnable(GL_SCISSOR_TEST);
\r
353 glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
\r
354 clipRect->getWidth(), clipRect->getHeight());
\r
357 const core::dimension2du& ss = texture->getOriginalSize();
\r
358 core::position2d<s32> targetPos(pos);
\r
359 // texcoords need to be flipped horizontally for RTTs
\r
360 const bool isRTT = texture->isRenderTarget();
\r
361 const f32 invW = 1.f / static_cast<f32>(ss.Width);
\r
362 const f32 invH = 1.f / static_cast<f32>(ss.Height);
\r
364 for (u32 i = 0; i < indices.size(); ++i)
\r
366 const s32 currentIndex = indices[i];
\r
367 if (!sourceRects[currentIndex].isValid())
\r
370 const core::rect<f32> tcoords(
\r
371 sourceRects[currentIndex].UpperLeftCorner.X * invW,
\r
372 (isRTT ? sourceRects[currentIndex].LowerRightCorner.Y : sourceRects[currentIndex].UpperLeftCorner.Y) * invH,
\r
373 sourceRects[currentIndex].LowerRightCorner.X * invW,
\r
374 (isRTT ? sourceRects[currentIndex].UpperLeftCorner.Y : sourceRects[currentIndex].LowerRightCorner.Y) * invH);
\r
376 const core::rect<s32> poss(targetPos, sourceRects[currentIndex].getSize());
\r
378 f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
379 f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
380 f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
381 f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
383 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
\r
384 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
\r
385 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
\r
386 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
\r
387 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
389 drawMeshBuffer(MBTriangleFanSize4);
\r
391 targetPos.X += sourceRects[currentIndex].getWidth();
\r
394 if (useScissorTest)
\r
395 glDisable(GL_SCISSOR_TEST);
\r
397 unlockRenderStateMode();
\r
402 void CWebGL1Driver::draw2DImageBatch(const video::ITexture* texture,
\r
403 const core::array<core::position2d<s32> >& positions,
\r
404 const core::array<core::rect<s32> >& sourceRects,
\r
405 const core::rect<s32>* clipRect,
\r
406 SColor color, bool useAlphaChannelOfTexture)
\r
411 const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
\r
415 chooseMaterial2D();
\r
416 if ( !setMaterialTexture(0, texture) )
\r
419 setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);
\r
420 lockRenderStateMode();
\r
422 for (u32 i = 0; i < drawCount; i++)
\r
424 core::position2d<s32> targetPos = positions[i];
\r
425 core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;
\r
426 // This needs to be signed as it may go negative.
\r
427 core::dimension2d<s32> sourceSize(sourceRects[i].getSize());
\r
431 if (targetPos.X < clipRect->UpperLeftCorner.X)
\r
433 sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
\r
434 if (sourceSize.Width <= 0)
\r
437 sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
\r
438 targetPos.X = clipRect->UpperLeftCorner.X;
\r
441 if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
\r
443 sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
\r
444 if (sourceSize.Width <= 0)
\r
448 if (targetPos.Y < clipRect->UpperLeftCorner.Y)
\r
450 sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
451 if (sourceSize.Height <= 0)
\r
454 sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
\r
455 targetPos.Y = clipRect->UpperLeftCorner.Y;
\r
458 if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
\r
460 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
\r
461 if (sourceSize.Height <= 0)
\r
466 // clip these coordinates
\r
468 if (targetPos.X < 0)
\r
470 sourceSize.Width += targetPos.X;
\r
471 if (sourceSize.Width <= 0)
\r
474 sourcePos.X -= targetPos.X;
\r
478 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
480 if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
\r
482 sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
\r
483 if (sourceSize.Width <= 0)
\r
487 if (targetPos.Y < 0)
\r
489 sourceSize.Height += targetPos.Y;
\r
490 if (sourceSize.Height <= 0)
\r
493 sourcePos.Y -= targetPos.Y;
\r
497 if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
\r
499 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
\r
500 if (sourceSize.Height <= 0)
\r
504 // ok, we've clipped everything.
\r
507 core::rect<f32> tcoords;
\r
508 tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;
\r
509 tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;
\r
510 tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);
\r
511 tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);
\r
513 const core::rect<s32> poss(targetPos, sourceSize);
\r
515 f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
516 f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
517 f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
518 f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
520 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
\r
521 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
\r
522 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
\r
523 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
\r
524 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
526 drawMeshBuffer(MBTriangleFanSize4);
\r
529 unlockRenderStateMode();
\r
532 //! draw a 2d rectangle
\r
533 void CWebGL1Driver::draw2DRectangle(SColor color,
\r
534 const core::rect<s32>& position,
\r
535 const core::rect<s32>* clip)
\r
537 chooseMaterial2D();
\r
538 setMaterialTexture(0, 0);
\r
540 setRenderStates2DMode(color.getAlpha() < 255, false, false);
\r
541 lockRenderStateMode();
\r
543 core::rect<s32> pos = position;
\r
546 pos.clipAgainst(*clip);
\r
548 if (!pos.isValid())
\r
551 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
553 f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
554 f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
555 f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
556 f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
558 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, 0, 0);
\r
559 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, 0, 0);
\r
560 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, 0, 0);
\r
561 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, 0, 0);
\r
562 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
564 drawMeshBuffer(MBTriangleFanSize4);
\r
566 unlockRenderStateMode();
\r
569 void CWebGL1Driver::draw2DRectangle(const core::rect<s32>& position,
\r
570 SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
\r
571 const core::rect<s32>* clip)
\r
573 core::rect<s32> pos = position;
\r
576 pos.clipAgainst(*clip);
\r
578 if (!pos.isValid())
\r
581 chooseMaterial2D();
\r
582 setMaterialTexture(0, 0);
\r
584 setRenderStates2DMode(colorLeftUp.getAlpha() < 255 ||
\r
585 colorRightUp.getAlpha() < 255 ||
\r
586 colorLeftDown.getAlpha() < 255 ||
\r
587 colorRightDown.getAlpha() < 255, false, false);
\r
588 lockRenderStateMode();
\r
590 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
592 f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
593 f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
594 f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
595 f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
597 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, colorLeftUp, 0, 0);
\r
598 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, colorRightUp, 0, 0);
\r
599 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, colorRightDown, 0, 0);
\r
600 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);
\r
601 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
603 drawMeshBuffer(MBTriangleFanSize4);
\r
605 unlockRenderStateMode();
\r
608 //! Draws a 2d line.
\r
609 void CWebGL1Driver::draw2DLine(const core::position2d<s32>& start, const core::position2d<s32>& end, SColor color)
\r
612 drawPixel(start.X, start.Y, color);
\r
615 chooseMaterial2D();
\r
616 setMaterialTexture(0, 0);
\r
618 setRenderStates2DMode(color.getAlpha() < 255, false, false);
\r
619 lockRenderStateMode();
\r
621 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
623 f32 startX = (f32)start.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
624 f32 endX = (f32)end.X / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
625 f32 startY = 2.f - (f32)start.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
626 f32 endY = 2.f - (f32)end.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
628 MBLinesSize2->Vertices[0] = S3DVertex(startX, startY, 0, 0, 0, 1, color, 0, 0);
\r
629 MBLinesSize2->Vertices[1] = S3DVertex(endX, endY, 0, 0, 0, 1, color, 1, 1);
\r
630 MBLinesSize2->setDirty(scene::EBT_VERTEX);
\r
632 drawMeshBuffer(MBLinesSize2);
\r
634 unlockRenderStateMode();
\r
638 void CWebGL1Driver::drawPixel(u32 x, u32 y, const SColor & color)
\r
640 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
\r
641 if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)
\r
644 chooseMaterial2D();
\r
645 setMaterialTexture(0, 0);
\r
647 setRenderStates2DMode(color.getAlpha() < 255, false, false);
\r
648 lockRenderStateMode();
\r
650 f32 X = (f32)x / (f32)renderTargetSize.Width * 2.f - 1.f;
\r
651 f32 Y = 2.f - (f32)y / (f32)renderTargetSize.Height * 2.f - 1.f;
\r
653 MBPointsSize1->Vertices[0] = S3DVertex(X, Y, 0, 0, 0, 1, color, 0, 0);
\r
654 MBPointsSize1->setDirty(scene::EBT_VERTEX);
\r
656 drawMeshBuffer(MBPointsSize1);
\r
658 unlockRenderStateMode();
\r
661 void CWebGL1Driver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color)
\r
663 MBLinesSize2->Vertices[0] = S3DVertex(start.X, start.Y, start.Z, 0, 0, 1, color, 0, 0);
\r
664 MBLinesSize2->Vertices[1] = S3DVertex(end.X, end.Y, end.Z, 0, 0, 1, color, 0, 0);
\r
665 MBLinesSize2->setDirty(scene::EBT_VERTEX);
\r
667 drawMeshBuffer(MBLinesSize2);
\r
670 void CWebGL1Driver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible)
\r
672 static bool first = true;
\r
676 os::Printer::log("WebGL1 driver does not yet support drawStencilShadowVolume", ELL_WARNING);
\r
677 os::Printer::log(__FILE__, irr::core::stringc(__LINE__).c_str(), ELL_WARNING);
\r
681 void CWebGL1Driver::drawStencilShadow(bool clearStencilBuffer,
\r
682 video::SColor leftUpEdge,
\r
683 video::SColor rightUpEdge,
\r
684 video::SColor leftDownEdge,
\r
685 video::SColor rightDownEdge)
\r
687 // NOTE: Might work, but untested as drawStencilShadowVolume is not yet supported.
\r
689 if (!StencilBuffer)
\r
692 chooseMaterial2D();
\r
693 setMaterialTexture(0, 0);
\r
695 setRenderStates2DMode(true, false, false);
\r
696 lockRenderStateMode();
\r
698 CacheHandler->setDepthMask(false);
\r
699 CacheHandler->setColorMask(ECP_ALL);
\r
701 CacheHandler->setBlend(true);
\r
702 CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\r
704 glEnable(GL_STENCIL_TEST);
\r
705 glStencilFunc(GL_NOTEQUAL, 0, ~0);
\r
706 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
\r
708 MBTriangleFanSize4->Vertices[0] = S3DVertex(-1.f, 1.f, 0.9f, 0, 0, 1, leftDownEdge, 0, 0);
\r
709 MBTriangleFanSize4->Vertices[1] = S3DVertex(1.f, 1.f, 0.9f, 0, 0, 1, leftUpEdge, 0, 0);
\r
710 MBTriangleFanSize4->Vertices[2] = S3DVertex(1.f, -1.f, 0.9f, 0, 0, 1, rightUpEdge, 0, 0);
\r
711 MBTriangleFanSize4->Vertices[3] = S3DVertex(-1.f, -1.f, 0.9f, 0, 0, 1, rightDownEdge, 0, 0);
\r
712 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);
\r
714 drawMeshBuffer(MBTriangleFanSize4);
\r
716 unlockRenderStateMode();
\r
718 if (clearStencilBuffer)
\r
719 glClear(GL_STENCIL_BUFFER_BIT);
\r
721 glDisable(GL_STENCIL_TEST);
\r
724 GLenum CWebGL1Driver::getZBufferBits() const
\r
726 // TODO: Never used, so not sure what this was really about (zbuffer used by device? Or for RTT's?)
\r
727 // If it's about device it might need a check like: GLint depthBits; glGetIntegerv(GL_DEPTH_BITS, &depthBits);
\r
728 // If it's about textures it might need a check for IRR_WEBGL_depth_texture
\r
732 switch (Params.ZBufferBits)
\r
734 #if defined(GL_OES_depth24)
\r
736 bits = GL_DEPTH_COMPONENT24_OES;
\r
739 #if defined(GL_OES_depth32)
\r
741 bits = GL_DEPTH_COMPONENT32_OES;
\r
745 bits = GL_DEPTH_COMPONENT16_OES;
\r
752 bool CWebGL1Driver::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,
\r
753 GLenum& pixelType, void(**converter)(const void*, s32, void*)) const
\r
755 bool supported = false;
\r
756 pixelFormat = GL_RGBA;
\r
757 pixelType = GL_UNSIGNED_BYTE;
\r
764 pixelFormat = GL_RGBA;
\r
765 pixelType = GL_UNSIGNED_SHORT_5_5_5_1;
\r
766 *converter = CColorConverter::convert_A1R5G5B5toR5G5B5A1;
\r
770 pixelFormat = GL_RGB;
\r
771 pixelType = GL_UNSIGNED_SHORT_5_6_5;
\r
775 pixelFormat = GL_RGB;
\r
776 pixelType = GL_UNSIGNED_BYTE;
\r
779 // WebGL doesn't seem to support GL_BGRA so we always convert
\r
781 pixelFormat = GL_RGBA;
\r
782 *converter = CColorConverter::convert_A8R8G8B8toA8B8G8R8;
\r
783 pixelType = GL_UNSIGNED_BYTE;
\r
785 #ifdef GL_EXT_texture_compression_dxt1
\r
787 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_s3tc) )
\r
790 pixelFormat = GL_RGBA;
\r
791 pixelType = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
\r
795 #ifdef GL_EXT_texture_compression_s3tc
\r
798 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_s3tc) )
\r
801 pixelFormat = GL_RGBA;
\r
802 pixelType = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
\r
806 #ifdef GL_EXT_texture_compression_s3tc
\r
809 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_s3tc) )
\r
812 pixelFormat = GL_RGBA;
\r
813 pixelType = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
\r
817 #ifdef GL_IMG_texture_compression_pvrtc
\r
818 case ECF_PVRTC_RGB2:
\r
819 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )
\r
822 pixelFormat = GL_RGB;
\r
823 pixelType = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
\r
827 #ifdef GL_IMG_texture_compression_pvrtc
\r
828 case ECF_PVRTC_ARGB2:
\r
829 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )
\r
832 pixelFormat = GL_RGBA;
\r
833 pixelType = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
\r
837 #ifdef GL_IMG_texture_compression_pvrtc
\r
838 case ECF_PVRTC_RGB4:
\r
839 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )
\r
842 pixelFormat = GL_RGB;
\r
843 pixelType = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
\r
847 #ifdef GL_IMG_texture_compression_pvrtc
\r
848 case ECF_PVRTC_ARGB4:
\r
849 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )
\r
852 pixelFormat = GL_RGBA;
\r
853 pixelType = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
\r
857 #ifdef GL_IMG_texture_compression_pvrtc2
\r
858 case ECF_PVRTC2_ARGB2:
\r
859 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )
\r
862 pixelFormat = GL_RGBA;
\r
863 pixelType = GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG;
\r
867 #ifdef GL_IMG_texture_compression_pvrtc2
\r
868 case ECF_PVRTC2_ARGB4:
\r
869 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )
\r
872 pixelFormat = GL_RGBA;
\r
873 pixelType = GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG;
\r
877 #ifdef GL_OES_compressed_ETC1_RGB8_texture
\r
879 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_etc1) )
\r
882 pixelFormat = GL_RGB;
\r
883 pixelType = GL_ETC1_RGB8_OES;
\r
887 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available
\r
890 pixelFormat = GL_RGB;
\r
891 pixelType = GL_COMPRESSED_RGB8_ETC2;
\r
894 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available
\r
895 case ECF_ETC2_ARGB:
\r
897 pixelFormat = GL_RGBA;
\r
898 pixelType = GL_COMPRESSED_RGBA8_ETC2_EAC;
\r
902 if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_depth_texture))
\r
905 pixelFormat = GL_DEPTH_COMPONENT;
\r
906 pixelType = GL_UNSIGNED_SHORT;
\r
910 if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_depth_texture))
\r
912 // NOTE: There is still no guarantee it will return a 32 bit depth buffer. It might convert stuff internally to 16 bit :-(
\r
914 pixelFormat = GL_DEPTH_COMPONENT;
\r
915 pixelType = GL_UNSIGNED_INT;
\r
919 if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_depth_texture))
\r
922 pixelFormat = 0x84F9; // GL_DEPTH_STENCIL
\r
923 pixelType = 0x84FA; // UNSIGNED_INT_24_8_WEBGL
\r
927 // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)
\r
930 // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)
\r
933 // Does not seem to be supported in WebGL so far
\r
936 // Does not seem to be supported in WebGL so far
\r
939 // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)
\r
942 // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)
\r
944 case ECF_A16B16G16R16F:
\r
945 #if defined(GL_OES_texture_half_float)
\r
946 if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_OES_texture_half_float))
\r
949 pixelFormat = GL_RGBA;
\r
950 pixelType = GL_HALF_FLOAT_OES ;
\r
955 // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)
\r
958 // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)
\r
960 case ECF_A32B32G32R32F:
\r
961 #if defined(GL_OES_texture_float)
\r
962 if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_OES_texture_half_float))
\r
965 pixelFormat = GL_RGBA;
\r
966 pixelType = GL_FLOAT ;
\r
974 // ES 2.0 says internalFormat must match pixelFormat (chapter 3.7.1 in Spec).
\r
975 // Doesn't mention if "match" means "equal" or some other way of matching, but
\r
976 // some bug on Emscripten and browsing discussions by others lead me to believe
\r
977 // it means they have to be equal. Note that this was different in OpenGL.
\r
978 internalFormat = pixelFormat;
\r
984 scene::SMeshBuffer* CWebGL1Driver::createSimpleMeshBuffer(irr::u32 numVertices, scene::E_PRIMITIVE_TYPE primitiveType, scene::E_HARDWARE_MAPPING vertexMappingHint, scene::E_HARDWARE_MAPPING indexMappingHint) const
\r
986 scene::SMeshBuffer* mbResult = new scene::SMeshBuffer();
\r
987 mbResult->Vertices.set_used(numVertices);
\r
988 mbResult->Indices.set_used(numVertices);
\r
989 for ( irr::u32 i=0; i < numVertices; ++i )
\r
990 mbResult->Indices[i] = i;
\r
992 mbResult->setPrimitiveType(primitiveType);
\r
993 mbResult->setHardwareMappingHint(vertexMappingHint, scene::EBT_VERTEX);
\r
994 mbResult->setHardwareMappingHint(indexMappingHint, scene::EBT_INDEX);
\r
995 mbResult->setDirty();
\r
1000 bool CWebGL1Driver::genericDriverInit(const core::dimension2d<u32>& screenSize, bool stencilBuffer)
\r
1002 Name = glGetString(GL_VERSION);
\r
1005 // print renderer information
\r
1006 VendorName = glGetString(GL_VENDOR);
\r
1007 os::Printer::log(VendorName.c_str(), ELL_INFORMATION);
\r
1009 // load extensions
\r
1010 initWebGLExtensions();
\r
1012 // reset cache handler
\r
1013 delete CacheHandler;
\r
1014 CacheHandler = new COGLES2CacheHandler(this);
\r
1016 StencilBuffer = stencilBuffer;
\r
1018 DriverAttributes->setAttribute("MaxTextures", (s32)Feature.MaxTextureUnits);
\r
1019 DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Feature.MaxTextureUnits);
\r
1020 DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy);
\r
1021 DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices);
\r
1022 DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize);
\r
1023 DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias);
\r
1024 DriverAttributes->setAttribute("Version", Version);
\r
1025 DriverAttributes->setAttribute("AntiAlias", AntiAlias);
\r
1027 glPixelStorei(GL_PACK_ALIGNMENT, 1);
\r
1029 UserClipPlane.reallocate(0);
\r
1031 for (s32 i = 0; i < ETS_COUNT; ++i)
\r
1032 setTransform(static_cast<E_TRANSFORMATION_STATE>(i), core::IdentityMatrix);
\r
1034 setAmbientLight(SColorf(0.0f, 0.0f, 0.0f, 0.0f));
\r
1035 glClearDepthf(1.0f);
\r
1037 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
\r
1038 glFrontFace(GL_CW);
\r
1040 // create material renderers
\r
1041 createMaterialRenderers();
\r
1043 // set the renderstates
\r
1044 setRenderStates3DMode();
\r
1047 setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
\r
1049 // create matrix for flipping textures
\r
1050 TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0, 0), core::vector2df(0, 1.0f), core::vector2df(1.0f, -1.0f));
\r
1052 // We need to reset once more at the beginning of the first rendering.
\r
1053 // This fixes problems with intermediate changes to the material during texture load.
\r
1054 ResetRenderStates = true;
\r
1056 testGLError(__LINE__);
\r
1061 void CWebGL1Driver::initWebGLExtensions()
\r
1063 // Stuff still a little bit hacky as we derive from ES2Driver with it's own extensions.
\r
1064 // We only get the feature-strings from WebGLExtensions.
\r
1068 WebGLExtensions.getGLExtensions();
\r
1070 // TODO: basically copied ES2 implementation, so not certain if 100% correct for WebGL
\r
1072 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &val);
\r
1073 Feature.MaxTextureUnits = static_cast<u8>(val);
\r
1075 #ifdef GL_EXT_texture_filter_anisotropic
\r
1076 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_EXT_texture_filter_anisotropic) )
\r
1078 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &val);
\r
1079 MaxAnisotropy = static_cast<u8>(val);
\r
1083 if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_OES_element_index_uint) ) // note: WebGL2 won't need extension as that got default there
\r
1085 MaxIndices=0xffffffff;
\r
1088 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val);
\r
1089 MaxTextureSize=static_cast<u32>(val);
\r
1091 #ifdef GL_MAX_TEXTURE_LOD_BIAS_EXT
\r
1092 // TODO: Found no info about this anywhere. It's no extension in WebGL
\r
1093 // and GL_MAX_TEXTURE_LOD_BIAS_EXT doesn't seem to be part of gl2ext.h in emscripten
\r
1094 glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &MaxTextureLODBias);
\r
1097 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, DimAliasedLine);
\r
1098 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, DimAliasedPoint);
\r
1099 Feature.MaxTextureUnits = core::min_(Feature.MaxTextureUnits, static_cast<u8>(MATERIAL_MAX_TEXTURES));
\r
1101 Feature.ColorAttachment = 1;
\r
1104 } // end namespace video
\r
1105 } // end namespace irr
\r
1107 #endif // _IRR_COMPILE_WITH_WEBGL1_
\r
1111 #ifndef _IRR_COMPILE_WITH_WEBGL1_
\r
1114 class IFileSystem;
\r
1120 #ifndef _IRR_COMPILE_WITH_WEBGL1_
\r
1121 class IVideoDriver;
\r
1122 class IContextManager;
\r
1125 IVideoDriver* createWebGL1Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager)
\r
1127 #ifdef _IRR_COMPILE_WITH_WEBGL1_
\r
1128 CWebGL1Driver* driver = new CWebGL1Driver(params, io, contextManager);
\r
1129 driver->genericDriverInit(params.WindowSize, params.Stencilbuffer); // don't call in constructor, it uses virtual function calls of driver
\r
1133 #endif // _IRR_COMPILE_WITH_WEBGL1_
\r
1136 } // end namespace
\r
1137 } // end namespace
\r