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
1203 // try to load file based on file extension
\r
1204 for (i = SurfaceLoader.size() - 1; i >= 0; --i)
\r
1206 if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
\r
1208 // reset file position which might have changed due to previous loadImage calls
\r
1210 imageArray = SurfaceLoader[i]->loadImages(file, type);
\r
1212 if (imageArray.size() == 0)
\r
1215 IImage* image = SurfaceLoader[i]->loadImage(file);
\r
1218 imageArray.push_back(image);
\r
1221 if (imageArray.size() > 0)
\r
1222 return imageArray;
\r
1226 // try to load file based on what is in it
\r
1227 for (i = SurfaceLoader.size() - 1; i >= 0; --i)
\r
1231 if (SurfaceLoader[i]->isALoadableFileFormat(file)
\r
1232 && !SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()) // extension was tried above already
\r
1236 imageArray = SurfaceLoader[i]->loadImages(file, type);
\r
1238 if (imageArray.size() == 0)
\r
1241 IImage* image = SurfaceLoader[i]->loadImage(file);
\r
1244 imageArray.push_back(image);
\r
1247 if (imageArray.size() > 0)
\r
1248 return imageArray;
\r
1253 return imageArray;
\r
1257 //! Writes the provided image to disk file
\r
1258 bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param)
\r
1260 io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
\r
1264 bool result = writeImageToFile(image, file, param);
\r
1270 //! Writes the provided image to a file.
\r
1271 bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param)
\r
1276 for (s32 i=SurfaceWriter.size()-1; i>=0; --i)
\r
1278 if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName()))
\r
1280 bool written = SurfaceWriter[i]->writeImage(file, image, param);
\r
1285 return false; // failed to write
\r
1289 //! Creates a software image from a byte array.
\r
1290 IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
\r
1291 const core::dimension2d<u32>& size, void *data, bool ownForeignMemory,
\r
1292 bool deleteMemory)
\r
1294 return new CImage(format, size, data, ownForeignMemory, deleteMemory);
\r
1298 //! Creates an empty software image.
\r
1299 IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
\r
1301 return new CImage(format, size);
\r
1305 //! Creates a software image from another image.
\r
1306 IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy)
\r
1308 os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
\r
1310 CImage* tmp = new CImage(format, imageToCopy->getDimension());
\r
1311 imageToCopy->copyTo(tmp);
\r
1316 //! Creates a software image from part of another image.
\r
1317 IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
\r
1319 os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
\r
1320 CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension());
\r
1321 imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size));
\r
1326 //! Creates a software image from part of a texture.
\r
1327 IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
\r
1329 if ((pos==core::position2di(0,0)) && (size == texture->getSize()))
\r
1331 void * data = texture->lock(ETLM_READ_ONLY);
\r
1334 IImage* image = new CImage(texture->getColorFormat(), size, data, false, false);
\r
1335 texture->unlock();
\r
1340 // make sure to avoid buffer overruns
\r
1341 // make the vector a separate variable for g++ 3.x
\r
1342 const core::vector2d<u32> leftUpper(core::clamp(static_cast<u32>(pos.X), 0u, texture->getSize().Width),
\r
1343 core::clamp(static_cast<u32>(pos.Y), 0u, texture->getSize().Height));
\r
1344 const core::rect<u32> clamped(leftUpper,
\r
1345 core::dimension2du(core::clamp(static_cast<u32>(size.Width), 0u, texture->getSize().Width),
\r
1346 core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
\r
1347 if (!clamped.isValid())
\r
1349 u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
\r
1352 IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
\r
1353 u8* dst = static_cast<u8*>(image->getData());
\r
1354 src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X;
\r
1355 for (u32 i=0; i<clamped.getHeight(); ++i)
\r
1357 video::CColorConverter::convert_viaFormat(src, texture->getColorFormat(), clamped.getWidth(), dst, image->getColorFormat());
\r
1358 src += texture->getPitch();
\r
1359 dst += image->getPitch();
\r
1361 texture->unlock();
\r
1367 //! Sets the fog mode.
\r
1368 void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end,
\r
1369 f32 density, bool pixelFog, bool rangeFog)
\r
1372 FogType = fogType;
\r
1375 FogDensity = density;
\r
1376 PixelFog = pixelFog;
\r
1377 RangeFog = rangeFog;
\r
1380 //! Gets the fog mode.
\r
1381 void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end,
\r
1382 f32& density, bool& pixelFog, bool& rangeFog)
\r
1385 fogType = FogType;
\r
1388 density = FogDensity;
\r
1389 pixelFog = PixelFog;
\r
1390 rangeFog = RangeFog;
\r
1393 //! Draws a mesh buffer
\r
1394 void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb)
\r
1399 //IVertexBuffer and IIndexBuffer later
\r
1400 SHWBufferLink *HWBuffer=getBufferLink(mb);
\r
1403 drawHardwareBuffer(HWBuffer);
\r
1405 drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), mb->getIndexType());
\r
1409 //! Draws the normals of a mesh buffer
\r
1410 void CNullDriver::drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length, SColor color)
\r
1412 const u32 count = mb->getVertexCount();
\r
1413 const bool normalize = mb->getMaterial().NormalizeNormals;
\r
1415 for (u32 i=0; i < count; ++i)
\r
1417 core::vector3df normalizedNormal = mb->getNormal(i);
\r
1419 normalizedNormal.normalize();
\r
1421 const core::vector3df& pos = mb->getPosition(i);
\r
1422 draw3DLine(pos, pos + (normalizedNormal * length), color);
\r
1427 CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb)
\r
1429 if (!mb || !isHardwareBufferRecommend(mb))
\r
1432 //search for hardware links
\r
1433 SHWBufferLink *HWBuffer = reinterpret_cast<SHWBufferLink*>(mb->getHWBuffer());
\r
1437 return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it
\r
1441 //! Update all hardware buffers, remove unused ones
\r
1442 void CNullDriver::updateAllHardwareBuffers()
\r
1444 auto it = HWBufferList.begin();
\r
1445 while (it != HWBufferList.end()) {
\r
1446 SHWBufferLink *Link = *it;
\r
1449 if (!Link->MeshBuffer || Link->MeshBuffer->getReferenceCount() == 1)
\r
1450 deleteHardwareBuffer(Link);
\r
1455 void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
\r
1459 HWBufferList.erase(HWBuffer->listPosition);
\r
1464 //! Remove hardware buffer
\r
1465 void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb)
\r
1469 SHWBufferLink *HWBuffer = reinterpret_cast<SHWBufferLink*>(mb->getHWBuffer());
\r
1471 deleteHardwareBuffer(HWBuffer);
\r
1475 //! Remove all hardware buffers
\r
1476 void CNullDriver::removeAllHardwareBuffers()
\r
1478 while (!HWBufferList.empty())
\r
1479 deleteHardwareBuffer(HWBufferList.front());
\r
1483 bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb)
\r
1485 if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
\r
1488 if (mb->getVertexCount()<MinVertexCountForVBO)
\r
1495 //! Create occlusion query.
\r
1496 /** Use node for identification and mesh for occlusion test. */
\r
1497 void CNullDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh)
\r
1503 if ((node->getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH))
\r
1505 else if (node->getType() == scene::ESNT_MESH)
\r
1506 mesh = static_cast<scene::IMeshSceneNode*>(node)->getMesh();
\r
1508 mesh = static_cast<scene::IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
\r
1513 //search for query
\r
1514 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1517 if (OcclusionQueries[index].Mesh != mesh)
\r
1519 OcclusionQueries[index].Mesh->drop();
\r
1520 OcclusionQueries[index].Mesh = mesh;
\r
1526 OcclusionQueries.push_back(SOccQuery(node, mesh));
\r
1527 node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY);
\r
1532 //! Remove occlusion query.
\r
1533 void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node)
\r
1535 //search for query
\r
1536 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1539 node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY);
\r
1540 OcclusionQueries.erase(index);
\r
1545 //! Remove all occlusion queries.
\r
1546 void CNullDriver::removeAllOcclusionQueries()
\r
1548 for (s32 i=OcclusionQueries.size()-1; i>=0; --i)
\r
1550 removeOcclusionQuery(OcclusionQueries[i].Node);
\r
1555 //! Run occlusion query. Draws mesh stored in query.
\r
1556 /** If the mesh shall be rendered visible, use
\r
1557 flag to enable the proper material setting. */
\r
1558 void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
\r
1562 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1565 OcclusionQueries[index].Run=0;
\r
1569 mat.Lighting=false;
\r
1570 mat.AntiAliasing=0;
\r
1571 mat.ColorMask=ECP_NONE;
\r
1572 mat.GouraudShading=false;
\r
1573 mat.ZWriteEnable=EZW_OFF;
\r
1576 setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
\r
1577 const scene::IMesh* mesh = OcclusionQueries[index].Mesh;
\r
1578 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
\r
1581 setMaterial(mesh->getMeshBuffer(i)->getMaterial());
\r
1582 drawMeshBuffer(mesh->getMeshBuffer(i));
\r
1587 //! Run all occlusion queries. Draws all meshes stored in queries.
\r
1588 /** If the meshes shall not be rendered visible, use
\r
1589 overrideMaterial to disable the color and depth buffer. */
\r
1590 void CNullDriver::runAllOcclusionQueries(bool visible)
\r
1592 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
1593 runOcclusionQuery(OcclusionQueries[i].Node, visible);
\r
1597 //! Update occlusion query. Retrieves results from GPU.
\r
1598 /** If the query shall not block, set the flag to false.
\r
1599 Update might not occur in this case, though */
\r
1600 void CNullDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
\r
1605 //! Update all occlusion queries. Retrieves results from GPU.
\r
1606 /** If the query shall not block, set the flag to false.
\r
1607 Update might not occur in this case, though */
\r
1608 void CNullDriver::updateAllOcclusionQueries(bool block)
\r
1610 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
1612 if (OcclusionQueries[i].Run==u32(~0))
\r
1614 updateOcclusionQuery(OcclusionQueries[i].Node, block);
\r
1615 ++OcclusionQueries[i].Run;
\r
1616 if (OcclusionQueries[i].Run>1000)
\r
1617 removeOcclusionQuery(OcclusionQueries[i].Node);
\r
1622 //! Return query result.
\r
1623 /** Return value is the number of visible pixels/fragments.
\r
1624 The value is a safe approximation, i.e. can be larger then the
\r
1625 actual value of pixels. */
\r
1626 u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const
\r
1632 //! Create render target.
\r
1633 IRenderTarget* CNullDriver::addRenderTarget()
\r
1639 //! Remove render target.
\r
1640 void CNullDriver::removeRenderTarget(IRenderTarget* renderTarget)
\r
1642 if (!renderTarget)
\r
1645 for (u32 i = 0; i < RenderTargets.size(); ++i)
\r
1647 if (RenderTargets[i] == renderTarget)
\r
1649 RenderTargets[i]->drop();
\r
1650 RenderTargets.erase(i);
\r
1658 //! Remove all render targets.
\r
1659 void CNullDriver::removeAllRenderTargets()
\r
1661 for (u32 i = 0; i < RenderTargets.size(); ++i)
\r
1662 RenderTargets[i]->drop();
\r
1664 RenderTargets.clear();
\r
1666 SharedRenderTarget = 0;
\r
1670 //! Only used by the internal engine. Used to notify the driver that
\r
1671 //! the window was resized.
\r
1672 void CNullDriver::OnResize(const core::dimension2d<u32>& size)
\r
1674 if (ViewPort.getWidth() == (s32)ScreenSize.Width &&
\r
1675 ViewPort.getHeight() == (s32)ScreenSize.Height)
\r
1676 ViewPort = core::rect<s32>(core::position2d<s32>(0,0),
\r
1677 core::dimension2di(size));
\r
1679 ScreenSize = size;
\r
1683 // adds a material renderer and drops it afterwards. To be used for internal creation
\r
1684 s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m)
\r
1686 s32 i = addMaterialRenderer(m);
\r
1695 //! Adds a new material renderer to the video device.
\r
1696 s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name)
\r
1701 SMaterialRenderer r;
\r
1702 r.Renderer = renderer;
\r
1705 if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ))
\r
1707 // set name of built in renderer so that we don't have to implement name
\r
1708 // setting in all available renderers.
\r
1709 r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()];
\r
1712 MaterialRenderers.push_back(r);
\r
1715 return MaterialRenderers.size()-1;
\r
1719 //! Sets the name of a material renderer.
\r
1720 void CNullDriver::setMaterialRendererName(u32 idx, const char* name)
\r
1722 if (idx < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
\r
1723 idx >= MaterialRenderers.size())
\r
1726 MaterialRenderers[idx].Name = name;
\r
1729 void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames)
\r
1731 if ( idx1 < MaterialRenderers.size() && idx2 < MaterialRenderers.size() )
\r
1733 irr::core::swap(MaterialRenderers[idx1].Renderer, MaterialRenderers[idx2].Renderer);
\r
1735 irr::core::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
\r
1740 //! Returns driver and operating system specific data about the IVideoDriver.
\r
1741 const SExposedVideoData& CNullDriver::getExposedVideoData()
\r
1743 return ExposedData;
\r
1747 //! Returns type of video driver
\r
1748 E_DRIVER_TYPE CNullDriver::getDriverType() const
\r
1754 //! deletes all material renderers
\r
1755 void CNullDriver::deleteMaterialRenders()
\r
1757 // delete material renderers
\r
1758 for (u32 i=0; i<MaterialRenderers.size(); ++i)
\r
1759 if (MaterialRenderers[i].Renderer)
\r
1760 MaterialRenderers[i].Renderer->drop();
\r
1762 MaterialRenderers.clear();
\r
1766 //! Returns pointer to material renderer or null
\r
1767 IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx) const
\r
1769 if ( idx < MaterialRenderers.size() )
\r
1770 return MaterialRenderers[idx].Renderer;
\r
1776 //! Returns amount of currently available material renderers.
\r
1777 u32 CNullDriver::getMaterialRendererCount() const
\r
1779 return MaterialRenderers.size();
\r
1783 //! Returns name of the material renderer
\r
1784 const char* CNullDriver::getMaterialRendererName(u32 idx) const
\r
1786 if ( idx < MaterialRenderers.size() )
\r
1787 return MaterialRenderers[idx].Name.c_str();
\r
1793 //! Returns pointer to the IGPUProgrammingServices interface.
\r
1794 IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices()
\r
1800 //! Adds a new material renderer to the VideoDriver, based on a high level shading language.
\r
1801 s32 CNullDriver::addHighLevelShaderMaterial(
\r
1802 const c8* vertexShaderProgram,
\r
1803 const c8* vertexShaderEntryPointName,
\r
1804 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
1805 const c8* pixelShaderProgram,
\r
1806 const c8* pixelShaderEntryPointName,
\r
1807 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
1808 const c8* geometryShaderProgram,
\r
1809 const c8* geometryShaderEntryPointName,
\r
1810 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
1811 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
1813 IShaderConstantSetCallBack* callback,
\r
1814 E_MATERIAL_TYPE baseMaterial,
\r
1817 os::Printer::log("High level shader materials not available (yet) in this driver, sorry");
\r
1822 //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
\r
1823 //! but tries to load the programs from files.
\r
1824 s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
\r
1825 const io::path& vertexShaderProgramFileName,
\r
1826 const c8* vertexShaderEntryPointName,
\r
1827 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
1828 const io::path& pixelShaderProgramFileName,
\r
1829 const c8* pixelShaderEntryPointName,
\r
1830 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
1831 const io::path& geometryShaderProgramFileName,
\r
1832 const c8* geometryShaderEntryPointName,
\r
1833 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
1834 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
1836 IShaderConstantSetCallBack* callback,
\r
1837 E_MATERIAL_TYPE baseMaterial,
\r
1840 io::IReadFile* vsfile = 0;
\r
1841 io::IReadFile* psfile = 0;
\r
1842 io::IReadFile* gsfile = 0;
\r
1844 if (vertexShaderProgramFileName.size() )
\r
1846 vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
\r
1849 os::Printer::log("Could not open vertex shader program file",
\r
1850 vertexShaderProgramFileName, ELL_WARNING);
\r
1854 if (pixelShaderProgramFileName.size() )
\r
1856 psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
\r
1859 os::Printer::log("Could not open pixel shader program file",
\r
1860 pixelShaderProgramFileName, ELL_WARNING);
\r
1864 if (geometryShaderProgramFileName.size() )
\r
1866 gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName);
\r
1869 os::Printer::log("Could not open geometry shader program file",
\r
1870 geometryShaderProgramFileName, ELL_WARNING);
\r
1874 s32 result = addHighLevelShaderMaterialFromFiles(
\r
1875 vsfile, vertexShaderEntryPointName, vsCompileTarget,
\r
1876 psfile, pixelShaderEntryPointName, psCompileTarget,
\r
1877 gsfile, geometryShaderEntryPointName, gsCompileTarget,
\r
1878 inType, outType, verticesOut,
\r
1879 callback, baseMaterial, userData);
\r
1894 //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
\r
1895 //! but tries to load the programs from files.
\r
1896 s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
\r
1897 io::IReadFile* vertexShaderProgram,
\r
1898 const c8* vertexShaderEntryPointName,
\r
1899 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
1900 io::IReadFile* pixelShaderProgram,
\r
1901 const c8* pixelShaderEntryPointName,
\r
1902 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
1903 io::IReadFile* geometryShaderProgram,
\r
1904 const c8* geometryShaderEntryPointName,
\r
1905 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
1906 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
1908 IShaderConstantSetCallBack* callback,
\r
1909 E_MATERIAL_TYPE baseMaterial,
\r
1916 if (vertexShaderProgram)
\r
1918 const long size = vertexShaderProgram->getSize();
\r
1921 vs = new c8[size+1];
\r
1922 vertexShaderProgram->read(vs, size);
\r
1927 if (pixelShaderProgram)
\r
1929 const long size = pixelShaderProgram->getSize();
\r
1932 // if both handles are the same we must reset the file
\r
1933 if (pixelShaderProgram==vertexShaderProgram)
\r
1934 pixelShaderProgram->seek(0);
\r
1935 ps = new c8[size+1];
\r
1936 pixelShaderProgram->read(ps, size);
\r
1941 if (geometryShaderProgram)
\r
1943 const long size = geometryShaderProgram->getSize();
\r
1946 // if both handles are the same we must reset the file
\r
1947 if ((geometryShaderProgram==vertexShaderProgram) ||
\r
1948 (geometryShaderProgram==pixelShaderProgram))
\r
1949 geometryShaderProgram->seek(0);
\r
1950 gs = new c8[size+1];
\r
1951 geometryShaderProgram->read(gs, size);
\r
1956 s32 result = this->addHighLevelShaderMaterial(
\r
1957 vs, vertexShaderEntryPointName, vsCompileTarget,
\r
1958 ps, pixelShaderEntryPointName, psCompileTarget,
\r
1959 gs, geometryShaderEntryPointName, gsCompileTarget,
\r
1960 inType, outType, verticesOut,
\r
1961 callback, baseMaterial, userData);
\r
1971 //! Adds a new material renderer to the VideoDriver, using pixel and/or
\r
1972 //! vertex shaders to render geometry.
\r
1973 s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram,
\r
1974 const c8* pixelShaderProgram,
\r
1975 IShaderConstantSetCallBack* callback,
\r
1976 E_MATERIAL_TYPE baseMaterial,
\r
1979 os::Printer::log("Shader materials not implemented yet in this driver, sorry.");
\r
1984 //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
\r
1985 //! programs from files.
\r
1986 s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram,
\r
1987 io::IReadFile* pixelShaderProgram,
\r
1988 IShaderConstantSetCallBack* callback,
\r
1989 E_MATERIAL_TYPE baseMaterial,
\r
1995 if (vertexShaderProgram)
\r
1997 const long size = vertexShaderProgram->getSize();
\r
2000 vs = new c8[size+1];
\r
2001 vertexShaderProgram->read(vs, size);
\r
2006 if (pixelShaderProgram)
\r
2008 const long size = pixelShaderProgram->getSize();
\r
2011 ps = new c8[size+1];
\r
2012 pixelShaderProgram->read(ps, size);
\r
2017 s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData);
\r
2026 //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
\r
2027 //! programs from files.
\r
2028 s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName,
\r
2029 const io::path& pixelShaderProgramFileName,
\r
2030 IShaderConstantSetCallBack* callback,
\r
2031 E_MATERIAL_TYPE baseMaterial,
\r
2034 io::IReadFile* vsfile = 0;
\r
2035 io::IReadFile* psfile = 0;
\r
2037 if (vertexShaderProgramFileName.size())
\r
2039 vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
\r
2042 os::Printer::log("Could not open vertex shader program file",
\r
2043 vertexShaderProgramFileName, ELL_WARNING);
\r
2048 if (pixelShaderProgramFileName.size())
\r
2050 psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
\r
2053 os::Printer::log("Could not open pixel shader program file",
\r
2054 pixelShaderProgramFileName, ELL_WARNING);
\r
2061 s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback,
\r
2062 baseMaterial, userData);
\r
2074 //! Creates a render target texture.
\r
2075 ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
\r
2076 const io::path&name, const ECOLOR_FORMAT format)
\r
2081 ITexture* CNullDriver::addRenderTargetTextureCubemap(const irr::u32 sideLen,
\r
2082 const io::path& name, const ECOLOR_FORMAT format)
\r
2087 void CNullDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
\r
2092 //! Returns a pointer to the mesh manipulator.
\r
2093 scene::IMeshManipulator* CNullDriver::getMeshManipulator()
\r
2095 return MeshManipulator;
\r
2099 //! Returns an image created from the last rendered frame.
\r
2100 IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
\r
2106 // prints renderer version
\r
2107 void CNullDriver::printVersion()
\r
2109 core::stringw namePrint = L"Using renderer: ";
\r
2110 namePrint += getName();
\r
2111 os::Printer::log(namePrint.c_str(), ELL_INFORMATION);
\r
2115 //! creates a video driver
\r
2116 IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
\r
2118 CNullDriver* nullDriver = new CNullDriver(io, screenSize);
\r
2120 // create empty material renderers
\r
2121 for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i)
\r
2123 IMaterialRenderer* imr = new IMaterialRenderer();
\r
2124 nullDriver->addMaterialRenderer(imr);
\r
2128 return nullDriver;
\r
2132 //! Set/unset a clipping plane.
\r
2133 //! There are at least 6 clipping planes available for the user to set at will.
\r
2134 //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
\r
2135 //! \param plane: The plane itself.
\r
2136 //! \param enable: If true, enable the clipping plane else disable it.
\r
2137 bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
\r
2143 //! Enable/disable a clipping plane.
\r
2144 void CNullDriver::enableClipPlane(u32 index, bool enable)
\r
2150 ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<u32>& size,
\r
2153 os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead");
\r
2154 ITexture* tex = addRenderTargetTexture(size, name);
\r
2160 void CNullDriver::setMinHardwareBufferVertexCount(u32 count)
\r
2162 MinVertexCountForVBO = count;
\r
2166 SOverrideMaterial& CNullDriver::getOverrideMaterial()
\r
2168 return OverrideMaterial;
\r
2172 //! Get the 2d override material for altering its values
\r
2173 SMaterial& CNullDriver::getMaterial2D()
\r
2175 return OverrideMaterial2D;
\r
2179 //! Enable the 2d override material
\r
2180 void CNullDriver::enableMaterial2D(bool enable)
\r
2182 OverrideMaterial2DEnabled=enable;
\r
2186 core::dimension2du CNullDriver::getMaxTextureSize() const
\r
2188 return core::dimension2du(0x10000,0x10000); // maybe large enough
\r
2191 bool CNullDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
\r
2193 // TODO: I suspect it would be nice if the material had an enum for further control.
\r
2194 // Especially it probably makes sense to allow disabling transparent render pass as soon as material.ZWriteEnable is on.
\r
2195 // 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
2196 // Or we could at least set return false when material.ZWriteEnable is EZW_ON? Still considering that...
\r
2197 // Be careful - this function is deeply connected to getWriteZBuffer as transparent render passes are usually about rendering with
\r
2198 // zwrite disabled and getWriteZBuffer calls this function.
\r
2200 video::IMaterialRenderer* rnd = getMaterialRenderer(material.MaterialType);
\r
2201 // TODO: I suspect IMaterialRenderer::isTransparent also often could use SMaterial as parameter
\r
2202 // We could for example then get rid of IsTransparent function in SMaterial and move that to the software material renderer.
\r
2203 if (rnd && rnd->isTransparent())
\r
2210 //! Color conversion convenience function
\r
2211 /** Convert an image (as array of pixels) from source to destination
\r
2212 array, thereby converting the color format. The pixel size is
\r
2213 determined by the color formats.
\r
2214 \param sP Pointer to source
\r
2215 \param sF Color format of source
\r
2216 \param sN Number of pixels to convert, both array must be large enough
\r
2217 \param dP Pointer to destination
\r
2218 \param dF Color format of destination
\r
2220 void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN,
\r
2221 void* dP, ECOLOR_FORMAT dF) const
\r
2223 video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF);
\r
2227 } // end namespace
\r
2228 } // end namespace
\r