1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\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 "CNullDriver.h"
\r
8 #include "CAttributes.h"
\r
9 #include "IReadFile.h"
\r
10 #include "IWriteFile.h"
\r
11 #include "IImageLoader.h"
\r
12 #include "IImageWriter.h"
\r
13 #include "IMaterialRenderer.h"
\r
14 #include "IAnimatedMeshSceneNode.h"
\r
15 #include "CMeshManipulator.h"
\r
16 #include "CColorConverter.h"
\r
17 #include "IReferenceCounted.h"
\r
18 #include "IRenderTarget.h"
\r
26 //! creates a loader which is able to load windows bitmaps
\r
27 IImageLoader* createImageLoaderBMP();
\r
29 //! creates a loader which is able to load jpeg images
\r
30 IImageLoader* createImageLoaderJPG();
\r
32 //! creates a loader which is able to load targa images
\r
33 IImageLoader* createImageLoaderTGA();
\r
35 //! creates a loader which is able to load png images
\r
36 IImageLoader* createImageLoaderPNG();
\r
38 //! creates a writer which is able to save jpg images
\r
39 IImageWriter* createImageWriterJPG();
\r
41 //! creates a writer which is able to save png images
\r
42 IImageWriter* createImageWriterPNG();
\r
46 CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
\r
47 : SharedRenderTarget(0), CurrentRenderTarget(0), CurrentRenderTargetSize(0, 0), FileSystem(io), MeshManipulator(0),
\r
48 ViewPort(0, 0, 0, 0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500),
\r
49 TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false)
\r
52 setDebugName("CNullDriver");
\r
55 DriverAttributes = new io::CAttributes();
\r
56 DriverAttributes->addInt("MaxTextures", MATERIAL_MAX_TEXTURES);
\r
57 DriverAttributes->addInt("MaxSupportedTextures", MATERIAL_MAX_TEXTURES);
\r
58 DriverAttributes->addInt("MaxAnisotropy", 1);
\r
59 // DriverAttributes->addInt("MaxUserClipPlanes", 0);
\r
60 // DriverAttributes->addInt("MaxAuxBuffers", 0);
\r
61 DriverAttributes->addInt("MaxMultipleRenderTargets", 1);
\r
62 DriverAttributes->addInt("MaxIndices", -1);
\r
63 DriverAttributes->addInt("MaxTextureSize", -1);
\r
64 // DriverAttributes->addInt("MaxGeometryVerticesOut", 0);
\r
65 // DriverAttributes->addFloat("MaxTextureLODBias", 0.f);
\r
66 DriverAttributes->addInt("Version", 1);
\r
67 // DriverAttributes->addInt("ShaderLanguageVersion", 0);
\r
68 // DriverAttributes->addInt("AntiAlias", 0);
\r
72 setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true);
\r
73 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);
\r
74 setTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS, true);
\r
75 setTextureCreationFlag(ETCF_ALLOW_MEMORY_COPY, true);
\r
77 ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(screenSize));
\r
79 // create manipulator
\r
80 MeshManipulator = new scene::CMeshManipulator();
\r
85 // create surface loaders and writers
\r
86 SurfaceLoader.push_back(video::createImageLoaderTGA());
\r
87 SurfaceLoader.push_back(video::createImageLoaderPNG());
\r
88 SurfaceLoader.push_back(video::createImageLoaderJPG());
\r
89 SurfaceLoader.push_back(video::createImageLoaderBMP());
\r
91 SurfaceWriter.push_back(video::createImageWriterJPG());
\r
92 SurfaceWriter.push_back(video::createImageWriterPNG());
\r
95 // set ExposedData to 0
\r
96 memset((void*)&ExposedData, 0, sizeof(ExposedData));
\r
97 for (u32 i=0; i<video::EVDF_COUNT; ++i)
\r
98 FeatureEnabled[i]=true;
\r
100 InitMaterial2D.AntiAliasing=video::EAAM_OFF;
\r
101 InitMaterial2D.Lighting=false;
\r
102 InitMaterial2D.ZWriteEnable=video::EZW_OFF;
\r
103 InitMaterial2D.ZBuffer=video::ECFN_DISABLED;
\r
104 InitMaterial2D.UseMipMaps=false;
\r
105 for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
\r
107 InitMaterial2D.TextureLayer[i].BilinearFilter=false;
\r
108 InitMaterial2D.TextureLayer[i].TextureWrapU=video::ETC_REPEAT;
\r
109 InitMaterial2D.TextureLayer[i].TextureWrapV=video::ETC_REPEAT;
\r
110 InitMaterial2D.TextureLayer[i].TextureWrapW = video::ETC_REPEAT;
\r
112 OverrideMaterial2D=InitMaterial2D;
\r
117 CNullDriver::~CNullDriver()
\r
119 if (DriverAttributes)
\r
120 DriverAttributes->drop();
\r
123 FileSystem->drop();
\r
125 if (MeshManipulator)
\r
126 MeshManipulator->drop();
\r
128 removeAllRenderTargets();
\r
130 deleteAllTextures();
\r
133 for (i=0; i<SurfaceLoader.size(); ++i)
\r
134 SurfaceLoader[i]->drop();
\r
136 for (i=0; i<SurfaceWriter.size(); ++i)
\r
137 SurfaceWriter[i]->drop();
\r
139 // delete material renderers
\r
140 deleteMaterialRenders();
\r
142 // delete hardware mesh buffers
\r
143 removeAllHardwareBuffers();
\r
147 //! Adds an external surface loader to the engine.
\r
148 void CNullDriver::addExternalImageLoader(IImageLoader* loader)
\r
154 SurfaceLoader.push_back(loader);
\r
158 //! Adds an external surface writer to the engine.
\r
159 void CNullDriver::addExternalImageWriter(IImageWriter* writer)
\r
165 SurfaceWriter.push_back(writer);
\r
169 //! Retrieve the number of image loaders
\r
170 u32 CNullDriver::getImageLoaderCount() const
\r
172 return SurfaceLoader.size();
\r
176 //! Retrieve the given image loader
\r
177 IImageLoader* CNullDriver::getImageLoader(u32 n)
\r
179 if (n < SurfaceLoader.size())
\r
180 return SurfaceLoader[n];
\r
185 //! Retrieve the number of image writers
\r
186 u32 CNullDriver::getImageWriterCount() const
\r
188 return SurfaceWriter.size();
\r
192 //! Retrieve the given image writer
\r
193 IImageWriter* CNullDriver::getImageWriter(u32 n)
\r
195 if (n < SurfaceWriter.size())
\r
196 return SurfaceWriter[n];
\r
201 //! deletes all textures
\r
202 void CNullDriver::deleteAllTextures()
\r
204 // we need to remove previously set textures which might otherwise be kept in the
\r
205 // last set material member. Could be optimized to reduce state changes.
\r
206 setMaterial(SMaterial());
\r
208 // reset render targets.
\r
210 for (u32 i=0; i<RenderTargets.size(); ++i)
\r
211 RenderTargets[i]->setTexture(0, 0);
\r
213 // remove textures.
\r
215 for (u32 i=0; i<Textures.size(); ++i)
\r
216 Textures[i].Surface->drop();
\r
220 SharedDepthTextures.clear();
\r
223 bool CNullDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
\r
225 PrimitivesDrawn = 0;
\r
229 bool CNullDriver::endScene()
\r
231 FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn);
\r
232 updateAllHardwareBuffers();
\r
233 updateAllOcclusionQueries();
\r
238 //! Disable a feature of the driver.
\r
239 void CNullDriver::disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag)
\r
241 FeatureEnabled[feature]=!flag;
\r
245 //! queries the features of the driver, returns true if feature is available
\r
246 bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
\r
252 //! Get attributes of the actual video driver
\r
253 const io::IAttributes& CNullDriver::getDriverAttributes() const
\r
255 return *DriverAttributes;
\r
259 //! sets transformation
\r
260 void CNullDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
\r
265 //! Returns the transformation set by setTransform
\r
266 const core::matrix4& CNullDriver::getTransform(E_TRANSFORMATION_STATE state) const
\r
268 return TransformationMatrix;
\r
272 //! sets a material
\r
273 void CNullDriver::setMaterial(const SMaterial& material)
\r
278 //! Removes a texture from the texture cache and deletes it, freeing lot of
\r
280 void CNullDriver::removeTexture(ITexture* texture)
\r
285 for (u32 i=0; i<Textures.size(); ++i)
\r
287 if (Textures[i].Surface == texture)
\r
297 //! Removes all texture from the texture cache and deletes them, freeing lot of
\r
299 void CNullDriver::removeAllTextures()
\r
301 setMaterial ( SMaterial() );
\r
302 deleteAllTextures();
\r
306 //! Returns a texture by index
\r
307 ITexture* CNullDriver::getTextureByIndex(u32 i)
\r
309 if ( i < Textures.size() )
\r
310 return Textures[i].Surface;
\r
316 //! Returns amount of textures currently loaded
\r
317 u32 CNullDriver::getTextureCount() const
\r
319 return Textures.size();
\r
323 //! Renames a texture
\r
324 void CNullDriver::renameTexture(ITexture* texture, const io::path& newName)
\r
326 // we can do a const_cast here safely, the name of the ITexture interface
\r
327 // is just readonly to prevent the user changing the texture name without invoking
\r
328 // this method, because the textures will need resorting afterwards
\r
330 io::SNamedPath& name = const_cast<io::SNamedPath&>(texture->getName());
\r
331 name.setPath(newName);
\r
336 ITexture* CNullDriver::addTexture(const core::dimension2d<u32>& size, const io::path& name, ECOLOR_FORMAT format)
\r
338 if (0 == name.size())
\r
340 os::Printer::log("Could not create ITexture, texture needs to have a non-empty name.", ELL_WARNING);
\r
344 IImage* image = new CImage(format, size);
\r
347 core::array<IImage*> imageArray(1);
\r
348 imageArray.push_back(image);
\r
350 if (checkImage(imageArray))
\r
352 t = createDeviceDependentTexture(name, image);
\r
366 ITexture* CNullDriver::addTexture(const io::path& name, IImage* image)
\r
368 if (0 == name.size())
\r
370 os::Printer::log("Could not create ITexture, texture needs to have a non-empty name.", ELL_WARNING);
\r
379 core::array<IImage*> imageArray(1);
\r
380 imageArray.push_back(image);
\r
382 if (checkImage(imageArray))
\r
384 t = createDeviceDependentTexture(name, image);
\r
396 ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX, IImage* imageNegX, IImage* imagePosY,
\r
397 IImage* imageNegY, IImage* imagePosZ, IImage* imageNegZ)
\r
399 if (0 == name.size() || !imagePosX || !imageNegX || !imagePosY || !imageNegY || !imagePosZ || !imageNegZ)
\r
404 core::array<IImage*> imageArray(6);
\r
405 imageArray.push_back(imagePosX);
\r
406 imageArray.push_back(imageNegX);
\r
407 imageArray.push_back(imagePosY);
\r
408 imageArray.push_back(imageNegY);
\r
409 imageArray.push_back(imagePosZ);
\r
410 imageArray.push_back(imageNegZ);
\r
412 if (checkImage(imageArray))
\r
414 t = createDeviceDependentTextureCubemap(name, imageArray);
\r
426 ITexture* CNullDriver::addTextureCubemap(const irr::u32 sideLen, const io::path& name, ECOLOR_FORMAT format)
\r
428 if ( 0 == sideLen )
\r
431 if (0 == name.size())
\r
433 os::Printer::log("Could not create ITexture, texture needs to have a non-empty name.", ELL_WARNING);
\r
437 core::array<IImage*> imageArray(6);
\r
438 for ( int i=0; i < 6; ++i )
\r
439 imageArray.push_back(new CImage(format, core::dimension2du(sideLen, sideLen)));
\r
442 if (checkImage(imageArray))
\r
444 t = createDeviceDependentTextureCubemap(name, imageArray);
\r
453 for ( int i=0; i < 6; ++i )
\r
454 imageArray[i]->drop();
\r
459 //! loads a Texture
\r
460 ITexture* CNullDriver::getTexture(const io::path& filename)
\r
462 // Identify textures by their absolute filenames if possible.
\r
463 const io::path absolutePath = FileSystem->getAbsolutePath(filename);
\r
465 ITexture* texture = findTexture(absolutePath);
\r
468 texture->updateSource(ETS_FROM_CACHE);
\r
472 // Then try the raw filename, which might be in an Archive
\r
473 texture = findTexture(filename);
\r
476 texture->updateSource(ETS_FROM_CACHE);
\r
480 // Now try to open the file using the complete path.
\r
481 io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath);
\r
485 // Try to open it using the raw filename.
\r
486 file = FileSystem->createAndOpenFile(filename);
\r
491 // Re-check name for actual archive names
\r
492 texture = findTexture(file->getFileName());
\r
495 texture->updateSource(ETS_FROM_CACHE);
\r
500 texture = loadTextureFromFile(file);
\r
505 texture->updateSource(ETS_FROM_FILE);
\r
506 addTexture(texture);
\r
507 texture->drop(); // drop it because we created it, one grab too much
\r
510 os::Printer::log("Could not load texture", filename, ELL_ERROR);
\r
515 os::Printer::log("Could not open file of texture", filename, ELL_WARNING);
\r
521 //! loads a Texture
\r
522 ITexture* CNullDriver::getTexture(io::IReadFile* file)
\r
524 ITexture* texture = 0;
\r
528 texture = findTexture(file->getFileName());
\r
532 texture->updateSource(ETS_FROM_CACHE);
\r
536 texture = loadTextureFromFile(file);
\r
540 texture->updateSource(ETS_FROM_FILE);
\r
541 addTexture(texture);
\r
542 texture->drop(); // drop it because we created it, one grab too much
\r
546 os::Printer::log("Could not load texture", file->getFileName(), ELL_WARNING);
\r
553 //! opens the file and loads it into the surface
\r
554 video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName )
\r
556 ITexture* texture = 0;
\r
558 E_TEXTURE_TYPE type = ETT_2D;
\r
560 core::array<IImage*> imageArray = createImagesFromFile(file, &type);
\r
562 if (checkImage(imageArray))
\r
567 texture = createDeviceDependentTexture(hashName.size() ? hashName : file->getFileName(), imageArray[0]);
\r
570 if (imageArray.size() >= 6 && imageArray[0] && imageArray[1] && imageArray[2] && imageArray[3] && imageArray[4] && imageArray[5])
\r
572 texture = createDeviceDependentTextureCubemap(hashName.size() ? hashName : file->getFileName(), imageArray);
\r
576 _IRR_DEBUG_BREAK_IF(true);
\r
581 os::Printer::log("Loaded texture", file->getFileName(), ELL_DEBUG);
\r
584 for (u32 i = 0; i < imageArray.size(); ++i)
\r
587 imageArray[i]->drop();
\r
594 //! adds a surface, not loaded or created by the Irrlicht Engine
\r
595 void CNullDriver::addTexture(video::ITexture* texture)
\r
600 s.Surface = texture;
\r
603 Textures.push_back(s);
\r
605 // the new texture is now at the end of the texture list. when searching for
\r
606 // the next new texture, the texture array will be sorted and the index of this texture
\r
607 // will be changed. to let the order be more consistent to the user, sort
\r
608 // the textures now already although this isn't necessary:
\r
615 //! looks if the image is already loaded
\r
616 video::ITexture* CNullDriver::findTexture(const io::path& filename)
\r
619 SDummyTexture dummy(filename, ETT_2D);
\r
620 s.Surface = &dummy;
\r
622 s32 index = Textures.binary_search(s);
\r
624 return Textures[index].Surface;
\r
629 ITexture* CNullDriver::createDeviceDependentTexture(const io::path& name, IImage* image)
\r
631 SDummyTexture* dummy = new SDummyTexture(name, ETT_2D);
\r
632 dummy->setSize(image->getDimension());
\r
636 ITexture* CNullDriver::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)
\r
638 return new SDummyTexture(name, ETT_CUBEMAP);
\r
641 bool CNullDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)
\r
646 bool CNullDriver::setRenderTarget(ITexture* texture, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)
\r
650 // create render target if require.
\r
651 if (!SharedRenderTarget)
\r
652 SharedRenderTarget = addRenderTarget();
\r
654 ITexture* depthTexture = 0;
\r
656 // try to find available depth texture with require size.
\r
657 for (u32 i = 0; i < SharedDepthTextures.size(); ++i)
\r
659 if (SharedDepthTextures[i]->getSize() == texture->getSize())
\r
661 depthTexture = SharedDepthTextures[i];
\r
667 // create depth texture if require.
\r
670 depthTexture = addRenderTargetTexture(texture->getSize(), "IRR_DEPTH_STENCIL", video::ECF_D24S8);
\r
671 SharedDepthTextures.push_back(depthTexture);
\r
674 SharedRenderTarget->setTexture(texture, depthTexture);
\r
676 return setRenderTargetEx(SharedRenderTarget, clearFlag, clearColor, clearDepth, clearStencil);
\r
680 return setRenderTargetEx(0, clearFlag, clearColor, clearDepth, clearStencil);
\r
684 //! sets a viewport
\r
685 void CNullDriver::setViewPort(const core::rect<s32>& area)
\r
690 //! gets the area of the current viewport
\r
691 const core::rect<s32>& CNullDriver::getViewPort() const
\r
697 //! draws a vertex primitive list
\r
698 void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
\r
700 if ((iType==EIT_16BIT) && (vertexCount>65536))
\r
701 os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
\r
702 PrimitivesDrawn += primitiveCount;
\r
706 //! draws a vertex primitive list in 2d
\r
707 void CNullDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
\r
709 if ((iType==EIT_16BIT) && (vertexCount>65536))
\r
710 os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
\r
711 PrimitivesDrawn += primitiveCount;
\r
715 //! Draws a 3d line.
\r
716 void CNullDriver::draw3DLine(const core::vector3df& start,
\r
717 const core::vector3df& end, SColor color)
\r
722 //! Draws a 3d axis aligned box.
\r
723 void CNullDriver::draw3DBox(const core::aabbox3d<f32>& box, SColor color)
\r
725 core::vector3df edges[8];
\r
726 box.getEdges(edges);
\r
728 // TODO: optimize into one big drawIndexPrimitive call.
\r
730 draw3DLine(edges[5], edges[1], color);
\r
731 draw3DLine(edges[1], edges[3], color);
\r
732 draw3DLine(edges[3], edges[7], color);
\r
733 draw3DLine(edges[7], edges[5], color);
\r
734 draw3DLine(edges[0], edges[2], color);
\r
735 draw3DLine(edges[2], edges[6], color);
\r
736 draw3DLine(edges[6], edges[4], color);
\r
737 draw3DLine(edges[4], edges[0], color);
\r
738 draw3DLine(edges[1], edges[0], color);
\r
739 draw3DLine(edges[3], edges[2], color);
\r
740 draw3DLine(edges[7], edges[6], color);
\r
741 draw3DLine(edges[5], edges[4], color);
\r
746 //! draws an 2d image
\r
747 void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos, bool useAlphaChannelOfTexture)
\r
752 draw2DImage(texture,destPos, core::rect<s32>(core::position2d<s32>(0,0),
\r
753 core::dimension2di(texture->getOriginalSize())),
\r
755 SColor(255,255,255,255),
\r
756 useAlphaChannelOfTexture
\r
761 //! draws a set of 2d images, using a color and the alpha channel of the
\r
762 //! texture if desired.
\r
763 void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
\r
764 const core::array<core::position2d<s32> >& positions,
\r
765 const core::array<core::rect<s32> >& sourceRects,
\r
766 const core::rect<s32>* clipRect,
\r
768 bool useAlphaChannelOfTexture)
\r
770 const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
\r
772 for (u32 i=0; i<drawCount; ++i)
\r
774 draw2DImage(texture, positions[i], sourceRects[i],
\r
775 clipRect, color, useAlphaChannelOfTexture);
\r
780 //! Draws a part of the texture into the rectangle.
\r
781 void CNullDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
\r
782 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
\r
783 const video::SColor* const colors, bool useAlphaChannelOfTexture)
\r
785 if (destRect.isValid())
\r
786 draw2DImage(texture, core::position2d<s32>(destRect.UpperLeftCorner),
\r
787 sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff),
\r
788 useAlphaChannelOfTexture);
\r
792 //! Draws a 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
\r
793 void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
\r
794 const core::rect<s32>& sourceRect,
\r
795 const core::rect<s32>* clipRect, SColor color,
\r
796 bool useAlphaChannelOfTexture)
\r
801 //! Draw a 2d rectangle
\r
802 void CNullDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos, const core::rect<s32>* clip)
\r
804 draw2DRectangle(pos, color, color, color, color, clip);
\r
809 //! Draws a 2d rectangle with a gradient.
\r
810 void CNullDriver::draw2DRectangle(const core::rect<s32>& pos,
\r
811 SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
\r
812 const core::rect<s32>* clip)
\r
818 //! Draws a 2d line.
\r
819 void CNullDriver::draw2DLine(const core::position2d<s32>& start,
\r
820 const core::position2d<s32>& end, SColor color)
\r
825 //! returns color format
\r
826 ECOLOR_FORMAT CNullDriver::getColorFormat() const
\r
832 //! returns screen size
\r
833 const core::dimension2d<u32>& CNullDriver::getScreenSize() const
\r
839 //! get current render target
\r
840 IRenderTarget* CNullDriver::getCurrentRenderTarget() const
\r
842 return CurrentRenderTarget;
\r
846 const core::dimension2d<u32>& CNullDriver::getCurrentRenderTargetSize() const
\r
848 if (CurrentRenderTargetSize.Width == 0)
\r
851 return CurrentRenderTargetSize;
\r
855 // returns current frames per second value
\r
856 s32 CNullDriver::getFPS() const
\r
858 return FPSCounter.getFPS();
\r
863 //! returns amount of primitives (mostly triangles) were drawn in the last frame.
\r
864 //! very useful method for statistics.
\r
865 u32 CNullDriver::getPrimitiveCountDrawn( u32 param ) const
\r
867 return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() : FPSCounter.getPrimitiveTotal();
\r
872 //! Sets the dynamic ambient light color. The default color is
\r
873 //! (0,0,0,0) which means it is dark.
\r
874 //! \param color: New color of the ambient light.
\r
875 void CNullDriver::setAmbientLight(const SColorf& color)
\r
877 AmbientLight = color;
\r
880 const SColorf& CNullDriver::getAmbientLight() const
\r
882 return AmbientLight;
\r
885 //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
\r
886 //! driver, it would return "Direct3D8".
\r
888 const wchar_t* CNullDriver::getName() const
\r
890 return L"Irrlicht NullDevice";
\r
894 //! Creates a boolean alpha channel of the texture based of an color key.
\r
895 void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
\r
896 video::SColor color,
\r
897 bool zeroTexels) const
\r
902 if (texture->getColorFormat() != ECF_A1R5G5B5 &&
\r
903 texture->getColorFormat() != ECF_A8R8G8B8 )
\r
905 os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
\r
909 if (texture->getColorFormat() == ECF_A1R5G5B5)
\r
911 u16 *p = (u16*)texture->lock();
\r
915 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
919 const core::dimension2d<u32> dim = texture->getSize();
\r
920 const u32 pitch = texture->getPitch() / 2;
\r
922 // color with alpha disabled (i.e. fully transparent)
\r
923 const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5());
\r
925 const u32 pixels = pitch * dim.Height;
\r
927 for (u32 pixel = 0; pixel < pixels; ++ pixel)
\r
929 // If the color matches the reference color, ignoring alphas,
\r
930 // set the alpha to zero.
\r
931 if(((*p) & 0x7fff) == refZeroAlpha)
\r
936 (*p) = refZeroAlpha;
\r
946 u32 *p = (u32*)texture->lock();
\r
950 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
954 core::dimension2d<u32> dim = texture->getSize();
\r
955 u32 pitch = texture->getPitch() / 4;
\r
957 // color with alpha disabled (fully transparent)
\r
958 const u32 refZeroAlpha = 0x00ffffff & color.color;
\r
960 const u32 pixels = pitch * dim.Height;
\r
961 for (u32 pixel = 0; pixel < pixels; ++ pixel)
\r
963 // If the color matches the reference color, ignoring alphas,
\r
964 // set the alpha to zero.
\r
965 if(((*p) & 0x00ffffff) == refZeroAlpha)
\r
970 (*p) = refZeroAlpha;
\r
978 texture->regenerateMipMapLevels();
\r
983 //! Creates an boolean alpha channel of the texture based of an color key position.
\r
984 void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
\r
985 core::position2d<s32> colorKeyPixelPos,
\r
986 bool zeroTexels) const
\r
991 if (texture->getColorFormat() != ECF_A1R5G5B5 &&
\r
992 texture->getColorFormat() != ECF_A8R8G8B8 )
\r
994 os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
\r
1000 if (texture->getColorFormat() == ECF_A1R5G5B5)
\r
1002 u16 *p = (u16*)texture->lock(ETLM_READ_ONLY);
\r
1006 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
1010 u32 pitch = texture->getPitch() / 2;
\r
1012 const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
\r
1014 colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit);
\r
1018 u32 *p = (u32*)texture->lock(ETLM_READ_ONLY);
\r
1022 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
1026 u32 pitch = texture->getPitch() / 4;
\r
1027 colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
\r
1030 texture->unlock();
\r
1031 makeColorKeyTexture(texture, colorKey, zeroTexels);
\r
1035 //! Returns the maximum amount of primitives (mostly vertices) which
\r
1036 //! the device is able to render with one drawIndexedTriangleList
\r
1038 u32 CNullDriver::getMaximalPrimitiveCount() const
\r
1040 return 0xFFFFFFFF;
\r
1044 //! checks triangle count and print warning if wrong
\r
1045 bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
\r
1047 const u32 m = getMaximalPrimitiveCount();
\r
1052 snprintf_irr(tmp, sizeof(tmp), "Could not draw triangles, too many primitives(%u), maximum is %u.", prmCount, m);
\r
1053 os::Printer::log(tmp, ELL_ERROR);
\r
1060 bool CNullDriver::checkImage(const core::array<IImage*>& image) const
\r
1062 bool status = true;
\r
1064 if (image.size() > 0)
\r
1066 ECOLOR_FORMAT lastFormat = image[0]->getColorFormat();
\r
1067 core::dimension2d<u32> lastSize = image[0]->getDimension();
\r
1069 for (u32 i = 0; i < image.size() && status; ++i)
\r
1071 ECOLOR_FORMAT format = image[i]->getColorFormat();
\r
1072 core::dimension2d<u32> size = image[i]->getDimension();
\r
1081 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
\r
1083 os::Printer::log("DXT texture compression not available.", ELL_ERROR);
\r
1086 else if (size.getOptimalSize(true, false) != size)
\r
1088 os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR);
\r
1092 case ECF_PVRTC_RGB2:
\r
1093 case ECF_PVRTC_ARGB2:
\r
1094 case ECF_PVRTC_RGB4:
\r
1095 case ECF_PVRTC_ARGB4:
\r
1096 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC))
\r
1098 os::Printer::log("PVRTC texture compression not available.", ELL_ERROR);
\r
1101 else if (size.getOptimalSize(true, false) != size)
\r
1103 os::Printer::log("Invalid size of image for PVRTC compressed texture, size of image must be power of two and squared.", ELL_ERROR);
\r
1107 case ECF_PVRTC2_ARGB2:
\r
1108 case ECF_PVRTC2_ARGB4:
\r
1109 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2))
\r
1111 os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR);
\r
1116 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1))
\r
1118 os::Printer::log("ETC1 texture compression not available.", ELL_ERROR);
\r
1122 case ECF_ETC2_RGB:
\r
1123 case ECF_ETC2_ARGB:
\r
1124 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2))
\r
1126 os::Printer::log("ETC2 texture compression not available.", ELL_ERROR);
\r
1134 if (format != lastFormat || size != lastSize)
\r
1146 //! Enables or disables a texture creation flag.
\r
1147 void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled)
\r
1149 if (enabled && ((flag == ETCF_ALWAYS_16_BIT) || (flag == ETCF_ALWAYS_32_BIT)
\r
1150 || (flag == ETCF_OPTIMIZED_FOR_QUALITY) || (flag == ETCF_OPTIMIZED_FOR_SPEED)))
\r
1152 // disable other formats
\r
1153 setTextureCreationFlag(ETCF_ALWAYS_16_BIT, false);
\r
1154 setTextureCreationFlag(ETCF_ALWAYS_32_BIT, false);
\r
1155 setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, false);
\r
1156 setTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED, false);
\r
1160 TextureCreationFlags = (TextureCreationFlags & (~flag)) |
\r
1161 ((((u32)!enabled)-1) & flag);
\r
1165 //! Returns if a texture creation flag is enabled or disabled.
\r
1166 bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const
\r
1168 return (TextureCreationFlags & flag)!=0;
\r
1171 core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type)
\r
1173 // TO-DO -> use 'move' feature from C++11 standard.
\r
1175 core::array<IImage*> imageArray;
\r
1177 if (filename.size() > 0)
\r
1179 io::IReadFile* file = FileSystem->createAndOpenFile(filename);
\r
1183 imageArray = createImagesFromFile(file, type);
\r
1187 os::Printer::log("Could not open file of image", filename, ELL_WARNING);
\r
1190 return imageArray;
\r
1193 core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type)
\r
1195 // TO-DO -> use 'move' feature from C++11 standard.
\r
1197 core::array<IImage*> imageArray;
\r
1200 return imageArray;
\r
1202 // try to load file based on file extension
\r
1203 for (int i = SurfaceLoader.size() - 1; i >= 0; --i) {
\r
1204 if (!SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
\r
1207 file->seek(0); // reset file position which might have changed due to previous loadImage calls
\r
1208 if (IImage *image = SurfaceLoader[i]->loadImage(file)) {
\r
1209 imageArray.push_back(image);
\r
1210 return imageArray;
\r
1214 // try to load file based on what is in it
\r
1215 for (int i = SurfaceLoader.size() - 1; i >= 0; --i) {
\r
1216 if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
\r
1217 continue; // extension was tried above already
\r
1218 file->seek(0); // dito
\r
1219 if (!SurfaceLoader[i]->isALoadableFileFormat(file))
\r
1223 if (IImage *image = SurfaceLoader[i]->loadImage(file)) {
\r
1224 imageArray.push_back(image);
\r
1225 return imageArray;
\r
1229 return imageArray;
\r
1233 //! Writes the provided image to disk file
\r
1234 bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param)
\r
1236 io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
\r
1240 bool result = writeImageToFile(image, file, param);
\r
1246 //! Writes the provided image to a file.
\r
1247 bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param)
\r
1252 for (s32 i=SurfaceWriter.size()-1; i>=0; --i)
\r
1254 if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName()))
\r
1256 bool written = SurfaceWriter[i]->writeImage(file, image, param);
\r
1261 return false; // failed to write
\r
1265 //! Creates a software image from a byte array.
\r
1266 IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
\r
1267 const core::dimension2d<u32>& size, void *data, bool ownForeignMemory,
\r
1268 bool deleteMemory)
\r
1270 return new CImage(format, size, data, ownForeignMemory, deleteMemory);
\r
1274 //! Creates an empty software image.
\r
1275 IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
\r
1277 return new CImage(format, size);
\r
1281 //! Creates a software image from another image.
\r
1282 IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy)
\r
1284 os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
\r
1286 CImage* tmp = new CImage(format, imageToCopy->getDimension());
\r
1287 imageToCopy->copyTo(tmp);
\r
1292 //! Creates a software image from part of another image.
\r
1293 IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
\r
1295 os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
\r
1296 CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension());
\r
1297 imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size));
\r
1302 //! Creates a software image from part of a texture.
\r
1303 IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
\r
1305 if ((pos==core::position2di(0,0)) && (size == texture->getSize()))
\r
1307 void * data = texture->lock(ETLM_READ_ONLY);
\r
1310 IImage* image = new CImage(texture->getColorFormat(), size, data, false, false);
\r
1311 texture->unlock();
\r
1316 // make sure to avoid buffer overruns
\r
1317 // make the vector a separate variable for g++ 3.x
\r
1318 const core::vector2d<u32> leftUpper(core::clamp(static_cast<u32>(pos.X), 0u, texture->getSize().Width),
\r
1319 core::clamp(static_cast<u32>(pos.Y), 0u, texture->getSize().Height));
\r
1320 const core::rect<u32> clamped(leftUpper,
\r
1321 core::dimension2du(core::clamp(static_cast<u32>(size.Width), 0u, texture->getSize().Width),
\r
1322 core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
\r
1323 if (!clamped.isValid())
\r
1325 u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
\r
1328 IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
\r
1329 u8* dst = static_cast<u8*>(image->getData());
\r
1330 src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X;
\r
1331 for (u32 i=0; i<clamped.getHeight(); ++i)
\r
1333 video::CColorConverter::convert_viaFormat(src, texture->getColorFormat(), clamped.getWidth(), dst, image->getColorFormat());
\r
1334 src += texture->getPitch();
\r
1335 dst += image->getPitch();
\r
1337 texture->unlock();
\r
1343 //! Sets the fog mode.
\r
1344 void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end,
\r
1345 f32 density, bool pixelFog, bool rangeFog)
\r
1348 FogType = fogType;
\r
1351 FogDensity = density;
\r
1352 PixelFog = pixelFog;
\r
1353 RangeFog = rangeFog;
\r
1356 //! Gets the fog mode.
\r
1357 void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end,
\r
1358 f32& density, bool& pixelFog, bool& rangeFog)
\r
1361 fogType = FogType;
\r
1364 density = FogDensity;
\r
1365 pixelFog = PixelFog;
\r
1366 rangeFog = RangeFog;
\r
1369 //! Draws a mesh buffer
\r
1370 void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb)
\r
1375 //IVertexBuffer and IIndexBuffer later
\r
1376 SHWBufferLink *HWBuffer=getBufferLink(mb);
\r
1379 drawHardwareBuffer(HWBuffer);
\r
1381 drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), mb->getIndexType());
\r
1385 //! Draws the normals of a mesh buffer
\r
1386 void CNullDriver::drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length, SColor color)
\r
1388 const u32 count = mb->getVertexCount();
\r
1389 const bool normalize = mb->getMaterial().NormalizeNormals;
\r
1391 for (u32 i=0; i < count; ++i)
\r
1393 core::vector3df normalizedNormal = mb->getNormal(i);
\r
1395 normalizedNormal.normalize();
\r
1397 const core::vector3df& pos = mb->getPosition(i);
\r
1398 draw3DLine(pos, pos + (normalizedNormal * length), color);
\r
1403 CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb)
\r
1405 if (!mb || !isHardwareBufferRecommend(mb))
\r
1408 //search for hardware links
\r
1409 SHWBufferLink *HWBuffer = reinterpret_cast<SHWBufferLink*>(mb->getHWBuffer());
\r
1413 return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it
\r
1417 //! Update all hardware buffers, remove unused ones
\r
1418 void CNullDriver::updateAllHardwareBuffers()
\r
1420 auto it = HWBufferList.begin();
\r
1421 while (it != HWBufferList.end()) {
\r
1422 SHWBufferLink *Link = *it;
\r
1425 if (!Link->MeshBuffer || Link->MeshBuffer->getReferenceCount() == 1)
\r
1426 deleteHardwareBuffer(Link);
\r
1431 void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
\r
1435 HWBufferList.erase(HWBuffer->listPosition);
\r
1440 //! Remove hardware buffer
\r
1441 void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb)
\r
1445 SHWBufferLink *HWBuffer = reinterpret_cast<SHWBufferLink*>(mb->getHWBuffer());
\r
1447 deleteHardwareBuffer(HWBuffer);
\r
1451 //! Remove all hardware buffers
\r
1452 void CNullDriver::removeAllHardwareBuffers()
\r
1454 while (!HWBufferList.empty())
\r
1455 deleteHardwareBuffer(HWBufferList.front());
\r
1459 bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb)
\r
1461 if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
\r
1464 if (mb->getVertexCount()<MinVertexCountForVBO)
\r
1471 //! Create occlusion query.
\r
1472 /** Use node for identification and mesh for occlusion test. */
\r
1473 void CNullDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh)
\r
1479 if ((node->getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH))
\r
1481 else if (node->getType() == scene::ESNT_MESH)
\r
1482 mesh = static_cast<scene::IMeshSceneNode*>(node)->getMesh();
\r
1484 mesh = static_cast<scene::IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
\r
1489 //search for query
\r
1490 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1493 if (OcclusionQueries[index].Mesh != mesh)
\r
1495 OcclusionQueries[index].Mesh->drop();
\r
1496 OcclusionQueries[index].Mesh = mesh;
\r
1502 OcclusionQueries.push_back(SOccQuery(node, mesh));
\r
1503 node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY);
\r
1508 //! Remove occlusion query.
\r
1509 void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node)
\r
1511 //search for query
\r
1512 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1515 node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY);
\r
1516 OcclusionQueries.erase(index);
\r
1521 //! Remove all occlusion queries.
\r
1522 void CNullDriver::removeAllOcclusionQueries()
\r
1524 for (s32 i=OcclusionQueries.size()-1; i>=0; --i)
\r
1526 removeOcclusionQuery(OcclusionQueries[i].Node);
\r
1531 //! Run occlusion query. Draws mesh stored in query.
\r
1532 /** If the mesh shall be rendered visible, use
\r
1533 flag to enable the proper material setting. */
\r
1534 void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
\r
1538 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1541 OcclusionQueries[index].Run=0;
\r
1545 mat.Lighting=false;
\r
1546 mat.AntiAliasing=0;
\r
1547 mat.ColorMask=ECP_NONE;
\r
1548 mat.GouraudShading=false;
\r
1549 mat.ZWriteEnable=EZW_OFF;
\r
1552 setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
\r
1553 const scene::IMesh* mesh = OcclusionQueries[index].Mesh;
\r
1554 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
\r
1557 setMaterial(mesh->getMeshBuffer(i)->getMaterial());
\r
1558 drawMeshBuffer(mesh->getMeshBuffer(i));
\r
1563 //! Run all occlusion queries. Draws all meshes stored in queries.
\r
1564 /** If the meshes shall not be rendered visible, use
\r
1565 overrideMaterial to disable the color and depth buffer. */
\r
1566 void CNullDriver::runAllOcclusionQueries(bool visible)
\r
1568 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
1569 runOcclusionQuery(OcclusionQueries[i].Node, visible);
\r
1573 //! Update occlusion query. Retrieves results from GPU.
\r
1574 /** If the query shall not block, set the flag to false.
\r
1575 Update might not occur in this case, though */
\r
1576 void CNullDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
\r
1581 //! Update all occlusion queries. Retrieves results from GPU.
\r
1582 /** If the query shall not block, set the flag to false.
\r
1583 Update might not occur in this case, though */
\r
1584 void CNullDriver::updateAllOcclusionQueries(bool block)
\r
1586 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
1588 if (OcclusionQueries[i].Run==u32(~0))
\r
1590 updateOcclusionQuery(OcclusionQueries[i].Node, block);
\r
1591 ++OcclusionQueries[i].Run;
\r
1592 if (OcclusionQueries[i].Run>1000)
\r
1593 removeOcclusionQuery(OcclusionQueries[i].Node);
\r
1598 //! Return query result.
\r
1599 /** Return value is the number of visible pixels/fragments.
\r
1600 The value is a safe approximation, i.e. can be larger then the
\r
1601 actual value of pixels. */
\r
1602 u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const
\r
1608 //! Create render target.
\r
1609 IRenderTarget* CNullDriver::addRenderTarget()
\r
1615 //! Remove render target.
\r
1616 void CNullDriver::removeRenderTarget(IRenderTarget* renderTarget)
\r
1618 if (!renderTarget)
\r
1621 for (u32 i = 0; i < RenderTargets.size(); ++i)
\r
1623 if (RenderTargets[i] == renderTarget)
\r
1625 RenderTargets[i]->drop();
\r
1626 RenderTargets.erase(i);
\r
1634 //! Remove all render targets.
\r
1635 void CNullDriver::removeAllRenderTargets()
\r
1637 for (u32 i = 0; i < RenderTargets.size(); ++i)
\r
1638 RenderTargets[i]->drop();
\r
1640 RenderTargets.clear();
\r
1642 SharedRenderTarget = 0;
\r
1646 //! Only used by the internal engine. Used to notify the driver that
\r
1647 //! the window was resized.
\r
1648 void CNullDriver::OnResize(const core::dimension2d<u32>& size)
\r
1650 if (ViewPort.getWidth() == (s32)ScreenSize.Width &&
\r
1651 ViewPort.getHeight() == (s32)ScreenSize.Height)
\r
1652 ViewPort = core::rect<s32>(core::position2d<s32>(0,0),
\r
1653 core::dimension2di(size));
\r
1655 ScreenSize = size;
\r
1659 // adds a material renderer and drops it afterwards. To be used for internal creation
\r
1660 s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m)
\r
1662 s32 i = addMaterialRenderer(m);
\r
1671 //! Adds a new material renderer to the video device.
\r
1672 s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name)
\r
1677 SMaterialRenderer r;
\r
1678 r.Renderer = renderer;
\r
1681 if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ))
\r
1683 // set name of built in renderer so that we don't have to implement name
\r
1684 // setting in all available renderers.
\r
1685 r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()];
\r
1688 MaterialRenderers.push_back(r);
\r
1691 return MaterialRenderers.size()-1;
\r
1695 //! Sets the name of a material renderer.
\r
1696 void CNullDriver::setMaterialRendererName(u32 idx, const char* name)
\r
1698 if (idx < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
\r
1699 idx >= MaterialRenderers.size())
\r
1702 MaterialRenderers[idx].Name = name;
\r
1705 void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames)
\r
1707 if ( idx1 < MaterialRenderers.size() && idx2 < MaterialRenderers.size() )
\r
1709 irr::core::swap(MaterialRenderers[idx1].Renderer, MaterialRenderers[idx2].Renderer);
\r
1711 irr::core::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
\r
1716 //! Returns driver and operating system specific data about the IVideoDriver.
\r
1717 const SExposedVideoData& CNullDriver::getExposedVideoData()
\r
1719 return ExposedData;
\r
1723 //! Returns type of video driver
\r
1724 E_DRIVER_TYPE CNullDriver::getDriverType() const
\r
1730 //! deletes all material renderers
\r
1731 void CNullDriver::deleteMaterialRenders()
\r
1733 // delete material renderers
\r
1734 for (u32 i=0; i<MaterialRenderers.size(); ++i)
\r
1735 if (MaterialRenderers[i].Renderer)
\r
1736 MaterialRenderers[i].Renderer->drop();
\r
1738 MaterialRenderers.clear();
\r
1742 //! Returns pointer to material renderer or null
\r
1743 IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx) const
\r
1745 if ( idx < MaterialRenderers.size() )
\r
1746 return MaterialRenderers[idx].Renderer;
\r
1752 //! Returns amount of currently available material renderers.
\r
1753 u32 CNullDriver::getMaterialRendererCount() const
\r
1755 return MaterialRenderers.size();
\r
1759 //! Returns name of the material renderer
\r
1760 const char* CNullDriver::getMaterialRendererName(u32 idx) const
\r
1762 if ( idx < MaterialRenderers.size() )
\r
1763 return MaterialRenderers[idx].Name.c_str();
\r
1769 //! Returns pointer to the IGPUProgrammingServices interface.
\r
1770 IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices()
\r
1776 //! Adds a new material renderer to the VideoDriver, based on a high level shading language.
\r
1777 s32 CNullDriver::addHighLevelShaderMaterial(
\r
1778 const c8* vertexShaderProgram,
\r
1779 const c8* vertexShaderEntryPointName,
\r
1780 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
1781 const c8* pixelShaderProgram,
\r
1782 const c8* pixelShaderEntryPointName,
\r
1783 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
1784 const c8* geometryShaderProgram,
\r
1785 const c8* geometryShaderEntryPointName,
\r
1786 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
1787 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
1789 IShaderConstantSetCallBack* callback,
\r
1790 E_MATERIAL_TYPE baseMaterial,
\r
1793 os::Printer::log("High level shader materials not available (yet) in this driver, sorry");
\r
1798 //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
\r
1799 //! but tries to load the programs from files.
\r
1800 s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
\r
1801 const io::path& vertexShaderProgramFileName,
\r
1802 const c8* vertexShaderEntryPointName,
\r
1803 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
1804 const io::path& pixelShaderProgramFileName,
\r
1805 const c8* pixelShaderEntryPointName,
\r
1806 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
1807 const io::path& geometryShaderProgramFileName,
\r
1808 const c8* geometryShaderEntryPointName,
\r
1809 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
1810 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
1812 IShaderConstantSetCallBack* callback,
\r
1813 E_MATERIAL_TYPE baseMaterial,
\r
1816 io::IReadFile* vsfile = 0;
\r
1817 io::IReadFile* psfile = 0;
\r
1818 io::IReadFile* gsfile = 0;
\r
1820 if (vertexShaderProgramFileName.size() )
\r
1822 vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
\r
1825 os::Printer::log("Could not open vertex shader program file",
\r
1826 vertexShaderProgramFileName, ELL_WARNING);
\r
1830 if (pixelShaderProgramFileName.size() )
\r
1832 psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
\r
1835 os::Printer::log("Could not open pixel shader program file",
\r
1836 pixelShaderProgramFileName, ELL_WARNING);
\r
1840 if (geometryShaderProgramFileName.size() )
\r
1842 gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName);
\r
1845 os::Printer::log("Could not open geometry shader program file",
\r
1846 geometryShaderProgramFileName, ELL_WARNING);
\r
1850 s32 result = addHighLevelShaderMaterialFromFiles(
\r
1851 vsfile, vertexShaderEntryPointName, vsCompileTarget,
\r
1852 psfile, pixelShaderEntryPointName, psCompileTarget,
\r
1853 gsfile, geometryShaderEntryPointName, gsCompileTarget,
\r
1854 inType, outType, verticesOut,
\r
1855 callback, baseMaterial, userData);
\r
1870 //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
\r
1871 //! but tries to load the programs from files.
\r
1872 s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
\r
1873 io::IReadFile* vertexShaderProgram,
\r
1874 const c8* vertexShaderEntryPointName,
\r
1875 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
1876 io::IReadFile* pixelShaderProgram,
\r
1877 const c8* pixelShaderEntryPointName,
\r
1878 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
1879 io::IReadFile* geometryShaderProgram,
\r
1880 const c8* geometryShaderEntryPointName,
\r
1881 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
1882 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
1884 IShaderConstantSetCallBack* callback,
\r
1885 E_MATERIAL_TYPE baseMaterial,
\r
1892 if (vertexShaderProgram)
\r
1894 const long size = vertexShaderProgram->getSize();
\r
1897 vs = new c8[size+1];
\r
1898 vertexShaderProgram->read(vs, size);
\r
1903 if (pixelShaderProgram)
\r
1905 const long size = pixelShaderProgram->getSize();
\r
1908 // if both handles are the same we must reset the file
\r
1909 if (pixelShaderProgram==vertexShaderProgram)
\r
1910 pixelShaderProgram->seek(0);
\r
1911 ps = new c8[size+1];
\r
1912 pixelShaderProgram->read(ps, size);
\r
1917 if (geometryShaderProgram)
\r
1919 const long size = geometryShaderProgram->getSize();
\r
1922 // if both handles are the same we must reset the file
\r
1923 if ((geometryShaderProgram==vertexShaderProgram) ||
\r
1924 (geometryShaderProgram==pixelShaderProgram))
\r
1925 geometryShaderProgram->seek(0);
\r
1926 gs = new c8[size+1];
\r
1927 geometryShaderProgram->read(gs, size);
\r
1932 s32 result = this->addHighLevelShaderMaterial(
\r
1933 vs, vertexShaderEntryPointName, vsCompileTarget,
\r
1934 ps, pixelShaderEntryPointName, psCompileTarget,
\r
1935 gs, geometryShaderEntryPointName, gsCompileTarget,
\r
1936 inType, outType, verticesOut,
\r
1937 callback, baseMaterial, userData);
\r
1947 //! Adds a new material renderer to the VideoDriver, using pixel and/or
\r
1948 //! vertex shaders to render geometry.
\r
1949 s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram,
\r
1950 const c8* pixelShaderProgram,
\r
1951 IShaderConstantSetCallBack* callback,
\r
1952 E_MATERIAL_TYPE baseMaterial,
\r
1955 os::Printer::log("Shader materials not implemented yet in this driver, sorry.");
\r
1960 //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
\r
1961 //! programs from files.
\r
1962 s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram,
\r
1963 io::IReadFile* pixelShaderProgram,
\r
1964 IShaderConstantSetCallBack* callback,
\r
1965 E_MATERIAL_TYPE baseMaterial,
\r
1971 if (vertexShaderProgram)
\r
1973 const long size = vertexShaderProgram->getSize();
\r
1976 vs = new c8[size+1];
\r
1977 vertexShaderProgram->read(vs, size);
\r
1982 if (pixelShaderProgram)
\r
1984 const long size = pixelShaderProgram->getSize();
\r
1987 ps = new c8[size+1];
\r
1988 pixelShaderProgram->read(ps, size);
\r
1993 s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData);
\r
2002 //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
\r
2003 //! programs from files.
\r
2004 s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName,
\r
2005 const io::path& pixelShaderProgramFileName,
\r
2006 IShaderConstantSetCallBack* callback,
\r
2007 E_MATERIAL_TYPE baseMaterial,
\r
2010 io::IReadFile* vsfile = 0;
\r
2011 io::IReadFile* psfile = 0;
\r
2013 if (vertexShaderProgramFileName.size())
\r
2015 vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
\r
2018 os::Printer::log("Could not open vertex shader program file",
\r
2019 vertexShaderProgramFileName, ELL_WARNING);
\r
2024 if (pixelShaderProgramFileName.size())
\r
2026 psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
\r
2029 os::Printer::log("Could not open pixel shader program file",
\r
2030 pixelShaderProgramFileName, ELL_WARNING);
\r
2037 s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback,
\r
2038 baseMaterial, userData);
\r
2050 //! Creates a render target texture.
\r
2051 ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
\r
2052 const io::path&name, const ECOLOR_FORMAT format)
\r
2057 ITexture* CNullDriver::addRenderTargetTextureCubemap(const irr::u32 sideLen,
\r
2058 const io::path& name, const ECOLOR_FORMAT format)
\r
2063 void CNullDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
\r
2068 //! Returns a pointer to the mesh manipulator.
\r
2069 scene::IMeshManipulator* CNullDriver::getMeshManipulator()
\r
2071 return MeshManipulator;
\r
2075 //! Returns an image created from the last rendered frame.
\r
2076 IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
\r
2082 // prints renderer version
\r
2083 void CNullDriver::printVersion()
\r
2085 core::stringw namePrint = L"Using renderer: ";
\r
2086 namePrint += getName();
\r
2087 os::Printer::log(namePrint.c_str(), ELL_INFORMATION);
\r
2091 //! creates a video driver
\r
2092 IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
\r
2094 CNullDriver* nullDriver = new CNullDriver(io, screenSize);
\r
2096 // create empty material renderers
\r
2097 for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i)
\r
2099 IMaterialRenderer* imr = new IMaterialRenderer();
\r
2100 nullDriver->addMaterialRenderer(imr);
\r
2104 return nullDriver;
\r
2108 //! Set/unset a clipping plane.
\r
2109 //! There are at least 6 clipping planes available for the user to set at will.
\r
2110 //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
\r
2111 //! \param plane: The plane itself.
\r
2112 //! \param enable: If true, enable the clipping plane else disable it.
\r
2113 bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
\r
2119 //! Enable/disable a clipping plane.
\r
2120 void CNullDriver::enableClipPlane(u32 index, bool enable)
\r
2126 ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<u32>& size,
\r
2129 os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead");
\r
2130 ITexture* tex = addRenderTargetTexture(size, name);
\r
2136 void CNullDriver::setMinHardwareBufferVertexCount(u32 count)
\r
2138 MinVertexCountForVBO = count;
\r
2142 SOverrideMaterial& CNullDriver::getOverrideMaterial()
\r
2144 return OverrideMaterial;
\r
2148 //! Get the 2d override material for altering its values
\r
2149 SMaterial& CNullDriver::getMaterial2D()
\r
2151 return OverrideMaterial2D;
\r
2155 //! Enable the 2d override material
\r
2156 void CNullDriver::enableMaterial2D(bool enable)
\r
2158 OverrideMaterial2DEnabled=enable;
\r
2162 core::dimension2du CNullDriver::getMaxTextureSize() const
\r
2164 return core::dimension2du(0x10000,0x10000); // maybe large enough
\r
2167 bool CNullDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
\r
2169 // TODO: I suspect it would be nice if the material had an enum for further control.
\r
2170 // Especially it probably makes sense to allow disabling transparent render pass as soon as material.ZWriteEnable is on.
\r
2171 // But then we might want an enum for the renderpass in material instead of just a transparency flag in material - and that's more work.
\r
2172 // Or we could at least set return false when material.ZWriteEnable is EZW_ON? Still considering that...
\r
2173 // Be careful - this function is deeply connected to getWriteZBuffer as transparent render passes are usually about rendering with
\r
2174 // zwrite disabled and getWriteZBuffer calls this function.
\r
2176 video::IMaterialRenderer* rnd = getMaterialRenderer(material.MaterialType);
\r
2177 // TODO: I suspect IMaterialRenderer::isTransparent also often could use SMaterial as parameter
\r
2178 // We could for example then get rid of IsTransparent function in SMaterial and move that to the software material renderer.
\r
2179 if (rnd && rnd->isTransparent())
\r
2186 //! Color conversion convenience function
\r
2187 /** Convert an image (as array of pixels) from source to destination
\r
2188 array, thereby converting the color format. The pixel size is
\r
2189 determined by the color formats.
\r
2190 \param sP Pointer to source
\r
2191 \param sF Color format of source
\r
2192 \param sN Number of pixels to convert, both array must be large enough
\r
2193 \param dP Pointer to destination
\r
2194 \param dF Color format of destination
\r
2196 void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN,
\r
2197 void* dP, ECOLOR_FORMAT dF) const
\r
2199 video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF);
\r
2203 } // end namespace
\r
2204 } // end namespace
\r