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 psd images
\r
36 IImageLoader* createImageLoaderPSD();
\r
38 //! creates a loader which is able to load psd images
\r
39 IImageLoader* createImageLoaderPVR();
\r
41 //! creates a loader which is able to load dds images
\r
42 IImageLoader* createImageLoaderDDS();
\r
44 //! creates a loader which is able to load pcx images
\r
45 IImageLoader* createImageLoaderPCX();
\r
47 //! creates a loader which is able to load png images
\r
48 IImageLoader* createImageLoaderPNG();
\r
50 //! creates a loader which is able to load WAL images
\r
51 IImageLoader* createImageLoaderWAL();
\r
53 //! creates a loader which is able to load halflife images
\r
54 IImageLoader* createImageLoaderHalfLife();
\r
56 //! creates a loader which is able to load lmp images
\r
57 IImageLoader* createImageLoaderLMP();
\r
59 //! creates a loader which is able to load ppm/pgm/pbm images
\r
60 IImageLoader* createImageLoaderPPM();
\r
62 //! creates a loader which is able to load rgb images
\r
63 IImageLoader* createImageLoaderRGB();
\r
66 //! creates a writer which is able to save bmp images
\r
67 IImageWriter* createImageWriterBMP();
\r
69 //! creates a writer which is able to save jpg images
\r
70 IImageWriter* createImageWriterJPG();
\r
72 //! creates a writer which is able to save tga images
\r
73 IImageWriter* createImageWriterTGA();
\r
75 //! creates a writer which is able to save psd images
\r
76 IImageWriter* createImageWriterPSD();
\r
78 //! creates a writer which is able to save pcx images
\r
79 IImageWriter* createImageWriterPCX();
\r
81 //! creates a writer which is able to save png images
\r
82 IImageWriter* createImageWriterPNG();
\r
84 //! creates a writer which is able to save ppm images
\r
85 IImageWriter* createImageWriterPPM();
\r
88 CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
\r
89 : SharedRenderTarget(0), CurrentRenderTarget(0), CurrentRenderTargetSize(0, 0), FileSystem(io), MeshManipulator(0),
\r
90 ViewPort(0, 0, 0, 0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500),
\r
91 TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false)
\r
94 setDebugName("CNullDriver");
\r
97 DriverAttributes = new io::CAttributes();
\r
98 DriverAttributes->addInt("MaxTextures", _IRR_MATERIAL_MAX_TEXTURES_);
\r
99 DriverAttributes->addInt("MaxSupportedTextures", _IRR_MATERIAL_MAX_TEXTURES_);
\r
100 DriverAttributes->addInt("MaxLights", getMaximalDynamicLightAmount());
\r
101 DriverAttributes->addInt("MaxAnisotropy", 1);
\r
102 // DriverAttributes->addInt("MaxUserClipPlanes", 0);
\r
103 // DriverAttributes->addInt("MaxAuxBuffers", 0);
\r
104 DriverAttributes->addInt("MaxMultipleRenderTargets", 1);
\r
105 DriverAttributes->addInt("MaxIndices", -1);
\r
106 DriverAttributes->addInt("MaxTextureSize", -1);
\r
107 // DriverAttributes->addInt("MaxGeometryVerticesOut", 0);
\r
108 // DriverAttributes->addFloat("MaxTextureLODBias", 0.f);
\r
109 DriverAttributes->addInt("Version", 1);
\r
110 // DriverAttributes->addInt("ShaderLanguageVersion", 0);
\r
111 // DriverAttributes->addInt("AntiAlias", 0);
\r
115 setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true);
\r
116 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);
\r
117 setTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS, true);
\r
118 setTextureCreationFlag(ETCF_ALLOW_MEMORY_COPY, true);
\r
120 ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(screenSize));
\r
122 // create manipulator
\r
123 MeshManipulator = new scene::CMeshManipulator();
\r
126 FileSystem->grab();
\r
128 // create surface loader
\r
130 #ifdef _IRR_COMPILE_WITH_WAL_LOADER_
\r
131 SurfaceLoader.push_back(video::createImageLoaderHalfLife());
\r
132 SurfaceLoader.push_back(video::createImageLoaderWAL());
\r
134 #ifdef _IRR_COMPILE_WITH_LMP_LOADER_
\r
135 SurfaceLoader.push_back(video::createImageLoaderLMP());
\r
137 #ifdef _IRR_COMPILE_WITH_PPM_LOADER_
\r
138 SurfaceLoader.push_back(video::createImageLoaderPPM());
\r
140 #ifdef _IRR_COMPILE_WITH_RGB_LOADER_
\r
141 SurfaceLoader.push_back(video::createImageLoaderRGB());
\r
143 #ifdef _IRR_COMPILE_WITH_PSD_LOADER_
\r
144 SurfaceLoader.push_back(video::createImageLoaderPSD());
\r
146 #ifdef _IRR_COMPILE_WITH_PVR_LOADER_
\r
147 SurfaceLoader.push_back(video::createImageLoaderPVR());
\r
149 #if defined(_IRR_COMPILE_WITH_DDS_LOADER_) || defined(_IRR_COMPILE_WITH_DDS_DECODER_LOADER_)
\r
150 SurfaceLoader.push_back(video::createImageLoaderDDS());
\r
152 #ifdef _IRR_COMPILE_WITH_PCX_LOADER_
\r
153 SurfaceLoader.push_back(video::createImageLoaderPCX());
\r
155 #ifdef _IRR_COMPILE_WITH_TGA_LOADER_
\r
156 SurfaceLoader.push_back(video::createImageLoaderTGA());
\r
158 #ifdef _IRR_COMPILE_WITH_PNG_LOADER_
\r
159 SurfaceLoader.push_back(video::createImageLoaderPNG());
\r
161 #ifdef _IRR_COMPILE_WITH_JPG_LOADER_
\r
162 SurfaceLoader.push_back(video::createImageLoaderJPG());
\r
164 #ifdef _IRR_COMPILE_WITH_BMP_LOADER_
\r
165 SurfaceLoader.push_back(video::createImageLoaderBMP());
\r
169 #ifdef _IRR_COMPILE_WITH_PPM_WRITER_
\r
170 SurfaceWriter.push_back(video::createImageWriterPPM());
\r
172 #ifdef _IRR_COMPILE_WITH_PCX_WRITER_
\r
173 SurfaceWriter.push_back(video::createImageWriterPCX());
\r
175 #ifdef _IRR_COMPILE_WITH_PSD_WRITER_
\r
176 SurfaceWriter.push_back(video::createImageWriterPSD());
\r
178 #ifdef _IRR_COMPILE_WITH_TGA_WRITER_
\r
179 SurfaceWriter.push_back(video::createImageWriterTGA());
\r
181 #ifdef _IRR_COMPILE_WITH_JPG_WRITER_
\r
182 SurfaceWriter.push_back(video::createImageWriterJPG());
\r
184 #ifdef _IRR_COMPILE_WITH_PNG_WRITER_
\r
185 SurfaceWriter.push_back(video::createImageWriterPNG());
\r
187 #ifdef _IRR_COMPILE_WITH_BMP_WRITER_
\r
188 SurfaceWriter.push_back(video::createImageWriterBMP());
\r
192 // set ExposedData to 0
\r
193 memset((void*)&ExposedData, 0, sizeof(ExposedData));
\r
194 for (u32 i=0; i<video::EVDF_COUNT; ++i)
\r
195 FeatureEnabled[i]=true;
\r
197 InitMaterial2D.AntiAliasing=video::EAAM_OFF;
\r
198 InitMaterial2D.Lighting=false;
\r
199 InitMaterial2D.ZWriteEnable=video::EZW_OFF;
\r
200 InitMaterial2D.ZBuffer=video::ECFN_DISABLED;
\r
201 InitMaterial2D.UseMipMaps=false;
\r
202 for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
\r
204 InitMaterial2D.TextureLayer[i].BilinearFilter=false;
\r
205 InitMaterial2D.TextureLayer[i].TextureWrapU=video::ETC_REPEAT;
\r
206 InitMaterial2D.TextureLayer[i].TextureWrapV=video::ETC_REPEAT;
\r
207 InitMaterial2D.TextureLayer[i].TextureWrapW = video::ETC_REPEAT;
\r
209 OverrideMaterial2D=InitMaterial2D;
\r
214 CNullDriver::~CNullDriver()
\r
216 if (DriverAttributes)
\r
217 DriverAttributes->drop();
\r
220 FileSystem->drop();
\r
222 if (MeshManipulator)
\r
223 MeshManipulator->drop();
\r
225 removeAllRenderTargets();
\r
227 deleteAllTextures();
\r
230 for (i=0; i<SurfaceLoader.size(); ++i)
\r
231 SurfaceLoader[i]->drop();
\r
233 for (i=0; i<SurfaceWriter.size(); ++i)
\r
234 SurfaceWriter[i]->drop();
\r
236 // delete material renderers
\r
237 deleteMaterialRenders();
\r
239 // delete hardware mesh buffers
\r
240 removeAllHardwareBuffers();
\r
244 //! Adds an external surface loader to the engine.
\r
245 void CNullDriver::addExternalImageLoader(IImageLoader* loader)
\r
251 SurfaceLoader.push_back(loader);
\r
255 //! Adds an external surface writer to the engine.
\r
256 void CNullDriver::addExternalImageWriter(IImageWriter* writer)
\r
262 SurfaceWriter.push_back(writer);
\r
266 //! Retrieve the number of image loaders
\r
267 u32 CNullDriver::getImageLoaderCount() const
\r
269 return SurfaceLoader.size();
\r
273 //! Retrieve the given image loader
\r
274 IImageLoader* CNullDriver::getImageLoader(u32 n)
\r
276 if (n < SurfaceLoader.size())
\r
277 return SurfaceLoader[n];
\r
282 //! Retrieve the number of image writers
\r
283 u32 CNullDriver::getImageWriterCount() const
\r
285 return SurfaceWriter.size();
\r
289 //! Retrieve the given image writer
\r
290 IImageWriter* CNullDriver::getImageWriter(u32 n)
\r
292 if (n < SurfaceWriter.size())
\r
293 return SurfaceWriter[n];
\r
298 //! deletes all textures
\r
299 void CNullDriver::deleteAllTextures()
\r
301 // we need to remove previously set textures which might otherwise be kept in the
\r
302 // last set material member. Could be optimized to reduce state changes.
\r
303 setMaterial(SMaterial());
\r
305 // reset render targets.
\r
307 for (u32 i=0; i<RenderTargets.size(); ++i)
\r
308 RenderTargets[i]->setTexture(0, 0);
\r
310 // remove textures.
\r
312 for (u32 i=0; i<Textures.size(); ++i)
\r
313 Textures[i].Surface->drop();
\r
317 SharedDepthTextures.clear();
\r
320 bool CNullDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
\r
322 PrimitivesDrawn = 0;
\r
326 bool CNullDriver::endScene()
\r
328 FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn);
\r
329 updateAllHardwareBuffers();
\r
330 updateAllOcclusionQueries();
\r
335 //! Disable a feature of the driver.
\r
336 void CNullDriver::disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag)
\r
338 FeatureEnabled[feature]=!flag;
\r
342 //! queries the features of the driver, returns true if feature is available
\r
343 bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
\r
349 //! Get attributes of the actual video driver
\r
350 const io::IAttributes& CNullDriver::getDriverAttributes() const
\r
352 return *DriverAttributes;
\r
356 //! sets transformation
\r
357 void CNullDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
\r
362 //! Returns the transformation set by setTransform
\r
363 const core::matrix4& CNullDriver::getTransform(E_TRANSFORMATION_STATE state) const
\r
365 return TransformationMatrix;
\r
369 //! sets a material
\r
370 void CNullDriver::setMaterial(const SMaterial& material)
\r
375 //! Removes a texture from the texture cache and deletes it, freeing lot of
\r
377 void CNullDriver::removeTexture(ITexture* texture)
\r
382 for (u32 i=0; i<Textures.size(); ++i)
\r
384 if (Textures[i].Surface == texture)
\r
394 //! Removes all texture from the texture cache and deletes them, freeing lot of
\r
396 void CNullDriver::removeAllTextures()
\r
398 setMaterial ( SMaterial() );
\r
399 deleteAllTextures();
\r
403 //! Returns a texture by index
\r
404 ITexture* CNullDriver::getTextureByIndex(u32 i)
\r
406 if ( i < Textures.size() )
\r
407 return Textures[i].Surface;
\r
413 //! Returns amount of textures currently loaded
\r
414 u32 CNullDriver::getTextureCount() const
\r
416 return Textures.size();
\r
420 //! Renames a texture
\r
421 void CNullDriver::renameTexture(ITexture* texture, const io::path& newName)
\r
423 // we can do a const_cast here safely, the name of the ITexture interface
\r
424 // is just readonly to prevent the user changing the texture name without invoking
\r
425 // this method, because the textures will need resorting afterwards
\r
427 io::SNamedPath& name = const_cast<io::SNamedPath&>(texture->getName());
\r
428 name.setPath(newName);
\r
433 ITexture* CNullDriver::addTexture(const core::dimension2d<u32>& size, const io::path& name, ECOLOR_FORMAT format)
\r
435 if (0 == name.size())
\r
437 os::Printer::log("Could not create ITexture, texture needs to have a non-empty name.", ELL_WARNING);
\r
441 IImage* image = new CImage(format, size);
\r
444 core::array<IImage*> imageArray(1);
\r
445 imageArray.push_back(image);
\r
447 if (checkImage(imageArray))
\r
449 t = createDeviceDependentTexture(name, image);
\r
463 ITexture* CNullDriver::addTexture(const io::path& name, IImage* image)
\r
465 if (0 == name.size())
\r
467 os::Printer::log("Could not create ITexture, texture needs to have a non-empty name.", ELL_WARNING);
\r
476 core::array<IImage*> imageArray(1);
\r
477 imageArray.push_back(image);
\r
479 if (checkImage(imageArray))
\r
481 t = createDeviceDependentTexture(name, image);
\r
493 ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX, IImage* imageNegX, IImage* imagePosY,
\r
494 IImage* imageNegY, IImage* imagePosZ, IImage* imageNegZ)
\r
496 if (0 == name.size() || !imagePosX || !imageNegX || !imagePosY || !imageNegY || !imagePosZ || !imageNegZ)
\r
501 core::array<IImage*> imageArray(6);
\r
502 imageArray.push_back(imagePosX);
\r
503 imageArray.push_back(imageNegX);
\r
504 imageArray.push_back(imagePosY);
\r
505 imageArray.push_back(imageNegY);
\r
506 imageArray.push_back(imagePosZ);
\r
507 imageArray.push_back(imageNegZ);
\r
509 if (checkImage(imageArray))
\r
511 t = createDeviceDependentTextureCubemap(name, imageArray);
\r
523 ITexture* CNullDriver::addTextureCubemap(const irr::u32 sideLen, const io::path& name, ECOLOR_FORMAT format)
\r
525 if ( 0 == sideLen )
\r
528 if (0 == name.size())
\r
530 os::Printer::log("Could not create ITexture, texture needs to have a non-empty name.", ELL_WARNING);
\r
534 core::array<IImage*> imageArray(6);
\r
535 for ( int i=0; i < 6; ++i )
\r
536 imageArray.push_back(new CImage(format, core::dimension2du(sideLen, sideLen)));
\r
539 if (checkImage(imageArray))
\r
541 t = createDeviceDependentTextureCubemap(name, imageArray);
\r
550 for ( int i=0; i < 6; ++i )
\r
551 imageArray[i]->drop();
\r
556 //! loads a Texture
\r
557 ITexture* CNullDriver::getTexture(const io::path& filename)
\r
559 // Identify textures by their absolute filenames if possible.
\r
560 const io::path absolutePath = FileSystem->getAbsolutePath(filename);
\r
562 ITexture* texture = findTexture(absolutePath);
\r
565 texture->updateSource(ETS_FROM_CACHE);
\r
569 // Then try the raw filename, which might be in an Archive
\r
570 texture = findTexture(filename);
\r
573 texture->updateSource(ETS_FROM_CACHE);
\r
577 // Now try to open the file using the complete path.
\r
578 io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath);
\r
582 // Try to open it using the raw filename.
\r
583 file = FileSystem->createAndOpenFile(filename);
\r
588 // Re-check name for actual archive names
\r
589 texture = findTexture(file->getFileName());
\r
592 texture->updateSource(ETS_FROM_CACHE);
\r
597 texture = loadTextureFromFile(file);
\r
602 texture->updateSource(ETS_FROM_FILE);
\r
603 addTexture(texture);
\r
604 texture->drop(); // drop it because we created it, one grab too much
\r
607 os::Printer::log("Could not load texture", filename, ELL_ERROR);
\r
612 os::Printer::log("Could not open file of texture", filename, ELL_WARNING);
\r
618 //! loads a Texture
\r
619 ITexture* CNullDriver::getTexture(io::IReadFile* file)
\r
621 ITexture* texture = 0;
\r
625 texture = findTexture(file->getFileName());
\r
629 texture->updateSource(ETS_FROM_CACHE);
\r
633 texture = loadTextureFromFile(file);
\r
637 texture->updateSource(ETS_FROM_FILE);
\r
638 addTexture(texture);
\r
639 texture->drop(); // drop it because we created it, one grab too much
\r
643 os::Printer::log("Could not load texture", file->getFileName(), ELL_WARNING);
\r
650 //! opens the file and loads it into the surface
\r
651 video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName )
\r
653 ITexture* texture = 0;
\r
655 E_TEXTURE_TYPE type = ETT_2D;
\r
657 core::array<IImage*> imageArray = createImagesFromFile(file, &type);
\r
659 if (checkImage(imageArray))
\r
664 texture = createDeviceDependentTexture(hashName.size() ? hashName : file->getFileName(), imageArray[0]);
\r
667 if (imageArray.size() >= 6 && imageArray[0] && imageArray[1] && imageArray[2] && imageArray[3] && imageArray[4] && imageArray[5])
\r
669 texture = createDeviceDependentTextureCubemap(hashName.size() ? hashName : file->getFileName(), imageArray);
\r
673 _IRR_DEBUG_BREAK_IF(true);
\r
678 os::Printer::log("Loaded texture", file->getFileName(), ELL_DEBUG);
\r
681 for (u32 i = 0; i < imageArray.size(); ++i)
\r
684 imageArray[i]->drop();
\r
691 //! adds a surface, not loaded or created by the Irrlicht Engine
\r
692 void CNullDriver::addTexture(video::ITexture* texture)
\r
697 s.Surface = texture;
\r
700 Textures.push_back(s);
\r
702 // the new texture is now at the end of the texture list. when searching for
\r
703 // the next new texture, the texture array will be sorted and the index of this texture
\r
704 // will be changed. to let the order be more consistent to the user, sort
\r
705 // the textures now already although this isn't necessary:
\r
712 //! looks if the image is already loaded
\r
713 video::ITexture* CNullDriver::findTexture(const io::path& filename)
\r
716 SDummyTexture dummy(filename, ETT_2D);
\r
717 s.Surface = &dummy;
\r
719 s32 index = Textures.binary_search(s);
\r
721 return Textures[index].Surface;
\r
726 ITexture* CNullDriver::createDeviceDependentTexture(const io::path& name, IImage* image)
\r
728 SDummyTexture* dummy = new SDummyTexture(name, ETT_2D);
\r
729 dummy->setSize(image->getDimension());
\r
733 ITexture* CNullDriver::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)
\r
735 return new SDummyTexture(name, ETT_CUBEMAP);
\r
738 bool CNullDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)
\r
743 bool CNullDriver::setRenderTarget(ITexture* texture, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)
\r
747 // create render target if require.
\r
748 if (!SharedRenderTarget)
\r
749 SharedRenderTarget = addRenderTarget();
\r
751 ITexture* depthTexture = 0;
\r
753 // try to find available depth texture with require size.
\r
754 for (u32 i = 0; i < SharedDepthTextures.size(); ++i)
\r
756 if (SharedDepthTextures[i]->getSize() == texture->getSize())
\r
758 depthTexture = SharedDepthTextures[i];
\r
764 // create depth texture if require.
\r
767 depthTexture = addRenderTargetTexture(texture->getSize(), "IRR_DEPTH_STENCIL", video::ECF_D24S8);
\r
768 SharedDepthTextures.push_back(depthTexture);
\r
771 SharedRenderTarget->setTexture(texture, depthTexture);
\r
773 return setRenderTargetEx(SharedRenderTarget, clearFlag, clearColor, clearDepth, clearStencil);
\r
777 return setRenderTargetEx(0, clearFlag, clearColor, clearDepth, clearStencil);
\r
781 //! sets a viewport
\r
782 void CNullDriver::setViewPort(const core::rect<s32>& area)
\r
787 //! gets the area of the current viewport
\r
788 const core::rect<s32>& CNullDriver::getViewPort() const
\r
794 //! draws a vertex primitive list
\r
795 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
797 if ((iType==EIT_16BIT) && (vertexCount>65536))
\r
798 os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
\r
799 PrimitivesDrawn += primitiveCount;
\r
803 //! draws a vertex primitive list in 2d
\r
804 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
806 if ((iType==EIT_16BIT) && (vertexCount>65536))
\r
807 os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
\r
808 PrimitivesDrawn += primitiveCount;
\r
812 //! Draws a 3d line.
\r
813 void CNullDriver::draw3DLine(const core::vector3df& start,
\r
814 const core::vector3df& end, SColor color)
\r
819 //! Draws a 3d triangle.
\r
820 void CNullDriver::draw3DTriangle(const core::triangle3df& triangle, SColor color)
\r
822 S3DVertex vertices[3];
\r
823 vertices[0].Pos=triangle.pointA;
\r
824 vertices[0].Color=color;
\r
825 vertices[0].Normal=triangle.getNormal().normalize();
\r
826 vertices[0].TCoords.set(0.f,0.f);
\r
827 vertices[1].Pos=triangle.pointB;
\r
828 vertices[1].Color=color;
\r
829 vertices[1].Normal=vertices[0].Normal;
\r
830 vertices[1].TCoords.set(0.5f,1.f);
\r
831 vertices[2].Pos=triangle.pointC;
\r
832 vertices[2].Color=color;
\r
833 vertices[2].Normal=vertices[0].Normal;
\r
834 vertices[2].TCoords.set(1.f,0.f);
\r
835 const u16 indexList[] = {0,1,2};
\r
836 drawVertexPrimitiveList(vertices, 3, indexList, 1, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT);
\r
840 //! Draws a 3d axis aligned box.
\r
841 void CNullDriver::draw3DBox(const core::aabbox3d<f32>& box, SColor color)
\r
843 core::vector3df edges[8];
\r
844 box.getEdges(edges);
\r
846 // TODO: optimize into one big drawIndexPrimitive call.
\r
848 draw3DLine(edges[5], edges[1], color);
\r
849 draw3DLine(edges[1], edges[3], color);
\r
850 draw3DLine(edges[3], edges[7], color);
\r
851 draw3DLine(edges[7], edges[5], color);
\r
852 draw3DLine(edges[0], edges[2], color);
\r
853 draw3DLine(edges[2], edges[6], color);
\r
854 draw3DLine(edges[6], edges[4], color);
\r
855 draw3DLine(edges[4], edges[0], color);
\r
856 draw3DLine(edges[1], edges[0], color);
\r
857 draw3DLine(edges[3], edges[2], color);
\r
858 draw3DLine(edges[7], edges[6], color);
\r
859 draw3DLine(edges[5], edges[4], color);
\r
864 //! draws an 2d image
\r
865 void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos, bool useAlphaChannelOfTexture)
\r
870 draw2DImage(texture,destPos, core::rect<s32>(core::position2d<s32>(0,0),
\r
871 core::dimension2di(texture->getOriginalSize())),
\r
873 SColor(255,255,255,255),
\r
874 useAlphaChannelOfTexture
\r
880 //! draws a set of 2d images, using a color and the alpha channel of the
\r
881 //! texture if desired. The images are drawn beginning at pos and concatenated
\r
882 //! in one line. All drawings are clipped against clipRect (if != 0).
\r
883 //! The subtextures are defined by the array of sourceRects and are chosen
\r
884 //! by the indices given.
\r
885 void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
\r
886 const core::position2d<s32>& pos,
\r
887 const core::array<core::rect<s32> >& sourceRects,
\r
888 const core::array<s32>& indices,
\r
890 const core::rect<s32>* clipRect, SColor color,
\r
891 bool useAlphaChannelOfTexture)
\r
893 core::position2d<s32> target(pos);
\r
895 for (u32 i=0; i<indices.size(); ++i)
\r
897 draw2DImage(texture, target, sourceRects[indices[i]],
\r
898 clipRect, color, useAlphaChannelOfTexture);
\r
899 target.X += sourceRects[indices[i]].getWidth();
\r
900 target.X += kerningWidth;
\r
904 //! draws a set of 2d images, using a color and the alpha channel of the
\r
905 //! texture if desired.
\r
906 void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
\r
907 const core::array<core::position2d<s32> >& positions,
\r
908 const core::array<core::rect<s32> >& sourceRects,
\r
909 const core::rect<s32>* clipRect,
\r
911 bool useAlphaChannelOfTexture)
\r
913 const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
\r
915 for (u32 i=0; i<drawCount; ++i)
\r
917 draw2DImage(texture, positions[i], sourceRects[i],
\r
918 clipRect, color, useAlphaChannelOfTexture);
\r
923 //! Draws a part of the texture into the rectangle.
\r
924 void CNullDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
\r
925 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
\r
926 const video::SColor* const colors, bool useAlphaChannelOfTexture)
\r
928 if (destRect.isValid())
\r
929 draw2DImage(texture, core::position2d<s32>(destRect.UpperLeftCorner),
\r
930 sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff),
\r
931 useAlphaChannelOfTexture);
\r
935 //! 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
936 void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
\r
937 const core::rect<s32>& sourceRect,
\r
938 const core::rect<s32>* clipRect, SColor color,
\r
939 bool useAlphaChannelOfTexture)
\r
944 //! Draws the outline of a 2d rectangle
\r
945 void CNullDriver::draw2DRectangleOutline(const core::recti& pos, SColor color)
\r
947 draw2DLine(pos.UpperLeftCorner, core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), color);
\r
948 draw2DLine(core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), pos.LowerRightCorner, color);
\r
949 draw2DLine(pos.LowerRightCorner, core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), color);
\r
950 draw2DLine(core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), pos.UpperLeftCorner, color);
\r
954 //! Draw a 2d rectangle
\r
955 void CNullDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos, const core::rect<s32>* clip)
\r
957 draw2DRectangle(pos, color, color, color, color, clip);
\r
962 //! Draws a 2d rectangle with a gradient.
\r
963 void CNullDriver::draw2DRectangle(const core::rect<s32>& pos,
\r
964 SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
\r
965 const core::rect<s32>* clip)
\r
971 //! Draws a 2d line.
\r
972 void CNullDriver::draw2DLine(const core::position2d<s32>& start,
\r
973 const core::position2d<s32>& end, SColor color)
\r
978 void CNullDriver::drawPixel(u32 x, u32 y, const SColor & color)
\r
983 //! Draws a non filled concyclic regular 2d polygon.
\r
984 void CNullDriver::draw2DPolygon(core::position2d<s32> center,
\r
985 f32 radius, video::SColor color, s32 count)
\r
990 core::position2d<s32> first;
\r
991 core::position2d<s32> a,b;
\r
993 for (s32 j=0; j<count; ++j)
\r
997 f32 p = j / (f32)count * (core::PI*2);
\r
998 a = center + core::position2d<s32>((s32)(sin(p)*radius), (s32)(cos(p)*radius));
\r
1003 draw2DLine(a, b, color);
\r
1006 draw2DLine(a, first, color);
\r
1010 //! returns color format
\r
1011 ECOLOR_FORMAT CNullDriver::getColorFormat() const
\r
1013 return ECF_R5G6B5;
\r
1017 //! returns screen size
\r
1018 const core::dimension2d<u32>& CNullDriver::getScreenSize() const
\r
1020 return ScreenSize;
\r
1024 //! get current render target
\r
1025 IRenderTarget* CNullDriver::getCurrentRenderTarget() const
\r
1027 return CurrentRenderTarget;
\r
1031 const core::dimension2d<u32>& CNullDriver::getCurrentRenderTargetSize() const
\r
1033 if (CurrentRenderTargetSize.Width == 0)
\r
1034 return ScreenSize;
\r
1036 return CurrentRenderTargetSize;
\r
1040 // returns current frames per second value
\r
1041 s32 CNullDriver::getFPS() const
\r
1043 return FPSCounter.getFPS();
\r
1048 //! returns amount of primitives (mostly triangles) were drawn in the last frame.
\r
1049 //! very useful method for statistics.
\r
1050 u32 CNullDriver::getPrimitiveCountDrawn( u32 param ) const
\r
1052 return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() : FPSCounter.getPrimitiveTotal();
\r
1057 //! Sets the dynamic ambient light color. The default color is
\r
1058 //! (0,0,0,0) which means it is dark.
\r
1059 //! \param color: New color of the ambient light.
\r
1060 void CNullDriver::setAmbientLight(const SColorf& color)
\r
1062 AmbientLight = color;
\r
1065 const SColorf& CNullDriver::getAmbientLight() const
\r
1067 return AmbientLight;
\r
1070 //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
\r
1071 //! driver, it would return "Direct3D8".
\r
1073 const wchar_t* CNullDriver::getName() const
\r
1075 return L"Irrlicht NullDevice";
\r
1080 //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
\r
1081 //! this: First, draw all geometry. Then use this method, to draw the shadow
\r
1082 //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow.
\r
1083 void CNullDriver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible)
\r
1088 //! Fills the stencil shadow with color. After the shadow volume has been drawn
\r
1089 //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
\r
1090 //! to draw the color of the shadow.
\r
1091 void CNullDriver::drawStencilShadow(bool clearStencilBuffer,
\r
1092 video::SColor leftUpEdge, video::SColor rightUpEdge,
\r
1093 video::SColor leftDownEdge, video::SColor rightDownEdge)
\r
1098 //! deletes all dynamic lights there are
\r
1099 void CNullDriver::deleteAllDynamicLights()
\r
1101 Lights.set_used(0);
\r
1105 //! adds a dynamic light
\r
1106 s32 CNullDriver::addDynamicLight(const SLight& light)
\r
1108 Lights.push_back(light);
\r
1109 return Lights.size() - 1;
\r
1112 //! Turns a dynamic light on or off
\r
1113 //! \param lightIndex: the index returned by addDynamicLight
\r
1114 //! \param turnOn: true to turn the light on, false to turn it off
\r
1115 void CNullDriver::turnLightOn(s32 lightIndex, bool turnOn)
\r
1121 //! returns the maximal amount of dynamic lights the device can handle
\r
1122 u32 CNullDriver::getMaximalDynamicLightAmount() const
\r
1128 //! Returns current amount of dynamic lights set
\r
1129 //! \return Current amount of dynamic lights set
\r
1130 u32 CNullDriver::getDynamicLightCount() const
\r
1132 return Lights.size();
\r
1136 //! Returns light data which was previously set by IVideoDriver::addDynamicLight().
\r
1137 //! \param idx: Zero based index of the light. Must be greater than 0 and smaller
\r
1138 //! than IVideoDriver()::getDynamicLightCount.
\r
1139 //! \return Light data.
\r
1140 const SLight& CNullDriver::getDynamicLight(u32 idx) const
\r
1142 if ( idx < Lights.size() )
\r
1143 return Lights[idx];
\r
1146 _IRR_DEBUG_BREAK_IF(true)
\r
1147 static const SLight dummy;
\r
1153 //! Creates a boolean alpha channel of the texture based of an color key.
\r
1154 void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
\r
1155 video::SColor color,
\r
1156 bool zeroTexels) const
\r
1161 if (texture->getColorFormat() != ECF_A1R5G5B5 &&
\r
1162 texture->getColorFormat() != ECF_A8R8G8B8 )
\r
1164 os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
\r
1168 if (texture->getColorFormat() == ECF_A1R5G5B5)
\r
1170 u16 *p = (u16*)texture->lock();
\r
1174 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
1178 const core::dimension2d<u32> dim = texture->getSize();
\r
1179 const u32 pitch = texture->getPitch() / 2;
\r
1181 // color with alpha disabled (i.e. fully transparent)
\r
1182 const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5());
\r
1184 const u32 pixels = pitch * dim.Height;
\r
1186 for (u32 pixel = 0; pixel < pixels; ++ pixel)
\r
1188 // If the color matches the reference color, ignoring alphas,
\r
1189 // set the alpha to zero.
\r
1190 if(((*p) & 0x7fff) == refZeroAlpha)
\r
1195 (*p) = refZeroAlpha;
\r
1201 texture->unlock();
\r
1205 u32 *p = (u32*)texture->lock();
\r
1209 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
1213 core::dimension2d<u32> dim = texture->getSize();
\r
1214 u32 pitch = texture->getPitch() / 4;
\r
1216 // color with alpha disabled (fully transparent)
\r
1217 const u32 refZeroAlpha = 0x00ffffff & color.color;
\r
1219 const u32 pixels = pitch * dim.Height;
\r
1220 for (u32 pixel = 0; pixel < pixels; ++ pixel)
\r
1222 // If the color matches the reference color, ignoring alphas,
\r
1223 // set the alpha to zero.
\r
1224 if(((*p) & 0x00ffffff) == refZeroAlpha)
\r
1229 (*p) = refZeroAlpha;
\r
1235 texture->unlock();
\r
1237 texture->regenerateMipMapLevels();
\r
1242 //! Creates an boolean alpha channel of the texture based of an color key position.
\r
1243 void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
\r
1244 core::position2d<s32> colorKeyPixelPos,
\r
1245 bool zeroTexels) const
\r
1250 if (texture->getColorFormat() != ECF_A1R5G5B5 &&
\r
1251 texture->getColorFormat() != ECF_A8R8G8B8 )
\r
1253 os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
\r
1259 if (texture->getColorFormat() == ECF_A1R5G5B5)
\r
1261 u16 *p = (u16*)texture->lock(ETLM_READ_ONLY);
\r
1265 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
1269 u32 pitch = texture->getPitch() / 2;
\r
1271 const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
\r
1273 colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit);
\r
1277 u32 *p = (u32*)texture->lock(ETLM_READ_ONLY);
\r
1281 os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
\r
1285 u32 pitch = texture->getPitch() / 4;
\r
1286 colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
\r
1289 texture->unlock();
\r
1290 makeColorKeyTexture(texture, colorKey, zeroTexels);
\r
1294 //! Returns the maximum amount of primitives (mostly vertices) which
\r
1295 //! the device is able to render with one drawIndexedTriangleList
\r
1297 u32 CNullDriver::getMaximalPrimitiveCount() const
\r
1299 return 0xFFFFFFFF;
\r
1303 //! checks triangle count and print warning if wrong
\r
1304 bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
\r
1306 const u32 m = getMaximalPrimitiveCount();
\r
1311 snprintf_irr(tmp, sizeof(tmp), "Could not draw triangles, too many primitives(%u), maximum is %u.", prmCount, m);
\r
1312 os::Printer::log(tmp, ELL_ERROR);
\r
1319 bool CNullDriver::checkImage(const core::array<IImage*>& image) const
\r
1321 bool status = true;
\r
1323 if (image.size() > 0)
\r
1325 ECOLOR_FORMAT lastFormat = image[0]->getColorFormat();
\r
1326 core::dimension2d<u32> lastSize = image[0]->getDimension();
\r
1328 for (u32 i = 0; i < image.size() && status; ++i)
\r
1330 ECOLOR_FORMAT format = image[i]->getColorFormat();
\r
1331 core::dimension2d<u32> size = image[i]->getDimension();
\r
1340 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
\r
1342 os::Printer::log("DXT texture compression not available.", ELL_ERROR);
\r
1345 else if (size.getOptimalSize(true, false) != size)
\r
1347 os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR);
\r
1351 case ECF_PVRTC_RGB2:
\r
1352 case ECF_PVRTC_ARGB2:
\r
1353 case ECF_PVRTC_RGB4:
\r
1354 case ECF_PVRTC_ARGB4:
\r
1355 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC))
\r
1357 os::Printer::log("PVRTC texture compression not available.", ELL_ERROR);
\r
1360 else if (size.getOptimalSize(true, false) != size)
\r
1362 os::Printer::log("Invalid size of image for PVRTC compressed texture, size of image must be power of two and squared.", ELL_ERROR);
\r
1366 case ECF_PVRTC2_ARGB2:
\r
1367 case ECF_PVRTC2_ARGB4:
\r
1368 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2))
\r
1370 os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR);
\r
1375 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1))
\r
1377 os::Printer::log("ETC1 texture compression not available.", ELL_ERROR);
\r
1381 case ECF_ETC2_RGB:
\r
1382 case ECF_ETC2_ARGB:
\r
1383 if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2))
\r
1385 os::Printer::log("ETC2 texture compression not available.", ELL_ERROR);
\r
1393 if (format != lastFormat || size != lastSize)
\r
1405 //! Enables or disables a texture creation flag.
\r
1406 void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled)
\r
1408 if (enabled && ((flag == ETCF_ALWAYS_16_BIT) || (flag == ETCF_ALWAYS_32_BIT)
\r
1409 || (flag == ETCF_OPTIMIZED_FOR_QUALITY) || (flag == ETCF_OPTIMIZED_FOR_SPEED)))
\r
1411 // disable other formats
\r
1412 setTextureCreationFlag(ETCF_ALWAYS_16_BIT, false);
\r
1413 setTextureCreationFlag(ETCF_ALWAYS_32_BIT, false);
\r
1414 setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, false);
\r
1415 setTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED, false);
\r
1419 TextureCreationFlags = (TextureCreationFlags & (~flag)) |
\r
1420 ((((u32)!enabled)-1) & flag);
\r
1424 //! Returns if a texture creation flag is enabled or disabled.
\r
1425 bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const
\r
1427 return (TextureCreationFlags & flag)!=0;
\r
1430 core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type)
\r
1432 // TO-DO -> use 'move' feature from C++11 standard.
\r
1434 core::array<IImage*> imageArray;
\r
1436 if (filename.size() > 0)
\r
1438 io::IReadFile* file = FileSystem->createAndOpenFile(filename);
\r
1442 imageArray = createImagesFromFile(file, type);
\r
1446 os::Printer::log("Could not open file of image", filename, ELL_WARNING);
\r
1449 return imageArray;
\r
1452 core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type)
\r
1454 // TO-DO -> use 'move' feature from C++11 standard.
\r
1456 core::array<IImage*> imageArray;
\r
1462 // try to load file based on file extension
\r
1463 for (i = SurfaceLoader.size() - 1; i >= 0; --i)
\r
1465 if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
\r
1467 // reset file position which might have changed due to previous loadImage calls
\r
1469 imageArray = SurfaceLoader[i]->loadImages(file, type);
\r
1471 if (imageArray.size() == 0)
\r
1474 IImage* image = SurfaceLoader[i]->loadImage(file);
\r
1477 imageArray.push_back(image);
\r
1480 if (imageArray.size() > 0)
\r
1481 return imageArray;
\r
1485 // try to load file based on what is in it
\r
1486 for (i = SurfaceLoader.size() - 1; i >= 0; --i)
\r
1490 if (SurfaceLoader[i]->isALoadableFileFormat(file)
\r
1491 && !SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()) // extension was tried above already
\r
1495 imageArray = SurfaceLoader[i]->loadImages(file, type);
\r
1497 if (imageArray.size() == 0)
\r
1500 IImage* image = SurfaceLoader[i]->loadImage(file);
\r
1503 imageArray.push_back(image);
\r
1506 if (imageArray.size() > 0)
\r
1507 return imageArray;
\r
1512 return imageArray;
\r
1516 //! Writes the provided image to disk file
\r
1517 bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param)
\r
1519 io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
\r
1523 bool result = writeImageToFile(image, file, param);
\r
1529 //! Writes the provided image to a file.
\r
1530 bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param)
\r
1535 for (s32 i=SurfaceWriter.size()-1; i>=0; --i)
\r
1537 if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName()))
\r
1539 bool written = SurfaceWriter[i]->writeImage(file, image, param);
\r
1544 return false; // failed to write
\r
1548 //! Creates a software image from a byte array.
\r
1549 IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
\r
1550 const core::dimension2d<u32>& size, void *data, bool ownForeignMemory,
\r
1551 bool deleteMemory)
\r
1553 return new CImage(format, size, data, ownForeignMemory, deleteMemory);
\r
1557 //! Creates an empty software image.
\r
1558 IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
\r
1560 return new CImage(format, size);
\r
1564 //! Creates a software image from another image.
\r
1565 IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy)
\r
1567 os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
\r
1569 CImage* tmp = new CImage(format, imageToCopy->getDimension());
\r
1570 imageToCopy->copyTo(tmp);
\r
1575 //! Creates a software image from part of another image.
\r
1576 IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
\r
1578 os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
\r
1579 CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension());
\r
1580 imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size));
\r
1585 //! Creates a software image from part of a texture.
\r
1586 IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
\r
1588 if ((pos==core::position2di(0,0)) && (size == texture->getSize()))
\r
1590 void * data = texture->lock(ETLM_READ_ONLY);
\r
1593 IImage* image = new CImage(texture->getColorFormat(), size, data, false, false);
\r
1594 texture->unlock();
\r
1599 // make sure to avoid buffer overruns
\r
1600 // make the vector a separate variable for g++ 3.x
\r
1601 const core::vector2d<u32> leftUpper(core::clamp(static_cast<u32>(pos.X), 0u, texture->getSize().Width),
\r
1602 core::clamp(static_cast<u32>(pos.Y), 0u, texture->getSize().Height));
\r
1603 const core::rect<u32> clamped(leftUpper,
\r
1604 core::dimension2du(core::clamp(static_cast<u32>(size.Width), 0u, texture->getSize().Width),
\r
1605 core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
\r
1606 if (!clamped.isValid())
\r
1608 u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
\r
1611 IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
\r
1612 u8* dst = static_cast<u8*>(image->getData());
\r
1613 src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X;
\r
1614 for (u32 i=0; i<clamped.getHeight(); ++i)
\r
1616 video::CColorConverter::convert_viaFormat(src, texture->getColorFormat(), clamped.getWidth(), dst, image->getColorFormat());
\r
1617 src += texture->getPitch();
\r
1618 dst += image->getPitch();
\r
1620 texture->unlock();
\r
1626 //! Sets the fog mode.
\r
1627 void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end,
\r
1628 f32 density, bool pixelFog, bool rangeFog)
\r
1631 FogType = fogType;
\r
1634 FogDensity = density;
\r
1635 PixelFog = pixelFog;
\r
1636 RangeFog = rangeFog;
\r
1639 //! Gets the fog mode.
\r
1640 void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end,
\r
1641 f32& density, bool& pixelFog, bool& rangeFog)
\r
1644 fogType = FogType;
\r
1647 density = FogDensity;
\r
1648 pixelFog = PixelFog;
\r
1649 rangeFog = RangeFog;
\r
1652 //! Draws a mesh buffer
\r
1653 void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb)
\r
1658 //IVertexBuffer and IIndexBuffer later
\r
1659 SHWBufferLink *HWBuffer=getBufferLink(mb);
\r
1662 drawHardwareBuffer(HWBuffer);
\r
1664 drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), mb->getIndexType());
\r
1668 //! Draws the normals of a mesh buffer
\r
1669 void CNullDriver::drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length, SColor color)
\r
1671 const u32 count = mb->getVertexCount();
\r
1672 const bool normalize = mb->getMaterial().NormalizeNormals;
\r
1674 for (u32 i=0; i < count; ++i)
\r
1676 core::vector3df normalizedNormal = mb->getNormal(i);
\r
1678 normalizedNormal.normalize();
\r
1680 const core::vector3df& pos = mb->getPosition(i);
\r
1681 draw3DLine(pos, pos + (normalizedNormal * length), color);
\r
1686 CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb)
\r
1688 if (!mb || !isHardwareBufferRecommend(mb))
\r
1691 //search for hardware links
\r
1692 SHWBufferLink *HWBuffer = reinterpret_cast<SHWBufferLink*>(mb->getHWBuffer());
\r
1696 return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it
\r
1700 //! Update all hardware buffers, remove unused ones
\r
1701 void CNullDriver::updateAllHardwareBuffers()
\r
1703 auto it = HWBufferList.begin();
\r
1704 while (it != HWBufferList.end()) {
\r
1705 SHWBufferLink *Link = *it;
\r
1708 if (!Link->MeshBuffer || Link->MeshBuffer->getReferenceCount() == 1)
\r
1709 deleteHardwareBuffer(Link);
\r
1714 void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
\r
1718 HWBufferList.erase(HWBuffer->listPosition);
\r
1723 //! Remove hardware buffer
\r
1724 void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb)
\r
1728 SHWBufferLink *HWBuffer = reinterpret_cast<SHWBufferLink*>(mb->getHWBuffer());
\r
1730 deleteHardwareBuffer(HWBuffer);
\r
1734 //! Remove all hardware buffers
\r
1735 void CNullDriver::removeAllHardwareBuffers()
\r
1737 while (!HWBufferList.empty())
\r
1738 deleteHardwareBuffer(HWBufferList.front());
\r
1742 bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb)
\r
1744 if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
\r
1747 if (mb->getVertexCount()<MinVertexCountForVBO)
\r
1754 //! Create occlusion query.
\r
1755 /** Use node for identification and mesh for occlusion test. */
\r
1756 void CNullDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh)
\r
1762 if ((node->getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH))
\r
1764 else if (node->getType() == scene::ESNT_MESH)
\r
1765 mesh = static_cast<scene::IMeshSceneNode*>(node)->getMesh();
\r
1767 mesh = static_cast<scene::IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
\r
1772 //search for query
\r
1773 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1776 if (OcclusionQueries[index].Mesh != mesh)
\r
1778 OcclusionQueries[index].Mesh->drop();
\r
1779 OcclusionQueries[index].Mesh = mesh;
\r
1785 OcclusionQueries.push_back(SOccQuery(node, mesh));
\r
1786 node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY);
\r
1791 //! Remove occlusion query.
\r
1792 void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node)
\r
1794 //search for query
\r
1795 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1798 node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY);
\r
1799 OcclusionQueries.erase(index);
\r
1804 //! Remove all occlusion queries.
\r
1805 void CNullDriver::removeAllOcclusionQueries()
\r
1807 for (s32 i=OcclusionQueries.size()-1; i>=0; --i)
\r
1809 removeOcclusionQuery(OcclusionQueries[i].Node);
\r
1814 //! Run occlusion query. Draws mesh stored in query.
\r
1815 /** If the mesh shall be rendered visible, use
\r
1816 flag to enable the proper material setting. */
\r
1817 void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
\r
1821 s32 index = OcclusionQueries.linear_search(SOccQuery(node));
\r
1824 OcclusionQueries[index].Run=0;
\r
1828 mat.Lighting=false;
\r
1829 mat.AntiAliasing=0;
\r
1830 mat.ColorMask=ECP_NONE;
\r
1831 mat.GouraudShading=false;
\r
1832 mat.ZWriteEnable=EZW_OFF;
\r
1835 setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
\r
1836 const scene::IMesh* mesh = OcclusionQueries[index].Mesh;
\r
1837 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
\r
1840 setMaterial(mesh->getMeshBuffer(i)->getMaterial());
\r
1841 drawMeshBuffer(mesh->getMeshBuffer(i));
\r
1846 //! Run all occlusion queries. Draws all meshes stored in queries.
\r
1847 /** If the meshes shall not be rendered visible, use
\r
1848 overrideMaterial to disable the color and depth buffer. */
\r
1849 void CNullDriver::runAllOcclusionQueries(bool visible)
\r
1851 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
1852 runOcclusionQuery(OcclusionQueries[i].Node, visible);
\r
1856 //! Update occlusion query. Retrieves results from GPU.
\r
1857 /** If the query shall not block, set the flag to false.
\r
1858 Update might not occur in this case, though */
\r
1859 void CNullDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
\r
1864 //! Update all occlusion queries. Retrieves results from GPU.
\r
1865 /** If the query shall not block, set the flag to false.
\r
1866 Update might not occur in this case, though */
\r
1867 void CNullDriver::updateAllOcclusionQueries(bool block)
\r
1869 for (u32 i=0; i<OcclusionQueries.size(); ++i)
\r
1871 if (OcclusionQueries[i].Run==u32(~0))
\r
1873 updateOcclusionQuery(OcclusionQueries[i].Node, block);
\r
1874 ++OcclusionQueries[i].Run;
\r
1875 if (OcclusionQueries[i].Run>1000)
\r
1876 removeOcclusionQuery(OcclusionQueries[i].Node);
\r
1881 //! Return query result.
\r
1882 /** Return value is the number of visible pixels/fragments.
\r
1883 The value is a safe approximation, i.e. can be larger then the
\r
1884 actual value of pixels. */
\r
1885 u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const
\r
1891 //! Create render target.
\r
1892 IRenderTarget* CNullDriver::addRenderTarget()
\r
1898 //! Remove render target.
\r
1899 void CNullDriver::removeRenderTarget(IRenderTarget* renderTarget)
\r
1901 if (!renderTarget)
\r
1904 for (u32 i = 0; i < RenderTargets.size(); ++i)
\r
1906 if (RenderTargets[i] == renderTarget)
\r
1908 RenderTargets[i]->drop();
\r
1909 RenderTargets.erase(i);
\r
1917 //! Remove all render targets.
\r
1918 void CNullDriver::removeAllRenderTargets()
\r
1920 for (u32 i = 0; i < RenderTargets.size(); ++i)
\r
1921 RenderTargets[i]->drop();
\r
1923 RenderTargets.clear();
\r
1925 SharedRenderTarget = 0;
\r
1929 //! Only used by the internal engine. Used to notify the driver that
\r
1930 //! the window was resized.
\r
1931 void CNullDriver::OnResize(const core::dimension2d<u32>& size)
\r
1933 if (ViewPort.getWidth() == (s32)ScreenSize.Width &&
\r
1934 ViewPort.getHeight() == (s32)ScreenSize.Height)
\r
1935 ViewPort = core::rect<s32>(core::position2d<s32>(0,0),
\r
1936 core::dimension2di(size));
\r
1938 ScreenSize = size;
\r
1942 // adds a material renderer and drops it afterwards. To be used for internal creation
\r
1943 s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m)
\r
1945 s32 i = addMaterialRenderer(m);
\r
1954 //! Adds a new material renderer to the video device.
\r
1955 s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name)
\r
1960 SMaterialRenderer r;
\r
1961 r.Renderer = renderer;
\r
1964 if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ))
\r
1966 // set name of built in renderer so that we don't have to implement name
\r
1967 // setting in all available renderers.
\r
1968 r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()];
\r
1971 MaterialRenderers.push_back(r);
\r
1974 return MaterialRenderers.size()-1;
\r
1978 //! Sets the name of a material renderer.
\r
1979 void CNullDriver::setMaterialRendererName(s32 idx, const char* name)
\r
1981 if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
\r
1982 idx >= (s32)MaterialRenderers.size())
\r
1985 MaterialRenderers[idx].Name = name;
\r
1988 void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames)
\r
1990 if ( idx1 < MaterialRenderers.size() && idx2 < MaterialRenderers.size() )
\r
1992 irr::core::swap(MaterialRenderers[idx1].Renderer, MaterialRenderers[idx2].Renderer);
\r
1994 irr::core::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
\r
1999 //! Returns driver and operating system specific data about the IVideoDriver.
\r
2000 const SExposedVideoData& CNullDriver::getExposedVideoData()
\r
2002 return ExposedData;
\r
2006 //! Returns type of video driver
\r
2007 E_DRIVER_TYPE CNullDriver::getDriverType() const
\r
2013 //! deletes all material renderers
\r
2014 void CNullDriver::deleteMaterialRenders()
\r
2016 // delete material renderers
\r
2017 for (u32 i=0; i<MaterialRenderers.size(); ++i)
\r
2018 if (MaterialRenderers[i].Renderer)
\r
2019 MaterialRenderers[i].Renderer->drop();
\r
2021 MaterialRenderers.clear();
\r
2025 //! Returns pointer to material renderer or null
\r
2026 IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx) const
\r
2028 if ( idx < MaterialRenderers.size() )
\r
2029 return MaterialRenderers[idx].Renderer;
\r
2035 //! Returns amount of currently available material renderers.
\r
2036 u32 CNullDriver::getMaterialRendererCount() const
\r
2038 return MaterialRenderers.size();
\r
2042 //! Returns name of the material renderer
\r
2043 const char* CNullDriver::getMaterialRendererName(u32 idx) const
\r
2045 if ( idx < MaterialRenderers.size() )
\r
2046 return MaterialRenderers[idx].Name.c_str();
\r
2052 //! Returns pointer to the IGPUProgrammingServices interface.
\r
2053 IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices()
\r
2059 //! Adds a new material renderer to the VideoDriver, based on a high level shading language.
\r
2060 s32 CNullDriver::addHighLevelShaderMaterial(
\r
2061 const c8* vertexShaderProgram,
\r
2062 const c8* vertexShaderEntryPointName,
\r
2063 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
2064 const c8* pixelShaderProgram,
\r
2065 const c8* pixelShaderEntryPointName,
\r
2066 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
2067 const c8* geometryShaderProgram,
\r
2068 const c8* geometryShaderEntryPointName,
\r
2069 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
2070 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
2072 IShaderConstantSetCallBack* callback,
\r
2073 E_MATERIAL_TYPE baseMaterial,
\r
2076 os::Printer::log("High level shader materials not available (yet) in this driver, sorry");
\r
2081 //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
\r
2082 //! but tries to load the programs from files.
\r
2083 s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
\r
2084 const io::path& vertexShaderProgramFileName,
\r
2085 const c8* vertexShaderEntryPointName,
\r
2086 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
2087 const io::path& pixelShaderProgramFileName,
\r
2088 const c8* pixelShaderEntryPointName,
\r
2089 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
2090 const io::path& geometryShaderProgramFileName,
\r
2091 const c8* geometryShaderEntryPointName,
\r
2092 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
2093 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
2095 IShaderConstantSetCallBack* callback,
\r
2096 E_MATERIAL_TYPE baseMaterial,
\r
2099 io::IReadFile* vsfile = 0;
\r
2100 io::IReadFile* psfile = 0;
\r
2101 io::IReadFile* gsfile = 0;
\r
2103 if (vertexShaderProgramFileName.size() )
\r
2105 vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
\r
2108 os::Printer::log("Could not open vertex shader program file",
\r
2109 vertexShaderProgramFileName, ELL_WARNING);
\r
2113 if (pixelShaderProgramFileName.size() )
\r
2115 psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
\r
2118 os::Printer::log("Could not open pixel shader program file",
\r
2119 pixelShaderProgramFileName, ELL_WARNING);
\r
2123 if (geometryShaderProgramFileName.size() )
\r
2125 gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName);
\r
2128 os::Printer::log("Could not open geometry shader program file",
\r
2129 geometryShaderProgramFileName, ELL_WARNING);
\r
2133 s32 result = addHighLevelShaderMaterialFromFiles(
\r
2134 vsfile, vertexShaderEntryPointName, vsCompileTarget,
\r
2135 psfile, pixelShaderEntryPointName, psCompileTarget,
\r
2136 gsfile, geometryShaderEntryPointName, gsCompileTarget,
\r
2137 inType, outType, verticesOut,
\r
2138 callback, baseMaterial, userData);
\r
2153 //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
\r
2154 //! but tries to load the programs from files.
\r
2155 s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
\r
2156 io::IReadFile* vertexShaderProgram,
\r
2157 const c8* vertexShaderEntryPointName,
\r
2158 E_VERTEX_SHADER_TYPE vsCompileTarget,
\r
2159 io::IReadFile* pixelShaderProgram,
\r
2160 const c8* pixelShaderEntryPointName,
\r
2161 E_PIXEL_SHADER_TYPE psCompileTarget,
\r
2162 io::IReadFile* geometryShaderProgram,
\r
2163 const c8* geometryShaderEntryPointName,
\r
2164 E_GEOMETRY_SHADER_TYPE gsCompileTarget,
\r
2165 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
\r
2167 IShaderConstantSetCallBack* callback,
\r
2168 E_MATERIAL_TYPE baseMaterial,
\r
2175 if (vertexShaderProgram)
\r
2177 const long size = vertexShaderProgram->getSize();
\r
2180 vs = new c8[size+1];
\r
2181 vertexShaderProgram->read(vs, size);
\r
2186 if (pixelShaderProgram)
\r
2188 const long size = pixelShaderProgram->getSize();
\r
2191 // if both handles are the same we must reset the file
\r
2192 if (pixelShaderProgram==vertexShaderProgram)
\r
2193 pixelShaderProgram->seek(0);
\r
2194 ps = new c8[size+1];
\r
2195 pixelShaderProgram->read(ps, size);
\r
2200 if (geometryShaderProgram)
\r
2202 const long size = geometryShaderProgram->getSize();
\r
2205 // if both handles are the same we must reset the file
\r
2206 if ((geometryShaderProgram==vertexShaderProgram) ||
\r
2207 (geometryShaderProgram==pixelShaderProgram))
\r
2208 geometryShaderProgram->seek(0);
\r
2209 gs = new c8[size+1];
\r
2210 geometryShaderProgram->read(gs, size);
\r
2215 s32 result = this->addHighLevelShaderMaterial(
\r
2216 vs, vertexShaderEntryPointName, vsCompileTarget,
\r
2217 ps, pixelShaderEntryPointName, psCompileTarget,
\r
2218 gs, geometryShaderEntryPointName, gsCompileTarget,
\r
2219 inType, outType, verticesOut,
\r
2220 callback, baseMaterial, userData);
\r
2230 //! Adds a new material renderer to the VideoDriver, using pixel and/or
\r
2231 //! vertex shaders to render geometry.
\r
2232 s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram,
\r
2233 const c8* pixelShaderProgram,
\r
2234 IShaderConstantSetCallBack* callback,
\r
2235 E_MATERIAL_TYPE baseMaterial,
\r
2238 os::Printer::log("Shader materials not implemented yet in this driver, sorry.");
\r
2243 //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
\r
2244 //! programs from files.
\r
2245 s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram,
\r
2246 io::IReadFile* pixelShaderProgram,
\r
2247 IShaderConstantSetCallBack* callback,
\r
2248 E_MATERIAL_TYPE baseMaterial,
\r
2254 if (vertexShaderProgram)
\r
2256 const long size = vertexShaderProgram->getSize();
\r
2259 vs = new c8[size+1];
\r
2260 vertexShaderProgram->read(vs, size);
\r
2265 if (pixelShaderProgram)
\r
2267 const long size = pixelShaderProgram->getSize();
\r
2270 ps = new c8[size+1];
\r
2271 pixelShaderProgram->read(ps, size);
\r
2276 s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData);
\r
2285 //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
\r
2286 //! programs from files.
\r
2287 s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName,
\r
2288 const io::path& pixelShaderProgramFileName,
\r
2289 IShaderConstantSetCallBack* callback,
\r
2290 E_MATERIAL_TYPE baseMaterial,
\r
2293 io::IReadFile* vsfile = 0;
\r
2294 io::IReadFile* psfile = 0;
\r
2296 if (vertexShaderProgramFileName.size())
\r
2298 vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
\r
2301 os::Printer::log("Could not open vertex shader program file",
\r
2302 vertexShaderProgramFileName, ELL_WARNING);
\r
2307 if (pixelShaderProgramFileName.size())
\r
2309 psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
\r
2312 os::Printer::log("Could not open pixel shader program file",
\r
2313 pixelShaderProgramFileName, ELL_WARNING);
\r
2320 s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback,
\r
2321 baseMaterial, userData);
\r
2333 //! Creates a render target texture.
\r
2334 ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
\r
2335 const io::path&name, const ECOLOR_FORMAT format)
\r
2340 ITexture* CNullDriver::addRenderTargetTextureCubemap(const irr::u32 sideLen,
\r
2341 const io::path& name, const ECOLOR_FORMAT format)
\r
2346 void CNullDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)
\r
2351 //! Returns a pointer to the mesh manipulator.
\r
2352 scene::IMeshManipulator* CNullDriver::getMeshManipulator()
\r
2354 return MeshManipulator;
\r
2358 //! Returns an image created from the last rendered frame.
\r
2359 IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
\r
2365 // prints renderer version
\r
2366 void CNullDriver::printVersion()
\r
2368 core::stringw namePrint = L"Using renderer: ";
\r
2369 namePrint += getName();
\r
2370 os::Printer::log(namePrint.c_str(), ELL_INFORMATION);
\r
2374 //! creates a video driver
\r
2375 IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
\r
2377 CNullDriver* nullDriver = new CNullDriver(io, screenSize);
\r
2379 // create empty material renderers
\r
2380 for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i)
\r
2382 IMaterialRenderer* imr = new IMaterialRenderer();
\r
2383 nullDriver->addMaterialRenderer(imr);
\r
2387 return nullDriver;
\r
2391 //! Set/unset a clipping plane.
\r
2392 //! There are at least 6 clipping planes available for the user to set at will.
\r
2393 //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
\r
2394 //! \param plane: The plane itself.
\r
2395 //! \param enable: If true, enable the clipping plane else disable it.
\r
2396 bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
\r
2402 //! Enable/disable a clipping plane.
\r
2403 void CNullDriver::enableClipPlane(u32 index, bool enable)
\r
2409 ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<u32>& size,
\r
2412 os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead");
\r
2413 ITexture* tex = addRenderTargetTexture(size, name);
\r
2419 void CNullDriver::setMinHardwareBufferVertexCount(u32 count)
\r
2421 MinVertexCountForVBO = count;
\r
2425 SOverrideMaterial& CNullDriver::getOverrideMaterial()
\r
2427 return OverrideMaterial;
\r
2431 //! Get the 2d override material for altering its values
\r
2432 SMaterial& CNullDriver::getMaterial2D()
\r
2434 return OverrideMaterial2D;
\r
2438 //! Enable the 2d override material
\r
2439 void CNullDriver::enableMaterial2D(bool enable)
\r
2441 OverrideMaterial2DEnabled=enable;
\r
2445 core::dimension2du CNullDriver::getMaxTextureSize() const
\r
2447 return core::dimension2du(0x10000,0x10000); // maybe large enough
\r
2450 bool CNullDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
\r
2452 // TODO: I suspect it would be nice if the material had an enum for further control.
\r
2453 // Especially it probably makes sense to allow disabling transparent render pass as soon as material.ZWriteEnable is on.
\r
2454 // 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
2455 // Or we could at least set return false when material.ZWriteEnable is EZW_ON? Still considering that...
\r
2456 // Be careful - this function is deeply connected to getWriteZBuffer as transparent render passes are usually about rendering with
\r
2457 // zwrite disabled and getWriteZBuffer calls this function.
\r
2459 video::IMaterialRenderer* rnd = getMaterialRenderer(material.MaterialType);
\r
2460 // TODO: I suspect IMaterialRenderer::isTransparent also often could use SMaterial as parameter
\r
2461 // We could for example then get rid of IsTransparent function in SMaterial and move that to the software material renderer.
\r
2462 if (rnd && rnd->isTransparent())
\r
2469 //! Color conversion convenience function
\r
2470 /** Convert an image (as array of pixels) from source to destination
\r
2471 array, thereby converting the color format. The pixel size is
\r
2472 determined by the color formats.
\r
2473 \param sP Pointer to source
\r
2474 \param sF Color format of source
\r
2475 \param sN Number of pixels to convert, both array must be large enough
\r
2476 \param dP Pointer to destination
\r
2477 \param dF Color format of destination
\r
2479 void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN,
\r
2480 void* dP, ECOLOR_FORMAT dF) const
\r
2482 video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF);
\r
2486 } // end namespace
\r
2487 } // end namespace
\r