1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#include "CNullDriver.h"
8
#include "CAttributes.h"
10
#include "IWriteFile.h"
11
#include "IImageLoader.h"
12
#include "IImageWriter.h"
13
#include "IMaterialRenderer.h"
14
#include "IAnimatedMeshSceneNode.h"
15
#include "CMeshManipulator.h"
16
#include "CColorConverter.h"
17
#include "IAttributeExchangingObject.h"
25
//! creates a loader which is able to load windows bitmaps
26
IImageLoader* createImageLoaderBMP();
28
//! creates a loader which is able to load jpeg images
29
IImageLoader* createImageLoaderJPG();
31
//! creates a loader which is able to load targa images
32
IImageLoader* createImageLoaderTGA();
34
//! creates a loader which is able to load psd images
35
IImageLoader* createImageLoaderPSD();
37
//! creates a loader which is able to load dds images
38
IImageLoader* createImageLoaderDDS();
40
//! creates a loader which is able to load pcx images
41
IImageLoader* createImageLoaderPCX();
43
//! creates a loader which is able to load png images
44
IImageLoader* createImageLoaderPNG();
46
//! creates a loader which is able to load WAL images
47
IImageLoader* createImageLoaderWAL();
49
//! creates a loader which is able to load halflife images
50
IImageLoader* createImageLoaderHalfLife();
52
//! creates a loader which is able to load lmp images
53
IImageLoader* createImageLoaderLMP();
55
//! creates a loader which is able to load ppm/pgm/pbm images
56
IImageLoader* createImageLoaderPPM();
58
//! creates a loader which is able to load rgb images
59
IImageLoader* createImageLoaderRGB();
62
//! creates a writer which is able to save bmp images
63
IImageWriter* createImageWriterBMP();
65
//! creates a writer which is able to save jpg images
66
IImageWriter* createImageWriterJPG();
68
//! creates a writer which is able to save tga images
69
IImageWriter* createImageWriterTGA();
71
//! creates a writer which is able to save psd images
72
IImageWriter* createImageWriterPSD();
74
//! creates a writer which is able to save pcx images
75
IImageWriter* createImageWriterPCX();
77
//! creates a writer which is able to save png images
78
IImageWriter* createImageWriterPNG();
80
//! creates a writer which is able to save ppm images
81
IImageWriter* createImageWriterPPM();
84
CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
85
: FileSystem(io), MeshManipulator(0), ViewPort(0,0,0,0), ScreenSize(screenSize),
86
PrimitivesDrawn(0), MinVertexCountForVBO(500), TextureCreationFlags(0),
87
OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false)
90
setDebugName("CNullDriver");
93
DriverAttributes = new io::CAttributes();
94
DriverAttributes->addInt("MaxTextures", _IRR_MATERIAL_MAX_TEXTURES_);
95
DriverAttributes->addInt("MaxSupportedTextures", _IRR_MATERIAL_MAX_TEXTURES_);
96
DriverAttributes->addInt("MaxLights", getMaximalDynamicLightAmount());
97
DriverAttributes->addInt("MaxAnisotropy", 1);
98
// DriverAttributes->addInt("MaxUserClipPlanes", 0);
99
// DriverAttributes->addInt("MaxAuxBuffers", 0);
100
DriverAttributes->addInt("MaxMultipleRenderTargets", 1);
101
DriverAttributes->addInt("MaxIndices", -1);
102
DriverAttributes->addInt("MaxTextureSize", -1);
103
// DriverAttributes->addInt("MaxGeometryVerticesOut", 0);
104
// DriverAttributes->addFloat("MaxTextureLODBias", 0.f);
105
DriverAttributes->addInt("Version", 1);
106
// DriverAttributes->addInt("ShaderLanguageVersion", 0);
107
// DriverAttributes->addInt("AntiAlias", 0);
111
setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true);
112
setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);
114
ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(screenSize));
116
// create manipulator
117
MeshManipulator = new scene::CMeshManipulator();
122
// create surface loader
124
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
125
SurfaceLoader.push_back(video::createImageLoaderHalfLife());
127
#ifdef _IRR_COMPILE_WITH_WAL_LOADER_
128
SurfaceLoader.push_back(video::createImageLoaderWAL());
130
#ifdef _IRR_COMPILE_WITH_LMP_LOADER_
131
SurfaceLoader.push_back(video::createImageLoaderLMP());
133
#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
134
SurfaceLoader.push_back(video::createImageLoaderPPM());
136
#ifdef _IRR_COMPILE_WITH_RGB_LOADER_
137
SurfaceLoader.push_back(video::createImageLoaderRGB());
139
#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
140
SurfaceLoader.push_back(video::createImageLoaderPSD());
142
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
143
SurfaceLoader.push_back(video::createImageLoaderDDS());
145
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
146
SurfaceLoader.push_back(video::createImageLoaderPCX());
148
#ifdef _IRR_COMPILE_WITH_TGA_LOADER_
149
SurfaceLoader.push_back(video::createImageLoaderTGA());
151
#ifdef _IRR_COMPILE_WITH_PNG_LOADER_
152
SurfaceLoader.push_back(video::createImageLoaderPNG());
154
#ifdef _IRR_COMPILE_WITH_JPG_LOADER_
155
SurfaceLoader.push_back(video::createImageLoaderJPG());
157
#ifdef _IRR_COMPILE_WITH_BMP_LOADER_
158
SurfaceLoader.push_back(video::createImageLoaderBMP());
162
#ifdef _IRR_COMPILE_WITH_PPM_WRITER_
163
SurfaceWriter.push_back(video::createImageWriterPPM());
165
#ifdef _IRR_COMPILE_WITH_PCX_WRITER_
166
SurfaceWriter.push_back(video::createImageWriterPCX());
168
#ifdef _IRR_COMPILE_WITH_PSD_WRITER_
169
SurfaceWriter.push_back(video::createImageWriterPSD());
171
#ifdef _IRR_COMPILE_WITH_TGA_WRITER_
172
SurfaceWriter.push_back(video::createImageWriterTGA());
174
#ifdef _IRR_COMPILE_WITH_JPG_WRITER_
175
SurfaceWriter.push_back(video::createImageWriterJPG());
177
#ifdef _IRR_COMPILE_WITH_PNG_WRITER_
178
SurfaceWriter.push_back(video::createImageWriterPNG());
180
#ifdef _IRR_COMPILE_WITH_BMP_WRITER_
181
SurfaceWriter.push_back(video::createImageWriterBMP());
185
// set ExposedData to 0
186
memset(&ExposedData, 0, sizeof(ExposedData));
187
for (u32 i=0; i<video::EVDF_COUNT; ++i)
188
FeatureEnabled[i]=true;
190
InitMaterial2D.AntiAliasing=video::EAAM_OFF;
191
InitMaterial2D.Lighting=false;
192
InitMaterial2D.ZWriteEnable=false;
193
InitMaterial2D.ZBuffer=video::ECFN_NEVER;
194
InitMaterial2D.UseMipMaps=false;
195
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
197
InitMaterial2D.TextureLayer[i].BilinearFilter=false;
198
InitMaterial2D.TextureLayer[i].TextureWrapU=video::ETC_REPEAT;
199
InitMaterial2D.TextureLayer[i].TextureWrapV=video::ETC_REPEAT;
201
OverrideMaterial2D=InitMaterial2D;
206
CNullDriver::~CNullDriver()
208
if (DriverAttributes)
209
DriverAttributes->drop();
215
MeshManipulator->drop();
219
for (i=0; i<SurfaceLoader.size(); ++i)
220
SurfaceLoader[i]->drop();
222
for (i=0; i<SurfaceWriter.size(); ++i)
223
SurfaceWriter[i]->drop();
225
// delete material renderers
226
deleteMaterialRenders();
228
// delete hardware mesh buffers
229
removeAllHardwareBuffers();
233
//! Adds an external surface loader to the engine.
234
void CNullDriver::addExternalImageLoader(IImageLoader* loader)
240
SurfaceLoader.push_back(loader);
244
//! Adds an external surface writer to the engine.
245
void CNullDriver::addExternalImageWriter(IImageWriter* writer)
251
SurfaceWriter.push_back(writer);
255
//! Retrieve the number of image loaders
256
u32 CNullDriver::getImageLoaderCount() const
258
return SurfaceLoader.size();
262
//! Retrieve the given image loader
263
IImageLoader* CNullDriver::getImageLoader(u32 n)
265
if (n < SurfaceLoader.size())
266
return SurfaceLoader[n];
271
//! Retrieve the number of image writers
272
u32 CNullDriver::getImageWriterCount() const
274
return SurfaceWriter.size();
278
//! Retrieve the given image writer
279
IImageWriter* CNullDriver::getImageWriter(u32 n)
281
if (n < SurfaceWriter.size())
282
return SurfaceWriter[n];
287
//! deletes all textures
288
void CNullDriver::deleteAllTextures()
290
// we need to remove previously set textures which might otherwise be kept in the
291
// last set material member. Could be optimized to reduce state changes.
292
setMaterial(SMaterial());
294
for (u32 i=0; i<Textures.size(); ++i)
295
Textures[i].Surface->drop();
302
//! applications must call this method before performing any rendering. returns false if failed.
303
bool CNullDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
304
const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
306
core::clearFPUException();
312
//! applications must call this method after performing any rendering. returns false if failed.
313
bool CNullDriver::endScene()
315
FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn);
316
updateAllHardwareBuffers();
317
updateAllOcclusionQueries();
322
//! Disable a feature of the driver.
323
void CNullDriver::disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag)
325
FeatureEnabled[feature]=!flag;
329
//! queries the features of the driver, returns true if feature is available
330
bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
336
//! Get attributes of the actual video driver
337
const io::IAttributes& CNullDriver::getDriverAttributes() const
339
return *DriverAttributes;
343
//! sets transformation
344
void CNullDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
349
//! Returns the transformation set by setTransform
350
const core::matrix4& CNullDriver::getTransform(E_TRANSFORMATION_STATE state) const
352
return TransformationMatrix;
357
void CNullDriver::setMaterial(const SMaterial& material)
362
//! Removes a texture from the texture cache and deletes it, freeing lot of
364
void CNullDriver::removeTexture(ITexture* texture)
369
for (u32 i=0; i<Textures.size(); ++i)
371
if (Textures[i].Surface == texture)
380
//! Removes all texture from the texture cache and deletes them, freeing lot of
382
void CNullDriver::removeAllTextures()
384
setMaterial ( SMaterial() );
389
//! Returns a texture by index
390
ITexture* CNullDriver::getTextureByIndex(u32 i)
392
if ( i < Textures.size() )
393
return Textures[i].Surface;
399
//! Returns amount of textures currently loaded
400
u32 CNullDriver::getTextureCount() const
402
return Textures.size();
406
//! Renames a texture
407
void CNullDriver::renameTexture(ITexture* texture, const io::path& newName)
409
// we can do a const_cast here safely, the name of the ITexture interface
410
// is just readonly to prevent the user changing the texture name without invoking
411
// this method, because the textures will need resorting afterwards
413
io::SNamedPath& name = const_cast<io::SNamedPath&>(texture->getName());
414
name.setPath(newName);
421
ITexture* CNullDriver::getTexture(const io::path& filename)
423
// Identify textures by their absolute filenames if possible.
424
const io::path absolutePath = FileSystem->getAbsolutePath(filename);
426
ITexture* texture = findTexture(absolutePath);
430
// Then try the raw filename, which might be in an Archive
431
texture = findTexture(filename);
435
// Now try to open the file using the complete path.
436
io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath);
440
// Try to open it using the raw filename.
441
file = FileSystem->createAndOpenFile(filename);
446
// Re-check name for actual archive names
447
texture = findTexture(file->getFileName());
454
texture = loadTextureFromFile(file);
460
texture->drop(); // drop it because we created it, one grab too much
463
os::Printer::log("Could not load texture", filename, ELL_ERROR);
468
os::Printer::log("Could not open file of texture", filename, ELL_WARNING);
475
ITexture* CNullDriver::getTexture(io::IReadFile* file)
477
ITexture* texture = 0;
481
texture = findTexture(file->getFileName());
486
texture = loadTextureFromFile(file);
491
texture->drop(); // drop it because we created it, one grab too much
495
os::Printer::log("Could not load texture", file->getFileName(), ELL_WARNING);
502
//! opens the file and loads it into the surface
503
video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName )
505
ITexture* texture = 0;
506
IImage* image = createImageFromFile(file);
510
// create texture from surface
511
texture = createDeviceDependentTexture(image, hashName.size() ? hashName : file->getFileName() );
512
os::Printer::log("Loaded texture", file->getFileName());
520
//! adds a surface, not loaded or created by the Irrlicht Engine
521
void CNullDriver::addTexture(video::ITexture* texture)
529
Textures.push_back(s);
531
// the new texture is now at the end of the texture list. when searching for
532
// the next new texture, the texture array will be sorted and the index of this texture
533
// will be changed. to let the order be more consistent to the user, sort
534
// the textures now already although this isn't necessary:
541
//! looks if the image is already loaded
542
video::ITexture* CNullDriver::findTexture(const io::path& filename)
545
SDummyTexture dummy(filename);
548
s32 index = Textures.binary_search(s);
550
return Textures[index].Surface;
556
//! Creates a texture from a loaded IImage.
557
ITexture* CNullDriver::addTexture(const io::path& name, IImage* image, void* mipmapData)
559
if ( 0 == name.size() || !image)
562
ITexture* t = createDeviceDependentTexture(image, name, mipmapData);
572
//! creates a Texture
573
ITexture* CNullDriver::addTexture(const core::dimension2d<u32>& size,
574
const io::path& name, ECOLOR_FORMAT format)
576
if(IImage::isRenderTargetOnlyFormat(format))
578
os::Printer::log("Could not create ITexture, format only supported for render target textures.", ELL_WARNING);
582
if ( 0 == name.size () )
585
IImage* image = new CImage(format, size);
586
ITexture* t = createDeviceDependentTexture(image, name);
598
//! returns a device dependent texture from a software surface (IImage)
599
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
600
ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData)
602
return new SDummyTexture(name);
606
//! set or reset special render targets
607
bool CNullDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
608
bool clearZBuffer, SColor color)
610
if (ERT_FRAME_BUFFER==target)
611
return setRenderTarget(0,clearTarget, clearZBuffer, color);
617
//! sets a render target
618
bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
619
bool clearZBuffer, SColor color)
625
//! Sets multiple render targets
626
bool CNullDriver::setRenderTarget(const core::array<video::IRenderTarget>& texture,
627
bool clearBackBuffer, bool clearZBuffer, SColor color)
634
void CNullDriver::setViewPort(const core::rect<s32>& area)
639
//! gets the area of the current viewport
640
const core::rect<s32>& CNullDriver::getViewPort() const
646
//! draws a vertex primitive list
647
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)
649
if ((iType==EIT_16BIT) && (vertexCount>65536))
650
os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
651
PrimitivesDrawn += primitiveCount;
655
//! draws a vertex primitive list in 2d
656
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)
658
if ((iType==EIT_16BIT) && (vertexCount>65536))
659
os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur.");
660
PrimitivesDrawn += primitiveCount;
665
void CNullDriver::draw3DLine(const core::vector3df& start,
666
const core::vector3df& end, SColor color)
671
//! Draws a 3d triangle.
672
void CNullDriver::draw3DTriangle(const core::triangle3df& triangle, SColor color)
674
S3DVertex vertices[3];
675
vertices[0].Pos=triangle.pointA;
676
vertices[0].Color=color;
677
vertices[0].Normal=triangle.getNormal().normalize();
678
vertices[0].TCoords.set(0.f,0.f);
679
vertices[1].Pos=triangle.pointB;
680
vertices[1].Color=color;
681
vertices[1].Normal=vertices[0].Normal;
682
vertices[1].TCoords.set(0.5f,1.f);
683
vertices[2].Pos=triangle.pointC;
684
vertices[2].Color=color;
685
vertices[2].Normal=vertices[0].Normal;
686
vertices[2].TCoords.set(1.f,0.f);
687
const u16 indexList[] = {0,1,2};
688
drawVertexPrimitiveList(vertices, 3, indexList, 1, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT);
692
//! Draws a 3d axis aligned box.
693
void CNullDriver::draw3DBox(const core::aabbox3d<f32>& box, SColor color)
695
core::vector3df edges[8];
698
// TODO: optimize into one big drawIndexPrimitive call.
700
draw3DLine(edges[5], edges[1], color);
701
draw3DLine(edges[1], edges[3], color);
702
draw3DLine(edges[3], edges[7], color);
703
draw3DLine(edges[7], edges[5], color);
704
draw3DLine(edges[0], edges[2], color);
705
draw3DLine(edges[2], edges[6], color);
706
draw3DLine(edges[6], edges[4], color);
707
draw3DLine(edges[4], edges[0], color);
708
draw3DLine(edges[1], edges[0], color);
709
draw3DLine(edges[3], edges[2], color);
710
draw3DLine(edges[7], edges[6], color);
711
draw3DLine(edges[5], edges[4], color);
716
//! draws an 2d image
717
void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos)
722
draw2DImage(texture,destPos, core::rect<s32>(core::position2d<s32>(0,0),
723
core::dimension2di(texture->getOriginalSize())));
728
//! draws a set of 2d images, using a color and the alpha channel of the
729
//! texture if desired. The images are drawn beginning at pos and concatenated
730
//! in one line. All drawings are clipped against clipRect (if != 0).
731
//! The subtextures are defined by the array of sourceRects and are chosen
732
//! by the indices given.
733
void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
734
const core::position2d<s32>& pos,
735
const core::array<core::rect<s32> >& sourceRects,
736
const core::array<s32>& indices,
738
const core::rect<s32>* clipRect, SColor color,
739
bool useAlphaChannelOfTexture)
741
core::position2d<s32> target(pos);
743
for (u32 i=0; i<indices.size(); ++i)
745
draw2DImage(texture, target, sourceRects[indices[i]],
746
clipRect, color, useAlphaChannelOfTexture);
747
target.X += sourceRects[indices[i]].getWidth();
748
target.X += kerningWidth;
752
//! draws a set of 2d images, using a color and the alpha channel of the
753
//! texture if desired.
754
void CNullDriver::draw2DImageBatch(const video::ITexture* texture,
755
const core::array<core::position2d<s32> >& positions,
756
const core::array<core::rect<s32> >& sourceRects,
757
const core::rect<s32>* clipRect,
759
bool useAlphaChannelOfTexture)
761
const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
763
for (u32 i=0; i<drawCount; ++i)
765
draw2DImage(texture, positions[i], sourceRects[i],
766
clipRect, color, useAlphaChannelOfTexture);
771
//! Draws a part of the texture into the rectangle.
772
void CNullDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
773
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
774
const video::SColor* const colors, bool useAlphaChannelOfTexture)
776
draw2DImage(texture, core::position2d<s32>(destRect.UpperLeftCorner),
777
sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff),
778
useAlphaChannelOfTexture);
782
//! 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.
783
void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
784
const core::rect<s32>& sourceRect,
785
const core::rect<s32>* clipRect, SColor color,
786
bool useAlphaChannelOfTexture)
791
//! Draws the outline of a 2d rectangle
792
void CNullDriver::draw2DRectangleOutline(const core::recti& pos, SColor color)
794
draw2DLine(pos.UpperLeftCorner, core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), color);
795
draw2DLine(core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), pos.LowerRightCorner, color);
796
draw2DLine(pos.LowerRightCorner, core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), color);
797
draw2DLine(core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), pos.UpperLeftCorner, color);
801
//! Draw a 2d rectangle
802
void CNullDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos, const core::rect<s32>* clip)
804
draw2DRectangle(pos, color, color, color, color, clip);
809
//! Draws a 2d rectangle with a gradient.
810
void CNullDriver::draw2DRectangle(const core::rect<s32>& pos,
811
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
812
const core::rect<s32>* clip)
819
void CNullDriver::draw2DLine(const core::position2d<s32>& start,
820
const core::position2d<s32>& end, SColor color)
825
void CNullDriver::drawPixel(u32 x, u32 y, const SColor & color)
830
//! Draws a non filled concyclic regular 2d polyon.
831
void CNullDriver::draw2DPolygon(core::position2d<s32> center,
832
f32 radius, video::SColor color, s32 count)
837
core::position2d<s32> first;
838
core::position2d<s32> a,b;
840
for (s32 j=0; j<count; ++j)
844
f32 p = j / (f32)count * (core::PI*2);
845
a = center + core::position2d<s32>((s32)(sin(p)*radius), (s32)(cos(p)*radius));
850
draw2DLine(a, b, color);
853
draw2DLine(a, first, color);
857
//! returns color format
858
ECOLOR_FORMAT CNullDriver::getColorFormat() const
864
//! returns screen size
865
const core::dimension2d<u32>& CNullDriver::getScreenSize() const
871
//! returns the current render target size,
872
//! or the screen size if render targets are not implemented
873
const core::dimension2d<u32>& CNullDriver::getCurrentRenderTargetSize() const
879
// returns current frames per second value
880
s32 CNullDriver::getFPS() const
882
return FPSCounter.getFPS();
887
//! returns amount of primitives (mostly triangles) were drawn in the last frame.
888
//! very useful method for statistics.
889
u32 CNullDriver::getPrimitiveCountDrawn( u32 param ) const
891
return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() : FPSCounter.getPrimitiveTotal();
896
//! Sets the dynamic ambient light color. The default color is
897
//! (0,0,0,0) which means it is dark.
898
//! \param color: New color of the ambient light.
899
void CNullDriver::setAmbientLight(const SColorf& color)
905
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
906
//! driver, it would return "Direct3D8".
908
const wchar_t* CNullDriver::getName() const
910
return L"Irrlicht NullDevice";
915
//! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
916
//! this: Frist, draw all geometry. Then use this method, to draw the shadow
917
//! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow.
918
void CNullDriver::drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail)
923
//! Fills the stencil shadow with color. After the shadow volume has been drawn
924
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
925
//! to draw the color of the shadow.
926
void CNullDriver::drawStencilShadow(bool clearStencilBuffer,
927
video::SColor leftUpEdge, video::SColor rightUpEdge,
928
video::SColor leftDownEdge, video::SColor rightDownEdge)
933
//! deletes all dynamic lights there are
934
void CNullDriver::deleteAllDynamicLights()
940
//! adds a dynamic light
941
s32 CNullDriver::addDynamicLight(const SLight& light)
943
Lights.push_back(light);
944
return Lights.size() - 1;
947
//! Turns a dynamic light on or off
948
//! \param lightIndex: the index returned by addDynamicLight
949
//! \param turnOn: true to turn the light on, false to turn it off
950
void CNullDriver::turnLightOn(s32 lightIndex, bool turnOn)
956
//! returns the maximal amount of dynamic lights the device can handle
957
u32 CNullDriver::getMaximalDynamicLightAmount() const
963
//! Returns current amount of dynamic lights set
964
//! \return Current amount of dynamic lights set
965
u32 CNullDriver::getDynamicLightCount() const
967
return Lights.size();
971
//! Returns light data which was previously set by IVideoDriver::addDynamicLight().
972
//! \param idx: Zero based index of the light. Must be greater than 0 and smaller
973
//! than IVideoDriver()::getDynamicLightCount.
974
//! \return Light data.
975
const SLight& CNullDriver::getDynamicLight(u32 idx) const
977
if ( idx < Lights.size() )
980
return *((SLight*)0);
984
//! Creates a boolean alpha channel of the texture based of an color key.
985
void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
987
bool zeroTexels) const
992
if (texture->getColorFormat() != ECF_A1R5G5B5 &&
993
texture->getColorFormat() != ECF_A8R8G8B8 )
995
os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
999
if (texture->getColorFormat() == ECF_A1R5G5B5)
1001
u16 *p = (u16*)texture->lock();
1005
os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
1009
const core::dimension2d<u32> dim = texture->getSize();
1010
const u32 pitch = texture->getPitch() / 2;
1012
// color with alpha disabled (i.e. fully transparent)
1013
const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5());
1015
const u32 pixels = pitch * dim.Height;
1017
for (u32 pixel = 0; pixel < pixels; ++ pixel)
1019
// If the colour matches the reference colour, ignoring alphas,
1020
// set the alpha to zero.
1021
if(((*p) & 0x7fff) == refZeroAlpha)
1026
(*p) = refZeroAlpha;
1036
u32 *p = (u32*)texture->lock();
1040
os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
1044
core::dimension2d<u32> dim = texture->getSize();
1045
u32 pitch = texture->getPitch() / 4;
1047
// color with alpha disabled (fully transparent)
1048
const u32 refZeroAlpha = 0x00ffffff & color.color;
1050
const u32 pixels = pitch * dim.Height;
1051
for (u32 pixel = 0; pixel < pixels; ++ pixel)
1053
// If the colour matches the reference colour, ignoring alphas,
1054
// set the alpha to zero.
1055
if(((*p) & 0x00ffffff) == refZeroAlpha)
1060
(*p) = refZeroAlpha;
1072
//! Creates an boolean alpha channel of the texture based of an color key position.
1073
void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
1074
core::position2d<s32> colorKeyPixelPos,
1075
bool zeroTexels) const
1080
if (texture->getColorFormat() != ECF_A1R5G5B5 &&
1081
texture->getColorFormat() != ECF_A8R8G8B8 )
1083
os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR);
1089
if (texture->getColorFormat() == ECF_A1R5G5B5)
1091
u16 *p = (u16*)texture->lock(ETLM_READ_ONLY);
1095
os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
1099
u32 pitch = texture->getPitch() / 2;
1101
const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
1103
colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit);
1107
u32 *p = (u32*)texture->lock(ETLM_READ_ONLY);
1111
os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR);
1115
u32 pitch = texture->getPitch() / 4;
1116
colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X];
1120
makeColorKeyTexture(texture, colorKey, zeroTexels);
1125
//! Creates a normal map from a height map texture.
1126
//! \param amplitude: Constant value by which the height information is multiplied.
1127
void CNullDriver::makeNormalMapTexture(video::ITexture* texture, f32 amplitude) const
1132
if (texture->getColorFormat() != ECF_A1R5G5B5 &&
1133
texture->getColorFormat() != ECF_A8R8G8B8 )
1135
os::Printer::log("Error: Unsupported texture color format for making normal map.", ELL_ERROR);
1139
core::dimension2d<u32> dim = texture->getSize();
1140
amplitude = amplitude / 255.0f;
1141
f32 vh = dim.Height / (f32)dim.Width;
1142
f32 hh = dim.Width / (f32)dim.Height;
1144
if (texture->getColorFormat() == ECF_A8R8G8B8)
1146
// ECF_A8R8G8B8 version
1148
s32 *p = (s32*)texture->lock();
1152
os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR);
1158
u32 pitch = texture->getPitch() / 4;
1160
s32* in = new s32[dim.Height * pitch];
1161
memcpy(in, p, dim.Height * pitch * 4);
1163
for (s32 x=0; x < s32(pitch); ++x)
1164
for (s32 y=0; y < s32(dim.Height); ++y)
1166
// TODO: this could be optimized really a lot
1168
core::vector3df h1((x-1)*hh, nml32(x-1, y, pitch, dim.Height, in)*amplitude, y*vh);
1169
core::vector3df h2((x+1)*hh, nml32(x+1, y, pitch, dim.Height, in)*amplitude, y*vh);
1170
//core::vector3df v1(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh);
1171
//core::vector3df v2(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh);
1172
core::vector3df v1(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y-1)*vh);
1173
core::vector3df v2(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y+1)*vh);
1175
core::vector3df v = v1-v2;
1176
core::vector3df h = h1-h2;
1178
core::vector3df n = v.crossProduct(h);
1181
n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1
1184
s32 height = (s32)nml32(x, y, pitch, dim.Height, in);
1185
p[y*pitch + x] = video::SColor(
1186
height, // store height in alpha
1187
(s32)n.X, (s32)n.Z, (s32)n.Y).color;
1195
// ECF_A1R5G5B5 version
1197
s16 *p = (s16*)texture->lock();
1201
os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR);
1205
u32 pitch = texture->getPitch() / 2;
1209
s16* in = new s16[dim.Height * pitch];
1210
memcpy(in, p, dim.Height * pitch * 2);
1212
for (s32 x=0; x < s32(pitch); ++x)
1213
for (s32 y=0; y < s32(dim.Height); ++y)
1215
// TODO: this could be optimized really a lot
1217
core::vector3df h1((x-1)*hh, nml16(x-1, y, pitch, dim.Height, in)*amplitude, y*vh);
1218
core::vector3df h2((x+1)*hh, nml16(x+1, y, pitch, dim.Height, in)*amplitude, y*vh);
1219
core::vector3df v1(x*hh, nml16(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh);
1220
core::vector3df v2(x*hh, nml16(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh);
1222
core::vector3df v = v1-v2;
1223
core::vector3df h = h1-h2;
1225
core::vector3df n = v.crossProduct(h);
1228
n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1
1231
p[y*pitch + x] = video::RGBA16((u32)n.X, (u32)n.Z, (u32)n.Y);
1238
texture->regenerateMipMapLevels();
1242
//! Returns the maximum amount of primitives (mostly vertices) which
1243
//! the device is able to render with one drawIndexedTriangleList
1245
u32 CNullDriver::getMaximalPrimitiveCount() const
1251
//! checks triangle count and print warning if wrong
1252
bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
1254
const u32 m = getMaximalPrimitiveCount();
1259
sprintf(tmp,"Could not draw triangles, too many primitives(%u), maxium is %u.", prmCount, m);
1260
os::Printer::log(tmp, ELL_ERROR);
1267
//! Enables or disables a texture creation flag.
1268
void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled)
1270
if (enabled && ((flag == ETCF_ALWAYS_16_BIT) || (flag == ETCF_ALWAYS_32_BIT)
1271
|| (flag == ETCF_OPTIMIZED_FOR_QUALITY) || (flag == ETCF_OPTIMIZED_FOR_SPEED)))
1273
// disable other formats
1274
setTextureCreationFlag(ETCF_ALWAYS_16_BIT, false);
1275
setTextureCreationFlag(ETCF_ALWAYS_32_BIT, false);
1276
setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, false);
1277
setTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED, false);
1281
TextureCreationFlags = (TextureCreationFlags & (~flag)) |
1282
((((u32)!enabled)-1) & flag);
1286
//! Returns if a texture creation flag is enabled or disabled.
1287
bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const
1289
return (TextureCreationFlags & flag)!=0;
1293
//! Creates a software image from a file.
1294
IImage* CNullDriver::createImageFromFile(const io::path& filename)
1296
if (!filename.size())
1300
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
1304
image = createImageFromFile(file);
1308
os::Printer::log("Could not open file of image", filename, ELL_WARNING);
1314
//! Creates a software image from a file.
1315
IImage* CNullDriver::createImageFromFile(io::IReadFile* file)
1324
// try to load file based on file extension
1325
for (i=SurfaceLoader.size()-1; i>=0; --i)
1327
if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
1329
// reset file position which might have changed due to previous loadImage calls
1331
image = SurfaceLoader[i]->loadImage(file);
1337
// try to load file based on what is in it
1338
for (i=SurfaceLoader.size()-1; i>=0; --i)
1342
if (SurfaceLoader[i]->isALoadableFileFormat(file))
1345
image = SurfaceLoader[i]->loadImage(file);
1351
return 0; // failed to load
1355
//! Writes the provided image to disk file
1356
bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param)
1358
io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
1362
bool result = writeImageToFile(image, file, param);
1368
//! Writes the provided image to a file.
1369
bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param)
1374
for (s32 i=SurfaceWriter.size()-1; i>=0; --i)
1376
if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName()))
1378
bool written = SurfaceWriter[i]->writeImage(file, image, param);
1383
return false; // failed to write
1387
//! Creates a software image from a byte array.
1388
IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
1389
const core::dimension2d<u32>& size,
1390
void *data, bool ownForeignMemory,
1393
if(IImage::isRenderTargetOnlyFormat(format))
1395
os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING);
1399
return new CImage(format, size, data, ownForeignMemory, deleteMemory);
1403
//! Creates an empty software image.
1404
IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
1406
if(IImage::isRenderTargetOnlyFormat(format))
1408
os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING);
1412
return new CImage(format, size);
1416
//! Creates a software image from another image.
1417
IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy)
1419
os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
1420
if(IImage::isRenderTargetOnlyFormat(format))
1422
os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING);
1426
CImage* tmp = new CImage(format, imageToCopy->getDimension());
1427
imageToCopy->copyTo(tmp);
1432
//! Creates a software image from part of another image.
1433
IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
1435
os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING);
1436
CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension());
1437
imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size));
1442
//! Creates a software image from part of a texture.
1443
IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
1445
if ((pos==core::position2di(0,0)) && (size == texture->getSize()))
1447
IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(ETLM_READ_ONLY), false);
1453
// make sure to avoid buffer overruns
1454
// make the vector a separate variable for g++ 3.x
1455
const core::vector2d<u32> leftUpper(core::clamp(static_cast<u32>(pos.X), 0u, texture->getSize().Width),
1456
core::clamp(static_cast<u32>(pos.Y), 0u, texture->getSize().Height));
1457
const core::rect<u32> clamped(leftUpper,
1458
core::dimension2du(core::clamp(static_cast<u32>(size.Width), 0u, texture->getSize().Width),
1459
core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
1460
if (!clamped.isValid())
1462
u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
1465
IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
1466
u8* dst = static_cast<u8*>(image->lock());
1467
src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X;
1468
for (u32 i=0; i<clamped.getHeight(); ++i)
1470
video::CColorConverter::convert_viaFormat(src, texture->getColorFormat(), clamped.getWidth(), dst, image->getColorFormat());
1471
src += texture->getPitch();
1472
dst += image->getPitch();
1481
//! Sets the fog mode.
1482
void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end,
1483
f32 density, bool pixelFog, bool rangeFog)
1489
FogDensity = density;
1490
PixelFog = pixelFog;
1491
RangeFog = rangeFog;
1494
//! Gets the fog mode.
1495
void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end,
1496
f32& density, bool& pixelFog, bool& rangeFog)
1502
density = FogDensity;
1503
pixelFog = PixelFog;
1504
rangeFog = RangeFog;
1507
//! Draws a mesh buffer
1508
void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb)
1513
//IVertexBuffer and IIndexBuffer later
1514
SHWBufferLink *HWBuffer=getBufferLink(mb);
1517
drawHardwareBuffer(HWBuffer);
1519
drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType());
1523
CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb)
1525
if (!mb || !isHardwareBufferRecommend(mb))
1528
//search for hardware links
1529
core::map< const scene::IMeshBuffer*,SHWBufferLink* >::Node* node = HWBufferMap.find(mb);
1531
return node->getValue();
1533
return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it
1537
//! Update all hardware buffers, remove unused ones
1538
void CNullDriver::updateAllHardwareBuffers()
1540
core::map<const scene::IMeshBuffer*,SHWBufferLink*>::ParentFirstIterator Iterator=HWBufferMap.getParentFirstIterator();
1542
for (;!Iterator.atEnd();Iterator++)
1544
SHWBufferLink *Link=Iterator.getNode()->getValue();
1547
if (Link->LastUsed>20000)
1549
deleteHardwareBuffer(Link);
1551
// todo: needs better fix
1552
Iterator = HWBufferMap.getParentFirstIterator();
1558
void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer)
1562
HWBufferMap.remove(HWBuffer->MeshBuffer);
1567
//! Remove hardware buffer
1568
void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb)
1570
core::map<const scene::IMeshBuffer*,SHWBufferLink*>::Node* node = HWBufferMap.find(mb);
1572
deleteHardwareBuffer(node->getValue());
1576
//! Remove all hardware buffers
1577
void CNullDriver::removeAllHardwareBuffers()
1579
while (HWBufferMap.size())
1580
deleteHardwareBuffer(HWBufferMap.getRoot()->getValue());
1584
bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb)
1586
if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
1589
if (mb->getVertexCount()<MinVertexCountForVBO)
1596
//! Create occlusion query.
1597
/** Use node for identification and mesh for occlusion test. */
1598
void CNullDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh)
1604
if ((node->getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH))
1606
else if (node->getType() == scene::ESNT_MESH)
1607
mesh = static_cast<scene::IMeshSceneNode*>(node)->getMesh();
1609
mesh = static_cast<scene::IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
1615
s32 index = OcclusionQueries.linear_search(SOccQuery(node));
1618
if (OcclusionQueries[index].Mesh != mesh)
1620
OcclusionQueries[index].Mesh->drop();
1621
OcclusionQueries[index].Mesh = mesh;
1627
OcclusionQueries.push_back(SOccQuery(node, mesh));
1628
node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY);
1633
//! Remove occlusion query.
1634
void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node)
1637
s32 index = OcclusionQueries.linear_search(SOccQuery(node));
1640
node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY);
1641
OcclusionQueries.erase(index);
1646
//! Remove all occlusion queries.
1647
void CNullDriver::removeAllOcclusionQueries()
1649
for (s32 i=OcclusionQueries.size()-1; i>=0; --i)
1651
removeOcclusionQuery(OcclusionQueries[i].Node);
1656
//! Run occlusion query. Draws mesh stored in query.
1657
/** If the mesh shall be rendered visible, use
1658
flag to enable the proper material setting. */
1659
void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
1663
s32 index = OcclusionQueries.linear_search(SOccQuery(node));
1666
OcclusionQueries[index].Run=0;
1672
mat.ColorMask=ECP_NONE;
1673
mat.GouraudShading=false;
1674
mat.ZWriteEnable=false;
1677
setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
1678
const scene::IMesh* mesh = OcclusionQueries[index].Mesh;
1679
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
1682
setMaterial(mesh->getMeshBuffer(i)->getMaterial());
1683
drawMeshBuffer(mesh->getMeshBuffer(i));
1688
//! Run all occlusion queries. Draws all meshes stored in queries.
1689
/** If the meshes shall not be rendered visible, use
1690
overrideMaterial to disable the color and depth buffer. */
1691
void CNullDriver::runAllOcclusionQueries(bool visible)
1693
for (u32 i=0; i<OcclusionQueries.size(); ++i)
1694
runOcclusionQuery(OcclusionQueries[i].Node, visible);
1698
//! Update occlusion query. Retrieves results from GPU.
1699
/** If the query shall not block, set the flag to false.
1700
Update might not occur in this case, though */
1701
void CNullDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
1706
//! Update all occlusion queries. Retrieves results from GPU.
1707
/** If the query shall not block, set the flag to false.
1708
Update might not occur in this case, though */
1709
void CNullDriver::updateAllOcclusionQueries(bool block)
1711
for (u32 i=0; i<OcclusionQueries.size(); ++i)
1713
if (OcclusionQueries[i].Run==u32(~0))
1715
updateOcclusionQuery(OcclusionQueries[i].Node, block);
1716
++OcclusionQueries[i].Run;
1717
if (OcclusionQueries[i].Run>1000)
1718
removeOcclusionQuery(OcclusionQueries[i].Node);
1723
//! Return query result.
1724
/** Return value is the number of visible pixels/fragments.
1725
The value is a safe approximation, i.e. can be larger then the
1726
actual value of pixels. */
1727
u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const
1733
//! Only used by the internal engine. Used to notify the driver that
1734
//! the window was resized.
1735
void CNullDriver::OnResize(const core::dimension2d<u32>& size)
1737
if (ViewPort.getWidth() == (s32)ScreenSize.Width &&
1738
ViewPort.getHeight() == (s32)ScreenSize.Height)
1739
ViewPort = core::rect<s32>(core::position2d<s32>(0,0),
1740
core::dimension2di(size));
1746
// adds a material renderer and drops it afterwards. To be used for internal creation
1747
s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m)
1749
s32 i = addMaterialRenderer(m);
1758
//! Adds a new material renderer to the video device.
1759
s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name)
1764
SMaterialRenderer r;
1765
r.Renderer = renderer;
1768
if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ))
1770
// set name of built in renderer so that we don't have to implement name
1771
// setting in all available renderers.
1772
r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()];
1775
MaterialRenderers.push_back(r);
1778
return MaterialRenderers.size()-1;
1782
//! Sets the name of a material renderer.
1783
void CNullDriver::setMaterialRendererName(s32 idx, const char* name)
1785
if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
1786
idx >= (s32)MaterialRenderers.size())
1789
MaterialRenderers[idx].Name = name;
1793
//! Creates material attributes list from a material, usable for serialization and more.
1794
io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMaterial& material,
1795
io::SAttributeReadWriteOptions* options)
1797
io::CAttributes* attr = new io::CAttributes(this);
1799
attr->addEnum("Type", material.MaterialType, sBuiltInMaterialTypeNames);
1801
attr->addColor("Ambient", material.AmbientColor);
1802
attr->addColor("Diffuse", material.DiffuseColor);
1803
attr->addColor("Emissive", material.EmissiveColor);
1804
attr->addColor("Specular", material.SpecularColor);
1806
attr->addFloat("Shininess", material.Shininess);
1807
attr->addFloat("Param1", material.MaterialTypeParam);
1808
attr->addFloat("Param2", material.MaterialTypeParam2);
1810
core::stringc prefix="Texture";
1812
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1814
if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename && material.getTexture(i))
1816
io::path path = FileSystem->getRelativeFilename(
1817
FileSystem->getAbsolutePath(material.getTexture(i)->getName()), options->Filename);
1818
attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i), path);
1821
attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i));
1824
attr->addBool("Wireframe", material.Wireframe);
1825
attr->addBool("GouraudShading", material.GouraudShading);
1826
attr->addBool("Lighting", material.Lighting);
1827
attr->addBool("ZWriteEnable", material.ZWriteEnable);
1828
attr->addInt("ZBuffer", material.ZBuffer);
1829
attr->addBool("BackfaceCulling", material.BackfaceCulling);
1830
attr->addBool("FrontfaceCulling", material.FrontfaceCulling);
1831
attr->addBool("FogEnable", material.FogEnable);
1832
attr->addBool("NormalizeNormals", material.NormalizeNormals);
1833
attr->addBool("UseMipMaps", material.UseMipMaps);
1834
attr->addInt("AntiAliasing", material.AntiAliasing);
1835
attr->addInt("ColorMask", material.ColorMask);
1837
prefix = "BilinearFilter";
1838
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1839
attr->addBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].BilinearFilter);
1840
prefix = "TrilinearFilter";
1841
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1842
attr->addBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TrilinearFilter);
1843
prefix = "AnisotropicFilter";
1844
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1845
attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter);
1846
prefix="TextureWrapU";
1847
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1848
attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapU, aTextureClampNames);
1849
prefix="TextureWrapV";
1850
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1851
attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapV, aTextureClampNames);
1853
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1854
attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].LODBias);
1860
//! Fills an SMaterial structure from attributes.
1861
void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attr)
1863
outMaterial.MaterialType = video::EMT_SOLID;
1865
core::stringc name = attr->getAttributeAsString("Type");
1869
for ( i=0; i < MaterialRenderers.size(); ++i)
1870
if ( name == MaterialRenderers[i].Name )
1872
outMaterial.MaterialType = (video::E_MATERIAL_TYPE)i;
1876
outMaterial.AmbientColor = attr->getAttributeAsColor("Ambient");
1877
outMaterial.DiffuseColor = attr->getAttributeAsColor("Diffuse");
1878
outMaterial.EmissiveColor = attr->getAttributeAsColor("Emissive");
1879
outMaterial.SpecularColor = attr->getAttributeAsColor("Specular");
1881
outMaterial.Shininess = attr->getAttributeAsFloat("Shininess");
1882
outMaterial.MaterialTypeParam = attr->getAttributeAsFloat("Param1");
1883
outMaterial.MaterialTypeParam2 = attr->getAttributeAsFloat("Param2");
1885
core::stringc prefix="Texture";
1886
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1887
outMaterial.setTexture(i, attr->getAttributeAsTexture((prefix+core::stringc(i+1)).c_str()));
1889
outMaterial.Wireframe = attr->getAttributeAsBool("Wireframe");
1890
outMaterial.GouraudShading = attr->getAttributeAsBool("GouraudShading");
1891
outMaterial.Lighting = attr->getAttributeAsBool("Lighting");
1892
outMaterial.ZWriteEnable = attr->getAttributeAsBool("ZWriteEnable");
1893
outMaterial.ZBuffer = (u8)attr->getAttributeAsInt("ZBuffer");
1894
outMaterial.BackfaceCulling = attr->getAttributeAsBool("BackfaceCulling");
1895
outMaterial.FrontfaceCulling = attr->getAttributeAsBool("FrontfaceCulling");
1896
outMaterial.FogEnable = attr->getAttributeAsBool("FogEnable");
1897
outMaterial.NormalizeNormals = attr->getAttributeAsBool("NormalizeNormals");
1898
if (attr->existsAttribute("UseMipMaps")) // legacy
1899
outMaterial.UseMipMaps = attr->getAttributeAsBool("UseMipMaps");
1901
outMaterial.UseMipMaps = true;
1904
outMaterial.AntiAliasing = attr->getAttributeAsInt("AntiAliasing");
1905
if (attr->existsAttribute("ColorMask"))
1906
outMaterial.ColorMask = attr->getAttributeAsInt("ColorMask");
1907
prefix = "BilinearFilter";
1908
if (attr->existsAttribute(prefix.c_str())) // legacy
1909
outMaterial.setFlag(EMF_BILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str()));
1911
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1912
outMaterial.TextureLayer[i].BilinearFilter = attr->getAttributeAsBool((prefix+core::stringc(i+1)).c_str());
1914
prefix = "TrilinearFilter";
1915
if (attr->existsAttribute(prefix.c_str())) // legacy
1916
outMaterial.setFlag(EMF_TRILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str()));
1918
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1919
outMaterial.TextureLayer[i].TrilinearFilter = attr->getAttributeAsBool((prefix+core::stringc(i+1)).c_str());
1921
prefix = "AnisotropicFilter";
1922
if (attr->existsAttribute(prefix.c_str())) // legacy
1923
outMaterial.setFlag(EMF_ANISOTROPIC_FILTER, attr->getAttributeAsBool(prefix.c_str()));
1925
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1926
outMaterial.TextureLayer[i].AnisotropicFilter = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str());
1928
prefix = "TextureWrap";
1929
if (attr->existsAttribute(prefix.c_str())) // legacy
1931
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1933
outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames);
1934
outMaterial.TextureLayer[i].TextureWrapV = outMaterial.TextureLayer[i].TextureWrapU;
1939
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1941
outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"U"+core::stringc(i+1)).c_str(), aTextureClampNames);
1942
outMaterial.TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"V"+core::stringc(i+1)).c_str(), aTextureClampNames);
1948
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
1949
outMaterial.TextureLayer[i].LODBias = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str());
1953
//! Returns driver and operating system specific data about the IVideoDriver.
1954
const SExposedVideoData& CNullDriver::getExposedVideoData()
1960
//! Returns type of video driver
1961
E_DRIVER_TYPE CNullDriver::getDriverType() const
1967
//! deletes all material renderers
1968
void CNullDriver::deleteMaterialRenders()
1970
// delete material renderers
1971
for (u32 i=0; i<MaterialRenderers.size(); ++i)
1972
if (MaterialRenderers[i].Renderer)
1973
MaterialRenderers[i].Renderer->drop();
1975
MaterialRenderers.clear();
1979
//! Returns pointer to material renderer or null
1980
IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx)
1982
if ( idx < MaterialRenderers.size() )
1983
return MaterialRenderers[idx].Renderer;
1989
//! Returns amount of currently available material renderers.
1990
u32 CNullDriver::getMaterialRendererCount() const
1992
return MaterialRenderers.size();
1996
//! Returns name of the material renderer
1997
const char* CNullDriver::getMaterialRendererName(u32 idx) const
1999
if ( idx < MaterialRenderers.size() )
2000
return MaterialRenderers[idx].Name.c_str();
2006
//! Returns pointer to the IGPUProgrammingServices interface.
2007
IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices()
2013
//! Adds a new material renderer to the VideoDriver, based on a high level shading language.
2014
s32 CNullDriver::addHighLevelShaderMaterial(
2015
const c8* vertexShaderProgram,
2016
const c8* vertexShaderEntryPointName,
2017
E_VERTEX_SHADER_TYPE vsCompileTarget,
2018
const c8* pixelShaderProgram,
2019
const c8* pixelShaderEntryPointName,
2020
E_PIXEL_SHADER_TYPE psCompileTarget,
2021
const c8* geometryShaderProgram,
2022
const c8* geometryShaderEntryPointName,
2023
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
2024
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
2026
IShaderConstantSetCallBack* callback,
2027
E_MATERIAL_TYPE baseMaterial,
2030
os::Printer::log("High level shader materials not available (yet) in this driver, sorry");
2035
//! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
2036
//! but tries to load the programs from files.
2037
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
2038
const io::path& vertexShaderProgramFileName,
2039
const c8* vertexShaderEntryPointName,
2040
E_VERTEX_SHADER_TYPE vsCompileTarget,
2041
const io::path& pixelShaderProgramFileName,
2042
const c8* pixelShaderEntryPointName,
2043
E_PIXEL_SHADER_TYPE psCompileTarget,
2044
const io::path& geometryShaderProgramFileName,
2045
const c8* geometryShaderEntryPointName,
2046
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
2047
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
2049
IShaderConstantSetCallBack* callback,
2050
E_MATERIAL_TYPE baseMaterial,
2053
io::IReadFile* vsfile = 0;
2054
io::IReadFile* psfile = 0;
2055
io::IReadFile* gsfile = 0;
2057
if (vertexShaderProgramFileName.size() )
2059
vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
2062
os::Printer::log("Could not open vertex shader program file",
2063
vertexShaderProgramFileName, ELL_WARNING);
2067
if (pixelShaderProgramFileName.size() )
2069
psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
2072
os::Printer::log("Could not open pixel shader program file",
2073
pixelShaderProgramFileName, ELL_WARNING);
2077
if (geometryShaderProgramFileName.size() )
2079
gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName);
2082
os::Printer::log("Could not open geometry shader program file",
2083
geometryShaderProgramFileName, ELL_WARNING);
2087
s32 result = addHighLevelShaderMaterialFromFiles(
2088
vsfile, vertexShaderEntryPointName, vsCompileTarget,
2089
psfile, pixelShaderEntryPointName, psCompileTarget,
2090
gsfile, geometryShaderEntryPointName, gsCompileTarget,
2091
inType, outType, verticesOut,
2092
callback, baseMaterial, userData);
2107
//! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description),
2108
//! but tries to load the programs from files.
2109
s32 CNullDriver::addHighLevelShaderMaterialFromFiles(
2110
io::IReadFile* vertexShaderProgram,
2111
const c8* vertexShaderEntryPointName,
2112
E_VERTEX_SHADER_TYPE vsCompileTarget,
2113
io::IReadFile* pixelShaderProgram,
2114
const c8* pixelShaderEntryPointName,
2115
E_PIXEL_SHADER_TYPE psCompileTarget,
2116
io::IReadFile* geometryShaderProgram,
2117
const c8* geometryShaderEntryPointName,
2118
E_GEOMETRY_SHADER_TYPE gsCompileTarget,
2119
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,
2121
IShaderConstantSetCallBack* callback,
2122
E_MATERIAL_TYPE baseMaterial,
2129
if (vertexShaderProgram)
2131
const long size = vertexShaderProgram->getSize();
2134
vs = new c8[size+1];
2135
vertexShaderProgram->read(vs, size);
2140
if (pixelShaderProgram)
2142
const long size = pixelShaderProgram->getSize();
2145
// if both handles are the same we must reset the file
2146
if (pixelShaderProgram==vertexShaderProgram)
2147
pixelShaderProgram->seek(0);
2148
ps = new c8[size+1];
2149
pixelShaderProgram->read(ps, size);
2154
if (geometryShaderProgram)
2156
const long size = geometryShaderProgram->getSize();
2159
// if both handles are the same we must reset the file
2160
if ((geometryShaderProgram==vertexShaderProgram) ||
2161
(geometryShaderProgram==pixelShaderProgram))
2162
geometryShaderProgram->seek(0);
2163
gs = new c8[size+1];
2164
geometryShaderProgram->read(gs, size);
2169
s32 result = this->addHighLevelShaderMaterial(
2170
vs, vertexShaderEntryPointName, vsCompileTarget,
2171
ps, pixelShaderEntryPointName, psCompileTarget,
2172
gs, geometryShaderEntryPointName, gsCompileTarget,
2173
inType, outType, verticesOut,
2174
callback, baseMaterial, userData);
2184
//! Adds a new material renderer to the VideoDriver, using pixel and/or
2185
//! vertex shaders to render geometry.
2186
s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram,
2187
const c8* pixelShaderProgram,
2188
IShaderConstantSetCallBack* callback,
2189
E_MATERIAL_TYPE baseMaterial,
2192
os::Printer::log("Shader materials not implemented yet in this driver, sorry.");
2197
//! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
2198
//! programs from files.
2199
s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram,
2200
io::IReadFile* pixelShaderProgram,
2201
IShaderConstantSetCallBack* callback,
2202
E_MATERIAL_TYPE baseMaterial,
2208
if (vertexShaderProgram)
2210
const long size = vertexShaderProgram->getSize();
2213
vs = new c8[size+1];
2214
vertexShaderProgram->read(vs, size);
2219
if (pixelShaderProgram)
2221
const long size = pixelShaderProgram->getSize();
2224
ps = new c8[size+1];
2225
pixelShaderProgram->read(ps, size);
2230
s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData);
2239
//! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the
2240
//! programs from files.
2241
s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName,
2242
const io::path& pixelShaderProgramFileName,
2243
IShaderConstantSetCallBack* callback,
2244
E_MATERIAL_TYPE baseMaterial,
2247
io::IReadFile* vsfile = 0;
2248
io::IReadFile* psfile = 0;
2250
if (vertexShaderProgramFileName.size())
2252
vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName);
2255
os::Printer::log("Could not open vertex shader program file",
2256
vertexShaderProgramFileName, ELL_WARNING);
2261
if (pixelShaderProgramFileName.size())
2263
psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName);
2266
os::Printer::log("Could not open pixel shader program file",
2267
pixelShaderProgramFileName, ELL_WARNING);
2274
s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback,
2275
baseMaterial, userData);
2287
//! Creates a render target texture.
2288
ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
2289
const io::path&name, const ECOLOR_FORMAT format)
2295
//! Clears the ZBuffer.
2296
void CNullDriver::clearZBuffer()
2301
//! Returns a pointer to the mesh manipulator.
2302
scene::IMeshManipulator* CNullDriver::getMeshManipulator()
2304
return MeshManipulator;
2308
//! Returns an image created from the last rendered frame.
2309
IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
2315
// prints renderer version
2316
void CNullDriver::printVersion()
2318
core::stringw namePrint = L"Using renderer: ";
2319
namePrint += getName();
2320
os::Printer::log(namePrint.c_str(), ELL_INFORMATION);
2324
//! creates a video driver
2325
IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize)
2327
CNullDriver* nullDriver = new CNullDriver(io, screenSize);
2329
// create empty material renderers
2330
for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i)
2332
IMaterialRenderer* imr = new IMaterialRenderer();
2333
nullDriver->addMaterialRenderer(imr);
2341
//! Set/unset a clipping plane.
2342
//! There are at least 6 clipping planes available for the user to set at will.
2343
//! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
2344
//! \param plane: The plane itself.
2345
//! \param enable: If true, enable the clipping plane else disable it.
2346
bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
2352
//! Enable/disable a clipping plane.
2353
void CNullDriver::enableClipPlane(u32 index, bool enable)
2359
ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d<u32>& size,
2362
os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead");
2363
ITexture* tex = addRenderTargetTexture(size, name);
2369
void CNullDriver::setMinHardwareBufferVertexCount(u32 count)
2371
MinVertexCountForVBO = count;
2375
SOverrideMaterial& CNullDriver::getOverrideMaterial()
2377
return OverrideMaterial;
2381
//! Get the 2d override material for altering its values
2382
SMaterial& CNullDriver::getMaterial2D()
2384
return OverrideMaterial2D;
2388
//! Enable the 2d override material
2389
void CNullDriver::enableMaterial2D(bool enable)
2391
OverrideMaterial2DEnabled=enable;
2395
core::dimension2du CNullDriver::getMaxTextureSize() const
2397
return core::dimension2du(0x10000,0x10000); // maybe large enough
2401
//! Color conversion convenience function
2402
/** Convert an image (as array of pixels) from source to destination
2403
array, thereby converting the color format. The pixel size is
2404
determined by the color formats.
2405
\param sP Pointer to source
2406
\param sF Color format of source
2407
\param sN Number of pixels to convert, both array must be large enough
2408
\param dP Pointer to destination
2409
\param dF Color format of destination
2411
void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN,
2412
void* dP, ECOLOR_FORMAT dF) const
2414
video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF);