Support for anti-aliasing modes per Material.

Initial support for Alpha To Coverage. Doesn't properly work on my laptop, so needs some more fixing and tuning before it actually works.
Fixed AntiAliasing on Win32/OpenGL.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2118 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2009-01-22 00:50:55 +00:00
parent a60d0af20f
commit 9c34c59233
6 changed files with 155 additions and 38 deletions

View File

@ -1,11 +1,19 @@
Changes in version 1.6
- Initial support for Alpha To Coverage, needs some more fixing until it works on all supported platforms.
- Added support for Anti-Aliasing modes per material
- Added an ICollisionCallback to ISceneNodeAnimatorCollisionResponse, to inform the application that a collision has occured. Thanks to garrittg for this.
- Added an startPosition parameter to createFlyCircleAnimator() to allow starting the animator at any position on the circle.
- Many uses of dimension2d<s32> changed to dimension2d<u32>, including IImage, ITexture and screen dimensions. You will have to change (at least) createDevice() calls to use dimension2d<u32>
- Added Doublebuffer flag to SIrrCreationParameters, for better finetuning
- Added Stereo-Framebuffer support for professional OpenGL cards
- Added IFileSystem::createMemoryWriteFile() to allow creation of an IWriteFile interface that uses an application supplied memory buffer.
- Added an IVideoDriver::writeImageToFile() overload that can take an IWriteFile interface.

View File

@ -68,6 +68,9 @@ namespace video
//! Access to all layers texture wrap settings. Overwrites separate layer settings.
EMF_TEXTURE_WRAP,
//! AntiAliasing mode
EMF_ANTI_ALIASING,
//! This is not a flag, but a value indicating how much flags there are.
EMF_MATERIAL_FLAG_COUNT
};

View File

@ -58,6 +58,32 @@ namespace video
dstFact = E_BLEND_FACTOR ( ( state & 0x000000FF ) );
}
//! These flags are used to specify the anti-aliasing and smoothing modes
/** Techniques supported are multisampling, geometry smoothing, and alpha
to coverage.
Some drivers don't support a per-material setting of the anti-aliasing
modes. In those cases, FSAA/multisampling is defined by the device mode
chosen upon creation via irr::SIrrCreationParameters.
*/
enum E_ANTI_ALIASING_MODE
{
//! Use to turn off anti-aliasing for this material
EAAM_OFF=0,
//! Default anti-aliasing mode
EAAM_SIMPLE=1,
//! High-quality anti-aliasing, not always supported, automatically enables SIMPLE mode
EAAM_QUALITY=3,
//! Line smoothing
EAAM_LINE_SMOOTH=4,
//! point smoothing, often in software and slow, only with OpenGL
EAAM_POINT_SMOOTH=8,
//! All typical anti-alias and smooth modes
EAAM_FULL_BASIC=15,
//! Enhanced anti-aliasing for transparent materials
/** Usually used with EMT_TRANSPARENT_ALPHA_REF and multisampling. */
EAAM_ALPHA_TO_COVERAGE=16
};
//! Maximum number of texture an SMaterial can have.
const u32 MATERIAL_MAX_TEXTURES = 4;
@ -72,7 +98,7 @@ namespace video
Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f),
Wireframe(false), PointCloud(false), GouraudShading(true), Lighting(true),
ZWriteEnable(true), BackfaceCulling(true), FrontfaceCulling(false),
FogEnable(false), NormalizeNormals(false), ZBuffer(1)
FogEnable(false), NormalizeNormals(false), ZBuffer(1), AntiAliasing(EAAM_SIMPLE|EAAM_LINE_SMOOTH)
{ }
//! Copy constructor
@ -118,6 +144,7 @@ namespace video
FogEnable = other.FogEnable;
NormalizeNormals = other.NormalizeNormals;
ZBuffer = other.ZBuffer;
AntiAliasing = other.AntiAliasing;
return *this;
}
@ -226,7 +253,10 @@ namespace video
/** Changed from bool to integer
(0 == ZBuffer Off, 1 == ZBuffer LessEqual, 2 == ZBuffer Equal)
*/
char ZBuffer;
u8 ZBuffer;
//! Sets the antialiasing mode
u8 AntiAliasing;
//! Gets the texture transformation matrix for level i
/** \param i The desired level. Must not be larger than MATERIAL_MAX_TEXTURES.
@ -331,6 +361,8 @@ namespace video
TextureLayer[i].TextureWrap = (E_TEXTURE_CLAMP)value;
}
break;
case EMF_ANTI_ALIASING:
AntiAliasing = value?1:0;
default:
break;
}
@ -374,6 +406,8 @@ namespace video
TextureLayer[1].TextureWrap ||
TextureLayer[2].TextureWrap ||
TextureLayer[3].TextureWrap);
case EMF_ANTI_ALIASING:
return (AntiAliasing==1);
case EMF_MATERIAL_FLAG_COUNT:
break;
}
@ -405,7 +439,8 @@ namespace video
BackfaceCulling != b.BackfaceCulling ||
FrontfaceCulling != b.FrontfaceCulling ||
FogEnable != b.FogEnable ||
NormalizeNormals != b.NormalizeNormals;
NormalizeNormals != b.NormalizeNormals||
AntiAliasing != b.AntiAliasing;
for (u32 i=0; (i<MATERIAL_MAX_TEXTURES) && !different; ++i)
{
different |= (TextureLayer[i] != b.TextureLayer[i]);

View File

@ -28,12 +28,13 @@ CD3D9Driver::CD3D9Driver(const core::dimension2d<u32>& screenSize, HWND window,
bool fullscreen, bool stencilbuffer,
io::IFileSystem* io, bool pureSoftware)
: CNullDriver(io, screenSize), CurrentRenderMode(ERM_NONE),
ResetRenderStates(true), Transformation3DChanged(false), StencilBuffer(stencilbuffer),
ResetRenderStates(true), Transformation3DChanged(false),
StencilBuffer(stencilbuffer), AntiAliasing(0),
D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0),
WindowId(0), SceneSourceRect(0),
LastVertexType((video::E_VERTEX_TYPE)-1), MaxTextureUnits(0), MaxUserClipPlanes(0),
MaxLightDistance(sqrtf(FLT_MAX)), LastSetLight(-1), ColorFormat(ECF_A8R8G8B8), DeviceLost(false),
Fullscreen(fullscreen), DriverWasReset(true)
MaxLightDistance(0.f), LastSetLight(-1), ColorFormat(ECF_A8R8G8B8), DeviceLost(false),
Fullscreen(fullscreen), DriverWasReset(true), AlphaToCoverageSupport(false)
{
#ifdef _DEBUG
setDebugName("CD3D9Driver");
@ -46,7 +47,7 @@ CD3D9Driver::CD3D9Driver(const core::dimension2d<u32>& screenSize, HWND window,
CurrentTexture[i] = 0;
LastTextureMipMapsAvailable[i] = false;
}
MaxLightDistance = sqrtf(FLT_MAX);
// create sphere map matrix
SphereMapMatrixD3D9._11 = 0.5f; SphereMapMatrixD3D9._12 = 0.0f;
@ -203,15 +204,16 @@ bool CD3D9Driver::initDriver(const core::dimension2d<u32>& screenSize,
os::Printer::log(tmp, ELL_INFORMATION);
// Assign vendor name based on vendor id.
VendorID= static_cast<u16>(dai.VendorId);
switch(dai.VendorId)
{
case 0x1002 : vendorName = "ATI Technologies Inc."; break;
case 0x10DE : vendorName = "NVIDIA Corporation"; break;
case 0x102B : vendorName = "Matrox Electronic Systems Ltd."; break;
case 0x121A : vendorName = "3dfx Interactive Inc"; break;
case 0x5333 : vendorName = "S3 Graphics Co., Ltd."; break;
case 0x8086 : vendorName = "Intel Corporation"; break;
default: vendorName = "Unknown VendorId: ";vendorName += (u32)dai.VendorId; break;
case 0x1002 : VendorName = "ATI Technologies Inc."; break;
case 0x10DE : VendorName = "NVIDIA Corporation"; break;
case 0x102B : VendorName = "Matrox Electronic Systems Ltd."; break;
case 0x121A : VendorName = "3dfx Interactive Inc"; break;
case 0x5333 : VendorName = "S3 Graphics Co., Ltd."; break;
case 0x8086 : VendorName = "Intel Corporation"; break;
default: VendorName = "Unknown VendorId: ";VendorName += (u32)dai.VendorId; break;
}
}
@ -297,6 +299,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d<u32>& screenSize,
os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING);
}
}
AntiAliasing = antiAlias;
// check stencil buffer compatibility
if (StencilBuffer)
@ -404,10 +407,6 @@ bool CD3D9Driver::initDriver(const core::dimension2d<u32>& screenSize,
// set default vertex shader
setVertexShader(EVT_STANDARD);
// enable antialiasing
if (antiAlias!=0)
pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
// set fog mode
setFog(FogColor, LinearFog, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
@ -424,6 +423,17 @@ bool CD3D9Driver::initDriver(const core::dimension2d<u32>& screenSize,
MaxTextureUnits = core::min_((u32)Caps.MaxSimultaneousTextures, MATERIAL_MAX_TEXTURES);
MaxUserClipPlanes = (u32)Caps.MaxUserClipPlanes;
if (VendorID==0x10DE)//NVidia
AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
(D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK);
else if (VendorID=0x1002)//ATI
AlphaToCoverageSupport = true; // TODO: Check unknown
#if 0
AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
(D3DFORMAT)MAKEFOURCC('A','2','M','1')) == S_OK);
#endif
// set the renderstates
setRenderStates3DMode();
@ -1742,6 +1752,39 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria
pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals);
}
// Anti Aliasing
if (resetAllRenderstates || lastmaterial.AntiAliasing != material.AntiAliasing)
{
if (AlphaToCoverageSupport && (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE))
{
if (VendorID==0x10DE)//NVidia
pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, MAKEFOURCC('A','T','O','C'));
// SSAA could give better results on NVidia cards
else if (VendorID==0x1002)//ATI
pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1'));
}
else if (AlphaToCoverageSupport && (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE))
{
if (VendorID==0x10DE)
pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN);
else if (VendorID==0x1002)
pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0'));
}
// enable antialiasing
if (AntiAliasing)
{
if (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))
pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
else if (lastmaterial.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))
pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
if (material.AntiAliasing & (EAAM_LINE_SMOOTH))
pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE);
else if (lastmaterial.AntiAliasing & (EAAM_LINE_SMOOTH))
pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE);
}
}
// thickness
if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness)
{

View File

@ -235,7 +235,7 @@ namespace video
virtual void enableClipPlane(u32 index, bool enable);
//! Returns the graphics card vendor name.
virtual core::stringc getVendorInfo() {return vendorName;}
virtual core::stringc getVendorInfo() {return VendorName;}
//! Check if the driver was recently reset.
virtual bool checkDriverReset() {return DriverWasReset;}
@ -340,6 +340,7 @@ namespace video
bool ResetRenderStates; // bool to make all renderstates be reseted if set.
bool Transformation3DChanged;
bool StencilBuffer;
u8 AntiAliasing;
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES];
core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode.
@ -361,7 +362,8 @@ namespace video
SColorf AmbientLight;
core::stringc vendorName;
core::stringc VendorName;
u16 VendorID;
core::array<SDepthSurface*> DepthBuffers;
@ -375,6 +377,7 @@ namespace video
bool DeviceLost;
bool Fullscreen;
bool DriverWasReset;
bool AlphaToCoverageSupport;
};

View File

@ -224,7 +224,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
s32 rv=0;
// Try to get an acceptable pixel format
while(rv==0 && iAttributes[19]>1)
while(rv==0 && iAttributes[21]>1)
{
s32 pixelFormat=0;
u32 numFormats=0;
@ -233,12 +233,12 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
if (valid && numFormats>0)
rv = pixelFormat;
else
iAttributes[19] -= 1;
iAttributes[21] -= 1;
}
if (rv)
{
PixelFormat=rv;
AntiAlias=iAttributes[19];
AntiAlias=iAttributes[21];
}
}
else
@ -528,21 +528,11 @@ bool COpenGLDriver::genericDriverInit(const core::dimension2d<u32>& screenSize,
glClearDepth(1.0);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
glDepthFunc(GL_LEQUAL);
glFrontFace(GL_CW);
if (AntiAlias >= 2)
{
if (FeatureAvailable[IRR_ARB_multisample])
glEnable(GL_MULTISAMPLE_ARB);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_LINE_SMOOTH);
}
// currently disabled, because often in software, and thus very slow
// glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
// glEnable(GL_POINT_SMOOTH);
UserClipPlane.reallocate(MaxUserClipPlanes);
UserClipPlaneEnabled.reallocate(MaxUserClipPlanes);
for (i=0; i<MaxUserClipPlanes; ++i)
@ -2143,6 +2133,41 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
glLineWidth(material.Thickness);
}
// Anti aliasing
if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing)
{
if (FeatureAvailable[IRR_ARB_multisample])
{
if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
if ((AntiAlias >= 2) && (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY)))
{
glEnable(GL_MULTISAMPLE_ARB);
#ifdef GL_NV_multisample_filter_hint
if (FeatureAvailable[IRR_NV_multisample_filter_hint])
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, (material.AntiAliasing & EAAM_QUALITY)?GL_NICEST:GL_FASTEST);
#endif
}
else
glDisable(GL_MULTISAMPLE_ARB);
}
if (AntiAlias >= 2)
{
if (material.AntiAliasing & EAAM_LINE_SMOOTH)
glEnable(GL_LINE_SMOOTH);
else if (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH)
glDisable(GL_LINE_SMOOTH);
if (material.AntiAliasing & EAAM_POINT_SMOOTH)
// often in software, and thus very slow
glEnable(GL_POINT_SMOOTH);
else if (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH)
glDisable(GL_POINT_SMOOTH);
}
}
setWrapMode(material);
// be sure to leave in texture stage 0