diff --git a/changes.txt b/changes.txt index fd1732bd..c213dfc6 100644 --- a/changes.txt +++ b/changes.txt @@ -9,6 +9,18 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point) -------------------------- Changes in 1.9 (not yet released) +- BurningVideo: 0.51 + - 10 year anniversary update + - Lighting model reworked. moved to eyespace like openGL. [Specular Highlights, Fog, Sphere/Reflection Map] + - increased internal s4DVertex to support 4 Textures and 4 Colors [switchable] + - Textures are handled as sRGB during Mipmap Generation. More accurate, less visual disruption + - 2D is drawn as 3D like hardware drivers. [switchable]. enables viewport scaling, material2D + - Texture Spatial Resolution Limiting working. [lower memory consumption,SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE] + - NormalMap for 1 Light accurate. still all lights are accumulated + - SuperTuxKart 8.0.1 playable + - Known Problems + - Depthbuffer range not equal to Hardware Drivers. Problems with Orthographic Stencil Shadows + - Triangle MipMap Selection. Wrong for TextureAtlas and Billboards - Fix CPLYMeshFileLoader checking for wrong vertex count when switching between 16/32 bit. Thanks @randomMesh for reporting. - Fix bug that AnimatedMeshSceneNode ignored ReadOnlyMaterials flag when checking materials for transparent render passes. - Unify checks if materials should use transparent render pass with new IVideoDriver::needsTransparentRenderPass function. diff --git a/examples/05.UserInterface/main.cpp b/examples/05.UserInterface/main.cpp index 501eed3d..deaba6f1 100644 --- a/examples/05.UserInterface/main.cpp +++ b/examples/05.UserInterface/main.cpp @@ -266,7 +266,7 @@ int main() /* And at last, we create a nice Irrlicht Engine logo in the top left corner. */ - env->addImage(driver->getTexture(mediaPath + "irrlichtlogo2.png"), + env->addImage(driver->getTexture(mediaPath + "irrlichtlogo3.png"), position2d(10,10)); diff --git a/examples/09.Meshviewer/main.cpp b/examples/09.Meshviewer/main.cpp index 010ad6eb..1a5f51a9 100644 --- a/examples/09.Meshviewer/main.cpp +++ b/examples/09.Meshviewer/main.cpp @@ -978,7 +978,7 @@ int main(int argc, char* argv[]) // load the irrlicht engine logo IGUIImage *img = - env->addImage(driver->getTexture("irrlichtlogo2.png"), + env->addImage(driver->getTexture("irrlichtlogo3.png"), core::position2d(10, driver->getScreenSize().Height - 128)); // lock the logo's edges to the bottom left corner of the screen diff --git a/examples/10.Shaders/main.cpp b/examples/10.Shaders/main.cpp index 1beb3deb..ff80bd51 100644 --- a/examples/10.Shaders/main.cpp +++ b/examples/10.Shaders/main.cpp @@ -236,6 +236,8 @@ int main() vsFileName = mediaPath + "opengl.vsh"; } break; + default: + break; } /* diff --git a/examples/11.PerPixelLighting/main.cpp b/examples/11.PerPixelLighting/main.cpp index c2e03af2..afa59cb5 100644 --- a/examples/11.PerPixelLighting/main.cpp +++ b/examples/11.PerPixelLighting/main.cpp @@ -285,9 +285,9 @@ int main() driver->getTexture(mediaPath + "rockwall.jpg")); room->setMaterialTexture(1, normalMap); - // Stones don't glitter.. - room->getMaterial(0).SpecularColor.set(0,0,0,0); - room->getMaterial(0).Shininess = 0.f; + // Stones don't glitter.. (but specular highlight for EMT_SOLID) + //room->getMaterial(0).SpecularColor.set(0,0,0,0); + //room->getMaterial(0).Shininess = 0.f; room->setMaterialFlag(video::EMF_FOG_ENABLE, true); room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID); @@ -365,7 +365,7 @@ int main() // add light 1 (more green) scene::ILightSceneNode* light1 = smgr->addLightSceneNode(0, core::vector3df(0,0,0), - video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f); + video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 400.0f); // add fly circle animator to light 1 scene::ISceneNodeAnimator* anim = @@ -398,7 +398,7 @@ int main() // add light 2 (red) scene::ISceneNode* light2 = smgr->addLightSceneNode(0, core::vector3df(0,0,0), - video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f); + video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 400.0f); // add fly circle animator to light 2 anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0), 200.0f, diff --git a/examples/12.TerrainRendering/main.cpp b/examples/12.TerrainRendering/main.cpp index 7c38598e..f9bc97e6 100644 --- a/examples/12.TerrainRendering/main.cpp +++ b/examples/12.TerrainRendering/main.cpp @@ -120,7 +120,7 @@ int main() const io::path mediaPath = getExampleMediaPath(); // add irrlicht logo - env->addImage(driver->getTexture(mediaPath + "irrlichtlogo2.png"), + env->addImage(driver->getTexture(mediaPath + "irrlichtlogo3.png"), core::position2d(10,10)); //set other font @@ -213,6 +213,7 @@ int main() terrain->getMeshBufferForLOD(*buffer, 0); video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); // Work on data or get the IndexBuffer with a similar call. + (void)data; // disable unused variable warnings buffer->drop(); // When done drop the buffer again. /* diff --git a/examples/16.Quake3MapShader/main.cpp b/examples/16.Quake3MapShader/main.cpp index e8a318dc..38062c5a 100644 --- a/examples/16.Quake3MapShader/main.cpp +++ b/examples/16.Quake3MapShader/main.cpp @@ -318,7 +318,7 @@ int IRRCALLCONV main(int argc, char* argv[]) device->getCursorControl()->setVisible(false); // load the engine logo - gui->addImage(driver->getTexture("irrlichtlogo2.png"), + gui->addImage(driver->getTexture("irrlichtlogo3.png"), core::position2d(10, 10)); // show the driver logo @@ -335,6 +335,8 @@ int IRRCALLCONV main(int argc, char* argv[]) case video::EDT_DIRECT3D9: gui->addImage(driver->getTexture("directxlogo.png"), pos); break; + default: + break; } /* @@ -355,14 +357,14 @@ int IRRCALLCONV main(int argc, char* argv[]) driver->endScene(); int fps = driver->getFPS(); - //if (lastFPS != fps) + if (1 || lastFPS != fps) { - io::IAttributes * const attr = smgr->getParameters(); core::stringw str = L"Q3 ["; str += driver->getName(); str += "] FPS:"; str += fps; #ifdef _IRR_SCENEMANAGER_DEBUG + io::IAttributes * const attr = smgr->getParameters(); str += " Cull:"; str += attr->getAttributeAsInt("calls"); str += "/"; diff --git a/examples/22.MaterialViewer/main.cpp b/examples/22.MaterialViewer/main.cpp index 83309260..358ce02c 100755 --- a/examples/22.MaterialViewer/main.cpp +++ b/examples/22.MaterialViewer/main.cpp @@ -429,7 +429,7 @@ void CMaterialControl::init(scene::IMeshSceneNode* node, IrrlichtDevice * device Driver = device->getVideoDriver (); gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); - scene::ISceneManager* smgr = device->getSceneManager(); + //scene::ISceneManager* smgr = device->getSceneManager(); const video::SMaterial & material = node->getMaterial(0); s32 top = pos.Y; diff --git a/examples/23.SMeshHandling/main.cpp b/examples/23.SMeshHandling/main.cpp index 2d413094..a4ef9ebc 100644 --- a/examples/23.SMeshHandling/main.cpp +++ b/examples/23.SMeshHandling/main.cpp @@ -57,7 +57,7 @@ typedef f32 generate_func(s16 x, s16 y, f32 s); f32 eggbox(s16 x, s16 y, f32 s) { const f32 r = 4.f*sqrtf((f32)(x*x + y*y))/s; - const f32 z = expf(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y)); + const f32 z = (f32)exp(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y)); return 0.25f+0.25f*z; } @@ -180,7 +180,7 @@ private: public: SMesh* Mesh; - TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f) + TMesh() : Width(0), Height(0), Scale(1.f), Mesh(0) { Mesh = new SMesh(); } diff --git a/examples/25.XmlHandling/main.cpp b/examples/25.XmlHandling/main.cpp index 657ad8dc..d022e5c2 100644 --- a/examples/25.XmlHandling/main.cpp +++ b/examples/25.XmlHandling/main.cpp @@ -142,6 +142,8 @@ public: //we were at the end of the video section so we reset our tag currentSection=L""; break; + default: + break; } } @@ -344,6 +346,8 @@ public: } } break; + default: + break; } } diff --git a/examples/Demo/CDemo.cpp b/examples/Demo/CDemo.cpp index 49dd7b6e..6c073ab3 100644 --- a/examples/Demo/CDemo.cpp +++ b/examples/Demo/CDemo.cpp @@ -497,6 +497,7 @@ void CDemo::loadSceneData() bill = sm->addBillboardSceneNode(0, core::dimension2d(100,100), waypoint[r]+ core::vector3df(0,20,0)); bill->setMaterialFlag(video::EMF_LIGHTING, false); + bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialTexture(0, driver->getTexture(mediaPath + "portal1.bmp")); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->addAnimator(anim); @@ -583,7 +584,7 @@ void CDemo::createLoadingScreen() const io::path mediaPath = getExampleMediaPath(); // irrlicht logo - device->getGUIEnvironment()->addImage(device->getVideoDriver()->getTexture(mediaPath + "irrlichtlogo2.png"), + device->getGUIEnvironment()->addImage(device->getVideoDriver()->getTexture(mediaPath + "irrlichtlogo3.png"), core::position2d(5,5)); // loading text @@ -648,8 +649,8 @@ void CDemo::shoot() else { // doesnt collide with wall - core::vector3df start = camera->getPosition(); - core::vector3df end = (camera->getTarget() - start); + start = camera->getPosition(); + end = (camera->getTarget() - start); end.normalize(); start += end*8.0f; end = start + (end * camera->getFarValue()); diff --git a/examples/Demo/CMainMenu.cpp b/examples/Demo/CMainMenu.cpp index ebc9469e..432c8727 100644 --- a/examples/Demo/CMainMenu.cpp +++ b/examples/Demo/CMainMenu.cpp @@ -27,9 +27,9 @@ CMainMenu::CMainMenu() bool CMainMenu::run() { - video::E_DRIVER_TYPE driverType = EDT_OPENGL; + video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; if (!IrrlichtDevice::isDriverSupported(video::EDT_OPENGL)) - driverType = video::video::EDT_BURNINGSVIDEO; + driverType = video::EDT_BURNINGSVIDEO; MenuDevice = createDevice(driverType, core::dimension2d(512, 384), 16, false, false, false, this); @@ -195,6 +195,7 @@ bool CMainMenu::run() { bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); + bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialTexture(0, driver->getTexture(mediaPath + "particlered.bmp")); } // add fly circle animator to the light @@ -213,6 +214,7 @@ bool CMainMenu::run() { bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); + bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialTexture(0, driver->getTexture(mediaPath + "portal1.bmp")); } // add fly circle animator to the light @@ -275,7 +277,7 @@ bool CMainMenu::run() { if (!selected) { - outDriver=video::E_DRIVER_TYPE(i); + driverType=video::E_DRIVER_TYPE(i); break; } --selected; diff --git a/source/Irrlicht/Android/jni/Android.mk b/source/Irrlicht/Android/jni/Android.mk index 54fb245b..05a2d281 100755 --- a/source/Irrlicht/Android/jni/Android.mk +++ b/source/Irrlicht/Android/jni/Android.mk @@ -31,6 +31,7 @@ LOCAL_SRC_FILES := \ aesGladman/pwd2key.cpp \ aesGladman/sha1.cpp \ aesGladman/sha2.cpp \ + burning_shader_color.cpp \ C3DSMeshFileLoader.cpp \ CAnimatedMeshHalfLife.cpp \ CAnimatedMeshMD2.cpp \ @@ -221,6 +222,7 @@ LOCAL_SRC_FILES := \ CTRGouraudWire.cpp \ CTriangleBBSelector.cpp \ CTriangleSelector.cpp \ + CTRGouraudNoZ2.cpp \ CTRNormalMap.cpp \ CTRStencilShadow.cpp \ CTRTextureBlend.cpp \ @@ -244,6 +246,7 @@ LOCAL_SRC_FILES := \ CTRTextureLightMap2_M4.cpp \ CTRTextureLightMapGouraud2_M4.cpp \ CTRTextureWire2.cpp \ + CTR_transparent_reflection_2_layer.cpp \ CVideoModeList.cpp \ CVolumeLightSceneNode.cpp \ CWADReader.cpp \ diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/source/Irrlicht/CAnimatedMeshSceneNode.cpp index 593496a4..de96749b 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -112,12 +112,12 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) if (FramesPerSecond > 0.f) //forwards... { if (CurrentFrameNr > EndFrame) - CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame)); + CurrentFrameNr = StartFrame + fmodf(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame)); } else //backwards... { if (CurrentFrameNr < StartFrame) - CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame)); + CurrentFrameNr = EndFrame - fmodf(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame)); } } else diff --git a/source/Irrlicht/CBlit.h b/source/Irrlicht/CBlit.h index d67a76b0..b7788289 100644 --- a/source/Irrlicht/CBlit.h +++ b/source/Irrlicht/CBlit.h @@ -10,6 +10,28 @@ namespace irr { +//! f18 - fixpoint 14.18 limit to 16k Textures +#define CBLIT_USE_FIXPOINT18 + +#if defined(CBLIT_USE_FIXPOINT18) + typedef int f18; + #define f18_one 262144 + #define f18_zero 0 + #define f32_to_f18(x)((f18)floorf(((x) * 262144.f) + 0.f)) + #define f32_to_f32(x)(x) + #define f18_floor(x) ((x)>>18) + #define f18_round(x) ((x+131.072)>>18) +#else + typedef float f18; + #define f18_one 1.f + #define f18_zero_dot_five 0.5f + #define f18_zero 0.f + #define f32_to_f18(x)(x) + #define f32_to_f32(x)(x) + #define f18_floor(x) ((int)(x)) + #define f18_round(x) ((int)(x+0.5f)) +#endif + struct SBlitJob { AbsRectangle Dest; @@ -17,23 +39,21 @@ namespace irr u32 argb; - void * src; - void * dst; + const void* src; + void* dst; - s32 width; - s32 height; + u32 width; //draw size + u32 height; - u32 srcPitch; - u32 dstPitch; - - u32 srcPixelMul; + u32 srcPixelMul; //pixel byte size u32 dstPixelMul; - bool stretch; - float x_stretch; - float y_stretch; + int srcPitch; //scanline byte size. allow negative for mirror + u32 dstPitch; - SBlitJob() : stretch(false) {} + bool stretch; + f32 x_stretch; + f32 y_stretch; }; // Bitfields Cohen Sutherland @@ -237,7 +257,7 @@ static void RenderLine32_Decal(video::IImage *t, } u32 *dst; - dst = (u32*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); + dst = (u32*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X * 4 ) ); if ( dy > dx ) { @@ -301,7 +321,7 @@ static void RenderLine32_Blend(video::IImage *t, } u32 *dst; - dst = (u32*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); + dst = (u32*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X * 4 ) ); if ( dy > dx ) { @@ -365,7 +385,7 @@ static void RenderLine16_Decal(video::IImage *t, } u16 *dst; - dst = (u16*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); + dst = (u16*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X * 2 ) ); if ( dy > dx ) { @@ -429,7 +449,7 @@ static void RenderLine16_Blend(video::IImage *t, } u16 *dst; - dst = (u16*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); + dst = (u16*) ( (u8*) t->getData() + ( p0.Y * t->getPitch() ) + ( p0.X * 2 ) ); if ( dy > dx ) { @@ -467,37 +487,57 @@ static void RenderLine16_Blend(video::IImage *t, */ static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job ) { - const u32 w = job->width; - const u32 h = job->height; if (job->stretch) { - const u32 *src = static_cast(job->src); - u32 *dst = static_cast(job->dst); - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const f18 wscale = f32_to_f18(job->x_stretch); + const f18 hscale = f32_to_f18(job->y_stretch); - for ( u32 dy = 0; dy < h; ++dy ) + f18 src_y = f18_zero; + + if (job->srcPixelMul == 4) { - const u32 src_y = (u32)(dy*hscale); - src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); + const u32 *src = (u32*)(job->src); + u32 *dst = (u32*)(job->dst); - for ( u32 dx = 0; dx < w; ++dx ) + for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale) { - const u32 src_x = (u32)(dx*wscale); - dst[dx] = src[src_x]; + src = (u32*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y)); + + f18 src_x = f18_zero; + for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale) + { + dst[dx] = src[f18_floor(src_x)]; + } + dst = (u32*)((u8*)(dst)+job->dstPitch); + } + } + else if (job->srcPixelMul == 2) + { + const u16 *src = (u16*)(job->src); + u16* dst = (u16*)(job->dst); + + for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale) + { + src = (u16*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y)); + + f18 src_x = f18_zero; + for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale) + { + dst[dx] = src[f18_floor(src_x)]; + } + dst = (u16*)((u8*)(dst)+job->dstPitch); } - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } else { - const u32 widthPitch = job->width * job->dstPixelMul; + const size_t widthPitch = job->width * job->dstPixelMul; const void *src = (void*) job->src; void *dst = (void*) job->dst; - for ( u32 dy = 0; dy != h; ++dy ) + for ( u32 dy = 0; dy < job->height; ++dy ) { - memcpy( dst, src, widthPitch ); + memcpy( dst, src, widthPitch); src = (void*) ( (u8*) (src) + job->srcPitch ); dst = (void*) ( (u8*) (dst) + job->dstPitch ); @@ -516,8 +556,8 @@ static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job ) if (job->stretch) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -562,8 +602,8 @@ static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job ) if (job->stretch) { - const float wscale = 3.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch * 3.f; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -607,8 +647,8 @@ static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) if (job->stretch) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -647,8 +687,8 @@ static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job ) if (job->stretch) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -697,8 +737,8 @@ static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) if (job->stretch) { - const float wscale = 3.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch * 3.f; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -715,11 +755,11 @@ static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) } else { - for ( s32 dy = 0; dy != job->height; ++dy ) + for ( u32 dy = 0; dy < job->height; ++dy ) { const u8* s = src; - for ( s32 dx = 0; dx != job->width; ++dx ) + for ( u32 dx = 0; dx < job->width; ++dx ) { dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; s += 3; @@ -740,8 +780,8 @@ static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job ) if (job->stretch) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -781,54 +821,21 @@ static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job ) */ static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) { - const u32 w = job->width; - const u32 h = job->height; - const u32 rdx = w>>1; + const f18 wscale = f32_to_f18(job->x_stretch); + const f18 hscale = f32_to_f18(job->y_stretch); - const u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; + f18 src_y = f18_zero; + u16 *dst = (u16*)job->dst; - if (job->stretch) + for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; - const u32 off = core::if_c_a_else_b(w&1, (u32)((w-1)*wscale), 0); - for ( u32 dy = 0; dy < h; ++dy ) + const u16* src = (u16*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y)); + f18 src_x = f18_zero; + for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale) { - const u32 src_y = (u32)(dy*hscale); - src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); - - for ( u32 dx = 0; dx < rdx; ++dx ) - { - const u32 src_x = (u32)(dx*wscale); - dst[dx] = PixelBlend16_simd( dst[dx], src[src_x] ); - } - if ( off ) - { - ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); - } - - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } - } - else - { - const u32 off = core::if_c_a_else_b(w&1, w-1, 0); - for (u32 dy = 0; dy != h; ++dy ) - { - for (u32 dx = 0; dx != rdx; ++dx ) - { - dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); - } - - if ( off ) - { - ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); - } - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + dst[dx] = PixelBlend16(dst[dx], src[f18_floor(src_x)]); } + dst = (u16*)((u8*)(dst)+job->dstPitch); } } @@ -836,40 +843,21 @@ static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) */ static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) { - const u32 w = job->width; - const u32 h = job->height; - const u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; + const f18 wscale = f32_to_f18(job->x_stretch); + const f18 hscale = f32_to_f18(job->y_stretch); - if (job->stretch) + f18 src_y = f18_zero; + u32 *dst = (u32*)job->dst; + for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; - for ( u32 dy = 0; dy < h; ++dy ) - { - const u32 src_y = (u32)(dy*hscale); - src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); + const u32* src = (u32*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y)); - for ( u32 dx = 0; dx < w; ++dx ) - { - const u32 src_x = (u32)(dx*wscale); - dst[dx] = PixelBlend32( dst[dx], src[src_x] ); - } - - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } - } - else - { - for ( u32 dy = 0; dy != h; ++dy ) + f18 src_x = f18_zero; + for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale) { - for ( u32 dx = 0; dx != w; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], src[dx] ); - } - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + dst[dx] = PixelBlend32(dst[dx], src[f18_floor(src_x)]); } + dst = (u32*)((u8*)(dst)+job->dstPitch); } } @@ -877,21 +865,26 @@ static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) */ static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) { - u16 *src = (u16*) job->src; - u16 *dst = (u16*) job->dst; + const u16 blend = video::A8R8G8B8toA1R5G5B5(job->argb); - u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb ); - for ( s32 dy = 0; dy != job->height; ++dy ) + const f18 wscale = f32_to_f18(job->x_stretch); + const f18 hscale = f32_to_f18(job->y_stretch); + + f18 src_y = f18_zero; + u16 *dst = (u16*)job->dst; + for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale) { - for ( s32 dx = 0; dx != job->width; ++dx ) + const u16* src = (u16*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y)); + f18 src_x = f18_zero; + for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale) { - if ( 0 == (src[dx] & 0x8000) ) + register u16 c0 = src[f18_floor(src_x)]; + if (0 == (c0 & 0x8000)) continue; - dst[dx] = PixelMul16_2( src[dx], blend ); + dst[dx] = PixelMul16_2(c0, blend); } - src = (u16*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + dst = (u16*)((u8*)(dst)+job->dstPitch); } } @@ -900,17 +893,21 @@ static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) */ static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job ) { - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; + const f18 wscale = f32_to_f18(job->x_stretch); + const f18 hscale = f32_to_f18(job->y_stretch); - for ( s32 dy = 0; dy != job->height; ++dy ) + u32* dst = (u32*)job->dst; + f18 src_y = f18_zero; + for (u32 dy = 0; dy < job->height; ++dy, src_y += hscale) { - for ( s32 dx = 0; dx != job->width; ++dx ) + const u32* src = (u32*)((u8*)(job->src) + job->srcPitch*f18_floor(src_y)); + + f18 src_x = f18_zero; + for (u32 dx = 0; dx < job->width; ++dx, src_x += wscale) { - dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); + dst[dx] = PixelBlend32(dst[dx], PixelMul32_2(src[f18_floor(src_x)], job->argb)); } - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + dst = (u32*)((u8*)(dst)+job->dstPitch); } } @@ -921,7 +918,7 @@ static void executeBlit_Color_16_to_16( const SBlitJob * job ) const u16 c = video::A8R8G8B8toA1R5G5B5(job->argb); u16 *dst = (u16*) job->dst; - for ( s32 dy = 0; dy != job->height; ++dy ) + for ( u32 dy = 0; dy < job->height; ++dy ) { memset16(dst, c, job->srcPitch); dst = (u16*) ( (u8*) (dst) + job->dstPitch ); @@ -934,7 +931,7 @@ static void executeBlit_Color_32_to_32( const SBlitJob * job ) { u32 *dst = (u32*) job->dst; - for ( s32 dy = 0; dy != job->height; ++dy ) + for ( u32 dy = 0; dy < job->height; ++dy ) { memset32( dst, job->argb, job->srcPitch ); dst = (u32*) ( (u8*) (dst) + job->dstPitch ); @@ -952,11 +949,11 @@ static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) return; const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb ); - for ( s32 dy = 0; dy != job->height; ++dy ) + for ( u32 dy = 0; dy != job->height; ++dy ) { - for ( s32 dx = 0; dx != job->width; ++dx ) + for ( u32 dx = 0; dx != job->width; ++dx ) { - dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha ); + dst[dx] = PixelBlend16( dst[dx], src, alpha ); } dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } @@ -966,19 +963,33 @@ static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) */ static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job ) { - u32 *dst = (u32*) job->dst; - const u32 alpha = extractAlpha( job->argb ); - const u32 src = job->argb; + if (0 == alpha) + return; - for ( s32 dy = 0; dy != job->height; ++dy ) + u32 *dst = (u32*)job->dst; + for ( u32 dy = 0; dy < job->height; ++dy ) { - for ( s32 dx = 0; dx != job->width; ++dx ) + for ( u32 dx = 0; dx < job->width; ++dx ) { - dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha ); + dst[dx] = PixelBlend32( dst[dx], job->argb, alpha ); } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } + +} + +/*! + Pixel => + color = sourceAlpha > 0 ? source, else dest + alpha = max(destAlpha, sourceAlpha) +*/ +inline u16 PixelCombine16(const u16 c2, const u16 c1) +{ + if (video::getAlpha(c1) > 0) + return c1; + else + return c2; } /*! @@ -1023,8 +1034,8 @@ static void executeBlit_TextureCombineColor_16_to_24( const SBlitJob * job ) if (job->stretch) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -1068,6 +1079,58 @@ static void executeBlit_TextureCombineColor_16_to_24( const SBlitJob * job ) } } +/*! + Pixel => + color = dest * ( 1 - SourceAlpha ) + source * SourceAlpha, + alpha = destAlpha * ( 1 - SourceAlpha ) + sourceAlpha + + where "1" means "full scale" (255) +*/ +inline u32 PixelCombine32(const u32 c2, const u32 c1) +{ + // alpha test + u32 alpha = c1 & 0xFF000000; + + if (0 == alpha) + return c2; + if (0xFF000000 == alpha) + { + return c1; + } + + alpha >>= 24; + + // add highbit alpha, if ( alpha > 127 ) alpha += 1; + // stretches [0;255] to [0;256] to avoid division by 255. use division 256 == shr 8 + alpha += (alpha >> 7); + + u32 srcRB = c1 & 0x00FF00FF; + u32 srcXG = c1 & 0x0000FF00; + + u32 dstRB = c2 & 0x00FF00FF; + u32 dstXG = c2 & 0x0000FF00; + + + u32 rb = srcRB - dstRB; + u32 xg = srcXG - dstXG; + + rb *= alpha; + xg *= alpha; + rb >>= 8; + xg >>= 8; + + rb += dstRB; + xg += dstXG; + + rb &= 0x00FF00FF; + xg &= 0x0000FF00; + + u32 sa = c1 >> 24; + u32 da = c2 >> 24; + u32 blendAlpha_fix8 = (sa * 256 + da * (256 - alpha)) >> 8; + return blendAlpha_fix8 << 24 | rb | xg; +} + /*! Combine alpha channels (increases alpha / reduces transparency) Destination alpha is treated as full 255 @@ -1081,8 +1144,8 @@ static void executeBlit_TextureCombineColor_32_to_24( const SBlitJob * job ) if (job->stretch) { - const float wscale = 1.f/job->x_stretch; - const float hscale = 1.f/job->y_stretch; + const float wscale = job->x_stretch; + const float hscale = job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { @@ -1130,9 +1193,9 @@ static void executeBlit_TextureCombineColor_32_to_32( const SBlitJob * job ) u32 *src = (u32*) job->src; u32 *dst = (u32*) job->dst; - for ( s32 dy = 0; dy != job->height; ++dy ) + for ( u32 dy = 0; dy != job->height; ++dy ) { - for ( s32 dx = 0; dx != job->width; ++dx ) + for (u32 dx = 0; dx != job->width; ++dx ) { dst[dx] = PixelCombine32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); } @@ -1220,26 +1283,46 @@ static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * // bounce clipping to texture -inline void setClip ( AbsRectangle &out, const core::rect *clip, - const video::IImage * tex, s32 passnative ) +inline void setClip(AbsRectangle &out, const core::rect *clip, + const video::IImage* tex, s32 passnative, const core::dimension2d* tex_org) { - if ( clip && 0 == tex && passnative ) + if (0 == tex) { - out.x0 = clip->UpperLeftCorner.X; - out.x1 = clip->LowerRightCorner.X; - out.y0 = clip->UpperLeftCorner.Y; - out.y1 = clip->LowerRightCorner.Y; + if (clip && passnative) + { + out.x0 = clip->UpperLeftCorner.X; + out.x1 = clip->LowerRightCorner.X; + out.y0 = clip->UpperLeftCorner.Y; + out.y1 = clip->LowerRightCorner.Y; + } + else + { + out.x0 = 0; + out.x1 = 0; + out.y0 = 0; + out.y1 = 0; + } return; } - const s32 w = tex ? tex->getDimension().Width : 0; - const s32 h = tex ? tex->getDimension().Height : 0; - if ( clip ) + const s32 w = tex->getDimension().Width; + const s32 h = tex->getDimension().Height; + + //driver could have changed texture size. + if (clip && tex_org && ((u32)w != tex_org->Width || (u32)h != tex_org->Height)) { - out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w ); - out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w ); - out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h ); - out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h ); + out.x0 = core::s32_clamp((clip->UpperLeftCorner.X*w) / tex_org->Width, 0, w - 1); + out.x1 = core::s32_clamp((clip->LowerRightCorner.X*w) / tex_org->Width, out.x0, w); + out.y0 = core::s32_clamp((clip->UpperLeftCorner.Y*h) / tex_org->Height, 0, h - 1); + out.y1 = core::s32_clamp((clip->LowerRightCorner.Y*h) / tex_org->Height, out.y0, h); + } + else if (clip) + { + //y-1 to prevent starting on illegal memory (not ideal!). + out.x0 = core::s32_clamp(clip->UpperLeftCorner.X, 0, w - 1); + out.x1 = core::s32_clamp(clip->LowerRightCorner.X, passnative ? 0 : out.x0, w); + out.y0 = core::s32_clamp(clip->UpperLeftCorner.Y, 0, h - 1); + out.y1 = core::s32_clamp(clip->LowerRightCorner.Y, passnative ? 0 : out.y0, h); } else { @@ -1275,8 +1358,8 @@ static s32 Blit(eBlitter operation, SBlitJob job; - setClip ( sourceClip, sourceClipping, source, 1 ); - setClip ( destClip, destClipping, dest, 0 ); + setClip ( sourceClip, sourceClipping, source, 1,0 ); + setClip ( destClip, destClipping, dest, 0,0 ); v.x0 = destPos ? destPos->X : 0; v.y0 = destPos ? destPos->Y : 0; @@ -1296,6 +1379,10 @@ static s32 Blit(eBlitter operation, job.argb = argb; + job.stretch = false; + job.x_stretch = 1.f; + job.y_stretch = 1.f; + if ( source ) { job.srcPitch = source->getPitch(); @@ -1317,9 +1404,10 @@ static s32 Blit(eBlitter operation, return 1; } +#if defined(SOFTWARE_DRIVER_2_2D_AS_2D) static s32 StretchBlit(eBlitter operation, - video::IImage* dest, const core::rect *destRect, - const core::rect *srcRect, video::IImage* const source, + video::IImage* dest, const core::rect* destClipping,const core::rect *destRect, + video::IImage* const source,const core::rect *srcRect, const core::dimension2d* source_org, u32 argb) { tExecuteBlit blitter = getBlitter2( operation, dest, source ); @@ -1330,9 +1418,15 @@ static s32 StretchBlit(eBlitter operation, SBlitJob job; + AbsRectangle destClip; + AbsRectangle v; + setClip(destClip, destClipping, dest, 0, 0); + setClip(v, destRect, 0, 1, 0); + if (!intersect(job.Dest, destClip, v)) + return 0; + // Clipping - setClip ( job.Source, srcRect, source, 1 ); - setClip ( job.Dest, destRect, dest, 0 ); + setClip ( job.Source, srcRect, source, 1, source_org); job.width = job.Dest.x1-job.Dest.x0; job.height = job.Dest.y1-job.Dest.y0; @@ -1340,14 +1434,25 @@ static s32 StretchBlit(eBlitter operation, job.argb = argb; // use original dest size, despite any clipping - job.x_stretch = (float)destRect->getWidth() / (float)(job.Source.x1-job.Source.x0); - job.y_stretch = (float)destRect->getHeight() / (float)(job.Source.y1-job.Source.y0); - job.stretch = (job.x_stretch != 1.f) || (job.y_stretch != 1.f); + const int dst_w = v.x1 - v.x0; // destRect->getWidth(); + const int dst_h = v.y1 - v.y0; // destRect->getHeight(); + const int src_w = job.Source.x1 - job.Source.x0; + const int src_h = job.Source.y1 - job.Source.y0; + + job.stretch = dst_w != src_w || dst_h != src_h; + job.x_stretch = dst_w ? (float)src_w / (float)dst_w : 1.f; + job.y_stretch = dst_h ? (float)src_h / (float)dst_h : 1.f; + if ( source ) { job.srcPitch = source->getPitch(); job.srcPixelMul = source->getBytesPerPixel(); + + //dest-clippling. advance source. loosing subpixel precision + job.Source.x0 += (s32)floorf(job.x_stretch * (job.Dest.x0 - v.x0)); + job.Source.y0 += (s32)floorf(job.y_stretch * (job.Dest.y0 - v.y0)); + job.src = (void*) ( (u8*) source->getData() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) ); } else @@ -1364,7 +1469,7 @@ static s32 StretchBlit(eBlitter operation, return 1; } - +#endif // Methods for Software drivers //! draws a rectangle diff --git a/source/Irrlicht/CBurningShader_Raster_Reference.cpp b/source/Irrlicht/CBurningShader_Raster_Reference.cpp index c04db94b..3d9dacc6 100644 --- a/source/Irrlicht/CBurningShader_Raster_Reference.cpp +++ b/source/Irrlicht/CBurningShader_Raster_Reference.cpp @@ -5,7 +5,7 @@ #include "IrrCompileConfig.h" #include "IBurningShader.h" -#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ +#if defined(_IRR_COMPILE_WITH_BURNINGSVIDEO_) && 0 namespace irr @@ -558,7 +558,7 @@ void CBurningShader_Raster_Reference::pShader_EMT_LIGHTMAP_M4 () getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); - pShader.dst[pShader.i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + pShader.dst[pShader.i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); @@ -578,7 +578,7 @@ void CBurningShader_Raster_Reference::pShader_1 () ty0 = tofix ( line.t[0][0].y, inversew ); getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); - pShader.dst[pShader.i] = fix_to_color ( r0, g0, b0 ); + pShader.dst[pShader.i] = fix_to_sample( r0, g0, b0 ); } @@ -690,15 +690,15 @@ REALINLINE void CBurningShader_Raster_Reference::depthWrite () REALINLINE void CBurningShader_Raster_Reference::scanline2() { // apply top-left fill-convention, left - pShader.xStart = core::ceil32_fast( line.x[0] ); - pShader.xEnd = core::ceil32_fast( line.x[1] ) - 1; + pShader.xStart = fill_convention_left( line.x[0] ); + pShader.xEnd = fill_convention_right( line.x[1] ); pShader.dx = pShader.xEnd - pShader.xStart; if ( pShader.dx < 0 ) return; // slopes - const f32 invDeltaX = core::reciprocal ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); const f32 subPixel = ( (f32) pShader.xStart ) - line.x[0]; // store slopes in endpoint, and correct first pixel @@ -707,7 +707,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline2() u32 i; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][1] = (line.c[i][1] - line.c[i][0]) * invDeltaX; @@ -721,6 +721,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline2() line.t[i][0] += line.t[i][1] * subPixel; } + SOFTWARE_DRIVER_2_CLIPCHECK_REF; pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); @@ -734,7 +735,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline2() // advance next pixel line.w[0] += line.w[1]; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][0] += line.c[i][1]; @@ -755,15 +756,15 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () u32 i; // apply top-left fill-convention, left - pShader.xStart = core::ceil32_fast( line.x[0] ); - pShader.xEnd = core::ceil32_fast( line.x[1] ) - 1; + pShader.xStart = fill_convention_left( line.x[0] ); + pShader.xEnd = fill_convention_right( line.x[1] ); pShader.dx = pShader.xEnd - pShader.xStart; if ( pShader.dx < 0 ) return; // slopes - const f32 invDeltaX = core::reciprocal ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); @@ -787,6 +788,9 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () case BD3DCMP_EQUAL: condition = a != pShader.z[pShader.i]; break; + default: + condition = 0; + break; } while ( a < pShader.z[pShader.i] ) { @@ -807,7 +811,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () a = (f32) pShader.i + subPixel; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][1] = (line.c[i][1] - line.c[i][0]) * invDeltaX; @@ -832,7 +836,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () line.w[0] += line.w[1]; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][0] += line.c[i][1]; @@ -847,7 +851,7 @@ REALINLINE void CBurningShader_Raster_Reference::scanline () } -void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CBurningShader_Raster_Reference::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { sScanConvertData scan; u32 i; @@ -859,9 +863,9 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); - scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); - scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); + scan.invDeltaY[0] = reciprocal_zero2( c->Pos.y - a->Pos.y ); + scan.invDeltaY[1] = reciprocal_zero2( b->Pos.y - a->Pos.y ); + scan.invDeltaY[2] = reciprocal_zero2( c->Pos.y - b->Pos.y ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -885,7 +889,7 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] = a->Color[i]; @@ -915,7 +919,7 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][1] = a->Color[i]; @@ -929,8 +933,8 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 } // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); subPixel = ( (f32) yStart ) - a->Pos.y; @@ -941,12 +945,13 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0] * subPixel; scan.c[i][1] += scan.slopeC[i][1] * subPixel; } - +#endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0] * subPixel; @@ -962,7 +967,7 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 line.x[scan.right] = scan.x[1]; line.w[scan.right] = scan.w[1]; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][scan.left] = scan.c[i][0]; @@ -984,12 +989,13 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0]; scan.c[i][1] += scan.slopeC[i][1]; } - +#endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0]; @@ -1010,7 +1016,7 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] = a->Color[i] + scan.slopeC[i][0] * temp[0]; @@ -1029,7 +1035,7 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][1] = b->Color[i]; @@ -1043,8 +1049,8 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 } // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); subPixel = ( (f32) yStart ) - b->Pos.y; @@ -1056,12 +1062,13 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0] * subPixel; scan.c[i][1] += scan.slopeC[i][1] * subPixel; } - +#endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0] * subPixel; @@ -1077,7 +1084,7 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 line.x[scan.right] = scan.x[1]; line.w[scan.right] = scan.w[1]; -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS > 0 for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][scan.left] = scan.c[i][0]; @@ -1099,12 +1106,13 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; - for ( i = 0; i != ShaderParam.TextureUnits; ++i ) +#if BURNING_MATERIAL_MAX_COLORS > 0 + for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0]; scan.c[i][1] += scan.slopeC[i][1]; } - +#endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0]; diff --git a/source/Irrlicht/CDepthBuffer.cpp b/source/Irrlicht/CDepthBuffer.cpp index e9126bda..eed72345 100644 --- a/source/Irrlicht/CDepthBuffer.cpp +++ b/source/Irrlicht/CDepthBuffer.cpp @@ -30,30 +30,32 @@ CDepthBuffer::CDepthBuffer(const core::dimension2d& size) //! destructor CDepthBuffer::~CDepthBuffer() { - delete [] Buffer; + if (Buffer) + { + delete[] Buffer; + Buffer = 0; + } } //! clears the zbuffer -void CDepthBuffer::clear() +void CDepthBuffer::clear(f32 value) { + ieee754 zMaxValue; #ifdef SOFTWARE_DRIVER_2_USE_WBUFFER - f32 zMax = 0.f; + zMaxValue.f = 1.f-value; #else - f32 zMax = 1.f; + zMaxValue.f = value; #endif - u32 zMaxValue; - zMaxValue = IR(zMax); - - memset32 ( Buffer, zMaxValue, TotalSize ); + memset32 ( Buffer, zMaxValue.u, TotalSize ); } -//! sets the new size of the zbuffer +//! sets the new size of the buffer void CDepthBuffer::setSize(const core::dimension2d& size) { if (size == Size) @@ -65,13 +67,13 @@ void CDepthBuffer::setSize(const core::dimension2d& size) Pitch = size.Width * sizeof ( fp24 ); TotalSize = Pitch * size.Height; - Buffer = new u8[TotalSize]; + Buffer = new u8[align_next(TotalSize,16)]; clear (); } -//! returns the size of the zbuffer +//! returns the size of the buffer const core::dimension2d& CDepthBuffer::getSize() const { return Size; @@ -80,11 +82,11 @@ const core::dimension2d& CDepthBuffer::getSize() const // ----------------------------------------------------------------- //! constructor -CStencilBuffer::CStencilBuffer(const core::dimension2d& size) -: Buffer(0), Size(0,0) +CStencilBuffer::CStencilBuffer(const core::dimension2d& size, unsigned bit) +: Buffer(0), Size(0,0),Bit(bit) { #ifdef _DEBUG - setDebugName("CDepthBuffer"); + setDebugName("CStencilBuffer"); #endif setSize(size); @@ -95,20 +97,30 @@ CStencilBuffer::CStencilBuffer(const core::dimension2d& size) //! destructor CStencilBuffer::~CStencilBuffer() { - delete [] Buffer; + if (Buffer) + { + delete[] Buffer; + Buffer = 0; + } } -//! clears the zbuffer -void CStencilBuffer::clear() +//! clears the buffer +void CStencilBuffer::clear(u8 value) { - memset32 ( Buffer, 0, TotalSize ); + u32 set = value; + if (Bit == 8) + { + set |= set << 8; + set |= set << 16; + } + memset32 ( Buffer, set, TotalSize ); } -//! sets the new size of the zbuffer +//! sets the new size of the buffer void CStencilBuffer::setSize(const core::dimension2d& size) { if (size == Size) @@ -118,15 +130,15 @@ void CStencilBuffer::setSize(const core::dimension2d& size) delete [] Buffer; - Pitch = size.Width * sizeof ( u32 ); + Pitch = size.Width * sizeof (tStencilSample); TotalSize = Pitch * size.Height; - Buffer = new u8[TotalSize]; + Buffer = new u8[align_next(TotalSize,16)]; clear (); } -//! returns the size of the zbuffer +//! returns the size of the buffer const core::dimension2d& CStencilBuffer::getSize() const { return Size; @@ -155,11 +167,11 @@ IDepthBuffer* createDepthBuffer(const core::dimension2d& size) } -//! creates a ZBuffer -IStencilBuffer* createStencilBuffer(const core::dimension2d& size) +//! creates a Stencil Buffer +IStencilBuffer* createStencilBuffer(const core::dimension2d& size, u32 bit) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ - return new CStencilBuffer(size); + return new CStencilBuffer(size,bit); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ diff --git a/source/Irrlicht/CDepthBuffer.h b/source/Irrlicht/CDepthBuffer.h index 7964efa6..aa9c33de 100644 --- a/source/Irrlicht/CDepthBuffer.h +++ b/source/Irrlicht/CDepthBuffer.h @@ -23,7 +23,7 @@ namespace video virtual ~CDepthBuffer(); //! clears the zbuffer - virtual void clear() _IRR_OVERRIDE_; + virtual void clear(f32 value=1.f) _IRR_OVERRIDE_; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) _IRR_OVERRIDE_; @@ -55,13 +55,13 @@ namespace video public: //! constructor - CStencilBuffer(const core::dimension2d& size); + CStencilBuffer(const core::dimension2d& size, unsigned bit); //! destructor virtual ~CStencilBuffer(); //! clears the zbuffer - virtual void clear() _IRR_OVERRIDE_; + virtual void clear(u8 value=0) _IRR_OVERRIDE_; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) _IRR_OVERRIDE_; @@ -80,11 +80,11 @@ namespace video private: - u8* Buffer; core::dimension2d Size; u32 TotalSize; u32 Pitch; + u32 Bit; }; } // end namespace video diff --git a/source/Irrlicht/CGUIContextMenu.cpp b/source/Irrlicht/CGUIContextMenu.cpp index c28d30ab..3a6484be 100644 --- a/source/Irrlicht/CGUIContextMenu.cpp +++ b/source/Irrlicht/CGUIContextMenu.cpp @@ -88,6 +88,7 @@ u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, boo s.IsSeparator = (text == 0); s.SubMenu = 0; s.CommandId = commandId; + s.PosY = 0; if (hasSubMenu) { diff --git a/source/Irrlicht/CImage.cpp b/source/Irrlicht/CImage.cpp index c59b0602..ffd23fcb 100644 --- a/source/Irrlicht/CImage.cpp +++ b/source/Irrlicht/CImage.cpp @@ -7,6 +7,7 @@ #include "CColorConverter.h" #include "CBlit.h" #include "os.h" +#include "SoftwareDriver2_helper.h" namespace irr { @@ -25,7 +26,7 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* d { const u32 dataSize = getDataSizeFromFormat(Format, Size.Width, Size.Height); - Data = new u8[dataSize]; + Data = new u8[align_next(dataSize,16)]; memcpy(Data, data, dataSize); DeleteMemory = true; } @@ -35,7 +36,7 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* d //! Constructor of empty image CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size) : IImage(format, size, true) { - Data = new u8[getDataSizeFromFormat(Format, Size.Width, Size.Height)]; + Data = new u8[align_next(getDataSizeFromFormat(Format, Size.Width, Size.Height),16)]; DeleteMemory = true; } @@ -133,9 +134,9 @@ void CImage::copyTo(IImage* target, const core::position2d& pos) return; } - if ( !Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0) + if (!Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0) && target && pos.X == 0 && pos.Y == 0 && - CColorConverter::canConvertFormat(Format, target->getColorFormat()) ) + CColorConverter::canConvertFormat(Format, target->getColorFormat())) { // No fast blitting, but copyToScaling uses other color conversions and might work irr::core::dimension2du dim(target->getDimension()); @@ -166,16 +167,9 @@ void CImage::copyToWithAlpha(IImage* target, const core::position2d& pos, c return; } - if ( combineAlpha ) - { - Blit(BLITTER_TEXTURE_COMBINE_ALPHA, target, clipRect, &pos, this, &sourceRect, color.color); - } - else - { - // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF - Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, - target, clipRect, &pos, this, &sourceRect, color.color); - } + eBlitter op = combineAlpha ? BLITTER_TEXTURE_COMBINE_ALPHA : + color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND : BLITTER_TEXTURE_ALPHA_COLOR_BLEND; + Blit(op,target, clipRect, &pos, this, &sourceRect, color.color); } @@ -386,5 +380,6 @@ inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) cons } + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/CImageLoaderRGB.cpp b/source/Irrlicht/CImageLoaderRGB.cpp index 1f0b141e..dfb4b8b0 100644 --- a/source/Irrlicht/CImageLoaderRGB.cpp +++ b/source/Irrlicht/CImageLoaderRGB.cpp @@ -555,7 +555,7 @@ void CImageLoaderRGB::readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgb // limit the count value to the remaining row size if (oPtr + count*rgb.Header.BPC > buf + rgb.Header.Xsize * rgb.Header.BPC) { - count = ( (buf + rgb.Header.Xsize * rgb.Header.BPC) - oPtr ) / rgb.Header.BPC; + count = (s32)( (buf + rgb.Header.Xsize * rgb.Header.BPC) - oPtr ) / rgb.Header.BPC; } if (count<=0) diff --git a/source/Irrlicht/CMY3DMeshFileLoader.h b/source/Irrlicht/CMY3DMeshFileLoader.h index 0c29802e..c0369d49 100644 --- a/source/Irrlicht/CMY3DMeshFileLoader.h +++ b/source/Irrlicht/CMY3DMeshFileLoader.h @@ -92,7 +92,9 @@ private: { SMyMaterialEntry () : Texture1FileName("null"), Texture2FileName("null"), - Texture1(0), Texture2(0), MaterialType(video::EMT_SOLID) {} + Texture1(0), Texture2(0), MaterialType(video::EMT_SOLID) { + Header.Name[0] = 0; + } SMyMaterialHeader Header; core::stringc Texture1FileName; diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index d4ce82ed..17dcec99 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -182,6 +182,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) smoothingGroup=0; else smoothingGroup=core::strtoul10(smooth); + + (void)smoothingGroup; // disable unused variable warnings } break; diff --git a/source/Irrlicht/COSOperator.cpp b/source/Irrlicht/COSOperator.cpp index 1bdbdc16..6cef827f 100644 --- a/source/Irrlicht/COSOperator.cpp +++ b/source/Irrlicht/COSOperator.cpp @@ -187,7 +187,8 @@ bool COSOperator::getProcessorSpeedMHz(u32* MHz) const if (file) { char buffer[1024]; - fread(buffer, 1, 1024, file); + size_t r = fread(buffer, 1, 1023, file); + buffer[r] = 0; buffer[1023]=0; core::stringc str(buffer); s32 pos = str.find("cpu MHz"); diff --git a/source/Irrlicht/CSoftware2MaterialRenderer.h b/source/Irrlicht/CSoftware2MaterialRenderer.h index 7a88bc2a..9715dc9d 100644 --- a/source/Irrlicht/CSoftware2MaterialRenderer.h +++ b/source/Irrlicht/CSoftware2MaterialRenderer.h @@ -26,6 +26,13 @@ public: { } + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ + { + if (Driver) + Driver->setFallback_Material(material.MaterialType); + } + protected: video::CBurningVideoDriver* Driver; @@ -47,7 +54,6 @@ public: }; - //! Transparent material renderer class CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR : public CSoftware2MaterialRenderer { @@ -75,40 +81,6 @@ public: }; -//! unsupported material renderer -class CBurningShader_REFERENCE : public CSoftware2MaterialRenderer -{ -public: - CBurningShader_REFERENCE ( video::CBurningVideoDriver* driver ) - : CSoftware2MaterialRenderer ( driver ) {} - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ - { - } - - virtual void OnUnsetMaterial() _IRR_OVERRIDE_ - { - } - - virtual bool isTransparent() const _IRR_OVERRIDE_ - { - return false; - } - - virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) _IRR_OVERRIDE_ - { - return true; - }; - - - virtual s32 getRenderCapability() const _IRR_OVERRIDE_ - { - return 1; - } - -}; - } // end namespace video diff --git a/source/Irrlicht/CSoftwareDriver2.cpp b/source/Irrlicht/CSoftwareDriver2.cpp index 8b514c9d..89f0f7b5 100644 --- a/source/Irrlicht/CSoftwareDriver2.cpp +++ b/source/Irrlicht/CSoftwareDriver2.cpp @@ -8,6 +8,7 @@ #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ #include "SoftwareDriver2_helper.h" +#include "CSoftwareTexture.h" #include "CSoftwareTexture2.h" #include "CSoftware2MaterialRenderer.h" #include "S3DVertex.h" @@ -15,7 +16,259 @@ #include "CBlit.h" -#define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.getTexture ( tex ) ) +// Matrix now here + +template +bool mat44_transposed_inverse(irr::core::CMatrix4& out, const irr::core::CMatrix4& M) +{ + const T* burning_restrict m = M.pointer(); + + double d = + (m[0] * m[5] - m[1] * m[4]) * (m[10] * m[15] - m[11] * m[14]) - + (m[0] * m[6] - m[2] * m[4]) * (m[9] * m[15] - m[11] * m[13]) + + (m[0] * m[7] - m[3] * m[4]) * (m[9] * m[14] - m[10] * m[13]) + + (m[1] * m[6] - m[2] * m[5]) * (m[8] * m[15] - m[11] * m[12]) - + (m[1] * m[7] - m[3] * m[5]) * (m[8] * m[14] - m[10] * m[12]) + + (m[2] * m[7] - m[3] * m[6]) * (m[8] * m[13] - m[9] * m[12]); + + if (fabs(d) < DBL_MIN) + { + out.makeIdentity(); + return false; + } + + d = 1.0 / d; + T* burning_restrict o = out.pointer(); + o[0] = (T)(d*(m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]))); + o[4] = (T)(d*(m[9] * (m[2] * m[15] - m[3] * m[14]) + m[10] * (m[3] * m[13] - m[1] * m[15]) + m[11] * (m[1] * m[14] - m[2] * m[13]))); + o[8] = (T)(d*(m[13] * (m[2] * m[7] - m[3] * m[6]) + m[14] * (m[3] * m[5] - m[1] * m[7]) + m[15] * (m[1] * m[6] - m[2] * m[5]))); + o[12] = (T)(d*(m[1] * (m[7] * m[10] - m[6] * m[11]) + m[2] * (m[5] * m[11] - m[7] * m[9]) + m[3] * (m[6] * m[9] - m[5] * m[10]))); + + o[1] = (T)(d*(m[6] * (m[8] * m[15] - m[11] * m[12]) + m[7] * (m[10] * m[12] - m[8] * m[14]) + m[4] * (m[11] * m[14] - m[10] * m[15]))); + o[5] = (T)(d*(m[10] * (m[0] * m[15] - m[3] * m[12]) + m[11] * (m[2] * m[12] - m[0] * m[14]) + m[8] * (m[3] * m[14] - m[2] * m[15]))); + o[9] = (T)(d*(m[14] * (m[0] * m[7] - m[3] * m[4]) + m[15] * (m[2] * m[4] - m[0] * m[6]) + m[12] * (m[3] * m[6] - m[2] * m[7]))); + o[13] = (T)(d*(m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]) + m[0] * (m[6] * m[11] - m[7] * m[10]))); + + o[2] = (T)(d*(m[7] * (m[8] * m[13] - m[9] * m[12]) + m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]))); + o[6] = (T)(d*(m[11] * (m[0] * m[13] - m[1] * m[12]) + m[8] * (m[1] * m[15] - m[3] * m[13]) + m[9] * (m[3] * m[12] - m[0] * m[15]))); + o[10] = (T)(d*(m[15] * (m[0] * m[5] - m[1] * m[4]) + m[12] * (m[1] * m[7] - m[3] * m[5]) + m[13] * (m[3] * m[4] - m[0] * m[7]))); + o[14] = (T)(d*(m[3] * (m[5] * m[8] - m[4] * m[9]) + m[0] * (m[7] * m[9] - m[5] * m[11]) + m[1] * (m[4] * m[11] - m[7] * m[8]))); + + o[3] = (T)(d*(m[4] * (m[10] * m[13] - m[9] * m[14]) + m[5] * (m[8] * m[14] - m[10] * m[12]) + m[6] * (m[9] * m[12] - m[8] * m[13]))); + o[7] = (T)(d*(m[8] * (m[2] * m[13] - m[1] * m[14]) + m[9] * (m[0] * m[14] - m[2] * m[12]) + m[10] * (m[1] * m[12] - m[0] * m[13]))); + o[11] = (T)(d*(m[12] * (m[2] * m[5] - m[1] * m[6]) + m[13] * (m[0] * m[6] - m[2] * m[4]) + m[14] * (m[1] * m[4] - m[0] * m[5]))); + o[15] = (T)(d*(m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]))); + + return true; +} + +#if 0 +// difference to CMatrix4::getInverse . higher precision in determinant. return identity on failure +template +bool mat44_inverse(CMatrix4& out, const CMatrix4& M) +{ + const T* m = M.pointer(); + + double d = + (m[0] * m[5] - m[1] * m[4]) * (m[10] * m[15] - m[11] * m[14]) - + (m[0] * m[6] - m[2] * m[4]) * (m[9] * m[15] - m[11] * m[13]) + + (m[0] * m[7] - m[3] * m[4]) * (m[9] * m[14] - m[10] * m[13]) + + (m[1] * m[6] - m[2] * m[5]) * (m[8] * m[15] - m[11] * m[12]) - + (m[1] * m[7] - m[3] * m[5]) * (m[8] * m[14] - m[10] * m[12]) + + (m[2] * m[7] - m[3] * m[6]) * (m[8] * m[13] - m[9] * m[12]); + + if (fabs(d) < DBL_MIN) + { + out.makeIdentity(); + return false; + } + + d = 1.0 / d; + T* o = out.pointer(); + o[0] = (T)(d*(m[5] * (m[10] * m[15] - m[11] * m[14]) + m[6] * (m[11] * m[13] - m[9] * m[15]) + m[7] * (m[9] * m[14] - m[10] * m[13]))); + o[1] = (T)(d*(m[9] * (m[2] * m[15] - m[3] * m[14]) + m[10] * (m[3] * m[13] - m[1] * m[15]) + m[11] * (m[1] * m[14] - m[2] * m[13]))); + o[2] = (T)(d*(m[13] * (m[2] * m[7] - m[3] * m[6]) + m[14] * (m[3] * m[5] - m[1] * m[7]) + m[15] * (m[1] * m[6] - m[2] * m[5]))); + o[3] = (T)(d*(m[1] * (m[7] * m[10] - m[6] * m[11]) + m[2] * (m[5] * m[11] - m[7] * m[9]) + m[3] * (m[6] * m[9] - m[5] * m[10]))); + + o[4] = (T)(d*(m[6] * (m[8] * m[15] - m[11] * m[12]) + m[7] * (m[10] * m[12] - m[8] * m[14]) + m[4] * (m[11] * m[14] - m[10] * m[15]))); + o[5] = (T)(d*(m[10] * (m[0] * m[15] - m[3] * m[12]) + m[11] * (m[2] * m[12] - m[0] * m[14]) + m[8] * (m[3] * m[14] - m[2] * m[15]))); + o[6] = (T)(d*(m[14] * (m[0] * m[7] - m[3] * m[4]) + m[15] * (m[2] * m[4] - m[0] * m[6]) + m[12] * (m[3] * m[6] - m[2] * m[7]))); + o[7] = (T)(d*(m[2] * (m[7] * m[8] - m[4] * m[11]) + m[3] * (m[4] * m[10] - m[6] * m[8]) + m[0] * (m[6] * m[11] - m[7] * m[10]))); + + o[8] = (T)(d*(m[7] * (m[8] * m[13] - m[9] * m[12]) + m[4] * (m[9] * m[15] - m[11] * m[13]) + m[5] * (m[11] * m[12] - m[8] * m[15]))); + o[9] = (T)(d*(m[11] * (m[0] * m[13] - m[1] * m[12]) + m[8] * (m[1] * m[15] - m[3] * m[13]) + m[9] * (m[3] * m[12] - m[0] * m[15]))); + o[10] = (T)(d*(m[15] * (m[0] * m[5] - m[1] * m[4]) + m[12] * (m[1] * m[7] - m[3] * m[5]) + m[13] * (m[3] * m[4] - m[0] * m[7]))); + o[11] = (T)(d*(m[3] * (m[5] * m[8] - m[4] * m[9]) + m[0] * (m[7] * m[9] - m[5] * m[11]) + m[1] * (m[4] * m[11] - m[7] * m[8]))); + + o[12] = (T)(d*(m[4] * (m[10] * m[13] - m[9] * m[14]) + m[5] * (m[8] * m[14] - m[10] * m[12]) + m[6] * (m[9] * m[12] - m[8] * m[13]))); + o[13] = (T)(d*(m[8] * (m[2] * m[13] - m[1] * m[14]) + m[9] * (m[0] * m[14] - m[2] * m[12]) + m[10] * (m[1] * m[12] - m[0] * m[13]))); + o[14] = (T)(d*(m[12] * (m[2] * m[5] - m[1] * m[6]) + m[13] * (m[0] * m[6] - m[2] * m[4]) + m[14] * (m[1] * m[4] - m[0] * m[5]))); + o[15] = (T)(d*(m[0] * (m[5] * m[10] - m[6] * m[9]) + m[1] * (m[6] * m[8] - m[4] * m[10]) + m[2] * (m[4] * m[9] - m[5] * m[8]))); + + return true; +} +#endif + +// void CMatrix4::transformVec4(T *out, const T * in) const +template +inline void transformVec4Vec4(const irr::core::CMatrix4& m, T* burning_restrict out, const T* burning_restrict in) +{ + const T* burning_restrict M = m.pointer(); + + out[0] = in[0] * M[0] + in[1] * M[4] + in[2] * M[8] + in[3] * M[12]; + out[1] = in[0] * M[1] + in[1] * M[5] + in[2] * M[9] + in[3] * M[13]; + out[2] = in[0] * M[2] + in[1] * M[6] + in[2] * M[10] + in[3] * M[14]; + out[3] = in[0] * M[3] + in[1] * M[7] + in[2] * M[11] + in[3] * M[15]; +} + +#if 0 +// void CMatrix4::transformVect(T *out, const core::vector3df &in) const +template +inline void transformVec3Vec4(const irr::core::CMatrix4& m,T* burning_restrict out, const core::vector3df &in) +{ + const T* burning_restrict M = m.pointer(); + out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; + out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; + out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; + out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15]; +} +#endif + +template +inline void rotateVec3Vec4(const irr::core::CMatrix4& m, T* burning_restrict out, const T* burning_restrict in) +{ + const T* burning_restrict M = m.pointer(); + + out[0] = in[0] * M[0] + in[1] * M[4] + in[2] * M[8]; + out[1] = in[0] * M[1] + in[1] * M[5] + in[2] * M[9]; + out[2] = in[0] * M[2] + in[1] * M[6] + in[2] * M[10]; + out[3] = 0.f; +} + +//based on https://github.com/ekmett/approximate/blob/master/cbits/fast.c powf_fast_precise +static inline float powf_limit(const float a, const float b) +{ + if (a <= 0.0000001f) return 0.f; + else if (a >= 1.f) return 1.f; + + /* calculate approximation with fraction of the exponent */ + int e = (int)b; + union { float f; int x; } u = { a }; + u.x = (int)((b - e) * (u.x - 1065353216) + 1065353216); + + float r = 1.0f; + float ua = a; + while (e) { + if (e & 1) { + r *= ua; + } + if (ua < 0.00000001f) + break; + ua *= ua; + e >>= 1; + } + + r *= u.f; + return r; +} + + +#if defined(Tweak_Burning) + +// run time parameter +struct tweakBurning +{ + tweakBurning() + { + current = 11; + step = 0.0001f; + + ndc_shrink_x = -0.75f; + ndc_scale_x = 0.5f; + ndc_trans_x = -0.5f; + + ndc_shrink_y = -0.75f; + ndc_scale_y = -0.5f; + ndc_trans_y = -0.5f; + + tex_w_add = 0.f; + tex_h_add = 0.f; + tex_cx_add = 0.f; + tex_cy_add = 0.f; + + AreaMinDrawSize = 0.001f; + } + int current; + + union + { + struct { + f32 step; + + f32 ndc_shrink_x; + f32 ndc_scale_x; + f32 ndc_trans_x; + + f32 ndc_shrink_y; + f32 ndc_scale_y; + f32 ndc_trans_y; + + f32 tex_w_add; + f32 tex_cx_add; + f32 tex_h_add; + f32 tex_cy_add; + + f32 AreaMinDrawSize; //! minimal visible covered area for primitive + }; + f32 val[16]; + }; + static const char* const name[16]; + void postEventFromUser(const SEvent& e); +}; + +const char* const tweakBurning::name[] = { "step", + "ndc_shrink_x","ndc_scale_x","ndc_trans_x", + "ndc_shrink_y","ndc_scale_y","ndc_trans_y", + "tex_w_add","tex_cx_add","tex_h_add","tex_cy_add", + "dc_area",0 }; + +void tweakBurning::postEventFromUser(const SEvent& e) +{ + int show = 0; + if (e.EventType == EET_KEY_INPUT_EVENT) + { + switch (e.KeyInput.Key) + { + case KEY_KEY_1: step *= 0.9f; if (step < 0.00001f) step = 0.0001f; show = 2; break; + case KEY_KEY_2: step *= 1.1f; show = 2; break; + + case KEY_KEY_3: if (!e.KeyInput.PressedDown) { current -= 1; if (current < 1) current = 11; show = 1; } break; + case KEY_KEY_4: if (!e.KeyInput.PressedDown) { current += 1; if (current > 11) current = 1; show = 1; } break; + + case KEY_KEY_5: val[current] -= e.KeyInput.Shift ? step * 100.f : step; show = 1; break; + case KEY_KEY_6: val[current] += e.KeyInput.Shift ? step * 100.f : step; show = 1; break; + default: + break; + } + } + if (show) + { + if (step < 0.0001f) step = 0.0001f; + char buf[256]; + if (show == 2) sprintf(buf, "%s %f\n", name[0], val[0]); + else sprintf(buf, "%s %f\n", name[current], val[current]); + os::Printer::print(buf); + } +} + +void CBurningVideoDriver::postEventFromUser(const void* sevent) +{ + if (sevent) Tweak.postEventFromUser(*(const SEvent*)sevent); +} + +tweakBurning Tweak; +#endif //defined(Tweak_Burning) + namespace irr @@ -28,13 +281,17 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& : CNullDriver(io, params.WindowSize), BackBuffer(0), Presenter(presenter), WindowId(0), SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), CurrentShader(0), - DepthBuffer(0), StencilBuffer ( 0 ), - CurrentOut ( 16 * 2, 256 ), Temp ( 16 * 2, 256 ) + DepthBuffer(0), StencilBuffer ( 0 ) { + //enable fpu exception + //unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM); + #ifdef _DEBUG setDebugName("CBurningVideoDriver"); #endif + VertexCache_map_source_format(); + // create backbuffer BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, params.WindowSize); if (BackBuffer) @@ -47,24 +304,25 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& // create stencil buffer if ( params.Stencilbuffer ) - StencilBuffer = video::createStencilBuffer(BackBuffer->getDimension()); + StencilBuffer = video::createStencilBuffer(BackBuffer->getDimension(),8); } - DriverAttributes->setAttribute("MaxTextures", 2); DriverAttributes->setAttribute("MaxIndices", 1<<16); - DriverAttributes->setAttribute("MaxTextureSize", SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE); + DriverAttributes->setAttribute("MaxTextures", BURNING_MATERIAL_MAX_TEXTURES); + DriverAttributes->setAttribute("MaxTextureSize", SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 1<<20); DriverAttributes->setAttribute("MaxLights", 1024 ); //glsl::gl_MaxLights); DriverAttributes->setAttribute("MaxTextureLODBias", 16.f); - DriverAttributes->setAttribute("Version", 49); + DriverAttributes->setAttribute("Version", 50); // create triangle renderers - irr::memset32 ( BurningShader, 0, sizeof ( BurningShader ) ); + memset( BurningShader, 0, sizeof ( BurningShader ) ); //BurningShader[ETR_FLAT] = createTRFlat2(DepthBuffer); //BurningShader[ETR_FLAT_WIRE] = createTRFlatWire2(DepthBuffer); BurningShader[ETR_GOURAUD] = createTriangleRendererGouraud2(this); - BurningShader[ETR_GOURAUD_ALPHA] = createTriangleRendererGouraudAlpha2(this ); - BurningShader[ETR_GOURAUD_ALPHA_NOZ] = createTRGouraudAlphaNoZ2(this ); + BurningShader[ETR_GOURAUD_NOZ] = createTriangleRendererGouraudNoZ2(this); + //BurningShader[ETR_GOURAUD_ALPHA] = createTriangleRendererGouraudAlpha2(this ); + BurningShader[ETR_GOURAUD_ALPHA_NOZ] = createTRGouraudAlphaNoZ2(this ); // 2D //BurningShader[ETR_GOURAUD_WIRE] = createTriangleRendererGouraudWire2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire2(DepthBuffer); @@ -89,13 +347,15 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& BurningShader[ETR_STENCIL_SHADOW] = createTRStencilShadow ( this ); BurningShader[ETR_TEXTURE_BLEND] = createTRTextureBlend( this ); - BurningShader[ETR_REFERENCE] = createTriangleRendererReference ( this ); + BurningShader[ETR_TRANSPARENT_REFLECTION_2_LAYER] = createTriangleRendererTexture_transparent_reflection_2_layer(this); + //BurningShader[ETR_REFERENCE] = createTriangleRendererReference ( this ); + BurningShader[ETR_COLOR] = create_burning_shader_color(this); // add the same renderer for all solid types CSoftware2MaterialRenderer_SOLID* smr = new CSoftware2MaterialRenderer_SOLID( this); CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR* tmr = new CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR( this); - CSoftware2MaterialRenderer_UNSUPPORTED * umr = new CSoftware2MaterialRenderer_UNSUPPORTED ( this ); + //CSoftware2MaterialRenderer_UNSUPPORTED * umr = new CSoftware2MaterialRenderer_UNSUPPORTED ( this ); //!TODO: addMaterialRenderer depends on pushing order.... addMaterialRenderer ( smr ); // EMT_SOLID @@ -108,7 +368,7 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M2, addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M4, addMaterialRenderer ( smr ); // EMT_DETAIL_MAP, - addMaterialRenderer ( umr ); // EMT_SPHERE_MAP, + addMaterialRenderer ( smr ); // EMT_SPHERE_MAP, addMaterialRenderer ( smr ); // EMT_REFLECTION_2_LAYER, addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ADD_COLOR, addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL, @@ -116,7 +376,7 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_VERTEX_ALPHA, addMaterialRenderer ( smr ); // EMT_TRANSPARENT_REFLECTION_2_LAYER, addMaterialRenderer ( smr ); // EMT_NORMAL_MAP_SOLID, - addMaterialRenderer ( umr ); // EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, + addMaterialRenderer ( tmr ); // EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, addMaterialRenderer ( tmr ); // EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, addMaterialRenderer ( smr ); // EMT_PARALLAX_MAP_SOLID, addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, @@ -125,16 +385,17 @@ CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& smr->drop (); tmr->drop (); - umr->drop (); + //umr->drop (); // select render target setRenderTargetImage(BackBuffer); //reset Lightspace - LightSpace.reset (); + EyeSpace.reset(); + EyeSpace.resetFog(); // select the right renderer - setCurrentShader(); + setMaterial(Material.org); } @@ -143,161 +404,45 @@ CBurningVideoDriver::~CBurningVideoDriver() { // delete Backbuffer if (BackBuffer) + { BackBuffer->drop(); + BackBuffer = 0; + } // delete triangle renderers - for (s32 i=0; idrop(); + BurningShader[i] = 0; + } } // delete Additional buffer if (StencilBuffer) + { StencilBuffer->drop(); + StencilBuffer = 0; + } if (DepthBuffer) + { DepthBuffer->drop(); + DepthBuffer = 0; + } if (RenderTargetTexture) + { RenderTargetTexture->drop(); + RenderTargetTexture = 0; + } if (RenderTargetSurface) + { RenderTargetSurface->drop(); -} - - -/*! - selects the right triangle renderer based on the render states. -*/ -void CBurningVideoDriver::setCurrentShader() -{ - ITexture *texture0 = Material.org.getTexture(0); - ITexture *texture1 = Material.org.getTexture(1); - - bool zMaterialTest = Material.org.ZBuffer != ECFN_DISABLED && - Material.org.ZWriteEnable != video::EZW_OFF && - ( AllowZWriteOnTransparent || !Material.org.isTransparent() ); - - EBurningFFShader shader = zMaterialTest ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ; - - TransformationFlag[ ETS_TEXTURE_0] &= ~(ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION); - LightSpace.Flags &= ~VERTEXTRANSFORM; - - switch ( Material.org.MaterialType ) - { - case EMT_ONETEXTURE_BLEND: - shader = ETR_TEXTURE_BLEND; - break; - - case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: - Material.org.MaterialTypeParam = 0.5f; - // fall through - case EMT_TRANSPARENT_ALPHA_CHANNEL: - if ( texture0 && texture0->hasAlpha () ) - { - shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ALPHA : ETR_TEXTURE_GOURAUD_ALPHA_NOZ; - break; - } - else - { - shader = ETR_TEXTURE_GOURAUD_VERTEX_ALPHA; - } - break; - - case EMT_TRANSPARENT_ADD_COLOR: - shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ADD : ETR_TEXTURE_GOURAUD_ADD_NO_Z; - break; - - case EMT_TRANSPARENT_VERTEX_ALPHA: - shader = ETR_TEXTURE_GOURAUD_VERTEX_ALPHA; - break; - - case EMT_LIGHTMAP: - case EMT_LIGHTMAP_LIGHTING: - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; - break; - - case EMT_LIGHTMAP_M2: - case EMT_LIGHTMAP_LIGHTING_M2: - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M2; - break; - - case EMT_LIGHTMAP_LIGHTING_M4: - if ( texture1 ) - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M4; - break; - case EMT_LIGHTMAP_M4: - if ( texture1 ) - shader = ETR_TEXTURE_LIGHTMAP_M4; - break; - - case EMT_LIGHTMAP_ADD: - if ( texture1 ) - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD; - break; - - case EMT_DETAIL_MAP: - if ( texture1 ) - shader = ETR_TEXTURE_GOURAUD_DETAIL_MAP; - break; - - case EMT_SPHERE_MAP: - TransformationFlag[ ETS_TEXTURE_0] |= ETF_TEXGEN_CAMERA_REFLECTION; // ETF_TEXGEN_CAMERA_NORMAL; - LightSpace.Flags |= VERTEXTRANSFORM; - break; - case EMT_REFLECTION_2_LAYER: - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; - TransformationFlag[ ETS_TEXTURE_1] |= ETF_TEXGEN_CAMERA_REFLECTION; - LightSpace.Flags |= VERTEXTRANSFORM; - break; - - case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: - case EMT_NORMAL_MAP_SOLID: - case EMT_PARALLAX_MAP_SOLID: - case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: - shader = ETR_NORMAL_MAP_SOLID; - LightSpace.Flags |= VERTEXTRANSFORM; - break; - - default: - break; - + RenderTargetSurface = 0; } - - if ( !texture0 ) - { - shader = ETR_GOURAUD; - } - - if ( Material.org.Wireframe ) - { - shader = ETR_TEXTURE_GOURAUD_WIRE; - } - - //shader = ETR_REFERENCE; - - // switchToTriangleRenderer - CurrentShader = BurningShader[shader]; - if ( CurrentShader ) - { - CurrentShader->setZCompareFunc ( Material.org.ZBuffer ); - CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); - CurrentShader->setMaterial ( Material ); - - switch ( shader ) - { - case ETR_TEXTURE_GOURAUD_ALPHA: - case ETR_TEXTURE_GOURAUD_ALPHA_NOZ: - case ETR_TEXTURE_BLEND: - CurrentShader->setParam ( 0, Material.org.MaterialTypeParam ); - break; - default: - break; - } - } - } @@ -305,31 +450,63 @@ void CBurningVideoDriver::setCurrentShader() //! queries the features of the driver, returns true if feature is available bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { - if (!FeatureEnabled[feature]) - return false; - + int on = 0; switch (feature) { #ifdef SOFTWARE_DRIVER_2_BILINEAR case EVDF_BILINEAR_FILTER: - return true; + on = 1; + break; #endif #ifdef SOFTWARE_DRIVER_2_MIPMAPPING case EVDF_MIP_MAP: - return true; + on = 1; + break; #endif case EVDF_STENCIL_BUFFER: - return StencilBuffer != 0; + on = StencilBuffer != 0; + break; case EVDF_RENDER_TO_TARGET: case EVDF_MULTITEXTURE: case EVDF_HARDWARE_TL: case EVDF_TEXTURE_NSQUARE: - return true; + case EVDF_TEXTURE_MATRIX: + on = 1; + break; + case EVDF_DEPTH_CLAMP: // shadow + on = 1; + break; + + case EVDF_TEXTURE_NPOT: // for 2D + on = 0; + break; + + case EVDF_ARB_FRAGMENT_PROGRAM_1: + case EVDF_ARB_VERTEX_PROGRAM_1: + on = 1; + break; +#if defined(PATCH_SUPERTUX_8_0_1) + case EVDF_TEXTURE_NPOT: + case EVDF_ARB_GLSL: + on = 1; + break; +#endif + +#if defined(SOFTWARE_DRIVER_2_2D_AS_3D) +#if defined(IRRLICHT_FREE_CANVAS) + case EVDF_VIEWPORT_SCALE_GUI: + on = 1; + break; +#endif +#endif default: - return false; + on = 0; + break; } + + return on && FeatureEnabled[feature]; } @@ -344,52 +521,161 @@ IRenderTarget* CBurningVideoDriver::addRenderTarget() } +//matrix multiplication +void CBurningVideoDriver::transform_calc(E_TRANSFORMATION_STATE_BURNING_VIDEO state) +{ + size_t* flag = TransformationFlag[TransformationStack]; + if (flag[state] & ETF_VALID ) return; + + //check + int ok = 0; + switch ( state ) + { + case ETS_PROJ_MODEL_VIEW: + if ( 0 == (flag[ETS_VIEW_PROJECTION] & ETF_VALID) ) transform_calc (ETS_VIEW_PROJECTION); + ok = flag[ETS_WORLD] & flag[ETS_VIEW] & flag[ETS_PROJECTION] & flag[ETS_VIEW_PROJECTION] & ETF_VALID; + break; + case ETS_VIEW_PROJECTION: + ok = flag[ETS_VIEW] & flag[ETS_PROJECTION] & ETF_VALID; + break; + case ETS_MODEL_VIEW: + ok = flag[ETS_WORLD] & flag[ETS_VIEW] & ETF_VALID; + break; + case ETS_NORMAL: + ok = flag[ETS_MODEL_VIEW] & ETF_VALID; + break; + default: + break; + } + + if ( !ok ) + { + char buf[256]; + sprintf(buf,"transform_calc not valid for %d\n",state); + os::Printer::log(buf, ELL_WARNING); + } + + core::matrix4* matrix = Transformation[TransformationStack]; + + switch ( state ) + { + case ETS_PROJ_MODEL_VIEW: + if (flag[ETS_WORLD] & ETF_IDENTITY ) + { + matrix[state] = matrix[ETS_VIEW_PROJECTION]; + } + else + { + matrix[state].setbyproduct_nocheck(matrix[ETS_VIEW_PROJECTION], matrix[ETS_WORLD]); + } + break; + + case ETS_VIEW_PROJECTION: + matrix[state].setbyproduct_nocheck (matrix[ETS_PROJECTION], matrix[ETS_VIEW]); + break; + case ETS_MODEL_VIEW: + if ( flag[ETS_WORLD] & ETF_IDENTITY ) + { + matrix[state] = matrix[ETS_VIEW]; + } + else + { + matrix[state].setbyproduct_nocheck(matrix[ETS_VIEW], matrix[ETS_WORLD]); + } + break; + case ETS_NORMAL: + mat44_transposed_inverse(matrix[state], matrix[ETS_MODEL_VIEW]); + break; + + default: + break; + } + flag[state] |= ETF_VALID; +} + //! sets transformation void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { - Transformation[state] = mat; - core::setbit_cond ( TransformationFlag[state], mat.isIdentity(), ETF_IDENTITY ); + size_t* flag = TransformationFlag[TransformationStack]; + core::matrix4* matrix = Transformation[TransformationStack]; +#if 0 + int changed = 1; + if (flag[state] & ETF_VALID) + { + changed = memcmp(mat.pointer(), matrix[state].pointer(), sizeof(mat)); + } + if (changed) +#endif + { + matrix[state] = mat; + flag[state] |= ETF_VALID; + } + + //maybe identity (mostly for texturematrix to avoid costly multiplication) +#if defined ( USE_MATRIX_TEST ) + burning_setbit( TransformationFlag[state], mat.getDefinitelyIdentityMatrix(), ETF_IDENTITY ); +#else + burning_setbit(flag[state], + !memcmp(mat.pointer(), core::IdentityMatrix.pointer(),sizeof(mat)),ETF_IDENTITY + ); +#endif + +#if 0 + if ( changed ) +#endif switch ( state ) { - case ETS_VIEW: - Transformation[ETS_VIEW_PROJECTION].setbyproduct_nocheck ( - Transformation[ETS_PROJECTION], - Transformation[ETS_VIEW] - ); - getCameraPosWorldSpace (); + case ETS_PROJECTION: + flag[ETS_PROJ_MODEL_VIEW] &= ~ETF_VALID; + flag[ETS_VIEW_PROJECTION] &= ~ETF_VALID; + break; + case ETS_VIEW: + flag[ETS_PROJ_MODEL_VIEW] &= ~ETF_VALID; + flag[ETS_VIEW_PROJECTION] &= ~ETF_VALID; + flag[ETS_MODEL_VIEW] &= ~ETF_VALID; + flag[ETS_NORMAL] &= ~ETF_VALID; break; - case ETS_WORLD: - if ( TransformationFlag[state] & ETF_IDENTITY ) - { - Transformation[ETS_WORLD_INVERSE] = Transformation[ETS_WORLD]; - TransformationFlag[ETS_WORLD_INVERSE] |= ETF_IDENTITY; - Transformation[ETS_CURRENT] = Transformation[ETS_VIEW_PROJECTION]; - } - else - { - //Transformation[ETS_WORLD].getInversePrimitive ( Transformation[ETS_WORLD_INVERSE] ); - Transformation[ETS_CURRENT].setbyproduct_nocheck ( - Transformation[ETS_VIEW_PROJECTION], - Transformation[ETS_WORLD] - ); - } - TransformationFlag[ETS_CURRENT] = 0; - //getLightPosObjectSpace (); + flag[ETS_PROJ_MODEL_VIEW] &= ~ETF_VALID; + flag[ETS_MODEL_VIEW] &= ~ETF_VALID; + flag[ETS_NORMAL] &= ~ETF_VALID; break; case ETS_TEXTURE_0: case ETS_TEXTURE_1: case ETS_TEXTURE_2: case ETS_TEXTURE_3: - if ( 0 == (TransformationFlag[state] & ETF_IDENTITY ) ) - LightSpace.Flags |= VERTEXTRANSFORM; +#if _IRR_MATERIAL_MAX_TEXTURES_>4 + case ETS_TEXTURE_4: +#endif +#if _IRR_MATERIAL_MAX_TEXTURES_>5 + case ETS_TEXTURE_5: +#endif +#if _IRR_MATERIAL_MAX_TEXTURES_>6 + case ETS_TEXTURE_6: +#endif +#if _IRR_MATERIAL_MAX_TEXTURES_>7 + case ETS_TEXTURE_7: +#endif + if ( 0 == (flag[state] & ETF_IDENTITY ) ) + { + EyeSpace.TL_Flag |= TL_TEXTURE_TRANSFORM; + } + break; default: break; } + } +//! Returns the transformation set by setTransform +const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE state) const +{ + return Transformation[TransformationStack][state]; +} + + bool CBurningVideoDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect* sourceRect) { CNullDriver::beginScene(clearFlag, clearColor, clearDepth, clearStencil, videoData, sourceRect); @@ -398,7 +684,7 @@ bool CBurningVideoDriver::beginScene(u16 clearFlag, SColor clearColor, f32 clear clearBuffers(clearFlag, clearColor, clearDepth, clearStencil); - memset ( TransformationFlag, 0, sizeof ( TransformationFlag ) ); + //memset ( TransformationFlag, 0, sizeof ( TransformationFlag ) ); return true; } @@ -438,13 +724,13 @@ bool CBurningVideoDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag return true; } - //! sets a render target void CBurningVideoDriver::setRenderTargetImage(video::CImage* image) { if (RenderTargetSurface) RenderTargetSurface->drop(); + core::dimension2d current = RenderTargetSize; RenderTargetSurface = image; RenderTargetSize.Width = 0; RenderTargetSize.Height = 0; @@ -455,7 +741,11 @@ void CBurningVideoDriver::setRenderTargetImage(video::CImage* image) RenderTargetSize = RenderTargetSurface->getDimension(); } - setViewPort(core::rect(0,0,RenderTargetSize.Width,RenderTargetSize.Height)); + int not_changed = current == RenderTargetSize; + burning_setbit(TransformationFlag[0][ETS_PROJECTION], not_changed, ETF_VALID); + burning_setbit(TransformationFlag[1][ETS_PROJECTION], not_changed, ETF_VALID); + + setViewPort(core::recti(RenderTargetSize)); if (DepthBuffer) DepthBuffer->setSize(RenderTargetSize); @@ -465,6 +755,67 @@ void CBurningVideoDriver::setRenderTargetImage(video::CImage* image) } +//--------- Transform from NDC to DC, transform TexCoo ---------------------------------------------- + +// controls subtexel and fill convention +#if defined(SOFTWARE_DRIVER_2_SUBTEXEL) +#define SOFTWARE_DRIVER_2_PIXEL_CENTER -0.5f +#else +#define SOFTWARE_DRIVER_2_PIXEL_CENTER -0.5f +#endif + +#if 1 + +// used to scale <-1,-1><1,1> to viewport +void buildNDCToDCMatrix(f32* m, const core::rect& viewport, f32 tx) +{ + m[0] = (viewport.getWidth() + tx) * 0.5f; + m[1] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ((viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X) * 0.5f); + + m[2] = (viewport.getHeight() + tx) * -0.5f; + m[3] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ((viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y) * 0.5f); +} + + +#else +// used to scale <-1,-1><1,1> to viewport +void buildNDCToDCMatrix( core::matrix4& out, const core::rect& viewport) +{ + //guard band to stay in screen bounds.(empirical). get holes left side otherwise or out of screen + //TODO: match openGL or D3D. + //assumption pixel center, top-left rule and rounding error projection deny exact match without additional clipping + //or triangle render scanline doesn't step on correct texel center + //or sampler is not on texel center + + f32* m = out.pointer(); +#if defined(Tweak_Burning) && 0 + m[0] = (viewport.getWidth() + Tweak.ndc_shrink_x ) * Tweak.ndc_scale_x; + m[5] = (viewport.getHeight() + Tweak.ndc_shrink_y ) * Tweak.ndc_scale_y; + m[12] = Tweak.ndc_trans_x + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); + m[13] = Tweak.ndc_trans_y + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); +#endif + + m[0] = (viewport.getWidth() - 0.75f ) * 0.5f; + m[1] = 0.f; + m[2] = 0.f; + m[3] = 0.f; + m[4] = 0.f; + m[5] = (viewport.getHeight() - 0.75f ) * -0.5f; + m[6] = 0.f; + m[7] = 0.f; + m[8] = 0.f; + m[9] = 0.f; + m[10] = 1.f; + m[11] = 0.f; + m[12] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); + m[13] = SOFTWARE_DRIVER_2_PIXEL_CENTER + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); + m[14] = 0.f; + m[15] = 1.f; +} +#endif + + +//--------- Transform from NCD to DC ---------------------------------------------- //! sets a viewport void CBurningVideoDriver::setViewPort(const core::rect& area) @@ -474,19 +825,40 @@ void CBurningVideoDriver::setViewPort(const core::rect& area) core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); ViewPort.clipAgainst(rendert); - Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 ); + buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[0], ViewPort,-0.375f); + buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[1], ViewPort, 0.f); // OverrideMaterial2DEnabled ? -0.375f : 0.f); if (CurrentShader) CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); } +void CBurningVideoDriver::setScissor(int x, int y, int width, int height) +{ + AbsRectangle v0; + v0.x0 = x; + v0.y0 = y; + v0.x1 = x+width; + v0.y1 = y+width; + + const core::dimension2d& rt = getCurrentRenderTargetSize(); + AbsRectangle v1; + v1.x0 = 0; + v1.y0 = 0; + v1.x1 = rt.Width; + v1.y1 = rt.Height; + + intersect(Scissor, v0, v1); +} + /* generic plane clipping in homogenous coordinates special case ndc frustum <-w,w>,<-w,w>,<-w,w> can be rewritten with compares e.q near plane, a.z < -a.w and b.z < -b.w + + cam is (0,0,-1) */ -const sVec4 CBurningVideoDriver::NDCPlane[6] = +const sVec4 CBurningVideoDriver::NDCPlane[6+2] = { sVec4( 0.f, 0.f, -1.f, -1.f ), // near sVec4( 0.f, 0.f, 1.f, -1.f ), // far @@ -497,7 +869,6 @@ const sVec4 CBurningVideoDriver::NDCPlane[6] = }; - /* test a vertex if it's inside the standard frustum @@ -507,24 +878,24 @@ const sVec4 CBurningVideoDriver::NDCPlane[6] = for ( u32 i = 0; i!= 6; ++i ) { dotPlane = v->Pos.dotProduct ( NDCPlane[i] ); - core::setbit_cond( flag, dotPlane <= 0.f, 1 << i ); + burning_setbit32( flag, dotPlane <= 0.f, 1 << i ); } // this is the base for ndc frustum <-w,w>,<-w,w>,<-w,w> - core::setbit_cond( flag, ( v->Pos.z - v->Pos.w ) <= 0.f, 1 ); - core::setbit_cond( flag, (-v->Pos.z - v->Pos.w ) <= 0.f, 2 ); - core::setbit_cond( flag, ( v->Pos.x - v->Pos.w ) <= 0.f, 4 ); - core::setbit_cond( flag, (-v->Pos.x - v->Pos.w ) <= 0.f, 8 ); - core::setbit_cond( flag, ( v->Pos.y - v->Pos.w ) <= 0.f, 16 ); - core::setbit_cond( flag, (-v->Pos.y - v->Pos.w ) <= 0.f, 32 ); + burning_setbit32( flag, ( v->Pos.z - v->Pos.w ) <= 0.f, 1 ); + burning_setbit32( flag, (-v->Pos.z - v->Pos.w ) <= 0.f, 2 ); + burning_setbit32( flag, ( v->Pos.x - v->Pos.w ) <= 0.f, 4 ); + burning_setbit32( flag, (-v->Pos.x - v->Pos.w ) <= 0.f, 8 ); + burning_setbit32( flag, ( v->Pos.y - v->Pos.w ) <= 0.f, 16 ); + burning_setbit32( flag, (-v->Pos.y - v->Pos.w ) <= 0.f, 32 ); */ #ifdef IRRLICHT_FAST_MATH -REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) const +REALINLINE size_t CBurningVideoDriver::clipToFrustumTest ( const s4DVertex* v ) const { - f32 test[6]; - u32 flag; + register size_t flag; + f32 test[8]; const f32 w = - v->Pos.w; // a conditional move is needed....FCOMI ( but we don't have it ) @@ -538,13 +909,22 @@ REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) c test[4] = v->Pos.y + w; test[5] = -v->Pos.y + w; + const u32* a = F32_AS_U32_POINTER(test); + flag = (a[0] ) >> 31; + flag |= (a[1] & 0x80000000) >> 30; + flag |= (a[2] & 0x80000000) >> 29; + flag |= (a[3] & 0x80000000) >> 28; + flag |= (a[4] & 0x80000000) >> 27; + flag |= (a[5] & 0x80000000) >> 26; + +/* flag = (IR ( test[0] ) ) >> 31; flag |= (IR ( test[1] ) & 0x80000000 ) >> 30; flag |= (IR ( test[2] ) & 0x80000000 ) >> 29; flag |= (IR ( test[3] ) & 0x80000000 ) >> 28; flag |= (IR ( test[4] ) & 0x80000000 ) >> 27; flag |= (IR ( test[5] ) & 0x80000000 ) >> 26; - +*/ /* flag = F32_LOWER_EQUAL_0 ( test[0] ); flag |= F32_LOWER_EQUAL_0 ( test[1] ) << 1; @@ -559,33 +939,24 @@ REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) c #else -REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) const +REALINLINE size_t clipToFrustumTest ( const s4DVertex* v ) { - u32 flag = 0; + size_t flag = 0; - flag |= v->Pos.z <= v->Pos.w ? 1 : 0; - flag |= -v->Pos.z <= v->Pos.w ? 2 : 0; + flag |= v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_NEAR : 0; + flag |= -v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_FAR : 0; - flag |= v->Pos.x <= v->Pos.w ? 4 : 0; - flag |= -v->Pos.x <= v->Pos.w ? 8 : 0; + flag |= v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_LEFT : 0; + flag |= -v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_RIGHT : 0; + + flag |= v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_BOTTOM : 0; + flag |= -v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_TOP : 0; - flag |= v->Pos.y <= v->Pos.w ? 16 : 0; - flag |= -v->Pos.y <= v->Pos.w ? 32 : 0; /* - if ( v->Pos.z <= v->Pos.w ) flag |= 1; - if (-v->Pos.z <= v->Pos.w ) flag |= 2; - - if ( v->Pos.x <= v->Pos.w ) flag |= 4; - if (-v->Pos.x <= v->Pos.w ) flag |= 8; - - if ( v->Pos.y <= v->Pos.w ) flag |= 16; - if (-v->Pos.y <= v->Pos.w ) flag |= 32; -*/ -/* - for ( u32 i = 0; i!= 6; ++i ) + for ( u32 i = 0; i <= 6; ++i ) { - core::setbit_cond( flag, v->Pos.dotProduct ( NDCPlane[i] ) <= 0.f, 1 << i ); + if (v->Pos.dot_xyzw(NDCPlane[i]) <= 0.f) flag |= ((size_t)1) << i; } */ return flag; @@ -593,87 +964,136 @@ REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) c #endif // _MSC_VER -u32 CBurningVideoDriver::clipToHyperPlane ( s4DVertex * dest, const s4DVertex * source, u32 inCount, const sVec4 &plane ) + +size_t clipToHyperPlane ( + s4DVertexPair* burning_restrict dest, + const s4DVertexPair* burning_restrict source, + const size_t inCount, + const sVec4& plane +) { - u32 outCount = 0; - s4DVertex * out = dest; + size_t outCount = 0; + s4DVertexPair* out = dest; - const s4DVertex * a; - const s4DVertex * b = source; + const s4DVertex* a; + const s4DVertex* b = source; - f32 bDotPlane; - - bDotPlane = b->Pos.dotProduct ( plane ); + ipoltype bDotPlane; + bDotPlane = b->Pos.dot_xyzw( plane ); +/* for( u32 i = 1; i < inCount + 1; ++i) { - // i really have problem +#if 0 + a = source + (i%inCount)*2; +#else const s32 condition = i - inCount; const s32 index = (( ( condition >> 31 ) & ( i ^ condition ) ) ^ condition ) << 1; - - a = &source[ index ]; + a = source + index; +#endif +*/ + //Sutherland–Hodgman + for(size_t i = 0; i < inCount; ++i) + { + a = source + (i == inCount-1 ? 0 : s4DVertex_ofs(i+1)); // current point inside - if ( a->Pos.dotProduct ( plane ) <= 0.f ) + if (ipol_lower_equal_0(a->Pos.dot_xyzw( plane )) ) { // last point outside - if ( F32_GREATER_0 ( bDotPlane ) ) + if (ipol_greater_0( bDotPlane ) ) { // intersect line segment with plane - out->interpolate ( *b, *a, bDotPlane / (b->Pos - a->Pos).dotProduct ( plane ) ); - out += 2; + out->interpolate(*b, *a, bDotPlane / (b->Pos - a->Pos).dot_xyzw(plane) ); + out += sizeof_s4DVertexPairRel; outCount += 1; } // copy current to out //*out = *a; - irr::memcpy32_small ( out, a, SIZEOF_SVERTEX * 2 ); + memcpy_s4DVertexPair( out, a); b = out; - out += 2; + out += sizeof_s4DVertexPairRel; outCount += 1; } else { // current point outside - - if ( F32_LOWER_EQUAL_0 ( bDotPlane ) ) + if (ipol_lower_equal_0( bDotPlane ) ) { // previous was inside // intersect line segment with plane - out->interpolate ( *b, *a, bDotPlane / (b->Pos - a->Pos).dotProduct ( plane ) ); - out += 2; + out->interpolate(*b, *a, bDotPlane / (b->Pos - a->Pos).dot_xyzw(plane) ); + out += sizeof_s4DVertexPairRel; outCount += 1; } // pointer b = a; } - bDotPlane = b->Pos.dotProduct ( plane ); - + bDotPlane = b->Pos.dot_xyzw( plane ); } return outCount; } -u32 CBurningVideoDriver::clipToFrustum ( s4DVertex *v0, s4DVertex * v1, const u32 vIn ) +/* + Clip on all planes. Clipper.data + clipmask per face +*/ +size_t CBurningVideoDriver::clipToFrustum(const size_t vIn /*, const size_t clipmask_for_face*/ ) { - u32 vOut = vIn; + s4DVertexPair* v0 = Clipper.data; + s4DVertexPair* v1 = Clipper_temp.data; + size_t vOut = vIn; + + //clear all clipping & projected flags + const u32 flag = v0[0].flag & VERTEX4D_FORMAT_MASK; + for (size_t g = 0; g != Clipper.ElementSize; ++g) + { + v0[g].flag = flag; + v1[g].flag = flag; + } + +#if 0 + for (size_t i = 0; i < 6; ++i) + { + v0 = i & 1 ? Clipper_temp.data : Clipper.data; + v1 = i & 1 ? Clipper.data : Clipper_temp.data; + + //clipMask checked outside - always clip all planes +#if 0 + if (0 == (clipMask & ((size_t)1< 0 + dest[g].Tex[0] = source[g].Tex[0]; +#endif +#if BURNING_MATERIAL_MAX_TEXTURES > 1 + dest[g].Tex[1] = source[g].Tex[1]; +#endif +#if BURNING_MATERIAL_MAX_TEXTURES > 2 + dest[g].Tex[2] = source[g].Tex[2]; +#endif +#if BURNING_MATERIAL_MAX_TEXTURES > 3 + dest[g].Tex[3] = source[g].Tex[3]; #endif - #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#endif + +#if BURNING_MATERIAL_MAX_COLORS > 0 #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - dest[g].Color[0] = source[g].Color[0] * iw; + dest[g].Color[0] = source[g].Color[0] * iw; // alpha? #else dest[g].Color[0] = source[g].Color[0]; #endif +#endif - #endif +#if BURNING_MATERIAL_MAX_COLORS > 1 +#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + dest[g].Color[1] = source[g].Color[1] * iw; // alpha? +#else + dest[g].Color[1] = source[g].Color[1]; +#endif +#endif + +#if BURNING_MATERIAL_MAX_COLORS > 2 +#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + dest[g].Color[2] = source[g].Color[2] * iw; // alpha? +#else + dest[g].Color[2] = source[g].Color[2]; +#endif +#endif + +#if BURNING_MATERIAL_MAX_COLORS > 3 +#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + dest[g].Color[3] = source[g].Color[3] * iw; // alpha? +#else + dest[g].Color[3] = source[g].Color[3]; +#endif +#endif + +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 dest[g].LightTangent[0] = source[g].LightTangent[0] * iw; - dest[g].Pos.w = iw; - } -} - - -inline void CBurningVideoDriver::ndc_2_dc_and_project2 ( const s4DVertex **v, const u32 size ) const -{ - u32 g; - - for ( g = 0; g != size; g += 1 ) - { - s4DVertex * a = (s4DVertex*) v[g]; - - if ( (a[1].flag & VERTEX4D_PROJECTED ) == VERTEX4D_PROJECTED ) - continue; - - a[1].flag = a->flag | VERTEX4D_PROJECTED; - - // project homogenous vertex, store 1/w - const f32 w = a->Pos.w; - const f32 iw = core::reciprocal ( w ); - - // to device coordinates - const f32 * p = Transformation [ ETS_CLIPSCALE ].pointer(); - a[1].Pos.x = iw * ( a->Pos.x * p[ 0] + w * p[12] ); - a[1].Pos.y = iw * ( a->Pos.y * p[ 5] + w * p[13] ); - -#ifndef SOFTWARE_DRIVER_2_USE_WBUFFER - a[1].Pos.z = a->Pos.z * iw; #endif - #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - a[1].Color[0] = a->Color[0] * iw; - #else - a[1].Color[0] = a->Color[0]; - #endif - #endif + } +} - a[1].LightTangent[0] = a[0].LightTangent[0] * iw; - a[1].Pos.w = iw; + +/*! + crossproduct in projected 2D, face +*/ +REALINLINE f32 CBurningVideoDriver::screenarea_inside(const s4DVertexPair* burning_restrict const face[] ) const +{ + return ( ((face[1]+1)->Pos.x - (face[0]+1)->Pos.x) * ((face[2]+1)->Pos.y - (face[0]+1)->Pos.y) ) - + ( ((face[2]+1)->Pos.x - (face[0]+1)->Pos.x) * ((face[1]+1)->Pos.y - (face[0]+1)->Pos.y) ); +/* + float signedArea = 0; + for (int k = 1; k < output->count; k++) { + signedArea += (output->vertices[k - 1].values[0] * output->vertices[k - 0].values[1]); + signedArea -= (output->vertices[k - 0].values[0] * output->vertices[k - 1].values[1]); + } +*/ +} + +#if 0 +static inline f32 dot(const sVec2& a,const sVec2& b) { return a.x * b.x + a.y * b.y; } +sVec2 dFdx(const sVec2& v) { return v; } +sVec2 dFdy(const sVec2& v) { return v; } + +f32 MipmapLevel(const sVec2& uv, const sVec2& textureSize) +{ + sVec2 dx = dFdx(uv * textureSize.x); + sVec2 dy = dFdy(uv * textureSize.y); + f32 d = core::max_(dot(dx, dx), dot(dy, dy)); + return log2f(sqrtf(d)); +} +#endif + +#define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.getTexture ( (u32)tex ) ) + +/*! + calculate from unprojected. + attribute need not to follow winding rule from position. + Edge-walking problem + Texture Wrapping problem + Atlas problem +*/ +REALINLINE s32 CBurningVideoDriver::lodFactor_inside(const s4DVertexPair* burning_restrict const face[], + const size_t m, f32 dc_area, f32 lod_bias) const +{ + /* + sVec2 a(v[1]->Tex[tex].x - v[0]->Tex[tex].x,v[1]->Tex[tex].y - v[0]->Tex[tex].y); + sVec2 b(v[2]->Tex[tex].x - v[0]->Tex[tex].x,v[2]->Tex[tex].y - v[0]->Tex[tex].y); + f32 area = a.x * b.y - b.x * a.y; + */ + + + /* + degenerate(A, B, C, minarea) = ((B - A).cross(C - A)).lengthSquared() < (4.0f * minarea * minarea); + check for collapsed or "long thin triangles" + */ + ieee754 signedArea; + + ieee754 t[4]; + t[0].f = face[1]->Tex[m].x - face[0]->Tex[m].x; + t[1].f = face[1]->Tex[m].y - face[0]->Tex[m].y; + + t[2].f = face[2]->Tex[m].x - face[0]->Tex[m].x; + t[3].f = face[2]->Tex[m].y - face[0]->Tex[m].y; + + //crossproduct in projected 2D -> screen area triangle + signedArea.f = t[0].f * t[3].f - t[2].f * t[1].f; + + //signedArea = + // ((face[1]->Tex[m].x - face[0]->Tex[m].x) * (face[2]->Tex[m].y - face[0]->Tex[m].y)) + // - ((face[2]->Tex[m].x - face[0]->Tex[m].x) * (face[1]->Tex[m].y - face[0]->Tex[m].y)); + + //if (signedArea*signedArea <= 0.00000000001f) + if (signedArea.fields.exp == 0 ) + { + ieee754 _max; + _max.u = t[0].abs.frac_exp; + if (t[1].abs.frac_exp > _max.u) _max.u = t[1].abs.frac_exp; + if (t[2].abs.frac_exp > _max.u) _max.u = t[2].abs.frac_exp; + if (t[3].abs.frac_exp > _max.u) _max.u = t[3].abs.frac_exp; + + signedArea.u = _max.fields.exp ? _max.u : ieee754_one; + +/* + //dot,length + ieee754 v[2]; + v[0].f = t[0] * t[2]; + v[1].f = t[1] * t[3]; + + //signedArea.f = t[4] > t[5] ? t[4] : t[5]; + signedArea.u = v[0].fields.frac > v[1].fields.frac ? v[0].u : v[1].u; + if (signedArea.fields.exp == 0) + { + return -1; + } +*/ } + //only guessing: take more detail (lower mipmap) in light+bump textures + //assume transparent add is ~50% transparent -> more detail + const u32* d = MAT_TEXTURE(m)->getMipMap0_Area(); + f32 texelspace = d[0] * d[1] * lod_bias; //(m ? 0.5f : 0.5f); + + ieee754 ratio; + ratio.f = (signedArea.f * texelspace) * dc_area; + ratio.fields.sign = 0; + + //log2(0)==denormal [ use high lod] [ only if dc_area == 0 checked outside ] +#if 0 + if (ratio.fields.exp == 0) + { + int g = 1; + } +#endif + //log2 + return (ratio.fields.exp & 0x80) ? ratio.fields.exp - 127 : 0; /*denormal very high lod*/ + + //return (ratio.f <= 1.f) ? 0 : 1; + //f32 texArea = MAT_TEXTURE(m)->getLODFactor(signedArea); // texelarea_inside(face, m); + //s32 lodFactor = s32_log2_f32(texArea * dc_area); /* avoid denorm */ + + //return MAT_TEXTURE(m)->getLODFactor(signedArea); } /*! - crossproduct in projected 2D -> screen area triangle + texcoo in current mipmap dimension (face, already clipped) + -> want to help fixpoint */ -inline f32 CBurningVideoDriver::screenarea ( const s4DVertex *v ) const +inline void CBurningVideoDriver::select_polygon_mipmap_inside(s4DVertex* burning_restrict face[], const size_t tex, const CSoftwareTexture2_Bound& b) const { - return ( ( v[3].Pos.x - v[1].Pos.x ) * ( v[5].Pos.y - v[1].Pos.y ) ) - - ( ( v[3].Pos.y - v[1].Pos.y ) * ( v[5].Pos.x - v[1].Pos.x ) ); -} - - -/*! -*/ -inline f32 CBurningVideoDriver::texelarea ( const s4DVertex *v, int tex ) const -{ - f32 z; - - z = ( (v[2].Tex[tex].x - v[0].Tex[tex].x ) * (v[4].Tex[tex].y - v[0].Tex[tex].y ) ) - - ( (v[4].Tex[tex].x - v[0].Tex[tex].x ) * (v[2].Tex[tex].y - v[0].Tex[tex].y ) ); - - return MAT_TEXTURE ( tex )->getLODFactor ( z ); -} - -/*! - crossproduct in projected 2D -*/ -inline f32 CBurningVideoDriver::screenarea2 ( const s4DVertex **v ) const -{ - return ( (( v[1] + 1 )->Pos.x - (v[0] + 1 )->Pos.x ) * ( (v[2] + 1 )->Pos.y - (v[0] + 1 )->Pos.y ) ) - - ( (( v[1] + 1 )->Pos.y - (v[0] + 1 )->Pos.y ) * ( (v[2] + 1 )->Pos.x - (v[0] + 1 )->Pos.x ) ); -} - -/*! -*/ -inline f32 CBurningVideoDriver::texelarea2 ( const s4DVertex **v, s32 tex ) const -{ - f32 z; - z = ( (v[1]->Tex[tex].x - v[0]->Tex[tex].x ) * (v[2]->Tex[tex].y - v[0]->Tex[tex].y ) ) - - ( (v[2]->Tex[tex].x - v[0]->Tex[tex].x ) * (v[1]->Tex[tex].y - v[0]->Tex[tex].y ) ); - - return MAT_TEXTURE ( tex )->getLODFactor ( z ); -} - - -/*! -*/ -inline void CBurningVideoDriver::select_polygon_mipmap ( s4DVertex *v, u32 vIn, u32 tex, const core::dimension2du& texSize ) const -{ - f32 f[2]; - - f[0] = (f32) texSize.Width - 0.25f; - f[1] = (f32) texSize.Height - 0.25f; - #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - for ( u32 g = 0; g != vIn; g += 2 ) - { - (v + g + 1 )->Tex[tex].x = (v + g + 0)->Tex[tex].x * ( v + g + 1 )->Pos.w * f[0]; - (v + g + 1 )->Tex[tex].y = (v + g + 0)->Tex[tex].y * ( v + g + 1 )->Pos.w * f[1]; - } +#if defined(Tweak_Burning) + (face[0] + 1)->Tex[tex].x = face[0]->Tex[tex].x * (face[0] + 1)->Pos.w * (b.w + Tweak.tex_w_add) + (b.cx + Tweak.tex_cx_add); + (face[0] + 1)->Tex[tex].y = face[0]->Tex[tex].y * (face[0] + 1)->Pos.w * (b.h + Tweak.tex_h_add) + (b.cy + Tweak.tex_cy_add); + + (face[1] + 1)->Tex[tex].x = face[1]->Tex[tex].x * (face[1] + 1)->Pos.w * (b.w + Tweak.tex_w_add) + (b.cx + Tweak.tex_cx_add); + (face[1] + 1)->Tex[tex].y = face[1]->Tex[tex].y * (face[1] + 1)->Pos.w * (b.h + Tweak.tex_h_add) + (b.cy + Tweak.tex_cy_add); + + (face[2] + 1)->Tex[tex].x = face[2]->Tex[tex].x * (face[2] + 1)->Pos.w * (b.w + Tweak.tex_w_add) + (b.cx + Tweak.tex_cx_add); + (face[2] + 1)->Tex[tex].y = face[2]->Tex[tex].y * (face[2] + 1)->Pos.w * (b.h + Tweak.tex_h_add) + (b.cy + Tweak.tex_cy_add); #else - for ( u32 g = 0; g != vIn; g += 2 ) - { - (v + g + 1 )->Tex[tex].x = (v + g + 0)->Tex[tex].x * f[0]; - (v + g + 1 )->Tex[tex].y = (v + g + 0)->Tex[tex].y * f[1]; - } + (face[0] + 1)->Tex[tex].x = face[0]->Tex[tex].x * (face[0] + 1)->Pos.w * b.w + b.cx; + (face[0] + 1)->Tex[tex].y = face[0]->Tex[tex].y * (face[0] + 1)->Pos.w * b.h + b.cy; + + (face[1] + 1)->Tex[tex].x = face[1]->Tex[tex].x * (face[1] + 1)->Pos.w * b.w + b.cx; + (face[1] + 1)->Tex[tex].y = face[1]->Tex[tex].y * (face[1] + 1)->Pos.w * b.h + b.cy; + + (face[2] + 1)->Tex[tex].x = face[2]->Tex[tex].x * (face[2] + 1)->Pos.w * b.w + b.cx; + (face[2] + 1)->Tex[tex].y = face[2]->Tex[tex].y * (face[2] + 1)->Pos.w * b.h + b.cy; #endif +#else + (face[0] + 1)->Tex[tex].x = face[0]->Tex[tex].x * b.w; + (face[0] + 1)->Tex[tex].y = face[0]->Tex[tex].y * b.h; + + (face[1] + 1)->Tex[tex].x = face[1]->Tex[tex].x * b.w; + (face[1] + 1)->Tex[tex].y = face[1]->Tex[tex].y * b.h; + + (face[2] + 1)->Tex[tex].x = face[2]->Tex[tex].x * b.w; + (face[2] + 1)->Tex[tex].y = face[2]->Tex[tex].y * b.h; +#endif + } -inline void CBurningVideoDriver::select_polygon_mipmap2 ( s4DVertex **v, u32 tex, const core::dimension2du& texSize ) const -{ - f32 f[2]; - - f[0] = (f32) texSize.Width - 0.25f; - f[1] = (f32) texSize.Height - 0.25f; - -#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * ( v[0] + 1 )->Pos.w * f[0]; - (v[0] + 1 )->Tex[tex].y = v[0]->Tex[tex].y * ( v[0] + 1 )->Pos.w * f[1]; - - (v[1] + 1 )->Tex[tex].x = v[1]->Tex[tex].x * ( v[1] + 1 )->Pos.w * f[0]; - (v[1] + 1 )->Tex[tex].y = v[1]->Tex[tex].y * ( v[1] + 1 )->Pos.w * f[1]; - - (v[2] + 1 )->Tex[tex].x = v[2]->Tex[tex].x * ( v[2] + 1 )->Pos.w * f[0]; - (v[2] + 1 )->Tex[tex].y = v[2]->Tex[tex].y * ( v[2] + 1 )->Pos.w * f[1]; - -#else - (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * f[0]; - (v[0] + 1 )->Tex[tex].y = v[0]->Tex[tex].y * f[1]; - - (v[1] + 1 )->Tex[tex].x = v[1]->Tex[tex].x * f[0]; - (v[1] + 1 )->Tex[tex].y = v[1]->Tex[tex].y * f[1]; - - (v[2] + 1 )->Tex[tex].x = v[2]->Tex[tex].x * f[0]; - (v[2] + 1 )->Tex[tex].y = v[2]->Tex[tex].y * f[1]; -#endif -} // Vertex Cache -const SVSize CBurningVideoDriver::vSize[] = + +//! setup Vertex Format +void CBurningVideoDriver::VertexCache_map_source_format() { - { VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 1 }, - { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex2TCoords),2 }, - { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_BUMP_DOT3, sizeof(S3DVertexTangents),2 }, - { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 2 }, // reflection map - { 0, sizeof(f32) * 3, 0 }, // core::vector3df* -}; + u32 s0 = sizeof(s4DVertex); + u32 s1 = sizeof(s4DVertex_proxy); + + if ( s1 <= sizeof_s4DVertex /2 ) + { + os::Printer::log ( "BurningVideo vertex format unnecessary to large", ELL_WARNING ); + } + + //memcpy_vertex + if ( s0 != sizeof_s4DVertex || ((sizeof_s4DVertex * sizeof_s4DVertexPairRel)&31)) + { + os::Printer::log ( "BurningVideo vertex format compile problem", ELL_ERROR ); + _IRR_DEBUG_BREAK_IF(1); + } + +#if defined(ENV64BIT) + if (sizeof(void*) != 8) + { + os::Printer::log("BurningVideo pointer should be 8 bytes", ELL_ERROR); + _IRR_DEBUG_BREAK_IF(1); + } +#endif + + SVSize* vSize = VertexCache.vSize; + //vSize[E4VT_STANDARD].Format = VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_LIGHT_1 | VERTEX4D_FORMAT_SPECULAR; + vSize[E4VT_STANDARD].Format = VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_2_FOG; + vSize[E4VT_STANDARD].Pitch = sizeof(S3DVertex); + vSize[E4VT_STANDARD].TexSize = 1; + vSize[E4VT_STANDARD].TexCooSize = 1; + + vSize[E4VT_2TCOORDS].Format = VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1; + vSize[E4VT_2TCOORDS].Pitch = sizeof(S3DVertex2TCoords); + vSize[E4VT_2TCOORDS].TexSize = 2; + vSize[E4VT_2TCOORDS].TexCooSize = 2; + + //vSize[E4VT_TANGENTS].Format = VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_LIGHT_1 | VERTEX4D_FORMAT_BUMP_DOT3; + vSize[E4VT_TANGENTS].Format = VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_2_FOG | VERTEX4D_FORMAT_LIGHT_1 | VERTEX4D_FORMAT_BUMP_DOT3; + vSize[E4VT_TANGENTS].Pitch = sizeof(S3DVertexTangents); + vSize[E4VT_TANGENTS].TexSize = 2; + vSize[E4VT_TANGENTS].TexCooSize = 2; + + // reflection map + vSize[E4VT_REFLECTION_MAP].Format = VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1; + vSize[E4VT_REFLECTION_MAP].Pitch = sizeof(S3DVertex); + vSize[E4VT_REFLECTION_MAP].TexSize = 2; + vSize[E4VT_REFLECTION_MAP].TexCooSize = 1; //TexCoo2 generated + + // shadow + vSize[E4VT_SHADOW].Format = 0; + vSize[E4VT_SHADOW].Pitch = sizeof(f32) * 3; // core::vector3df* + vSize[E4VT_SHADOW].TexSize = 0; + vSize[E4VT_SHADOW].TexCooSize = 0; + + // color shading only (no texture) + vSize[E4VT_NO_TEXTURE].Format = VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_LIGHT_1 | VERTEX4D_FORMAT_SPECULAR; + vSize[E4VT_NO_TEXTURE].Pitch = sizeof(S3DVertex); + vSize[E4VT_NO_TEXTURE].TexSize = 0; + vSize[E4VT_NO_TEXTURE].TexCooSize = 0; + + //Line + vSize[E4VT_LINE].Format = VERTEX4D_FORMAT_COLOR_1; + vSize[E4VT_LINE].Pitch = sizeof(S3DVertex); + vSize[E4VT_LINE].TexSize = 0; + vSize[E4VT_LINE].TexCooSize = 0; + + size_t size; + for ( size_t i = 0; i < E4VT_COUNT; ++i ) + { + size_t& flag = vSize[i].Format; + +#if !defined(SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR) + flag &= ~VERTEX4D_FORMAT_SPECULAR; +#endif + if ( vSize[i].TexSize > BURNING_MATERIAL_MAX_TEXTURES ) + vSize[i].TexSize = BURNING_MATERIAL_MAX_TEXTURES; + + size = (flag & VERTEX4D_FORMAT_MASK_TEXTURE) >> 16; + if ( size > BURNING_MATERIAL_MAX_TEXTURES ) + { + flag = (flag & ~VERTEX4D_FORMAT_MASK_TEXTURE) | (BURNING_MATERIAL_MAX_TEXTURES << 16); + } + + size = (flag & VERTEX4D_FORMAT_MASK_COLOR) >> 20; + if ( size > BURNING_MATERIAL_MAX_COLORS ) + { + flag = (flag & ~VERTEX4D_FORMAT_MASK_COLOR) | (BURNING_MATERIAL_MAX_COLORS << 20); + } + + size = (flag & VERTEX4D_FORMAT_MASK_LIGHT) >> 24; + if ( size > BURNING_MATERIAL_MAX_LIGHT_TANGENT) + { + flag = (flag & ~VERTEX4D_FORMAT_MASK_LIGHT) | (BURNING_MATERIAL_MAX_LIGHT_TANGENT << 24); + } + } + + VertexCache.mem.resize(VERTEXCACHE_ELEMENT * 2); + VertexCache.vType = E4VT_STANDARD; + + Clipper.resize(VERTEXCACHE_ELEMENT * 2); + Clipper_temp.resize(VERTEXCACHE_ELEMENT * 2); + + TransformationStack = 0; + memset(TransformationFlag, 0, sizeof(TransformationFlag)); + memset(Transformation_ETS_CLIPSCALE, 0, sizeof(Transformation_ETS_CLIPSCALE)); + + Material.resetRenderStates = true; + Material.Fallback_MaterialType = EMT_SOLID; + + +} /*! - fill a cache line with transformed, light and clipp test triangles + fill a cache line with transformed, light and clip test triangles + overhead - if primitive is outside or culled, vertexLighting and TextureTransform is still done */ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 destIndex) { - u8 * source; - s4DVertex *dest; + u8* burning_restrict source; + s4DVertex* burning_restrict dest; - source = (u8*) VertexCache.vertices + ( sourceIndex * vSize[VertexCache.vType].Pitch ); + source = (u8*) VertexCache.vertices + ( sourceIndex * VertexCache.vSize[VertexCache.vType].Pitch ); // it's a look ahead so we never hit it.. // but give priority... @@ -890,71 +1487,233 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest VertexCache.info[ destIndex ].hit = 0; // destination Vertex - dest = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( destIndex << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); + dest = VertexCache.mem.data + s4DVertex_ofs(destIndex); + + //Irrlicht S3DVertex,S3DVertex2TCoords,S3DVertexTangents + const S3DVertex* base = ((S3DVertex*)source); // transform Model * World * Camera * Projection * NDCSpace matrix - const S3DVertex *base = ((S3DVertex*) source ); - Transformation [ ETS_CURRENT].transformVect ( &dest->Pos.x, base->Pos ); + const core::matrix4* matrix = Transformation[TransformationStack]; + matrix[ETS_PROJ_MODEL_VIEW].transformVect(&dest->Pos.x, base->Pos); - //mhm ;-) maybe no goto - if ( VertexCache.vType == 4 ) goto clipandproject; + //mhm ... maybe no goto + if (VertexCache.vType == E4VT_SHADOW) + { + //core::vector3df i = base->Pos; + //i.Z -= 0.5f; + //matrix[ETS_PROJ_MODEL_VIEW].transformVect(&dest->Pos.x, i); + + //GL_DEPTH_CLAMP,EVDF_DEPTH_CLAMP + //if ( dest->Pos.z < dest->Pos.w) + // dest->Pos.z = dest->Pos.w*0.99f; + + //glPolygonOffset // self shadow wanted or not? + dest->Pos.w *= 1.005f; + + //flag |= v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_NEAR : 0; + //flag |= -v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_FAR : 0; + + goto clipandproject; + } #if defined (SOFTWARE_DRIVER_2_LIGHTING) || defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) - // vertex normal in light space - if ( Material.org.Lighting || (LightSpace.Flags & VERTEXTRANSFORM) ) + // vertex, normal in light(eye) space + if ( Material.org.Lighting || (EyeSpace.TL_Flag & (TL_TEXTURE_TRANSFORM|TL_FOG)) ) { - if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY ) - { - LightSpace.normal.set ( base->Normal.X, base->Normal.Y, base->Normal.Z, 1.f ); - LightSpace.vertex.set ( base->Pos.X, base->Pos.Y, base->Pos.Z, 1.f ); - } - else - { - Transformation[ETS_WORLD].rotateVect ( &LightSpace.normal.x, base->Normal ); + sVec4 vertex4; //eye coordinate position of vertex + matrix[ETS_MODEL_VIEW].transformVect ( &vertex4.x, base->Pos ); - // vertex in light space - if ( LightSpace.Flags & ( POINTLIGHT | FOG | SPECULAR | VERTEXTRANSFORM) ) - Transformation[ETS_WORLD].transformVect ( &LightSpace.vertex.x, base->Pos ); - } + f32 iw = reciprocal_zero(vertex4.w); + EyeSpace.vertex.x = vertex4.x * iw; + EyeSpace.vertex.y = vertex4.y * iw; + EyeSpace.vertex.z = vertex4.z * iw; + EyeSpace.vertex.w = iw; - if ( LightSpace.Flags & NORMALIZE ) - LightSpace.normal.normalize_xyz(); + //EyeSpace.cam_distance = EyeSpace.vertex.length_xyz(); + EyeSpace.cam_dir = EyeSpace.vertex; + EyeSpace.cam_dir.normalize_dir_xyz(); + + matrix[ETS_NORMAL].rotateVect(&EyeSpace.normal.x, base->Normal); + if (EyeSpace.TL_Flag & TL_NORMALIZE_NORMALS) + EyeSpace.normal.normalize_dir_xyz(); } #endif -#if defined ( SOFTWARE_DRIVER_2_USE_VERTEX_COLOR ) - // apply lighting model - #if defined (SOFTWARE_DRIVER_2_LIGHTING) - if ( Material.org.Lighting ) - { - lightVertex ( dest, base->Color.color ); - } - else - { - dest->Color[0].setA8R8G8B8 ( base->Color.color ); - } - #else - dest->Color[0].setA8R8G8B8 ( base->Color.color ); - #endif +#if BURNING_MATERIAL_MAX_COLORS > 1 + dest->Color[1].a = 1.f; + dest->Color[1].r = 0.f; + dest->Color[1].g = 0.f; + dest->Color[1].b = 0.f; #endif +#if BURNING_MATERIAL_MAX_COLORS > 2 + dest->Color[2].a = 1.f; + dest->Color[2].r = 0.f; + dest->Color[2].g = 0.f; + dest->Color[2].b = 0.f; +#endif + +#if BURNING_MATERIAL_MAX_COLORS > 3 + dest->Color[3].a = 1.f; + dest->Color[3].r = 0.f; + dest->Color[3].g = 0.f; + dest->Color[3].b = 0.f; +#endif + +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + dest->LightTangent[0].x = 0.f; + dest->LightTangent[0].y = 0.f; + dest->LightTangent[0].z = 0.f; +#endif + + +#if BURNING_MATERIAL_MAX_COLORS > 0 +// apply lighting model +#if defined (SOFTWARE_DRIVER_2_LIGHTING) + if ( Material.org.Lighting ) + { + lightVertex_eye ( dest, base->Color.color ); + } + else + { + dest->Color[0].setA8R8G8B8 ( base->Color.color ); + } +#else + dest->Color[0].setA8R8G8B8 ( base->Color.color ); +#endif +#endif + + //vertex fog + if (EyeSpace.TL_Flag & TL_FOG ) //Material.org.FogEnable + { + f32 fog_factor = 1.f; + + // GL_FRAGMENT_DEPTH -> abs(EyeSpace.vertex.z) + ieee754 fog_frag_coord; + fog_frag_coord.f = EyeSpace.vertex.z; + fog_frag_coord.fields.sign = 0; + + switch (FogType) + { + case EFT_FOG_LINEAR: + fog_factor = (FogEnd - fog_frag_coord.f) * EyeSpace.fog_scale; + break; + case EFT_FOG_EXP: + fog_factor = (f32)exp(-FogDensity * fog_frag_coord.f); + break; + case EFT_FOG_EXP2: + fog_factor = (f32)exp(-FogDensity * FogDensity * fog_frag_coord.f * fog_frag_coord.f); + break; + } + + sVec4* a = dest->Color + ((VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_COLOR_2_FOG) ? 1 : 0); + a->a = core::clamp(fog_factor, 0.f, 1.f); + } + // Texture Transform -#if !defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) - irr::memcpy32_small ( &dest->Tex[0],&base->TCoords, - vSize[VertexCache.vType].TexSize << 3 // * ( sizeof ( f32 ) * 2 ) - ); -#else +#if defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) - if ( 0 == (LightSpace.Flags & VERTEXTRANSFORM) ) + if ( 0 == (EyeSpace.TL_Flag & TL_TEXTURE_TRANSFORM) ) +#endif // SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM { - irr::memcpy32_small ( &dest->Tex[0],&base->TCoords, - vSize[VertexCache.vType].TexSize << 3 // * ( sizeof ( f32 ) * 2 ) - ); + // Irrlicht TCoords and TCoords2 must be contiguous memory. baseTCoord has no 4 byte aligned start address! + const f32* baseTCoord = &base->TCoords.X; + + switch (VertexCache.vSize[VertexCache.vType].TexCooSize) + { +#if BURNING_MATERIAL_MAX_TEXTURES == 4 + case 0: + dest->Tex[0].x = 0.f; + dest->Tex[0].y = 0.f; + dest->Tex[1].x = 0.f; + dest->Tex[1].y = 0.f; + dest->Tex[2].x = 0.f; + dest->Tex[2].y = 0.f; + dest->Tex[3].x = 0.f; + dest->Tex[3].y = 0.f; + break; + case 1: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + dest->Tex[1].x = 0.f; + dest->Tex[1].y = 0.f; + dest->Tex[2].x = 0.f; + dest->Tex[2].y = 0.f; + dest->Tex[3].x = 0.f; + dest->Tex[3].y = 0.f; + break; + case 2: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + dest->Tex[1].x = baseTCoord[2]; + dest->Tex[1].y = baseTCoord[3]; + dest->Tex[2].x = 0.f; + dest->Tex[2].y = 0.f; + dest->Tex[3].x = 0.f; + dest->Tex[3].y = 0.f; + break; + case 3: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + dest->Tex[1].x = baseTCoord[2]; + dest->Tex[1].y = baseTCoord[3]; + dest->Tex[2].x = baseTCoord[4]; + dest->Tex[2].y = baseTCoord[5]; + dest->Tex[3].x = 0.f; + dest->Tex[3].y = 0.f; + break; + case 4: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + dest->Tex[1].x = baseTCoord[2]; + dest->Tex[1].y = baseTCoord[3]; + dest->Tex[2].x = baseTCoord[4]; + dest->Tex[2].y = baseTCoord[5]; + dest->Tex[3].x = baseTCoord[6]; + dest->Tex[3].y = baseTCoord[7]; + break; +#endif + +#if BURNING_MATERIAL_MAX_TEXTURES == 2 + case 0: + dest->Tex[0].x = 0.f; + dest->Tex[0].y = 0.f; + dest->Tex[1].x = 0.f; + dest->Tex[1].y = 0.f; + break; + + case 1: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + dest->Tex[1].x = 0.f; + dest->Tex[1].y = 0.f; + break; + case 2: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + dest->Tex[1].x = baseTCoord[2]; + dest->Tex[1].y = baseTCoord[3]; + break; +#endif +#if BURNING_MATERIAL_MAX_TEXTURES == 1 + case 0: + dest->Tex[0].x = 0.f; + dest->Tex[0].y = 0.f; + break; + case 1: + dest->Tex[0].x = baseTCoord[0]; + dest->Tex[0].y = baseTCoord[1]; + break; +#endif + default: + break; + } } +#if defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) else { /* @@ -968,222 +1727,195 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest Uw Vw 0 0 */ - u32 t; - sVec4 n; - sVec2 srcT; + const sVec4& u = EyeSpace.cam_dir; // EyeSpace.vertex.normalized + const sVec4& n = EyeSpace.normal; + sVec4 r; - for ( t = 0; t != vSize[VertexCache.vType].TexSize; ++t ) + const size_t* flag = TransformationFlag[TransformationStack]; + for ( u32 t = 0; t != VertexCache.vSize[VertexCache.vType].TexSize; ++t ) { - const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ]; - // texgen - if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & (ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION) ) + if (flag[ETS_TEXTURE_0+t] & ETF_TEXGEN_CAMERA_SPHERE ) { - n.x = LightSpace.campos.x - LightSpace.vertex.x; - n.y = LightSpace.campos.x - LightSpace.vertex.y; - n.z = LightSpace.campos.x - LightSpace.vertex.z; - n.normalize_xyz(); - n.x += LightSpace.normal.x; - n.y += LightSpace.normal.y; - n.z += LightSpace.normal.z; - n.normalize_xyz(); + //reflect(u,N) u - 2.0 * dot(N, u) * N + // cam is (0,0,-1), tex flipped + f32 dot = -2.f * n.dot_xyz(u); + r.x = u.x + dot * n.x; + r.y = u.y + dot * n.y; + r.z = u.z + dot * n.z; - const f32 *view = Transformation[ETS_VIEW].pointer(); + //openGL + f32 m = 2.f * sqrtf(r.x*r.x+r.y*r.y+(r.z+1.f)*(r.z+1.f)); + dest[0].Tex[t].x = r.x / m + 0.5f; + dest[0].Tex[t].y = -r.y / m + 0.5f; - if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & ETF_TEXGEN_CAMERA_REFLECTION ) +/* + //~d3d with spheremap scale + f32 m = 0.25f / (0.00001f + sqrtf(r.x*r.x+r.y*r.y+r.z*r.z)); + dest[0].Tex[t].x = r.x * m + 0.5f; + dest[0].Tex[t].y = -r.y * m + 0.5f; +*/ + } + else if (flag[ETS_TEXTURE_0+t] & ETF_TEXGEN_CAMERA_REFLECTION ) + { + //reflect(u,N) u - 2.0 * dot(N, u) * N + // cam is (0,0,-1), tex flipped + f32 dot = -2.f * n.dot_xyz(u); + r.x = u.x + dot * n.x; + r.y = u.y + dot * n.y; + r.z = u.z + dot * n.z; + + //openGL + dest[0].Tex[t].x = r.x; + dest[0].Tex[t].y = -r.y; +/* + //~d3d with spheremap scale + dest[0].Tex[t].x = r.x; + dest[0].Tex[t].y = r.y; +*/ + } + else if (VertexCache.vSize[VertexCache.vType].TexCooSize > t) + { + const f32* M = matrix[ETS_TEXTURE_0 + t].pointer(); + + // Irrlicht TCoords and TCoords2 must be contiguous memory. baseTCoord has no 4 byte aligned start address! + const f32* baseTCoord = &base->TCoords.X; + + sVec4 srcT; + srcT.x = baseTCoord[(t * 2) + 0]; + srcT.y = baseTCoord[(t * 2) + 1]; + + switch ( Material.org.TextureLayer[t].TextureWrapU ) { - srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[4] + n.z * view[8] )); - srcT.y = 0.5f * ( 1.f + (n.x * view[1] + n.y * view[5] + n.z * view[9] )); + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); + break; + case ETC_MIRROR: + dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; + if (core::fract(dest->Tex[t].x)>0.5f) + dest->Tex[t].x=1.f-dest->Tex[t].x; + break; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); + if (core::fract(dest->Tex[t].x)>0.5f) + dest->Tex[t].x=1.f-dest->Tex[t].x; + break; + case ETC_REPEAT: + default: + dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; + break; } - else + switch ( Material.org.TextureLayer[t].TextureWrapV ) { - srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[1] + n.z * view[2] )); - srcT.y = 0.5f * ( 1.f + (n.x * view[4] + n.y * view[5] + n.z * view[6] )); + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); + break; + case ETC_MIRROR: + dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; + if (core::fract(dest->Tex[t].y)>0.5f) + dest->Tex[t].y=1.f-dest->Tex[t].y; + break; + case ETC_MIRROR_CLAMP: + case ETC_MIRROR_CLAMP_TO_EDGE: + case ETC_MIRROR_CLAMP_TO_BORDER: + dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); + if (core::fract(dest->Tex[t].y)>0.5f) + dest->Tex[t].y=1.f-dest->Tex[t].y; + break; + case ETC_REPEAT: + default: + dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; + break; } } - else - { - irr::memcpy32_small ( &srcT,(&base->TCoords) + t, - sizeof ( f32 ) * 2 ); - } - - switch ( Material.org.TextureLayer[t].TextureWrapU ) - { - case ETC_CLAMP: - case ETC_CLAMP_TO_EDGE: - case ETC_CLAMP_TO_BORDER: - dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); - break; - case ETC_MIRROR: - dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; - if (core::fract(dest->Tex[t].x)>0.5f) - dest->Tex[t].x=1.f-dest->Tex[t].x; - break; - case ETC_MIRROR_CLAMP: - case ETC_MIRROR_CLAMP_TO_EDGE: - case ETC_MIRROR_CLAMP_TO_BORDER: - dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); - if (core::fract(dest->Tex[t].x)>0.5f) - dest->Tex[t].x=1.f-dest->Tex[t].x; - break; - case ETC_REPEAT: - default: - dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; - break; - } - switch ( Material.org.TextureLayer[t].TextureWrapV ) - { - case ETC_CLAMP: - case ETC_CLAMP_TO_EDGE: - case ETC_CLAMP_TO_BORDER: - dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); - break; - case ETC_MIRROR: - dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; - if (core::fract(dest->Tex[t].y)>0.5f) - dest->Tex[t].y=1.f-dest->Tex[t].y; - break; - case ETC_MIRROR_CLAMP: - case ETC_MIRROR_CLAMP_TO_EDGE: - case ETC_MIRROR_CLAMP_TO_BORDER: - dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); - if (core::fract(dest->Tex[t].y)>0.5f) - dest->Tex[t].y=1.f-dest->Tex[t].y; - break; - case ETC_REPEAT: - default: - dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; - break; - } } } -#if 0 - // tangent space light vector, emboss - if ( Lights.size () && ( vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_BUMP_DOT3 ) ) - { - const S3DVertexTangents *tangent = ((S3DVertexTangents*) source ); - const SBurningShaderLight &light = LightSpace.Light[0]; - sVec4 vp; - - vp.x = light.pos.x - LightSpace.vertex.x; - vp.y = light.pos.y - LightSpace.vertex.y; - vp.z = light.pos.z - LightSpace.vertex.z; - - vp.normalize_xyz(); - - LightSpace.tangent.x = vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z; - LightSpace.tangent.y = vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z; - //LightSpace.tangent.z = vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z; - LightSpace.tangent.z = 0.f; - LightSpace.tangent.normalize_xyz(); - - f32 scale = 1.f / 128.f; - if ( Material.org.MaterialTypeParam > 0.f ) - scale = Material.org.MaterialTypeParam; - - // emboss, shift coordinates - dest->Tex[1].x = dest->Tex[0].x + LightSpace.tangent.x * scale; - dest->Tex[1].y = dest->Tex[0].y + LightSpace.tangent.y * scale; - //dest->Tex[1].z = LightSpace.tangent.z * scale; - } -#endif - - if ( LightSpace.Light.size () && ( vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_BUMP_DOT3 ) ) +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + if ((EyeSpace.TL_Flag & TL_LIGHT0_IS_NORMAL_MAP) && + ((VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_MASK_TANGENT) == VERTEX4D_FORMAT_BUMP_DOT3) + ) { const S3DVertexTangents *tangent = ((S3DVertexTangents*) source ); sVec4 vp; - - dest->LightTangent[0].x = 0.f; - dest->LightTangent[0].y = 0.f; - dest->LightTangent[0].z = 0.f; - for ( u32 i = 0; i < 2 && i < LightSpace.Light.size (); ++i ) + sVec4 light_accu; + light_accu.x = 0.f; + light_accu.y = 0.f; + light_accu.z = 0.f; + light_accu.w = 0.f; + for ( u32 i = 0; i < 2 && i < EyeSpace.Light.size (); ++i ) { - const SBurningShaderLight &light = LightSpace.Light[i]; - + const SBurningShaderLight &light = EyeSpace.Light[i]; if ( !light.LightIsOn ) continue; - vp.x = light.pos.x - LightSpace.vertex.x; - vp.y = light.pos.y - LightSpace.vertex.y; - vp.z = light.pos.z - LightSpace.vertex.z; - - /* - vp.x = light.pos_objectspace.x - base->Pos.X; - vp.y = light.pos_objectspace.y - base->Pos.Y; - vp.z = light.pos_objectspace.z - base->Pos.Z; - */ - - vp.normalize_xyz(); - - - // transform by tangent matrix - sVec3 l; - #if 1 - l.x = (vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z ); - l.y = (vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z ); - l.z = (vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z ); - #else - l.x = (vp.x * tangent->Tangent.X + vp.y * tangent->Binormal.X + vp.z * tangent->Normal.X ); - l.y = (vp.x * tangent->Tangent.Y + vp.y * tangent->Binormal.Y + vp.z * tangent->Normal.Y ); - l.z = (vp.x * tangent->Tangent.Z + vp.y * tangent->Binormal.Z + vp.z * tangent->Normal.Z ); - #endif - - - /* - f32 scale = 1.f / 128.f; - scale /= dest->LightTangent[0].b; - - // emboss, shift coordinates - dest->Tex[1].x = dest->Tex[0].x + l.r * scale; - dest->Tex[1].y = dest->Tex[0].y + l.g * scale; - */ - dest->Tex[1].x = dest->Tex[0].x; - dest->Tex[1].y = dest->Tex[0].y; - - // scale bias - dest->LightTangent[0].x += l.x; - dest->LightTangent[0].y += l.y; - dest->LightTangent[0].z += l.z; - } - dest->LightTangent[0].setLength ( 0.5f ); - dest->LightTangent[0].x += 0.5f; - dest->LightTangent[0].y += 0.5f; - dest->LightTangent[0].z += 0.5f; - } - - + // lightcolor with standard model + // but shader is different. treating light and vertex in same space +#if 1 + vp.x = light.pos.x - base->Pos.X; + vp.y = light.pos.y - base->Pos.Y; + vp.z = light.pos.z - base->Pos.Z; +#else + vp.x = light.pos4.x - EyeSpace.vertex.x; + vp.y = light.pos4.y - EyeSpace.vertex.y; + vp.z = light.pos4.z - EyeSpace.vertex.z; #endif -clipandproject: - dest[0].flag = dest[1].flag = vSize[VertexCache.vType].Format; + // transform by tangent matrix + light_accu.x += (vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z ); + light_accu.y += (vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z ); + light_accu.z += (vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z ); + } + //normalize [-1,+1] to [0,1] -> obsolete + light_accu.normalize_pack_xyz(dest->LightTangent[0],1.f, 0.f); + dest->Tex[1].x = dest->Tex[0].x; + dest->Tex[1].y = dest->Tex[0].y; - // test vertex - dest[0].flag |= clipToFrustumTest ( dest); + } + else if (Material.org.Lighting) + { + //dest->LightTangent[0].x = 0.f; + //dest->LightTangent[0].y = 0.f; + //dest->LightTangent[0].z = 0.f; + } +#endif //if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + +#endif // SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + +clipandproject: + + // test vertex visible + dest[0].flag = (u32) (clipToFrustumTest(dest) | VertexCache.vSize[VertexCache.vType].Format); + dest[1].flag = dest[0].flag; // to DC Space, project homogenous vertex if ( (dest[0].flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE ) { - ndc_2_dc_and_project2 ( (const s4DVertex**) &dest, 1 ); + ndc_2_dc_and_project ( dest+1, dest, s4DVertex_ofs(1)); } - //return dest; } -// -REALINLINE s4DVertex * CBurningVideoDriver::VertexCache_getVertex ( const u32 sourceIndex ) +//todo: this should return only index +s4DVertexPair* CBurningVideoDriver::VertexCache_getVertex ( const u32 sourceIndex ) const { - for ( s32 i = 0; i < VERTEXCACHE_ELEMENT; ++i ) + for ( size_t i = 0; i < VERTEXCACHE_ELEMENT; ++i ) { if ( VertexCache.info[ i ].index == sourceIndex ) { - return (s4DVertex *) ( (u8*) VertexCache.mem.data + ( i << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); + return VertexCache.mem.data + s4DVertex_ofs(i); } } - return 0; + return VertexCache.mem.data; //error } @@ -1192,24 +1924,29 @@ REALINLINE s4DVertex * CBurningVideoDriver::VertexCache_getVertex ( const u32 so fill blockwise on the next 16(Cache_Size) unique vertices in indexlist merge the next 16 vertices with the current */ -REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) +void CBurningVideoDriver::VertexCache_get(s4DVertexPair* face[4]) { - SCacheInfo info[VERTEXCACHE_ELEMENT]; - // next primitive must be complete in cache - if ( VertexCache.indicesIndex - VertexCache.indicesRun < 3 && + if ( VertexCache.indicesIndex - VertexCache.indicesRun < VertexCache.primitiveHasVertex && VertexCache.indicesIndex < VertexCache.indexCount ) { + + size_t i; + //memset(info, VERTEXCACHE_MISS, sizeof(info)); + for (i = 0; i != VERTEXCACHE_ELEMENT; ++i) + { + VertexCache.info_temp[i].hit = VERTEXCACHE_MISS; + VertexCache.info_temp[i].index = VERTEXCACHE_MISS; + } + // rewind to start of primitive VertexCache.indicesIndex = VertexCache.indicesRun; - irr::memset32 ( info, VERTEXCACHE_MISS, sizeof ( info ) ); // get the next unique vertices cache line u32 fillIndex = 0; u32 dIndex = 0; - u32 i = 0; u32 sourceIndex = 0; while ( VertexCache.indicesIndex < VertexCache.indexCount && @@ -1218,13 +1955,14 @@ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) { switch ( VertexCache.iType ) { - case 1: + case E4IT_16BIT: sourceIndex = ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ]; break; - case 2: + case E4IT_32BIT: sourceIndex = ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ]; break; - case 4: + default: + case E4IT_NONE: sourceIndex = VertexCache.indicesIndex; break; } @@ -1235,7 +1973,7 @@ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) s32 exist = 0; for ( dIndex = 0; dIndex < fillIndex; ++dIndex ) { - if ( info[ dIndex ].index == sourceIndex ) + if (VertexCache.info_temp[ dIndex ].index == sourceIndex ) { exist = 1; break; @@ -1244,7 +1982,7 @@ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) if ( 0 == exist ) { - info[fillIndex++].index = sourceIndex; + VertexCache.info_temp[fillIndex++].index = sourceIndex; } } @@ -1259,9 +1997,9 @@ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) { for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) { - if ( VertexCache.info[ dIndex ].index == info[i].index ) + if ( VertexCache.info[ dIndex ].index == VertexCache.info_temp[i].index ) { - info[i].hit = dIndex; + VertexCache.info_temp[i].hit = dIndex; VertexCache.info[ dIndex ].hit = 1; break; } @@ -1271,45 +2009,46 @@ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) // fill new for ( i = 0; i!= fillIndex; ++i ) { - if ( info[i].hit != VERTEXCACHE_MISS ) + if (VertexCache.info_temp[i].hit != VERTEXCACHE_MISS ) continue; for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) { if ( 0 == VertexCache.info[dIndex].hit ) { - VertexCache_fill ( info[i].index, dIndex ); + VertexCache_fill (VertexCache.info_temp[i].index, dIndex ); VertexCache.info[dIndex].hit += 1; - info[i].hit = dIndex; + VertexCache.info_temp[i].hit = dIndex; break; } } } } - const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); + //const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); + const u32 i0 = VertexCache.pType != scene::EPT_TRIANGLE_FAN ? VertexCache.indicesRun : 0; switch ( VertexCache.iType ) { - case 1: + case E4IT_16BIT: { - const u16 *p = (const u16 *) VertexCache.indices; + const u16* p = (const u16*) VertexCache.indices; face[0] = VertexCache_getVertex ( p[ i0 ] ); face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); } break; - case 2: + case E4IT_32BIT: { - const u32 *p = (const u32 *) VertexCache.indices; + const u32* p = (const u32*) VertexCache.indices; face[0] = VertexCache_getVertex ( p[ i0 ] ); face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); } break; - case 4: + case E4IT_NONE: face[0] = VertexCache_getVertex ( VertexCache.indicesRun + 0 ); face[1] = VertexCache_getVertex ( VertexCache.indicesRun + 1 ); face[2] = VertexCache_getVertex ( VertexCache.indicesRun + 2 ); @@ -1318,122 +2057,149 @@ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) face[0] = face[1] = face[2] = VertexCache_getVertex(VertexCache.indicesRun + 0); break; } - - VertexCache.indicesRun += VertexCache.primitivePitch; + face[3] = face[0]; // quad unsupported + VertexCache.indicesRun += VertexCache.indicesPitch; } + /*! */ -REALINLINE void CBurningVideoDriver::VertexCache_getbypass ( s4DVertex ** face ) -{ - const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); - - if ( VertexCache.iType == 1 ) - { - const u16 *p = (const u16 *) VertexCache.indices; - VertexCache_fill ( p[ i0 ], 0 ); - VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); - VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); - } - else - { - const u32 *p = (const u32 *) VertexCache.indices; - VertexCache_fill ( p[ i0 ], 0 ); - VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); - VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); - } - - VertexCache.indicesRun += VertexCache.primitivePitch; - - face[0] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 0 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); - face[1] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 1 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); - face[2] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 2 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); - -} - -/*! -*/ -void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount, +int CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount, const void* indices, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { + + // These calls would lead to crashes due to wrong index usage. + // The vertex cache needs to be rewritten for these primitives. + if (0 == CurrentShader || + pType == scene::EPT_POINTS || pType == scene::EPT_LINE_STRIP || + pType == scene::EPT_LINE_LOOP || pType == scene::EPT_LINES || + pType == scene::EPT_POLYGON || + pType == scene::EPT_POINT_SPRITES) + { + return 1; + } + VertexCache.vertices = vertices; VertexCache.vertexCount = vertexCount; + switch (Material.org.MaterialType) // (Material.Fallback_MaterialType) + { + case EMT_REFLECTION_2_LAYER: + case EMT_TRANSPARENT_REFLECTION_2_LAYER: + VertexCache.vType = E4VT_REFLECTION_MAP; + break; + default: + VertexCache.vType = (e4DVertexType)vType; + break; + } + + //check material + SVSize* vSize = VertexCache.vSize; + for (int m = (int)vSize[VertexCache.vType].TexSize-1; m >= 0 ; --m) + { + ITexture* tex = MAT_TEXTURE(m); + if (!tex) + { + vSize[E4VT_NO_TEXTURE] = vSize[VertexCache.vType]; + vSize[E4VT_NO_TEXTURE].TexSize = m; + vSize[E4VT_NO_TEXTURE].TexCooSize = m; + VertexCache.vType = E4VT_NO_TEXTURE; + //flags downconvert? + } + } + VertexCache.indices = indices; VertexCache.indicesIndex = 0; VertexCache.indicesRun = 0; - if ( Material.org.MaterialType == video::EMT_REFLECTION_2_LAYER ) - VertexCache.vType = 3; - else - VertexCache.vType = vType; - VertexCache.pType = pType; - switch ( iType ) { - case EIT_16BIT: VertexCache.iType = 1; break; - case EIT_32BIT: VertexCache.iType = 2; break; + case EIT_16BIT: VertexCache.iType = E4IT_16BIT; break; + case EIT_32BIT: VertexCache.iType = E4IT_32BIT; break; default: - VertexCache.iType = iType; break; + VertexCache.iType = (e4DIndexType)iType; break; } + if (!VertexCache.indices) + VertexCache.iType = E4IT_NONE; + VertexCache.pType = pType; + VertexCache.primitiveHasVertex = 3; + VertexCache.indicesPitch = 1; switch ( VertexCache.pType ) { // most types here will not work as expected, only triangles/triangle_fan // is known to work. case scene::EPT_POINTS: VertexCache.indexCount = primitiveCount; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 1; break; case scene::EPT_LINE_STRIP: VertexCache.indexCount = primitiveCount+1; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 2; break; case scene::EPT_LINE_LOOP: VertexCache.indexCount = primitiveCount+1; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 2; break; case scene::EPT_LINES: VertexCache.indexCount = 2*primitiveCount; - VertexCache.primitivePitch = 2; + VertexCache.indicesPitch = 2; + VertexCache.primitiveHasVertex = 2; break; case scene::EPT_TRIANGLE_STRIP: VertexCache.indexCount = primitiveCount+2; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 3; break; case scene::EPT_TRIANGLES: VertexCache.indexCount = primitiveCount + primitiveCount + primitiveCount; - VertexCache.primitivePitch = 3; + VertexCache.indicesPitch = 3; + VertexCache.primitiveHasVertex = 3; break; case scene::EPT_TRIANGLE_FAN: VertexCache.indexCount = primitiveCount + 2; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 3; break; case scene::EPT_QUAD_STRIP: VertexCache.indexCount = 2*primitiveCount + 2; - VertexCache.primitivePitch = 2; + VertexCache.indicesPitch = 2; + VertexCache.primitiveHasVertex = 4; break; case scene::EPT_QUADS: VertexCache.indexCount = 4*primitiveCount; - VertexCache.primitivePitch = 4; + VertexCache.indicesPitch = 4; + VertexCache.primitiveHasVertex = 4; break; case scene::EPT_POLYGON: VertexCache.indexCount = primitiveCount+1; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = primitiveCount; break; case scene::EPT_POINT_SPRITES: VertexCache.indexCount = primitiveCount; - VertexCache.primitivePitch = 1; + VertexCache.indicesPitch = 1; + VertexCache.primitiveHasVertex = 1; break; } - irr::memset32 ( VertexCache.info, VERTEXCACHE_MISS, sizeof ( VertexCache.info ) ); + //memset( VertexCache.info, VERTEXCACHE_MISS, sizeof ( VertexCache.info ) ); + for (size_t i = 0; i != VERTEXCACHE_ELEMENT; ++i) + { + VertexCache.info[i].hit = VERTEXCACHE_MISS; + VertexCache.info[i].index = VERTEXCACHE_MISS; + } + return 0; } +//! draws a vertex primitive list void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) @@ -1444,134 +2210,138 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); - // These calls would lead to crashes due to wrong index usage. - // The vertex cache needs to be rewritten for these primitives. - if (pType==scene::EPT_POINTS || pType==scene::EPT_LINE_STRIP || - pType==scene::EPT_LINE_LOOP || pType==scene::EPT_LINES || - pType==scene::EPT_POLYGON || - pType==scene::EPT_POINT_SPRITES) + if (VertexCache_reset(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType)) return; - if ( 0 == CurrentShader ) - return; - - VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType, iType ); - - const s4DVertex * face[3]; - - f32 dc_area; - s32 lodLevel; - u32 i; - u32 g; - u32 m; - video::CSoftwareTexture2* tex; - - for ( i = 0; i < (u32) primitiveCount; ++i ) + if ((u32)Material.org.MaterialType < MaterialRenderers.size()) { + MaterialRenderers[Material.org.MaterialType].Renderer->OnRender(this, vType); + } + + //Matrices needed for this primitive + transform_calc(ETS_PROJ_MODEL_VIEW); + if ( Material.org.Lighting || (EyeSpace.TL_Flag & (TL_TEXTURE_TRANSFORM | TL_FOG)) ) + { + transform_calc(ETS_MODEL_VIEW); + transform_calc(ETS_NORMAL); + } + + + s4DVertexPair* face[4]; + + size_t vOut; + size_t vertex_from_clipper; // from VertexCache or CurrentOut + size_t has_vertex_run; + + for ( size_t primitive_run = 0; primitive_run < primitiveCount; ++primitive_run) + { + //collect pointer to face vertices VertexCache_get(face); - // if fully outside or outside on same side - if ( ( (face[0]->flag | face[1]->flag | face[2]->flag) & VERTEX4D_CLIPMASK ) - != VERTEX4D_INSIDE - ) - continue; + register size_t clipMask_i; + register size_t clipMask_o; - // if fully inside - if ( ( face[0]->flag & face[1]->flag & face[2]->flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE ) + clipMask_i = face[0]->flag; + clipMask_o = face[0]->flag; + + for (has_vertex_run = 1; has_vertex_run < VertexCache.primitiveHasVertex; ++has_vertex_run) { - dc_area = screenarea2 ( face ); - if ( Material.org.BackfaceCulling && F32_LOWER_EQUAL_0( dc_area ) ) - continue; - else - if ( Material.org.FrontfaceCulling && F32_GREATER_EQUAL_0( dc_area ) ) - continue; + clipMask_i |= face[has_vertex_run]->flag; // if fully outside or outside on same side + clipMask_o &= face[has_vertex_run]->flag; // if fully inside + } + + clipMask_i &= VERTEX4D_CLIPMASK; + clipMask_o &= VERTEX4D_CLIPMASK; + + if (clipMask_i != VERTEX4D_INSIDE ) + { + // if primitive fully outside or outside on same side + continue; + vOut = 0; + vertex_from_clipper = 0; + } + else if (clipMask_o == VERTEX4D_INSIDE ) + { + // if primitive fully inside + vOut = VertexCache.primitiveHasVertex; + vertex_from_clipper = 0; + } + else +#if defined(SOFTWARE_DRIVER_2_CLIPPING) + { + // else if not complete inside clipping necessary + // check: clipping should reuse vertexcache (try to minimize clipping) + for (has_vertex_run = 0; has_vertex_run < VertexCache.primitiveHasVertex; ++has_vertex_run) + { + memcpy_s4DVertexPair(Clipper.data + s4DVertex_ofs(has_vertex_run), face[has_vertex_run]); + } + + vOut = clipToFrustum(VertexCache.primitiveHasVertex); + vertex_from_clipper = 1; + + // to DC Space, project homogenous vertex + ndc_2_dc_and_project(Clipper.data + s4DVertex_proj(0), Clipper.data, s4DVertex_ofs(vOut)); + } +#else + { + continue; + vOut = 0; + vertex_from_clipper = 0; + } +#endif + // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. ) + for (has_vertex_run = 0; (has_vertex_run + VertexCache.primitiveHasVertex) <= vOut; has_vertex_run += 1) + { + // set from clipped geometry + if (vertex_from_clipper) + { + face[0] = Clipper.data + s4DVertex_ofs(0); + face[1] = Clipper.data + s4DVertex_ofs(has_vertex_run + 1); + face[2] = Clipper.data + s4DVertex_ofs(has_vertex_run + 2); + } + + //area of primitive in device space + f32 dc_area = screenarea_inside(face); + + //geometric clipping has problem with invisible or very small Triangles + //size_t sign = dc_area < 0.001f ? CULL_BACK : dc_area > 0.001f ? CULL_FRONT : CULL_INVISIBLE; + ieee754 t; + t.f = dc_area; + size_t sign = t.fields.sign ? CULL_BACK : CULL_FRONT; + sign |= t.abs.frac_exp < 981668463 /*0.01f*/ ? CULL_INVISIBLE : 0; + if (Material.CullFlag & sign) + break; //continue; + + //select mipmap ratio between drawing space and texture space + dc_area = reciprocal_zero(dc_area); // select mipmap - dc_area = core::reciprocal ( dc_area ); - for ( m = 0; m != vSize[VertexCache.vType].TexSize; ++m ) + for (size_t m = 0; m < VertexCache.vSize[VertexCache.vType].TexSize; ++m) { - if ( 0 == (tex = MAT_TEXTURE ( m )) ) - { - CurrentShader->setTextureParam(m, 0, 0); - continue; - } + video::CSoftwareTexture2* tex = MAT_TEXTURE(m); - lodLevel = s32_log2_f32 ( texelarea2 ( face, m ) * dc_area ); - CurrentShader->setTextureParam(m, tex, lodLevel ); - select_polygon_mipmap2 ( (s4DVertex**) face, m, tex->getSize() ); + //only guessing: take more detail (lower mipmap) in light+bump textures + //assume transparent add is ~50% transparent -> more detail + f32 lod_bias = Material.org.MaterialType == EMT_TRANSPARENT_ADD_COLOR ? 0.1f : 0.33f; + lod_bias *= tex->get_lod_bias(); + s32 lodFactor = lodFactor_inside(face, m, dc_area, lod_bias); + + CurrentShader->setTextureParam(m, tex, lodFactor); + //currently shader receives texture coordinate as Pixelcoo of 1 Texture + select_polygon_mipmap_inside(face, m, tex->getTexBound()); } - // rasterize - CurrentShader->drawTriangle ( face[0] + 1, face[1] + 1, face[2] + 1 ); - continue; - } - - // else if not complete inside clipping necessary - irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 0 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[0], SIZEOF_SVERTEX * 2 ); - irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 1 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[1], SIZEOF_SVERTEX * 2 ); - irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 2 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[2], SIZEOF_SVERTEX * 2 ); - - const u32 flag = CurrentOut.data->flag & VERTEX4D_FORMAT_MASK; - - for ( g = 0; g != CurrentOut.ElementSize; ++g ) - { - CurrentOut.data[g].flag = flag; - Temp.data[g].flag = flag; - } - - u32 vOut; - vOut = clipToFrustum ( CurrentOut.data, Temp.data, 3 ); - if ( vOut < 3 ) - continue; - - vOut <<= 1; - - // to DC Space, project homogenous vertex - ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut ); - - // check 2d backface culling on first - dc_area = screenarea ( CurrentOut.data ); - if ( Material.org.BackfaceCulling && F32_LOWER_EQUAL_0 ( dc_area ) ) - continue; - else if ( Material.org.FrontfaceCulling && F32_GREATER_EQUAL_0( dc_area ) ) - continue; - - // select mipmap - dc_area = core::reciprocal ( dc_area ); - for ( m = 0; m != vSize[VertexCache.vType].TexSize; ++m ) - { - if ( 0 == (tex = MAT_TEXTURE ( m )) ) - { - CurrentShader->setTextureParam(m, 0, 0); - continue; - } - - lodLevel = s32_log2_f32 ( texelarea ( CurrentOut.data, m ) * dc_area ); - CurrentShader->setTextureParam(m, tex, lodLevel ); - select_polygon_mipmap ( CurrentOut.data, vOut, m, tex->getSize() ); - } - - - // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. ) - for ( g = 0; g <= vOut - 6; g += 2 ) - { - // rasterize - CurrentShader->drawTriangle ( CurrentOut.data + 0 + 1, - CurrentOut.data + g + 3, - CurrentOut.data + g + 5); + CurrentShader->drawWireFrameTriangle(face[0] + 1, face[1] + 1, face[2] + 1); + vertex_from_clipper = 1; } } - // dump statistics -/* - char buf [64]; - sprintf ( buf,"VCount:%d PCount:%d CacheMiss: %d", - vertexCount, primitiveCount, - VertexCache.CacheMiss - ); - os::Printer::log( buf ); -*/ + //release texture + for (size_t m = 0; m < VertexCache.vSize[VertexCache.vType].TexSize; ++m) + { + CurrentShader->setTextureParam(m, 0, 0); + } } @@ -1581,8 +2351,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert //! \param color: New color of the ambient light. void CBurningVideoDriver::setAmbientLight(const SColorf& color) { - CNullDriver::setAmbientLight(color); - LightSpace.Global_AmbientLight.setColorf ( color ); + EyeSpace.Global_AmbientLight.setColorf ( color ); } @@ -1600,54 +2369,102 @@ s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) l.DiffuseColor.setColorf ( dl.DiffuseColor ); l.SpecularColor.setColorf ( dl.SpecularColor ); + //should always be valid? + sVec4 nDirection; + nDirection.x = dl.Direction.X; + nDirection.y = dl.Direction.Y; + nDirection.z = dl.Direction.Z; + nDirection.normalize_dir_xyz(); + + switch ( dl.Type ) { - case video::ELT_DIRECTIONAL: - l.pos.x = -dl.Direction.X; - l.pos.y = -dl.Direction.Y; - l.pos.z = -dl.Direction.Z; - l.pos.w = 1.f; + case ELT_DIRECTIONAL: + l.pos.x = dl.Position.X; + l.pos.y = dl.Position.Y; + l.pos.z = dl.Position.Z; + l.pos.w = 0.f; + + l.constantAttenuation = 1.f; + l.linearAttenuation = 0.f; + l.quadraticAttenuation = 0.f; + + l.spotDirection.x = -nDirection.x; + l.spotDirection.y = -nDirection.y; + l.spotDirection.z = -nDirection.z; + l.spotDirection.w = 0.f; + l.spotCosCutoff = -1.f; + l.spotCosInnerCutoff = 1.f; + l.spotExponent = 0.f; break; + case ELT_POINT: - case ELT_SPOT: - LightSpace.Flags |= POINTLIGHT; l.pos.x = dl.Position.X; l.pos.y = dl.Position.Y; l.pos.z = dl.Position.Z; l.pos.w = 1.f; -/* - l.radius = (1.f / dl.Attenuation.Y) * (1.f / dl.Attenuation.Y); + l.constantAttenuation = dl.Attenuation.X; l.linearAttenuation = dl.Attenuation.Y; l.quadraticAttenuation = dl.Attenuation.Z; -*/ - l.radius = dl.Radius * dl.Radius; + + l.spotDirection.x = -nDirection.x; + l.spotDirection.y = -nDirection.y; + l.spotDirection.z = -nDirection.z; + l.spotDirection.w = 0.f; + l.spotCosCutoff = -1.f; + l.spotCosInnerCutoff = 1.f; + l.spotExponent = 0.f; + break; + + case ELT_SPOT: + l.pos.x = dl.Position.X; + l.pos.y = dl.Position.Y; + l.pos.z = dl.Position.Z; + l.pos.w = 1.f; + l.constantAttenuation = dl.Attenuation.X; - l.linearAttenuation = 1.f / dl.Radius; + l.linearAttenuation = dl.Attenuation.Y; l.quadraticAttenuation = dl.Attenuation.Z; + l.spotDirection.x = nDirection.x; + l.spotDirection.y = nDirection.y; + l.spotDirection.z = nDirection.z; + l.spotDirection.w = 0.0f; + l.spotCosCutoff = cosf(dl.OuterCone * 2.0f * core::DEGTORAD * 0.5f); + l.spotCosInnerCutoff = cosf(dl.InnerCone * 2.0f * core::DEGTORAD * 0.5f); + l.spotExponent = dl.Falloff; break; default: break; } - LightSpace.Light.push_back ( l ); - return LightSpace.Light.size() - 1; + //which means ETS_VIEW + setTransform(ETS_WORLD,irr::core::IdentityMatrix); + transform_calc(ETS_MODEL_VIEW); + + const core::matrix4* matrix = Transformation[TransformationStack]; + transformVec4Vec4(matrix[ETS_MODEL_VIEW], &l.pos4.x, &l.pos.x ); + rotateVec3Vec4(matrix[ETS_MODEL_VIEW], &l.spotDirection4.x, &l.spotDirection.x ); + + EyeSpace.Light.push_back ( l ); + return EyeSpace.Light.size() - 1; } + //! Turns a dynamic light on or off void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn) { - if(lightIndex > -1 && lightIndex < (s32)LightSpace.Light.size()) + if((u32)lightIndex < EyeSpace.Light.size()) { - LightSpace.Light[lightIndex].LightIsOn = turnOn; + EyeSpace.Light[lightIndex].LightIsOn = turnOn; } } //! deletes all dynamic lights there are void CBurningVideoDriver::deleteAllDynamicLights() { - LightSpace.reset (); + EyeSpace.reset (); CNullDriver::deleteAllDynamicLights(); } @@ -1655,248 +2472,498 @@ void CBurningVideoDriver::deleteAllDynamicLights() //! returns the maximal amount of dynamic lights the device can handle u32 CBurningVideoDriver::getMaximalDynamicLightAmount() const { - return 8; + return 8; //no limit 8 only for convenience } //! sets a material void CBurningVideoDriver::setMaterial(const SMaterial& material) { +// ---------- Override Material.org = material; + OverrideMaterial.apply(Material.org); + + const SMaterial& in = Material.org; + +// ---------- Notify Shader + // unset old material + u32 mi; + mi = (u32)Material.lastMaterial.MaterialType; + if (mi != material.MaterialType && mi < MaterialRenderers.size()) + MaterialRenderers[mi].Renderer->OnUnsetMaterial(); + + // set new material. + mi = (u32)in.MaterialType; + if (mi < MaterialRenderers.size()) + MaterialRenderers[mi].Renderer->OnSetMaterial( + in, Material.lastMaterial, Material.resetRenderStates, this); + + Material.lastMaterial = in; + Material.resetRenderStates = false; + + //CSoftware2MaterialRenderer sets Material.Fallback_MaterialType + + //Material.Fallback_MaterialType = material.MaterialType; + +//----------------- + + //Material.org = material; + Material.CullFlag = CULL_INVISIBLE | (in.BackfaceCulling ? CULL_BACK : 0) | (in.FrontfaceCulling ? CULL_FRONT : 0); + + size_t* flag = TransformationFlag[TransformationStack]; #ifdef SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM - for (u32 i = 0; i < 2; ++i) + for (u32 m = 0; m < BURNING_MATERIAL_MAX_TEXTURES /*&& m < vSize[VertexCache.vType].TexSize*/; ++m) { - setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), - material.getTextureMatrix(i)); + setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + m),in.getTextureMatrix(m)); + flag[ETS_TEXTURE_0+m] &= ~ETF_TEXGEN_MASK; } #endif #ifdef SOFTWARE_DRIVER_2_LIGHTING - Material.AmbientColor.setR8G8B8 ( Material.org.AmbientColor.color ); - Material.DiffuseColor.setR8G8B8 ( Material.org.DiffuseColor.color ); - Material.EmissiveColor.setR8G8B8 ( Material.org.EmissiveColor.color ); - Material.SpecularColor.setR8G8B8 ( Material.org.SpecularColor.color ); - core::setbit_cond ( LightSpace.Flags, Material.org.Shininess != 0.f, SPECULAR ); - core::setbit_cond ( LightSpace.Flags, Material.org.FogEnable, FOG ); - core::setbit_cond ( LightSpace.Flags, Material.org.NormalizeNormals, NORMALIZE ); + Material.AmbientColor.setA8R8G8B8( in.AmbientColor.color ); + Material.DiffuseColor.setA8R8G8B8( in.ColorMaterial ? 0xFFFFFFFF : in.DiffuseColor.color ); + Material.EmissiveColor.setA8R8G8B8(in.EmissiveColor.color ); + Material.SpecularColor.setA8R8G8B8( in.SpecularColor.color ); + + burning_setbit(EyeSpace.TL_Flag, in.Lighting, TL_LIGHT); + burning_setbit( EyeSpace.TL_Flag, (in.Shininess != 0.f) & (in.SpecularColor.color & 0x00ffffff), TL_SPECULAR ); + burning_setbit( EyeSpace.TL_Flag, in.FogEnable, TL_FOG ); + burning_setbit( EyeSpace.TL_Flag, in.NormalizeNormals, TL_NORMALIZE_NORMALS ); + //if (EyeSpace.Flags & SPECULAR ) EyeSpace.Flags |= NORMALIZE_NORMALS; + #endif - setCurrentShader(); -} + //--------------- setCurrentShader + + ITexture* texture0 = in.getTexture(0); + ITexture* texture1 = in.getTexture(1); + //ITexture* texture2 = in.getTexture(2); + //ITexture* texture3 = in.getTexture(3); + + //visual studio code analysis + u32 maxTex = BURNING_MATERIAL_MAX_TEXTURES; + if (maxTex < 1) texture0 = 0; + if (maxTex < 2) texture1 = 0; + //if (maxTex < 3) texture2 = 0; + //if (maxTex < 4) texture3 = 0; + + EyeSpace.TL_Flag &= ~(TL_TEXTURE_TRANSFORM | TL_LIGHT0_IS_NORMAL_MAP); + + //todo: seperate depth test from depth write + Material.depth_write = getWriteZBuffer(in); + Material.depth_test = in.ZBuffer != ECFN_DISABLED && Material.depth_write; + + EBurningFFShader shader = Material.depth_test ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ; + + switch (Material.Fallback_MaterialType) //(Material.org.MaterialType) + { + case EMT_ONETEXTURE_BLEND: + shader = ETR_TEXTURE_BLEND; + break; + + case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: + Material.org.MaterialTypeParam = 0.5f; + //fallthrough + + case EMT_TRANSPARENT_ALPHA_CHANNEL: + if (texture0 && texture0->hasAlpha()) + { + shader = Material.depth_test ? ETR_TEXTURE_GOURAUD_ALPHA : ETR_TEXTURE_GOURAUD_ALPHA_NOZ; + } + else + { + //fall back to EMT_TRANSPARENT_VERTEX_ALPHA + shader = ETR_TEXTURE_GOURAUD_VERTEX_ALPHA; + } + break; + + case EMT_TRANSPARENT_ADD_COLOR: + shader = Material.depth_test ? ETR_TEXTURE_GOURAUD_ADD : ETR_TEXTURE_GOURAUD_ADD_NO_Z; + break; + + case EMT_TRANSPARENT_VERTEX_ALPHA: + shader = ETR_TEXTURE_GOURAUD_VERTEX_ALPHA; + break; + + case EMT_LIGHTMAP: + case EMT_LIGHTMAP_LIGHTING: + if (texture1) + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; + break; + + case EMT_LIGHTMAP_M2: + case EMT_LIGHTMAP_LIGHTING_M2: + if (texture1) + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M2; + break; + + case EMT_LIGHTMAP_LIGHTING_M4: + if (texture1) + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M4; + break; + case EMT_LIGHTMAP_M4: + if (texture1) + shader = ETR_TEXTURE_LIGHTMAP_M4; + break; + + case EMT_LIGHTMAP_ADD: + if (texture1) + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD; + break; + + case EMT_DETAIL_MAP: + if (texture1) + shader = ETR_TEXTURE_GOURAUD_DETAIL_MAP; + break; + + case EMT_SPHERE_MAP: + flag[ETS_TEXTURE_0] |= ETF_TEXGEN_CAMERA_SPHERE; + EyeSpace.TL_Flag |= TL_TEXTURE_TRANSFORM; + break; + case EMT_REFLECTION_2_LAYER: + case EMT_TRANSPARENT_REFLECTION_2_LAYER: + if (texture1) + { + shader = ETR_TRANSPARENT_REFLECTION_2_LAYER; + flag[ETS_TEXTURE_1] |= ETF_TEXGEN_CAMERA_REFLECTION; + EyeSpace.TL_Flag |= TL_TEXTURE_TRANSFORM; + } + break; + + case EMT_NORMAL_MAP_SOLID: + case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR: + case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: + if (texture1) + { + shader = ETR_NORMAL_MAP_SOLID; + EyeSpace.TL_Flag |= TL_TEXTURE_TRANSFORM | TL_LIGHT0_IS_NORMAL_MAP; + } + break; + case EMT_PARALLAX_MAP_SOLID: + case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR: + case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: + if (texture1) + { + shader = ETR_NORMAL_MAP_SOLID; + EyeSpace.TL_Flag |= TL_TEXTURE_TRANSFORM | TL_LIGHT0_IS_NORMAL_MAP; + } + break; + + default: + break; + + } + + if (!texture0) + { + shader = Material.depth_test ? ETR_GOURAUD : + shader == ETR_TEXTURE_GOURAUD_VERTEX_ALPHA ? + ETR_GOURAUD_ALPHA_NOZ: // 2D Gradient + ETR_GOURAUD_NOZ; + + shader = ETR_COLOR; + } + + if (in.Wireframe) + { + IBurningShader* candidate = BurningShader[shader]; + if (!candidate || (candidate && !candidate->canWireFrame())) + { + shader = ETR_TEXTURE_GOURAUD_WIRE; + } + } + + if (in.PointCloud) + { + IBurningShader* candidate = BurningShader[shader]; + if (!candidate || (candidate && !candidate->canPointCloud())) + { + shader = ETR_TEXTURE_GOURAUD_WIRE; + } + } + + //shader = ETR_REFERENCE; + + // switchToTriangleRenderer + CurrentShader = BurningShader[shader]; + if (CurrentShader) + { + CurrentShader->setTLFlag(EyeSpace.TL_Flag); + if (EyeSpace.TL_Flag & TL_FOG) CurrentShader->setFog(FogColor); + if (EyeSpace.TL_Flag & TL_SCISSOR) CurrentShader->setScissor(Scissor); + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); + CurrentShader->OnSetMaterial(Material); + CurrentShader->pushEdgeTest(in.Wireframe, in.PointCloud, 0); + } -/*! - Camera Position in World Space +/* + mi = (u32)Material.org.MaterialType; + if (mi < MaterialRenderers.size()) + MaterialRenderers[mi].Renderer->OnRender(this, (video::E_VERTEX_TYPE)VertexCache.vType); */ -void CBurningVideoDriver::getCameraPosWorldSpace () -{ - Transformation[ETS_VIEW_INVERSE] = Transformation[ ETS_VIEW ]; - Transformation[ETS_VIEW_INVERSE].makeInverse (); - TransformationFlag[ETS_VIEW_INVERSE] = 0; - - const f32 *M = Transformation[ETS_VIEW_INVERSE].pointer (); - - /* The viewpoint is at (0., 0., 0.) in eye space. - Turning this into a vector [0 0 0 1] and multiply it by - the inverse of the view matrix, the resulting vector is the - object space location of the camera. - */ - - LightSpace.campos.x = M[12]; - LightSpace.campos.y = M[13]; - LightSpace.campos.z = M[14]; - LightSpace.campos.w = 1.f; } -void CBurningVideoDriver::getLightPosObjectSpace () -{ - if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY ) - { - Transformation[ETS_WORLD_INVERSE] = Transformation[ETS_WORLD]; - TransformationFlag[ETS_WORLD_INVERSE] |= ETF_IDENTITY; - } - else - { - Transformation[ETS_WORLD].getInverse ( Transformation[ETS_WORLD_INVERSE] ); - TransformationFlag[ETS_WORLD_INVERSE] &= ~ETF_IDENTITY; - } - - for ( u32 i = 0; i < 1 && i < LightSpace.Light.size(); ++i ) - { - SBurningShaderLight &l = LightSpace.Light[i]; - - Transformation[ETS_WORLD_INVERSE].transformVec3 ( &l.pos_objectspace.x, &l.pos.x ); - } -} - - -#ifdef SOFTWARE_DRIVER_2_LIGHTING //! Sets the fog mode. void CBurningVideoDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); - LightSpace.FogColor.setA8R8G8B8 ( color.color ); + + EyeSpace.fog_scale = reciprocal_zero2(FogEnd - FogStart); } + + +#if defined(SOFTWARE_DRIVER_2_LIGHTING) && BURNING_MATERIAL_MAX_COLORS > 0 + + /*! applies lighting model */ -void CBurningVideoDriver::lightVertex ( s4DVertex *dest, u32 vertexargb ) +void CBurningVideoDriver::lightVertex_eye(s4DVertex *dest, u32 vertexargb) { - sVec3 dColor; + //gl_FrontLightModelProduct.sceneColor = gl_FrontMaterial.emission + gl_FrontMaterial.ambient * gl_LightModel.ambient - dColor = LightSpace.Global_AmbientLight; - dColor.add ( Material.EmissiveColor ); - - if ( Lights.size () == 0 ) - { - dColor.saturate( dest->Color[0], vertexargb); - return; - } - - sVec3 ambient; - sVec3 diffuse; - sVec3 specular; + sVec3Color ambient; + sVec3Color diffuse; + sVec3Color specular; // the universe started in darkness.. - ambient.set ( 0.f, 0.f, 0.f ); - diffuse.set ( 0.f, 0.f, 0.f ); - specular.set ( 0.f, 0.f, 0.f ); + ambient = EyeSpace.Global_AmbientLight; + diffuse.set(0.f); + specular.set(0.f); u32 i; f32 dot; - f32 len; + f32 distance; f32 attenuation; sVec4 vp; // unit vector vertex to light sVec4 lightHalf; // blinn-phong reflection - for ( i = 0; i!= LightSpace.Light.size (); ++i ) - { - const SBurningShaderLight &light = LightSpace.Light[i]; + f32 spotDot; // cos of angle between spotlight and point on surface - if ( !light.LightIsOn ) + for (i = 0; i < EyeSpace.Light.size(); ++i) + { + const SBurningShaderLight& light = EyeSpace.Light[i]; + if (!light.LightIsOn) continue; - // accumulate ambient - ambient.add ( light.AmbientColor ); - - switch ( light.Type ) + switch (light.Type) { - case video::ELT_SPOT: - case video::ELT_POINT: - // surface to light - vp.x = light.pos.x - LightSpace.vertex.x; - vp.y = light.pos.y - LightSpace.vertex.y; - vp.z = light.pos.z - LightSpace.vertex.z; - //vp.x = light.pos_objectspace.x - LightSpace.vertex.x; - //vp.y = light.pos_objectspace.y - LightSpace.vertex.x; - //vp.z = light.pos_objectspace.z - LightSpace.vertex.x; + case ELT_DIRECTIONAL: - len = vp.get_length_xyz_square(); - if ( light.radius < len ) - continue; + //angle between normal and light vector + dot = EyeSpace.normal.dot_xyz(light.spotDirection4); - len = core::reciprocal_squareroot ( len ); + // accumulate ambient + ambient.add_rgb(light.AmbientColor); - // build diffuse reflection + // diffuse component + if (dot > 0.f) + diffuse.mad_rgb(light.DiffuseColor, dot); + break; - //angle between normal and light vector - vp.mul ( len ); - dot = LightSpace.normal.dot_xyz ( vp ); - if ( dot < 0.f ) - continue; + case ELT_POINT: + // surface to light + vp.x = light.pos4.x - EyeSpace.vertex.x; + vp.y = light.pos4.y - EyeSpace.vertex.y; + vp.z = light.pos4.z - EyeSpace.vertex.z; - attenuation = light.constantAttenuation + ( 1.f - ( len * light.linearAttenuation ) ); + distance = vp.length_xyz(); - // diffuse component - diffuse.mulAdd ( light.DiffuseColor, 3.f * dot * attenuation ); + attenuation = light.constantAttenuation + + light.linearAttenuation * distance + + light.quadraticAttenuation * (distance * distance); + attenuation = reciprocal_one(attenuation); - if ( !(LightSpace.Flags & SPECULAR) ) - continue; + //att = clamp(1.0 - dist/radius, 0.0, 1.0); att *= att - // build specular - // surface to view - lightHalf.x = LightSpace.campos.x - LightSpace.vertex.x; - lightHalf.y = LightSpace.campos.y - LightSpace.vertex.y; - lightHalf.z = LightSpace.campos.z - LightSpace.vertex.z; - lightHalf.normalize_xyz(); - lightHalf += vp; - lightHalf.normalize_xyz(); + // accumulate ambient + ambient.mad_rgb(light.AmbientColor, attenuation); - // specular - dot = LightSpace.normal.dot_xyz ( lightHalf ); - if ( dot < 0.f ) - continue; + // build diffuse reflection - //specular += light.SpecularColor * ( powf ( Material.org.Shininess ,dot ) * attenuation ); - specular.mulAdd ( light.SpecularColor, dot * attenuation ); - break; + //angle between normal and light vector + vp.mul_xyz(reciprocal_zero(distance)); //normalize + dot = EyeSpace.normal.dot_xyz(vp); + if (dot <= 0.f) continue; - case video::ELT_DIRECTIONAL: + // diffuse component + diffuse.mad_rgb(light.DiffuseColor, dot * attenuation); - //angle between normal and light vector - dot = LightSpace.normal.dot_xyz ( light.pos ); - if ( dot < 0.f ) - continue; + if (!(EyeSpace.TL_Flag & TL_SPECULAR)) + continue; - // diffuse component - diffuse.mulAdd ( light.DiffuseColor, dot ); - break; - default: - break; + lightHalf.x = vp.x + 0.f; // EyeSpace.cam_eye_pos.x; + lightHalf.y = vp.y + 0.f; // EyeSpace.cam_eye_pos.y; + lightHalf.z = vp.z - 1.f; // EyeSpace.cam_eye_pos.z; + lightHalf.normalize_dir_xyz(); + + //specular += light.SpecularColor * pow(max(dot(Eyespace.normal,lighthalf),0,Material.org.Shininess)*attenuation + specular.mad_rgb(light.SpecularColor, + powf_limit(EyeSpace.normal.dot_xyz(lightHalf), Material.org.Shininess)*attenuation + ); + break; + + case ELT_SPOT: + // surface to light + vp.x = light.pos4.x - EyeSpace.vertex.x; + vp.y = light.pos4.y - EyeSpace.vertex.y; + vp.z = light.pos4.z - EyeSpace.vertex.z; + + distance = vp.length_xyz(); + + //normalize + vp.mul_xyz(reciprocal_zero(distance)); + + // point on surface inside cone of illumination + spotDot = vp.dot_minus_xyz(light.spotDirection4); + if (spotDot < light.spotCosCutoff) + continue; + + attenuation = light.constantAttenuation + + light.linearAttenuation * distance + + light.quadraticAttenuation * distance * distance; + attenuation = reciprocal_one(attenuation); + attenuation *= powf_limit(spotDot, light.spotExponent); + + // accumulate ambient + ambient.mad_rgb(light.AmbientColor, attenuation); + + + // build diffuse reflection + //angle between normal and light vector + dot = EyeSpace.normal.dot_xyz(vp); + if (dot < 0.f) continue; + + // diffuse component + diffuse.mad_rgb(light.DiffuseColor, dot * attenuation); + + if (!(EyeSpace.TL_Flag & TL_SPECULAR)) + continue; + + lightHalf.x = vp.x + 0.f; // EyeSpace.cam_eye_pos.x; + lightHalf.y = vp.y + 0.f; // EyeSpace.cam_eye_pos.y; + lightHalf.z = vp.z - 1.f; // EyeSpace.cam_eye_pos.z; + lightHalf.normalize_dir_xyz(); + + //specular += light.SpecularColor * pow(max(dot(Eyespace.normal,lighthalf),0,Material.org.Shininess)*attenuation + specular.mad_rgb(light.SpecularColor, + powf_limit(EyeSpace.normal.dot_xyz(lightHalf), Material.org.Shininess)*attenuation + ); + break; + + default: + break; } } // sum up lights - dColor.mulAdd (ambient, Material.AmbientColor ); - dColor.mulAdd (diffuse, Material.DiffuseColor); - dColor.mulAdd (specular, Material.SpecularColor); + sVec3Color dColor; + dColor.set(0.f); + dColor.mad_rgbv(diffuse, Material.DiffuseColor); + + //diffuse * vertex color. + //has to move to shader (for vertex color only this will fit [except clamping]) + + sVec3Color c; + c.setA8R8G8B8(vertexargb); + dColor.r *= c.r; + dColor.g *= c.g; + dColor.b *= c.b; + + //separate specular +#if defined(SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR) + if ((VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_COLOR_2_FOG)) + { + specular.sat_xyz(dest->Color[1], Material.SpecularColor); + } + else + if ( !(EyeSpace.TL_Flag & TL_LIGHT0_IS_NORMAL_MAP) && + (VertexCache.vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_MASK_LIGHT) + ) + { + specular.sat_xyz(dest->LightTangent[0], Material.SpecularColor); + } + else +#endif + { + dColor.mad_rgbv(specular, Material.SpecularColor); + } + + + dColor.mad_rgbv(ambient, Material.AmbientColor); + dColor.add_rgb(Material.EmissiveColor); + + + dColor.sat(dest->Color[0], vertexargb); - dColor.saturate ( dest->Color[0], vertexargb ); } #endif +CImage* getImage(const video::ITexture* texture) +{ + if (!texture) return 0; + + CImage* img = 0; + switch (texture->getDriverType()) + { + case EDT_BURNINGSVIDEO: + img = ((CSoftwareTexture2*)texture)->getImage(); + break; + case EDT_SOFTWARE: + img = ((CSoftwareTexture*)texture)->getImage(); + break; + default: + os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR); + break; + } + return img; +} + +/* + draw2DImage with single color scales into destination quad & cliprect(more like viewport) + draw2DImage with 4 color scales on destination and cliprect is scissor +*/ + +static const u16 quad_triangle_indexList[6] = { 0,1,2,0,2,3 }; + + +#if defined(SOFTWARE_DRIVER_2_2D_AS_2D) //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos, - const core::rect& sourceRect, - const core::rect* clipRect, SColor color, - bool useAlphaChannelOfTexture) + const core::rect& sourceRect, + const core::rect* clipRect, SColor color, + bool useAlphaChannelOfTexture) { if (texture) { + if (texture->getOriginalSize() != texture->getSize()) + { + core::rect destRect(destPos, sourceRect.getSize()); + SColor c4[4] = { color,color,color,color }; + draw2DImage(texture, destRect, sourceRect, clipRect, c4, useAlphaChannelOfTexture); + return; + } + if (texture->getDriverType() != EDT_BURNINGSVIDEO) { os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR); return; } -#if 0 - // 2d methods don't use viewPort - core::position2di dest = destPos; - core::recti clip=ViewPort; - if (ViewPort.getSize().Width != ScreenSize.Width) - { - dest.X=ViewPort.UpperLeftCorner.X+core::round32_fast(destPos.X*ViewPort.getWidth()/(f32)ScreenSize.Width); - dest.Y=ViewPort.UpperLeftCorner.Y+core::round32_fast(destPos.Y*ViewPort.getHeight()/(f32)ScreenSize.Height); - if (clipRect) - { - clip.constrainTo(*clipRect); - } - clipRect = &clip; - } -#endif if (useAlphaChannelOfTexture) ((CSoftwareTexture2*)texture)->getImage()->copyToWithAlpha( - RenderTargetSurface, destPos, sourceRect, color, clipRect); + RenderTargetSurface, destPos, sourceRect, color, clipRect); else ((CSoftwareTexture2*)texture)->getImage()->copyTo( RenderTargetSurface, destPos, sourceRect, clipRect); @@ -1906,8 +2973,8 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core //! Draws a part of the texture into the rectangle. void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::rect& destRect, - const core::rect& sourceRect, const core::rect* clipRect, - const video::SColor* const colors, bool useAlphaChannelOfTexture) + const core::rect& sourceRect, const core::rect* clipRect, + const video::SColor* const colors, bool useAlphaChannelOfTexture) { if (texture) { @@ -1917,53 +2984,460 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core return; } - if (useAlphaChannelOfTexture) - StretchBlit(BLITTER_TEXTURE_ALPHA_BLEND, RenderTargetSurface, &destRect, &sourceRect, - ((CSoftwareTexture2*)texture)->getImage(), (colors ? colors[0].color : 0)); - else - StretchBlit(BLITTER_TEXTURE, RenderTargetSurface, &destRect, &sourceRect, - ((CSoftwareTexture2*)texture)->getImage(), (colors ? colors[0].color : 0)); + u32 argb = (colors ? colors[0].color : 0xFFFFFFFF); + eBlitter op = useAlphaChannelOfTexture ? + (argb == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND : BLITTER_TEXTURE_ALPHA_COLOR_BLEND) : BLITTER_TEXTURE; + + StretchBlit(op, RenderTargetSurface, clipRect, &destRect, + ((CSoftwareTexture2*)texture)->getImage(), &sourceRect, &texture->getOriginalSize(), argb); + } } +//!Draws an 2d rectangle with a gradient. +void CBurningVideoDriver::draw2DRectangle(const core::rect& position, + SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, + const core::rect* clip) +{ + core::rect p(position); + if (clip) p.clipAgainst(*clip); + if (p.isValid()) drawRectangle(RenderTargetSurface, p, colorLeftUp); +} + +#endif //defined(SOFTWARE_DRIVER_2_2D_AS_2D) + + + + + +#if 0 +void transform_for_BlitJob2D( SBlitJob& out, + const S3DVertex quad2DVertices[4], const core::dimension2d& renderTargetSize, + CBurningVideoDriver* driver +) +{ + //assume. z = 0.f, w = 1.f + //MVP 2D + core::matrix4 m; + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); + m.setTranslation(core::vector3df(-1.f, 1.f, 0)); + + //setTransform(ETS_WORLD, m); + //m.setTranslation(core::vector3df(0.375f, 0.375f, 0.0f)); + //setTransform(ETS_VIEW, m); + + s4DVertexPair v[4*sizeof_s4DVertexPairRel]; + for (int i = 0; i < 4; ++i) + { + m.transformVect(&v[s4DVertex_ofs(i)].Pos.x, quad2DVertices[i].Pos); + v[s4DVertex_ofs(i)].Tex[0].x = quad2DVertices[i].TCoords.X; + v[s4DVertex_ofs(i)].Tex[0].y = quad2DVertices[i].TCoords.Y; + v[s4DVertex_ofs(i)].Color[0].setA8R8G8B8(quad2DVertices[i].Color.color); + v[s4DVertex_ofs(i)].flag = VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1; + v[s4DVertex_ofs(i)].flag |= clipToFrustumTest(v + i); + } + + size_t vOut = driver->clipToFrustum(4); + + struct s2DVertex + { + union + { + struct { + f32 x, y; + f32 u, v; + f32 a, r, g, b; + }; + f32 attr[8]; + }; + + // f = a * t + b * ( 1 - t ) + void interpolate(const s2DVertex& b, const s2DVertex& a, const f32 t) + { + for (int i = 0; i < 8; ++i) + { + attr[i] = b.attr[i] + ((a.attr[i] - b.attr[i]) * t); + } + } + + }; + + // 0 5 + f32 m2[2]; + m2[0] = renderTargetSize.Width ? 2.f / renderTargetSize.Width : 0.f; + m2[1] = renderTargetSize.Height ? -2.f / renderTargetSize.Height : 0.f; + + s2DVertex p[4]; + for (int i = 0; i < 4; ++i) + { + p[i].x = quad2DVertices[i].Pos.X*m2[0] - 1.f; + p[i].y = quad2DVertices[i].Pos.Y*m2[1] + 1.f; + p[i].u = quad2DVertices[i].TCoords.X; + p[i].v = quad2DVertices[i].TCoords.Y; + + p[i].a = quad2DVertices[i].Color.getAlpha() * (1.f / 255.f); + p[i].r = quad2DVertices[i].Color.getRed() * (1.f / 255.f); + p[i].g = quad2DVertices[i].Color.getBlue() * (1.f / 255.f); + p[i].b = quad2DVertices[i].Color.getGreen() * (1.f / 255.f); + + } + +} +#endif + + +//! Enable the 2d override material +void CBurningVideoDriver::enableMaterial2D(bool enable) +{ + CNullDriver::enableMaterial2D(enable); + burning_setbit(TransformationFlag[1][ETS_PROJECTION], 0, ETF_VALID); +} + +size_t compare_2d_material(const SMaterial& a, const SMaterial& b) +{ + size_t flag = 0; + flag |= a.MaterialType == b.MaterialType ? 0 : 1; + flag |= a.ZBuffer == b.ZBuffer ? 0 : 2; + flag |= a.TextureLayer[0].Texture == b.TextureLayer[0].Texture ? 0 : 4; + flag |= a.TextureLayer[0].BilinearFilter == b.TextureLayer[0].BilinearFilter ? 0 : 8; + flag |= a.MaterialTypeParam == b.MaterialTypeParam ? 0 : 16; + if (flag) return flag; + + flag |= a.TextureLayer[1].Texture == b.TextureLayer[1].Texture ? 0 : 32; + flag |= a.ZWriteEnable == b.ZWriteEnable ? 0 : 64; + + return flag; +} + +void CBurningVideoDriver::setRenderStates2DMode(const video::SColor& color, video::ITexture* texture, bool useAlphaChannelOfTexture) +{ + //save current 3D Material + //Material.save3D = Material.org; + + //build new 2D Material + + bool vertexAlpha = color.getAlpha() < 255; + + //2D uses textureAlpa*vertexAlpha 3D not.. + if (useAlphaChannelOfTexture && texture && texture->hasAlpha()) + { + Material.mat2D.MaterialType = EMT_TRANSPARENT_ALPHA_CHANNEL; + } + else if (vertexAlpha) + { + Material.mat2D.MaterialType = EMT_TRANSPARENT_VERTEX_ALPHA; + } + else + { + Material.mat2D.MaterialType = EMT_SOLID; + } + + Material.mat2D.ZBuffer = ECFN_DISABLED; + Material.mat2D.ZWriteEnable = EZW_OFF; + Material.mat2D.Lighting = false; + + Material.mat2D.setTexture(0, (video::ITexture*)texture); + + //used for text. so stay as sharp as possible (like HW Driver) + bool mip = false; + + const SMaterial& currentMaterial = (!OverrideMaterial2DEnabled) ? InitMaterial2D : OverrideMaterial2D; + mip = currentMaterial.TextureLayer[0].BilinearFilter; + + Material.mat2D.setFlag(video::EMF_BILINEAR_FILTER, mip); + + + //switch to 2D Matrix Stack [ Material set Texture Matrix ] + TransformationStack = 1; + + //2D GUI Matrix + if (!(TransformationFlag[TransformationStack][ETS_PROJECTION] & ETF_VALID)) + { + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + core::matrix4 m(core::matrix4::EM4CONST_NOTHING); + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); + m.setTranslation(core::vector3df(-1.f, 1.f, 0)); + setTransform(ETS_PROJECTION, m); + + m.makeIdentity(); + setTransform(ETS_WORLD, m); + + if ( mip ) m.setTranslation(core::vector3df(0.375f, 0.375f, 0.0f)); + + setTransform(ETS_VIEW, m); + + buildNDCToDCMatrix(Transformation_ETS_CLIPSCALE[TransformationStack], ViewPort, mip ? -0.187f : 0.f); + + } + + //compare + if (compare_2d_material(Material.org,Material.mat2D)) + { + setMaterial(Material.mat2D); + } + if (CurrentShader) + { + CurrentShader->setPrimitiveColor(color.color); + } + +} + +void CBurningVideoDriver::setRenderStates3DMode() +{ + //restoreRenderStates3DMode + + //setMaterial(Material.save3D); + //switch to 3D Matrix Stack + TransformationStack = 0; +} + +//! draws a vertex primitive list in 2d +void CBurningVideoDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) +{ + if (!checkPrimitiveCount(primitiveCount)) + return; + + CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); + + bool useAlphaChannelOfTexture = false; + video::SColor color(0xFFFFFFFF); + switch (Material.org.MaterialType) + { + case EMT_TRANSPARENT_ALPHA_CHANNEL: + useAlphaChannelOfTexture = true; + break; + case EMT_TRANSPARENT_VERTEX_ALPHA: + color.setAlpha(127); + break; + default: + break; + } + setRenderStates2DMode(color, Material.org.getTexture(0), useAlphaChannelOfTexture); + + drawVertexPrimitiveList(vertices, vertexCount, + indexList, primitiveCount, + vType, pType, iType); + + setRenderStates3DMode(); + +} + +//setup a quad +#if defined(SOFTWARE_DRIVER_2_2D_AS_3D) + +//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. +void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos, + const core::rect& sourceRect, + const core::rect* clipRect, SColor color, + bool useAlphaChannelOfTexture) +{ + if (!texture) + return; + + if (!sourceRect.isValid()) + return; + + // clip these coordinates + core::rect targetRect(destPos, sourceRect.getSize()); + if (clipRect) + { + targetRect.clipAgainst(*clipRect); + if (targetRect.getWidth() < 0 || targetRect.getHeight() < 0) + return; + } + + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + targetRect.clipAgainst(core::rect(0, 0, (s32)renderTargetSize.Width, (s32)renderTargetSize.Height)); + if (targetRect.getWidth() < 0 || targetRect.getHeight() < 0) + return; + + // ok, we've clipped everything. + // now draw it. + const core::dimension2d sourceSize(targetRect.getSize()); + const core::position2d sourcePos(sourceRect.UpperLeftCorner + (targetRect.UpperLeftCorner - destPos)); + + const core::dimension2d& tex_orgsize = texture->getOriginalSize(); + const f32 invW = 1.f / static_cast(tex_orgsize.Width); + const f32 invH = 1.f / static_cast(tex_orgsize.Height); + const core::rect tcoords( + sourcePos.X * invW, + sourcePos.Y * invH, + (sourcePos.X + sourceSize.Width) * invW, + (sourcePos.Y + sourceSize.Height) * invH); + + + Quad2DVertices[0].Color = color; + Quad2DVertices[1].Color = color; + Quad2DVertices[2].Color = color; + Quad2DVertices[3].Color = color; + + Quad2DVertices[0].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[1].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[2].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f); + Quad2DVertices[3].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f); + + Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); + Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); + Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); + Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); + + //SBlitJob job; + //transform_for_BlitJob2D(job, Quad2DVertices, renderTargetSize,this); + + setRenderStates2DMode(color, (video::ITexture*) texture, useAlphaChannelOfTexture); + + drawVertexPrimitiveList(Quad2DVertices, 4, + quad_triangle_indexList, 2, + EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); + + setRenderStates3DMode(); + +} + + +//! Draws a part of the texture into the rectangle. +void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::rect& destRect, + const core::rect& sourceRect, const core::rect* clipRect, + const video::SColor* const colors, bool useAlphaChannelOfTexture) +{ + const core::dimension2d& st = texture->getOriginalSize(); + const f32 invW = 1.f / static_cast(st.Width); + const f32 invH = 1.f / static_cast(st.Height); + const core::rect tcoords( + sourceRect.UpperLeftCorner.X * invW, + sourceRect.UpperLeftCorner.Y * invH, + sourceRect.LowerRightCorner.X * invW, + sourceRect.LowerRightCorner.Y *invH); + + const video::SColor temp[4] = + { + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF + }; + + const video::SColor* const useColor = colors ? colors : temp; + + + Quad2DVertices[0].Color = useColor[0]; + Quad2DVertices[1].Color = useColor[3]; + Quad2DVertices[2].Color = useColor[2]; + Quad2DVertices[3].Color = useColor[1]; + + Quad2DVertices[0].Pos = core::vector3df((f32)destRect.UpperLeftCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[1].Pos = core::vector3df((f32)destRect.LowerRightCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[2].Pos = core::vector3df((f32)destRect.LowerRightCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f); + Quad2DVertices[3].Pos = core::vector3df((f32)destRect.UpperLeftCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f); + + Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); + Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); + Quad2DVertices[2].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); + Quad2DVertices[3].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); + + + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + + if (clipRect) + { + if (!clipRect->isValid()) + return; + + //glEnable(GL_SCISSOR_TEST); + EyeSpace.TL_Flag |= TL_SCISSOR; + setScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y, + clipRect->getWidth(), clipRect->getHeight()); + } + + video::SColor alphaTest; + alphaTest.color = useColor[0].color & useColor[0].color & useColor[0].color & useColor[0].color; + + //SBlitJob job; + //transform_for_BlitJob2D(job, Quad2DVertices, renderTargetSize, this); + + setRenderStates2DMode(alphaTest, (video::ITexture*) texture, useAlphaChannelOfTexture); + + drawVertexPrimitiveList(Quad2DVertices, 4, + quad_triangle_indexList, 2, + EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); + + + if (clipRect) + EyeSpace.TL_Flag &= ~TL_SCISSOR; + + setRenderStates3DMode(); + + +} + + +//!Draws an 2d rectangle with a gradient. +void CBurningVideoDriver::draw2DRectangle(const core::rect& position, + SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, + const core::rect* clip) +{ + core::rect pos = position; + + if (clip) + pos.clipAgainst(*clip); + + if (!pos.isValid()) + return; + + Quad2DVertices[0].Color = colorLeftUp; + Quad2DVertices[1].Color = colorRightUp; + Quad2DVertices[2].Color = colorRightDown; + Quad2DVertices[3].Color = colorLeftDown; + + Quad2DVertices[0].Pos = core::vector3df((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[1].Pos = core::vector3df((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[2].Pos = core::vector3df((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f); + Quad2DVertices[3].Pos = core::vector3df((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f); + + Quad2DVertices[0].TCoords.X = 0.f; + Quad2DVertices[0].TCoords.Y = 0.f; + Quad2DVertices[1].TCoords.X = 0.f; + Quad2DVertices[1].TCoords.Y = 0.f; + Quad2DVertices[2].TCoords.X = 0.f; + Quad2DVertices[3].TCoords.Y = 0.f; + Quad2DVertices[3].TCoords.X = 0.f; + Quad2DVertices[3].TCoords.Y = 0.f; + + + video::SColor alphaTest; + alphaTest.color = colorLeftUp.color & colorRightUp.color & colorRightDown.color & colorLeftDown.color; + setRenderStates2DMode(alphaTest, 0, 0); + + drawVertexPrimitiveList(Quad2DVertices, 4, + quad_triangle_indexList, 2, + EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); + + setRenderStates3DMode(); + +} + + +#endif // SOFTWARE_DRIVER_2_2D_AS_3D + + + + + //! Draws a 2d line. void CBurningVideoDriver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { - drawLine(BackBuffer, start, end, color ); + drawLine(RenderTargetSurface, start, end, color ); } //! Draws a pixel void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor & color) { - BackBuffer->setPixel(x, y, color, true); -} - - -//! draw an 2d rectangle -void CBurningVideoDriver::draw2DRectangle(SColor color, const core::rect& pos, - const core::rect* clip) -{ - if (clip) - { - core::rect p(pos); - - p.clipAgainst(*clip); - - if(!p.isValid()) - return; - - drawRectangle(BackBuffer, p, color); - } - else - { - if(!pos.isValid()) - return; - - drawRectangle(BackBuffer, pos, color); - } + RenderTargetSurface->setPixel(x, y, color, true); } @@ -1973,13 +3447,13 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) { // make sure width and height are multiples of 2 core::dimension2d realSize(size); - +/* if (realSize.Width % 2) realSize.Width += 1; if (realSize.Height % 2) realSize.Height += 1; - +*/ if (ScreenSize != realSize) { if (ViewPort.getWidth() == (s32)ScreenSize.Width && @@ -2012,164 +3486,73 @@ const core::dimension2d& CBurningVideoDriver::getCurrentRenderTargetSize() } -//!Draws an 2d rectangle with a gradient. -void CBurningVideoDriver::draw2DRectangle(const core::rect& position, - SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, - const core::rect* clip) -{ -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - - core::rect pos = position; - - if (clip) - pos.clipAgainst(*clip); - - if (!pos.isValid()) - return; - - const core::dimension2d renderTargetSize ( ViewPort.getSize() ); - - const s32 xPlus = -(renderTargetSize.Width>>1); - const f32 xFact = 1.0f / (renderTargetSize.Width>>1); - - const s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1); - const f32 yFact = 1.0f / (renderTargetSize.Height>>1); - - // fill VertexCache direct - s4DVertex *v; - - VertexCache.vertexCount = 4; - - VertexCache.info[0].index = 0; - VertexCache.info[1].index = 1; - VertexCache.info[2].index = 2; - VertexCache.info[3].index = 3; - - v = &VertexCache.mem.data [ 0 ]; - - v[0].Pos.set ( (f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.UpperLeftCorner.Y) * yFact, 0.f, 1.f ); - v[0].Color[0].setA8R8G8B8 ( colorLeftUp.color ); - - v[2].Pos.set ( (f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- pos.UpperLeftCorner.Y) * yFact, 0.f, 1.f ); - v[2].Color[0].setA8R8G8B8 ( colorRightUp.color ); - - v[4].Pos.set ( (f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.f ,1.f ); - v[4].Color[0].setA8R8G8B8 ( colorRightDown.color ); - - v[6].Pos.set ( (f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.f, 1.f ); - v[6].Color[0].setA8R8G8B8 ( colorLeftDown.color ); - - s32 i; - u32 g; - - for ( i = 0; i!= 8; i += 2 ) - { - v[i + 0].flag = clipToFrustumTest ( v + i ); - v[i + 1].flag = 0; - if ( (v[i].flag & VERTEX4D_INSIDE ) == VERTEX4D_INSIDE ) - { - ndc_2_dc_and_project ( v + i + 1, v + i, 2 ); - } - } - - - IBurningShader * render; - - render = BurningShader [ ETR_GOURAUD_ALPHA_NOZ ]; - render->setRenderTarget(RenderTargetSurface, ViewPort); - - static const s16 indexList[6] = {0,1,2,0,2,3}; - - s4DVertex * face[3]; - - for ( i = 0; i!= 6; i += 3 ) - { - face[0] = VertexCache_getVertex ( indexList [ i + 0 ] ); - face[1] = VertexCache_getVertex ( indexList [ i + 1 ] ); - face[2] = VertexCache_getVertex ( indexList [ i + 2 ] ); - - // test clipping - u32 test = face[0]->flag & face[1]->flag & face[2]->flag & VERTEX4D_INSIDE; - - if ( test == VERTEX4D_INSIDE ) - { - render->drawTriangle ( face[0] + 1, face[1] + 1, face[2] + 1 ); - continue; - } - // Todo: all vertices are clipped in 2d.. - // is this true ? - u32 vOut = 6; - memcpy ( CurrentOut.data + 0, face[0], sizeof ( s4DVertex ) * 2 ); - memcpy ( CurrentOut.data + 2, face[1], sizeof ( s4DVertex ) * 2 ); - memcpy ( CurrentOut.data + 4, face[2], sizeof ( s4DVertex ) * 2 ); - - vOut = clipToFrustum ( CurrentOut.data, Temp.data, 3 ); - if ( vOut < 3 ) - continue; - - vOut <<= 1; - // to DC Space, project homogenous vertex - ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut ); - - // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. ) - for ( g = 0; g <= vOut - 6; g += 2 ) - { - // rasterize - render->drawTriangle ( CurrentOut.data + 1, &CurrentOut.data[g + 3], &CurrentOut.data[g + 5] ); - } - - } -#else - draw2DRectangle ( colorLeftUp, position, clip ); -#endif -} - - //! Draws a 3d line. void CBurningVideoDriver::draw3DLine(const core::vector3df& start, - const core::vector3df& end, SColor color) + const core::vector3df& end, SColor color_start) { - Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[0].Pos.x, start ); - Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[2].Pos.x, end ); + SColor color_end = color_start; - u32 g; - u32 vOut; + VertexCache.primitiveHasVertex = 2; + VertexCache.vType = E4VT_LINE; - // no clipping flags - for ( g = 0; g != CurrentOut.ElementSize; ++g ) - { - CurrentOut.data[g].flag = 0; - Temp.data[g].flag = 0; - } + s4DVertex* v = Clipper.data; - // vertices count per line - vOut = clipToFrustum ( CurrentOut.data, Temp.data, 2 ); - if ( vOut < 2 ) - return; + transform_calc(ETS_PROJ_MODEL_VIEW); + const core::matrix4* matrix = Transformation[TransformationStack]; + matrix[ETS_PROJ_MODEL_VIEW].transformVect ( &v[0].Pos.x, start ); + matrix[ETS_PROJ_MODEL_VIEW].transformVect ( &v[2].Pos.x, end ); - vOut <<= 1; - - IBurningShader * line; - line = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ]; - line->setRenderTarget(RenderTargetSurface, ViewPort); - - // to DC Space, project homogenous vertex - ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut ); - - // unproject vertex color -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - for ( g = 0; g != vOut; g+= 2 ) - { - CurrentOut.data[ g + 1].Color[0].setA8R8G8B8 ( color.color ); - } +#if BURNING_MATERIAL_MAX_COLORS > 0 + v[0].Color[0].setA8R8G8B8 ( color_start.color ); + v[2].Color[0].setA8R8G8B8 ( color_end.color ); #endif - - for ( g = 0; g <= vOut - 4; g += 2 ) + u32 i; + for (i = 0; i < 4; i += sizeof_s4DVertexPairRel) { - // rasterize - line->drawLine ( CurrentOut.data + 1, CurrentOut.data + g + 3 ); + v[i + 0].flag = (u32)(VertexCache.vSize[VertexCache.vType].Format); + v[i + 1].flag = v[i + 0].flag; } + + + size_t g; + size_t vOut; + + // vertices count per line + vOut = clipToFrustum (VertexCache.primitiveHasVertex); + if ( vOut < VertexCache.primitiveHasVertex) + return; + + vOut *= sizeof_s4DVertexPairRel; + + // to DC Space, project homogenous vertex + ndc_2_dc_and_project ( v + 1, v, vOut ); + + // unproject vertex color +#if 0 +#if BURNING_MATERIAL_MAX_COLORS > 0 + for ( g = 0; g != vOut; g+= 2 ) + { + v[ g + 1].Color[0].setA8R8G8B8 ( color.color ); + } +#endif +#endif + + IBurningShader * shader = 0; + if ( CurrentShader && CurrentShader->canWireFrame() ) shader = CurrentShader; + else shader = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ]; + shader = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ]; + + shader->pushEdgeTest(1,0,1); + shader->setRenderTarget(RenderTargetSurface, ViewPort); + + for ( g = 0; g <= vOut - 4; g += sizeof_s4DVertexPairRel) + { + shader->drawLine ( v + 1 + g, v + 1 + g + sizeof_s4DVertexPairRel); + } + + shader->popEdgeTest(); + } @@ -2178,20 +3561,22 @@ void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const wchar_t* CBurningVideoDriver::getName() const { #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL - return L"Burning's Video 0.49 beautiful"; + return L"Burning's Video 0.51 beautiful"; #elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST ) - return L"Burning's Video 0.49 ultra fast"; + return L"Burning's Video 0.51 ultra fast"; #elif defined ( BURNINGVIDEO_RENDERER_FAST ) - return L"Burning's Video 0.49 fast"; + return L"Burning's Video 0.51 fast"; +#elif defined ( BURNINGVIDEO_RENDERER_CE ) + return L"Burning's Video 0.51 CE"; #else - return L"Burning's Video 0.49"; + return L"Burning's Video 0.51"; #endif } //! Returns the graphics card vendor name. core::stringc CBurningVideoDriver::getVendorInfo() { - return "Burning's Video: Ing. Thomas Alten (c) 2006-2015"; + return "Burning's Video: Ing. Thomas Alten (c) 2006-2020"; } @@ -2209,19 +3594,12 @@ ECOLOR_FORMAT CBurningVideoDriver::getColorFormat() const } -//! Returns the transformation set by setTransform -const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE state) const -{ - return Transformation[state]; -} - - //! Creates a render target texture. ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) { IImage* img = createImage(BURNINGSHADER_COLOR_FORMAT, size); - ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET ); + ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET,this); img->drop(); addTexture(tex); tex->drop(); @@ -2234,12 +3612,31 @@ void CBurningVideoDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 ste RenderTargetSurface->fill(color); if ((flag & ECBF_DEPTH) && DepthBuffer) - DepthBuffer->clear(); + DepthBuffer->clear(depth); if ((flag & ECBF_STENCIL) && StencilBuffer) - StencilBuffer->clear(); + StencilBuffer->clear(stencil); } +#if 0 +void CBurningVideoDriver::saveBuffer() +{ + static int shotCount = 0; + char buf[256]; + if (BackBuffer) + { + sprintf(buf, "shot/%04d_b.png", shotCount); + writeImageToFile(BackBuffer, buf); + } + if (StencilBuffer) + { + CImage stencil(ECF_A8R8G8B8, StencilBuffer->getSize(), StencilBuffer->lock(), true, false); + sprintf(buf, "shot/%04d_s.ppm", shotCount); + writeImageToFile(&stencil, buf); + } + shotCount += 1; +} +#endif //! Returns an image created from the last rendered frame. IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) @@ -2259,9 +3656,17 @@ IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video ITexture* CBurningVideoDriver::createDeviceDependentTexture(const io::path& name, IImage* image) { - CSoftwareTexture2* texture = new CSoftwareTexture2(image, name, (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0) | - (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE)); + u32 flags = + ((TextureCreationFlags & ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0) + | ((TextureCreationFlags & ETCF_AUTO_GENERATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP_AUTO : 0) + | ((TextureCreationFlags & ETCF_ALLOW_NON_POWER_2) ? CSoftwareTexture2::ALLOW_NPOT : 0) +#if defined(IRRLICHT_sRGB) + | ((TextureCreationFlags & ETCF_IMAGE_IS_LINEAR) ? CSoftwareTexture2::IMAGE_IS_LINEAR : 0) + | ((TextureCreationFlags & ETCF_TEXTURE_IS_LINEAR) ? CSoftwareTexture2::TEXTURE_IS_LINEAR : 0) +#endif + ; + CSoftwareTexture2* texture = new CSoftwareTexture2(image, name, flags, this); return texture; } @@ -2275,7 +3680,7 @@ ITexture* CBurningVideoDriver::createDeviceDependentTextureCubemap(const io::pat //! call. u32 CBurningVideoDriver::getMaximalPrimitiveCount() const { - return 0xFFFFFFFF; + return 0x7FFFFFFF; } @@ -2285,58 +3690,61 @@ u32 CBurningVideoDriver::getMaximalPrimitiveCount() const void CBurningVideoDriver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { const u32 count = triangles.size(); - IBurningShader *shader = BurningShader [ ETR_STENCIL_SHADOW ]; - - CurrentShader = shader; - shader->setRenderTarget(RenderTargetSurface, ViewPort); + if (!StencilBuffer || !count) + return; Material.org.MaterialType = video::EMT_SOLID; Material.org.Lighting = false; Material.org.ZWriteEnable = video::EZW_OFF; - Material.org.ZBuffer = ECFN_LESSEQUAL; - LightSpace.Flags &= ~VERTEXTRANSFORM; + Material.org.ZBuffer = ECFN_LESS; + CurrentShader = BurningShader[ETR_STENCIL_SHADOW]; + + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); + CurrentShader->pushEdgeTest(Material.org.Wireframe, 0,0); + + //setMaterial + EyeSpace.TL_Flag &= ~(TL_TEXTURE_TRANSFORM | TL_LIGHT0_IS_NORMAL_MAP); + CurrentShader->setTLFlag(EyeSpace.TL_Flag); //glStencilMask(~0); //glStencilFunc(GL_ALWAYS, 0, ~0); - if (true)// zpass does not work yet - { - Material.org.BackfaceCulling = true; - Material.org.FrontfaceCulling = false; - shader->setParam ( 0, 0 ); - shader->setParam ( 1, 1 ); - shader->setParam ( 2, 0 ); - drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 ); - //glStencilOp(GL_KEEP, incr, GL_KEEP); - //glDrawArrays(GL_TRIANGLES,0,count); + //glEnable(GL_DEPTH_CLAMP); + if (zfail) + { Material.org.BackfaceCulling = false; Material.org.FrontfaceCulling = true; - shader->setParam ( 0, 0 ); - shader->setParam ( 1, 2 ); - shader->setParam ( 2, 0 ); - drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 ); - //glStencilOp(GL_KEEP, decr, GL_KEEP); - //glDrawArrays(GL_TRIANGLES,0,count); + Material.CullFlag = CULL_FRONT | CULL_INVISIBLE; + + CurrentShader->setStencilOp( StencilOp_KEEP, StencilOp_INCR, StencilOp_KEEP); + drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); + + Material.org.BackfaceCulling = true; + Material.org.FrontfaceCulling = false; + Material.CullFlag = CULL_BACK | CULL_INVISIBLE; + + CurrentShader->setStencilOp( StencilOp_KEEP, StencilOp_DECR, StencilOp_KEEP); + drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); } else // zpass { Material.org.BackfaceCulling = true; Material.org.FrontfaceCulling = false; - shader->setParam ( 0, 0 ); - shader->setParam ( 1, 0 ); - shader->setParam ( 2, 1 ); - //glStencilOp(GL_KEEP, GL_KEEP, incr); - //glDrawArrays(GL_TRIANGLES,0,count); + Material.CullFlag = CULL_BACK | CULL_INVISIBLE; + + CurrentShader->setStencilOp( StencilOp_KEEP, StencilOp_KEEP, StencilOp_INCR); + drawVertexPrimitiveList(triangles.const_pointer(), count, 0, count / 3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); Material.org.BackfaceCulling = false; Material.org.FrontfaceCulling = true; - shader->setParam ( 0, 0 ); - shader->setParam ( 1, 0 ); - shader->setParam ( 2, 2 ); - //glStencilOp(GL_KEEP, GL_KEEP, decr); - //glDrawArrays(GL_TRIANGLES,0,count); + Material.CullFlag = CULL_FRONT | CULL_INVISIBLE; + + CurrentShader->setStencilOp(StencilOp_KEEP, StencilOp_KEEP, StencilOp_DECR); + drawVertexPrimitiveList(triangles.const_pointer(), count, 0, count / 3, (video::E_VERTEX_TYPE) E4VT_SHADOW, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) E4IT_NONE); } + //glDisable(GL_DEPTH_CLAMP); + } //! Fills the stencil shadow with color. After the shadow volume has been drawn @@ -2351,30 +3759,44 @@ void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SCol const u32 h = RenderTargetSurface->getDimension().Height; const u32 w = RenderTargetSurface->getDimension().Width; tVideoSample *dst; - u32 *stencil; - u32* const stencilBase=(u32*) StencilBuffer->lock(); + const tStencilSample* stencil; + +#if defined(SOFTWARE_DRIVER_2_32BIT) + const u32 alpha = extractAlpha(leftUpEdge.color); + const u32 src = leftUpEdge.color; +#else + const u16 alpha = extractAlpha( leftUpEdge.color ) >> 3; + const u32 src = video::A8R8G8B8toA1R5G5B5( leftUpEdge.color ); +#endif + for ( u32 y = 0; y < h; ++y ) { dst = (tVideoSample*)RenderTargetSurface->getData() + ( y * w ); - stencil = stencilBase + ( y * w ); + stencil = (tStencilSample*)StencilBuffer->lock() + (y * w); for ( u32 x = 0; x < w; ++x ) { - if ( stencil[x] > 1 ) + if ( stencil[x] ) { - dst[x] = PixelBlend32 ( dst[x], leftUpEdge.color ); +#if defined(SOFTWARE_DRIVER_2_32BIT) + dst[x] = PixelBlend32 ( dst[x], src,alpha ); +#else + dst[x] = PixelBlend16( dst[x], src, alpha ); +#endif } } } - StencilBuffer->clear(); + if ( clearStencilBuffer ) + StencilBuffer->clear(0); } core::dimension2du CBurningVideoDriver::getMaxTextureSize() const { - return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE); + return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 1 << 20, + SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 1 << 20); } bool CBurningVideoDriver::queryTextureFormat(ECOLOR_FORMAT format) const @@ -2384,9 +3806,134 @@ bool CBurningVideoDriver::queryTextureFormat(ECOLOR_FORMAT format) const bool CBurningVideoDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const { - return CNullDriver::needsTransparentRenderPass(material) || material.isTransparent(); + return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation(); // || material.isTransparent(); } +s32 CBurningVideoDriver::addShaderMaterial(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) +{ + s32 materialID = -1; + + IBurningShader* shader = new IBurningShader( + this, materialID, + vertexShaderProgram, 0, video::EVST_VS_1_1, + pixelShaderProgram, 0, video::EPST_PS_1_1, + 0, 0, EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + + shader->drop(); + + return materialID; +} + +//! Adds a new material renderer to the VideoDriver, based on a high level shading language. +s32 CBurningVideoDriver::addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, + scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData + ) +{ + s32 materialID = -1; + + IBurningShader* shader = new IBurningShader( + this, materialID, + vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, + pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, + geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, + callback, baseMaterial, userData); + + shader->drop(); + + return materialID; +} + + +void CBurningVideoDriver::setFallback_Material(E_MATERIAL_TYPE fallback_MaterialType) +{ + //this should be in material.... + Material.Fallback_MaterialType = fallback_MaterialType; +} + +void CBurningVideoDriver::setBasicRenderStates(const SMaterial& material, + const SMaterial& lastMaterial, + bool resetAllRenderstates) +{ + +} + +//! Return an index constant for the vertex shader based on a name. +s32 CBurningVideoDriver::getVertexShaderConstantID(const c8* name) +{ + return -1; +} + +bool CBurningVideoDriver::setVertexShaderConstant(s32 index, const f32* floats, int count) +{ + return true; +} + +bool CBurningVideoDriver::setVertexShaderConstant(s32 index, const s32* ints, int count) +{ + return true; +} + +bool CBurningVideoDriver::setVertexShaderConstant(s32 index, const u32* ints, int count) +{ + return true; +} + +void CBurningVideoDriver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ +} + +//! Return an index constant for the pixel shader based on a name. +s32 CBurningVideoDriver::getPixelShaderConstantID(const c8* name) +{ + return -1; +} + +bool CBurningVideoDriver::setPixelShaderConstant(s32 index, const f32* floats, int count) +{ + return false; +} + +bool CBurningVideoDriver::setPixelShaderConstant(s32 index, const s32* ints, int count) +{ + return false; +} + +bool CBurningVideoDriver::setPixelShaderConstant(s32 index, const u32* ints, int count) +{ + return false; +} + +void CBurningVideoDriver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1) +{ +} + +//! Get pointer to the IVideoDriver interface +/** \return Pointer to the IVideoDriver interface */ +IVideoDriver* CBurningVideoDriver::getVideoDriver() +{ + return this; +} } // end namespace video } // end namespace irr @@ -2394,41 +3941,6 @@ bool CBurningVideoDriver::needsTransparentRenderPass(const irr::video::SMaterial #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ -#if defined(_IRR_WINDOWS_) && defined(_IRR_COMPILE_WITH_BURNINGSVIDEO_) - #include - -struct dreadglobal -{ - DWORD dreadid; - HANDLE dread; - irr::video::CBurningVideoDriver *driver; - HANDLE sync; - - const irr::SIrrlichtCreationParameters* params; - irr::io::IFileSystem* io; - irr::video::IImagePresenter* presenter; -}; - -namespace -{ - dreadglobal burning_dread; -} - -DWORD WINAPI dreadFun( void *p) -{ - printf("Hi This is burning dread\n"); - burning_dread.driver = new irr::video::CBurningVideoDriver(*burning_dread.params, burning_dread.io, burning_dread.presenter); - - SetEvent (burning_dread.sync ); - while ( 1 ) - { - Sleep ( 1000 ); - } - return 0; -} - -#endif - namespace irr { namespace video @@ -2438,21 +3950,9 @@ namespace video IVideoDriver* createBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ - - #ifdef _IRR_WINDOWS_ - burning_dread.sync = CreateEventA ( 0, 0, 0, "burnevent0" ); - burning_dread.params = ¶ms; - burning_dread.io = io; - burning_dread.presenter = presenter; - burning_dread.dread = CreateThread ( 0, 0, dreadFun, 0, 0, &burning_dread.dreadid ); - WaitForSingleObject (burning_dread.sync, INFINITE ); - return burning_dread.driver; + return new CBurningVideoDriver(params, io, presenter); #else - return new CBurningVideoDriver(params, io, presenter); - #endif - - #else - return 0; + return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } diff --git a/source/Irrlicht/CSoftwareDriver2.h b/source/Irrlicht/CSoftwareDriver2.h index 3e9d2aaf..803deae6 100644 --- a/source/Irrlicht/CSoftwareDriver2.h +++ b/source/Irrlicht/CSoftwareDriver2.h @@ -13,11 +13,12 @@ #include "irrString.h" #include "SIrrCreationParameters.h" + namespace irr { namespace video { - class CBurningVideoDriver : public CNullDriver + class CBurningVideoDriver : public CNullDriver, public IMaterialRendererServices { public: @@ -39,14 +40,15 @@ namespace video //! sets a material virtual void setMaterial(const SMaterial& material) _IRR_OVERRIDE_; - virtual bool setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor = SColor(255,0,0,0), - f32 clearDepth = 1.f, u8 clearStencil = 0) _IRR_OVERRIDE_; + virtual bool setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, + f32 clearDepth, u8 clearStencil) _IRR_OVERRIDE_; //! sets a viewport virtual void setViewPort(const core::rect& area) _IRR_OVERRIDE_; + virtual void setScissor(int x, int y, int width, int height); - virtual bool beginScene(u16 clearFlag, SColor clearColor = SColor(255,0,0,0), f32 clearDepth = 1.f, u8 clearStencil = 0, - const SExposedVideoData& videoData = SExposedVideoData(), core::rect* sourceRect = 0) _IRR_OVERRIDE_; + virtual bool beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, + const SExposedVideoData& videoData, core::rect* sourceRect) _IRR_OVERRIDE_; virtual bool endScene() _IRR_OVERRIDE_; @@ -83,23 +85,44 @@ namespace video const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) _IRR_OVERRIDE_; + //! draws a vertex primitive list in 2d + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) _IRR_OVERRIDE_; + + + //! draws an 2d image + //virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, bool useAlphaChannelOfTexture) _IRR_OVERRIDE_; + + /* NullDriver calls + draw2DImage(texture, destPos, + core::rect(core::position2d(0, 0), core::dimension2di(texture->getOriginalSize())), + 0, + SColor(255, 255, 255, 255), + useAlphaChannelOfTexture + */ + //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_; - //! Draws a part of the texture into the rectangle. + //! Draws a part of the texture into the rectangle. virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false) _IRR_OVERRIDE_; //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, - const core::vector3df& end, SColor color = SColor(255,255,255,255)) _IRR_OVERRIDE_; + const core::vector3df& end, SColor color_start) _IRR_OVERRIDE_; //! draw an 2d rectangle - virtual void draw2DRectangle(SColor color, const core::rect& pos, - const core::rect* clip = 0) _IRR_OVERRIDE_; + //virtual void draw2DRectangle(SColor color, const core::rect& pos, + // const core::rect* clip = 0) _IRR_OVERRIDE_; + + /* NullDriver calls + draw2DRectangle(pos, color, color, color, color, clip); + */ //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, @@ -131,7 +154,7 @@ namespace video virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN) _IRR_OVERRIDE_; - virtual void clearBuffers(u16 flag, SColor color = SColor(255,0,0,0), f32 depth = 1.f, u8 stencil = 0) _IRR_OVERRIDE_; + virtual void clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) _IRR_OVERRIDE_; //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) _IRR_OVERRIDE_; @@ -155,6 +178,9 @@ namespace video video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)) _IRR_OVERRIDE_; + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable = true) _IRR_OVERRIDE_; + //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() _IRR_OVERRIDE_; @@ -170,8 +196,70 @@ namespace video IDepthBuffer * getDepthBuffer () { return DepthBuffer; } IStencilBuffer * getStencilBuffer () { return StencilBuffer; } + //#define Tweak_Burning +#if defined(Tweak_Burning) + virtual void postEventFromUser(const void* sevent) _IRR_OVERRIDE_; +#endif + + //! Adds a new material renderer to the VideoDriver, using pixel and/or + //! vertex shaders to render geometry. + virtual s32 addShaderMaterial(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) _IRR_OVERRIDE_; + + //! Adds a new material renderer to the VideoDriver, based on a high level shading + //! language. Currently only HLSL in D3D9 is supported. + virtual s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName = 0, + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const c8* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = 0, + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) _IRR_OVERRIDE_; + + //IMaterialRendererService + + virtual void setBasicRenderStates(const SMaterial& material, + const SMaterial& lastMaterial, + bool resetAllRenderstates) _IRR_OVERRIDE_; + + //pass BaseMaterialID + void setFallback_Material(E_MATERIAL_TYPE fallback_MaterialType); + + //! Return an index constant for the vertex shader based on a name. + virtual s32 getVertexShaderConstantID(const c8* name) _IRR_OVERRIDE_; + virtual bool setVertexShaderConstant(s32 index, const f32* floats, int count) _IRR_OVERRIDE_; + virtual bool setVertexShaderConstant(s32 index, const s32* ints, int count) _IRR_OVERRIDE_; + virtual bool setVertexShaderConstant(s32 index, const u32* ints, int count) _IRR_OVERRIDE_; + virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) _IRR_OVERRIDE_; + + //! Return an index constant for the pixel shader based on a name. + virtual s32 getPixelShaderConstantID(const c8* name) _IRR_OVERRIDE_; + virtual bool setPixelShaderConstant(s32 index, const f32* floats, int count) _IRR_OVERRIDE_; + virtual bool setPixelShaderConstant(s32 index, const s32* ints, int count) _IRR_OVERRIDE_; + virtual bool setPixelShaderConstant(s32 index, const u32* ints, int count) _IRR_OVERRIDE_; + + virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) _IRR_OVERRIDE_; + + //! Get pointer to the IVideoDriver interface + /** \return Pointer to the IVideoDriver interface */ + virtual IVideoDriver* getVideoDriver() _IRR_OVERRIDE_; + protected: + void saveBuffer(); + //! sets a render target void setRenderTargetImage(video::CImage* image); @@ -191,9 +279,6 @@ namespace video video::IImage* RenderTargetSurface; core::dimension2d RenderTargetSize; - //! selects the right triangle renderer based on the render states. - void setCurrentShader(); - IBurningShader* CurrentShader; IBurningShader* BurningShader[ETR2_COUNT]; @@ -210,78 +295,89 @@ namespace video enum E_TRANSFORMATION_STATE_BURNING_VIDEO { ETS_VIEW_PROJECTION = ETS_COUNT, - ETS_CURRENT, - ETS_CLIPSCALE, - ETS_VIEW_INVERSE, - ETS_WORLD_INVERSE, + ETS_PROJ_MODEL_VIEW, + ETS_MODEL_VIEW, + ETS_NORMAL, //3x3 ModelView Tansposed Inverse - ETS_COUNT_BURNING + ETS_COUNT_BURNING = 16 }; enum E_TRANSFORMATION_FLAG { - ETF_IDENTITY = 1, - ETF_TEXGEN_CAMERA_NORMAL = 2, - ETF_TEXGEN_CAMERA_REFLECTION = 4, + ETF_VALID = 1, + ETF_IDENTITY = 2, + ETF_TEXGEN_CAMERA_SPHERE = 4, + ETF_TEXGEN_CAMERA_REFLECTION = 8, + ETF_TEXGEN_WRAP = 16, + ETF_TEXGEN_MASK = ETF_TEXGEN_CAMERA_SPHERE | ETF_TEXGEN_CAMERA_REFLECTION | ETF_TEXGEN_WRAP }; - u32 TransformationFlag[ETS_COUNT_BURNING]; - core::matrix4 Transformation[ETS_COUNT_BURNING]; + core::matrix4 Transformation[2][ETS_COUNT_BURNING]; + size_t TransformationFlag[2][ETS_COUNT_BURNING]; // E_TRANSFORMATION_FLAG - void getCameraPosWorldSpace (); - void getLightPosObjectSpace (); + size_t TransformationStack; // 0 .. 3D , 1 .. 2D + void setRenderStates2DMode(const video::SColor& color,video::ITexture* texture,bool useAlphaChannelOfTexture); + void setRenderStates3DMode(); + + //ETS_CLIPSCALE, // moved outside to stay at 16 matrices + f32 Transformation_ETS_CLIPSCALE[2][4]; + void transform_calc(E_TRANSFORMATION_STATE_BURNING_VIDEO state); + + //core::recti ViewPort; + AbsRectangle Scissor; // Vertex Cache - static const SVSize vSize[]; - SVertexCache VertexCache; - void VertexCache_reset (const void* vertices, u32 vertexCount, + int VertexCache_reset (const void* vertices, u32 vertexCount, const void* indices, u32 indexCount, E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); - void VertexCache_get ( const s4DVertex ** face ); - void VertexCache_getbypass ( s4DVertex ** face ); + void VertexCache_get (s4DVertexPair* face[4] ); + void VertexCache_map_source_format(); void VertexCache_fill ( const u32 sourceIndex,const u32 destIndex ); - s4DVertex * VertexCache_getVertex ( const u32 sourceIndex ); + s4DVertexPair* VertexCache_getVertex ( const u32 sourceIndex ) const; // culling & clipping - u32 clipToHyperPlane ( s4DVertex * dest, const s4DVertex * source, u32 inCount, const sVec4 &plane ); - u32 clipToFrustumTest ( const s4DVertex * v ) const; - u32 clipToFrustum ( s4DVertex *source, s4DVertex * temp, const u32 vIn ); + //size_t inline clipToHyperPlane (s4DVertexPair* burning_restrict dest, const s4DVertexPair* burning_restrict source, const size_t inCount, const sVec4 &plane ); + //size_t inline clipToFrustumTest ( const s4DVertex * v ) const; + public: + size_t clipToFrustum( const size_t vIn /*, const size_t clipmask_for_face*/ ); + protected: + + // holds transformed, clipped vertices for a triangle. triangle expands on clipping + // Buffer is in in pairs of 4DVertex (0 ... ndc, 1 .. dc and projected) + SAligned4DVertex Clipper; + SAligned4DVertex Clipper_temp; #ifdef SOFTWARE_DRIVER_2_LIGHTING + void lightVertex_eye ( s4DVertex *dest, u32 vertexargb ); +#endif - void lightVertex ( s4DVertex *dest, u32 vertexargb ); //! Sets the fog mode. virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) _IRR_OVERRIDE_; -#endif - // holds transformed, clipped vertices - SAlignedVertex CurrentOut; - SAlignedVertex Temp; + void ndc_2_dc_and_project (s4DVertexPair* dest,const s4DVertexPair* source, const size_t vIn ) const; - void ndc_2_dc_and_project ( s4DVertex *dest,s4DVertex *source, u32 vIn ) const; - f32 screenarea ( const s4DVertex *v0 ) const; - void select_polygon_mipmap ( s4DVertex *source, u32 vIn, u32 tex, const core::dimension2du& texSize ) const; - f32 texelarea ( const s4DVertex *v0, int tex ) const; + //const is misleading. **v is const that true, but not *v.. + f32 screenarea_inside (const s4DVertexPair* burning_restrict const face[] ) const; + s32 lodFactor_inside ( const s4DVertexPair* burning_restrict const face[], const size_t tex, f32 dc_area, f32 lod_bias ) const; + void select_polygon_mipmap_inside ( s4DVertex* burning_restrict face[], const size_t tex, const CSoftwareTexture2_Bound& b ) const; - - void ndc_2_dc_and_project2 ( const s4DVertex **v, const u32 size ) const; - f32 screenarea2 ( const s4DVertex **v ) const; - f32 texelarea2 ( const s4DVertex **v, int tex ) const; - void select_polygon_mipmap2 ( s4DVertex **source, u32 tex, const core::dimension2du& texSize ) const; - - - SBurningShaderLightSpace LightSpace; + void getCameraPosWorldSpace(); + SBurningShaderEyeSpace EyeSpace; SBurningShaderMaterial Material; - static const sVec4 NDCPlane[6]; + static const sVec4 NDCPlane[6+2]; + + //! Built-in 2D quad for 2D rendering. + S3DVertex Quad2DVertices[4]; + }; } // end namespace video diff --git a/source/Irrlicht/CSoftwareTexture2.cpp b/source/Irrlicht/CSoftwareTexture2.cpp index 44a7e6be..b17e462d 100644 --- a/source/Irrlicht/CSoftwareTexture2.cpp +++ b/source/Irrlicht/CSoftwareTexture2.cpp @@ -9,6 +9,7 @@ #include "SoftwareDriver2_helper.h" #include "CSoftwareTexture2.h" #include "CSoftwareDriver2.h" +#include "CBlit.h" #include "os.h" namespace irr @@ -16,125 +17,204 @@ namespace irr namespace video { +//! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB) +void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect* dstRect, const video::IImage* src, const core::rect* srcRect, size_t flags); + //! constructor -CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags) - : ITexture(name, ETT_2D), MipMapLOD(0), Flags ( flags ), OriginalFormat(video::ECF_UNKNOWN) +CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags, CBurningVideoDriver* driver) + : ITexture(name +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) + , ETT_2D +#endif + ) + ,MipMapLOD(0), Flags(flags), Driver(driver) { #ifdef _DEBUG setDebugName("CSoftwareTexture2"); #endif #ifndef SOFTWARE_DRIVER_2_MIPMAPPING - Flags &= ~GEN_MIPMAP; + Flags &= ~(GEN_MIPMAP| GEN_MIPMAP_AUTO); #endif - + //set baseclass properties DriverType = EDT_BURNINGSVIDEO; ColorFormat = BURNINGSHADER_COLOR_FORMAT; IsRenderTarget = (Flags & IS_RENDERTARGET) != 0; - - memset32 ( MipMap, 0, sizeof ( MipMap ) ); + HasMipMaps = (Flags & GEN_MIPMAP) != 0; + MipMap0_Area[0] = 1; + MipMap0_Area[1] = 1; + LodBIAS = 0.75f; + for ( size_t i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) MipMap[i] = 0; + if (!image) return; - if (image) + OriginalSize = image->getDimension(); + OriginalColorFormat = image->getColorFormat(); + + +#if defined(IRRLICHT_sRGB) + if ( Flags & IMAGE_IS_LINEAR ) image->set_sRGB(0); +#else + //guessing linear image + if (name.find("light") >= 0 || + name.find("bump") >= 0 || + name.find("height") >= 0 + ) { - bool IsCompressed = false; - - if (IImage::isCompressedFormat(image->getColorFormat())) - { - os::Printer::log("Texture compression not available.", ELL_ERROR); - IsCompressed = true; - } - - OriginalSize = image->getDimension(); - OriginalFormat = image->getColorFormat(); - - core::dimension2d optSize( - OriginalSize.getOptimalSize(0 != (Flags & NP2_SIZE), - false, true, - SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE) - ); - - if (OriginalSize == optSize) - { - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); - - if (!IsCompressed) - image->copyTo(MipMap[0]); - } - else - { - char buf[256]; - core::stringw showName ( name ); - snprintf_irr ( buf, 256, "Burningvideo: Warning Texture %ls reformat %dx%d -> %dx%d,%d", - showName.c_str(), - OriginalSize.Width, OriginalSize.Height, optSize.Width, optSize.Height, - BURNINGSHADER_COLOR_FORMAT - ); - - OriginalSize = optSize; - os::Printer::log ( buf, ELL_WARNING ); - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); - - if (!IsCompressed) - image->copyToScalingBoxFilter ( MipMap[0],0, false ); - } - - Size = MipMap[MipMapLOD]->getDimension(); - Pitch = MipMap[MipMapLOD]->getPitch(); - - OrigImageDataSizeInPixels = (f32) 0.3f * MipMap[0]->getImageDataSizeInPixels(); - - HasMipMaps = (Flags & GEN_MIPMAP) != 0; - - regenerateMipMapLevels(image->getMipMapsData()); + Flags |= TEXTURE_IS_LINEAR | IMAGE_IS_LINEAR; } +#endif + + bool isCompressed = IImage::isCompressedFormat(OriginalColorFormat); + if (isCompressed) + { + os::Printer::log("Texture compression not available.", ELL_ERROR); + } + + //visual studio code warning + u32 maxTexSize = SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE; + core::dimension2d optSize( OriginalSize.getOptimalSize( + (Flags & ALLOW_NPOT) ? 0 : 1, // requirePowerOfTwo + false, // requireSquare + (Flags & ALLOW_NPOT) ? 1 : maxTexSize == 0, // larger + (Flags & ALLOW_NPOT) ? 0 : maxTexSize // maxValue + ) + ); + + if (OriginalSize == optSize) + { + MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); +#if defined(IRRLICHT_sRGB) + MipMap[0]->set_sRGB( (Flags & TEXTURE_IS_LINEAR ) ? 0 : image->get_sRGB() ); +#endif + if (!isCompressed) + image->copyTo(MipMap[0]); + } + else + { + char buf[256]; + core::stringw showName ( name ); + snprintf_irr ( buf, sizeof(buf), "Burningvideo: Warning Texture %ls reformat %ux%u,%d -> %ux%u,%d", + showName.c_str(), + OriginalSize.Width, OriginalSize.Height, OriginalColorFormat, + optSize.Width, optSize.Height,BURNINGSHADER_COLOR_FORMAT + ); + + os::Printer::log ( buf, ELL_WARNING ); + MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); +#if defined(IRRLICHT_sRGB) + MipMap[0]->set_sRGB( (Flags & TEXTURE_IS_LINEAR ) ? 0 : image->get_sRGB() ); +#endif + if (!isCompressed) + { + //image->copyToScalingBoxFilter ( MipMap[0],0, false ); + Resample_subSampling(BLITTER_TEXTURE,MipMap[0],0,image,0, Flags); + } + // if Original Size is used for calculation ( 2D position, font) it will be wrong + //OriginalSize = optSize; + } + + //select highest mipmap 0 + regenerateMipMapLevels(image->getMipMapsData()); } //! destructor CSoftwareTexture2::~CSoftwareTexture2() { - for ( s32 i = 0; i!= SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) + for ( size_t i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) { if ( MipMap[i] ) + { MipMap[i]->drop(); + MipMap[i] = 0; + } } } + //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture +#if !defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) +#else +void CSoftwareTexture2::regenerateMipMapLevels(void* data) +#endif { - if (!hasMipMaps()) - return; - - s32 i; + int i; // release for ( i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) { if ( MipMap[i] ) + { MipMap[i]->drop(); + MipMap[i] = 0; + } } core::dimension2d newSize; - core::dimension2d origSize = Size; - for (i=1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + if (HasMipMaps && ( (Flags & GEN_MIPMAP_AUTO) || 0 == data ) ) { - newSize = MipMap[i-1]->getDimension(); - newSize.Width = core::s32_max ( 1, newSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); - newSize.Height = core::s32_max ( 1, newSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); - origSize.Width = core::s32_max(1, origSize.Width >> 1); - origSize.Height = core::s32_max(1, origSize.Height >> 1); - - if (data) + //need memory also if autogen mipmap disabled + for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) { - if (OriginalFormat != BURNINGSHADER_COLOR_FORMAT) + const core::dimension2du& upperDim = MipMap[i - 1]->getDimension(); + //isotropic + newSize.Width = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Width >> 1); + newSize.Height = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Height >> 1); + if (upperDim == newSize) + break; + + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); +#if defined(IRRLICHT_sRGB) + MipMap[i]->set_sRGB(MipMap[i - 1]->get_sRGB()); +#endif + //MipMap[i]->fill ( 0xFFFF4040 ); + //MipMap[i-1]->copyToScalingBoxFilter( MipMap[i], 0, false ); + Resample_subSampling(BLITTER_TEXTURE, MipMap[i], 0, MipMap[0], 0, Flags); + } + } + else if (HasMipMaps && data) + { + //deactivated outside mipdata until TA knows how to handle this. + + //query mipmap dimension + u8* mip_current = (u8*)data; + const u8* mip_end = (u8*)data; + + core::dimension2d origSize = OriginalSize; + i = 1; + do + { + if (origSize.Width > 1) origSize.Width >>= 1; + if (origSize.Height > 1) origSize.Height >>= 1; + mip_end += IImage::getDataSizeFromFormat(OriginalColorFormat, origSize.Width, origSize.Height); + i += 1; + } while ((origSize.Width != 1 || origSize.Height != 1) && i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX); + + //TODO: this is not true + LodBIAS = i*0.75f; + + origSize = OriginalSize; + for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX && mip_current < mip_end; ++i) + { + const core::dimension2du& upperDim = MipMap[i - 1]->getDimension(); + //isotropic + newSize.Width = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Width >> 1); + newSize.Height = core::s32_max(SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE, upperDim.Height >> 1); + if (upperDim == newSize) + break; + + if (origSize.Width > 1) origSize.Width >>= 1; + if (origSize.Height > 1) origSize.Height >>= 1; + + if (OriginalColorFormat != BURNINGSHADER_COLOR_FORMAT) { - IImage* tmpImage = new CImage(OriginalFormat, origSize, data, true, false); + IImage* tmpImage = new CImage(OriginalColorFormat, origSize, mip_current, true, false); MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - if (origSize==newSize) + if (origSize == newSize) tmpImage->copyTo(MipMap[i]); else tmpImage->copyToScalingBoxFilter(MipMap[i]); @@ -142,33 +222,121 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) } else { - if (origSize==newSize) - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, data, false); + if (origSize == newSize) + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mip_current, false); else { MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, data, true, false); + IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mip_current, true, false); tmpImage->copyToScalingBoxFilter(MipMap[i]); tmpImage->drop(); } } - data = (u8*)data +origSize.getArea()*IImage::getBitsPerPixelFromFormat(OriginalFormat)/8; + mip_current += IImage::getDataSizeFromFormat(OriginalColorFormat, origSize.Width, origSize.Height); + } + } + + + //visualize mipmap + for (i=1; i < 0 && i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + { +/* + static u32 color[] = { + 0x30bf7f00,0x3040bf00,0x30bf00bf,0x3000bf00, + 0x300080bf,0x30bf4000,0x300040bf,0x307f00bf, + 0x30bf0000,0x3000bfbf,0x304000bf,0x307fbf00, + 0x8000bf7f,0x80bf0040,0x80bfbf00,0x800000bf + }; +*/ + static u32 color[] = { + 0xFFFFFFFF,0xFFFF0000,0xFF00FF00,0xFF0000FF, + 0xFFFFFF00,0xFF00FFFF,0xFFFF00FF,0xFF0000FF, + 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFF0000FF, + 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFFFF00FF + }; + + if ( MipMap[i] ) + { + core::rect p (core::position2di(0,0),MipMap[i]->getDimension()); + SColor c((color[i & 15] & 0x00FFFFFF) | 0xFF000000); + Blit(BLITTER_TEXTURE_ALPHA_COLOR_BLEND, MipMap[i], 0, 0, MipMap[i], &p, c.color); + } + } + + //save mipmap chain + if ( 0 ) + { + char buf[256]; + const char* name = getName().getPath().c_str(); + int filename = 0; + //int ext = -1; + i = 0; + while (name[i]) + { + if (name[i] == '/' || name[i] == '\\') filename = i + 1; + //if (name[i] == '.') ext = i; + i += 1; + } + for (i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + { + if (MipMap[i]) + { + snprintf_irr(buf, sizeof(buf),"mip/%s_%02d.png", name + filename,i); + Driver->writeImageToFile(MipMap[i], buf); + } + } + } + + calcDerivative(); +} + +void CSoftwareTexture2::calcDerivative() +{ + //reset current MipMap + MipMapLOD = 0; + if (MipMap[0]) + { + const core::dimension2du& dim = MipMap[0]->getDimension(); + MipMap0_Area[0] = dim.Width; + MipMap0_Area[1] = dim.Height; // screensize of a triangle + + Size = dim; // MipMap[MipMapLOD]->getDimension(); + Pitch = MipMap[MipMapLOD]->getPitch(); + } + + //preCalc mipmap texel center boundaries + for ( s32 i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) + { + CSoftwareTexture2_Bound& b = TexBound[i]; + if (MipMap[i]) + { + const core::dimension2du& dim = MipMap[i]->getDimension(); + //f32 u = 1.f / dim.Width; + //f32 v = 1.f / dim.Height; + + b.w = dim.Width - 1.f; + b.h = dim.Height - 1.f; + b.cx = 0.f; //u*0.005f; + b.cy = 0.f; //v*0.005f; } else { - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - - //static u32 color[] = { 0, 0xFFFF0000, 0xFF00FF00,0xFF0000FF,0xFFFFFF00,0xFFFF00FF,0xFF00FFFF,0xFF0F0F0F }; - MipMap[i]->fill ( 0 ); - MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0, false ); + b.w = 0.f; + b.h = 0.f; + b.cx = 0.f; + b.cy = 0.f; } } + } /* Software Render Target 2 */ CSoftwareRenderTarget2::CSoftwareRenderTarget2(CBurningVideoDriver* driver) : Driver(driver) +#if defined(PATCH_SUPERTUX_8_0_1_with_1_9_0) +, IRenderTarget(0) +#endif { DriverType = EDT_BURNINGSVIDEO; @@ -216,6 +384,290 @@ ITexture* CSoftwareRenderTarget2::getTexture() const } + +static const float srgb_8bit_to_linear_float[1 << 8] = { + 0.0f, 3.03527e-4f, 6.07054e-4f, 9.10581e-4f, + 0.001214108f, 0.001517635f, 0.001821162f, 0.0021246888f, + 0.002428216f, 0.002731743f, 0.00303527f, 0.0033465358f, + 0.0036765074f, 0.004024717f, 0.004391442f, 0.0047769537f, + 0.005181517f, 0.005605392f, 0.0060488335f, 0.006512091f, + 0.0069954107f, 0.007499032f, 0.008023193f, 0.008568126f, + 0.009134059f, 0.009721218f, 0.010329823f, 0.010960095f, + 0.011612245f, 0.012286489f, 0.0129830325f, 0.013702083f, + 0.014443845f, 0.015208516f, 0.015996294f, 0.016807377f, + 0.017641956f, 0.018500222f, 0.019382363f, 0.020288564f, + 0.021219011f, 0.022173885f, 0.023153368f, 0.024157634f, + 0.025186861f, 0.026241222f, 0.027320893f, 0.02842604f, + 0.029556835f, 0.030713445f, 0.031896032f, 0.033104766f, + 0.034339808f, 0.035601314f, 0.036889452f, 0.038204372f, + 0.039546236f, 0.0409152f, 0.04231141f, 0.04373503f, + 0.045186203f, 0.046665087f, 0.048171826f, 0.049706567f, + 0.051269464f, 0.05286065f, 0.05448028f, 0.056128494f, + 0.057805438f, 0.059511244f, 0.06124606f, 0.06301002f, + 0.06480327f, 0.066625945f, 0.068478175f, 0.0703601f, + 0.07227185f, 0.07421357f, 0.07618539f, 0.07818743f, + 0.08021983f, 0.082282715f, 0.084376216f, 0.086500466f, + 0.08865559f, 0.09084172f, 0.093058966f, 0.09530747f, + 0.097587354f, 0.09989873f, 0.10224174f, 0.10461649f, + 0.107023105f, 0.10946172f, 0.111932434f, 0.11443538f, + 0.11697067f, 0.119538434f, 0.122138776f, 0.12477182f, + 0.12743768f, 0.13013647f, 0.13286832f, 0.13563333f, + 0.13843162f, 0.14126329f, 0.14412847f, 0.14702727f, + 0.14995979f, 0.15292616f, 0.15592647f, 0.15896083f, + 0.16202939f, 0.1651322f, 0.1682694f, 0.17144111f, + 0.1746474f, 0.17788842f, 0.18116425f, 0.18447499f, + 0.18782078f, 0.19120169f, 0.19461784f, 0.19806932f, + 0.20155625f, 0.20507874f, 0.20863687f, 0.21223076f, + 0.21586053f, 0.21952623f, 0.22322798f, 0.2269659f, + 0.23074007f, 0.23455061f, 0.2383976f, 0.24228115f, + 0.24620135f, 0.2501583f, 0.25415212f, 0.25818288f, + 0.2622507f, 0.26635563f, 0.27049783f, 0.27467734f, + 0.2788943f, 0.28314877f, 0.28744087f, 0.29177067f, + 0.2961383f, 0.3005438f, 0.30498734f, 0.30946895f, + 0.31398875f, 0.3185468f, 0.32314324f, 0.32777813f, + 0.33245155f, 0.33716366f, 0.34191445f, 0.3467041f, + 0.35153264f, 0.35640016f, 0.36130682f, 0.36625263f, + 0.3712377f, 0.37626216f, 0.38132605f, 0.38642946f, + 0.3915725f, 0.39675525f, 0.4019778f, 0.40724024f, + 0.41254264f, 0.4178851f, 0.4232677f, 0.42869052f, + 0.43415368f, 0.4396572f, 0.44520122f, 0.45078582f, + 0.45641103f, 0.46207702f, 0.4677838f, 0.4735315f, + 0.4793202f, 0.48514995f, 0.4910209f, 0.496933f, + 0.5028865f, 0.50888133f, 0.5149177f, 0.5209956f, + 0.52711517f, 0.53327644f, 0.5394795f, 0.5457245f, + 0.55201143f, 0.55834043f, 0.5647115f, 0.57112485f, + 0.57758045f, 0.58407843f, 0.59061885f, 0.5972018f, + 0.60382736f, 0.61049557f, 0.6172066f, 0.62396044f, + 0.63075715f, 0.6375969f, 0.6444797f, 0.65140563f, + 0.65837485f, 0.66538733f, 0.67244315f, 0.6795425f, + 0.6866853f, 0.6938718f, 0.7011019f, 0.7083758f, + 0.71569353f, 0.7230551f, 0.73046076f, 0.73791045f, + 0.74540424f, 0.7529422f, 0.7605245f, 0.76815116f, + 0.7758222f, 0.7835378f, 0.791298f, 0.7991027f, + 0.8069523f, 0.8148466f, 0.82278574f, 0.8307699f, + 0.838799f, 0.8468732f, 0.8549926f, 0.8631572f, + 0.8713671f, 0.8796224f, 0.8879231f, 0.8962694f, + 0.9046612f, 0.91309863f, 0.92158186f, 0.9301109f, + 0.9386857f, 0.9473065f, 0.9559733f, 0.9646863f, + 0.9734453f, 0.9822506f, 0.9911021f, 1.0f, +}; +/* +int linear_to_srgb_8bit(const float x) { + if (x <= 0.f) return 0; + if (x >= 1.f) return 255; + const float *table = SRGB_8BIT_TO_LINEAR_FLOAT; + int y = 0; + for (int i = 128; i != 0; i >>= 1) { + if (table[y + i] <= x) + y += i; + } + if (x - table[y] <= table[y + 1] - x) + return y; + else + return y + 1; +} +*/ + + +u32 linear_to_srgb_8bit(const float v) +{ + ieee754 c; + c.f = v; + const register size_t x = c.u; + const u32 *table = (u32*)srgb_8bit_to_linear_float; + register u32 y = 0; + y += table[y + 128] <= x ? 128 : 0; + y += table[y + 64] <= x ? 64 : 0; + y += table[y + 32] <= x ? 32 : 0; + y += table[y + 16] <= x ? 16 : 0; + y += table[y + 8] <= x ? 8 : 0; + y += table[y + 4] <= x ? 4 : 0; + y += table[y + 2] <= x ? 2 : 0; + y += table[y + 1] <= x ? 1 : 0; + + return y; +} + +// 2D Region half open [x0;x1[ +struct absrect2 +{ + s32 x0; + s32 y0; + s32 x1; + s32 y1; +}; + +static inline int clipTest(absrect2 &o, const core::rect* a, const absrect2& b) +{ + if (a == 0) + { + o.x0 = b.x0; + o.y0 = b.y0; + o.x1 = b.x1; + o.y1 = b.y1; + } + else + { + o.x0 = core::s32_max(a->UpperLeftCorner.X, b.x0); + o.x1 = core::s32_min(a->LowerRightCorner.X, b.x1); + o.y0 = core::s32_max(a->UpperLeftCorner.Y, b.y0); + o.y1 = core::s32_min(a->LowerRightCorner.Y, b.y1); + } + int clipTest = 0; + clipTest |= o.x0 >= o.x1 ? 1 : 0; + clipTest |= o.y0 >= o.y1 ? 2 : 0; + return clipTest; +} + +//! stretches srcRect src to dstRect dst, applying a sliding window box filter in linear color space (sRGB->linear->sRGB) +// todo: texture jumps (mip selection problem) +void Resample_subSampling(eBlitter op, video::IImage* dst, const core::rect* dstRect, + const video::IImage* src, const core::rect* srcRect,size_t flags) +{ + const absrect2 dst_clip = { 0,0,(s32)dst->getDimension().Width,(s32)dst->getDimension().Height }; + absrect2 dc; + if (clipTest(dc, dstRect, dst_clip)) return; + const video::ECOLOR_FORMAT dstFormat = dst->getColorFormat(); + u8* dstData = (u8*)dst->getData(); + + const absrect2 src_clip = { 0,0,(s32)src->getDimension().Width,(s32)src->getDimension().Height }; + absrect2 sc; + if (clipTest(sc, srcRect, src_clip)) return; + const video::ECOLOR_FORMAT srcFormat = src->getColorFormat(); + const u8* srcData = (u8*)src->getData(); + +#if defined(IRRLICHT_sRGB) + const int dst_sRGB = dst->get_sRGB(); + const int src_sRGB = src->get_sRGB(); +#else + const int dst_sRGB = (flags & CSoftwareTexture2::TEXTURE_IS_LINEAR) ? 0 : 1; + const int src_sRGB = (flags & CSoftwareTexture2::IMAGE_IS_LINEAR) ? 0 : 1; +#endif + + + + float scale[2]; + scale[0] = (float)(sc.x1 - sc.x0) / (float)(dc.x1 - dc.x0); + scale[1] = (float)(sc.y1 - sc.y0) / (float)(dc.y1 - dc.y0); + const float rs = 1.f / (scale[0] * scale[1]); + + float sum[4]; + u32 sbgra = 0; + + float f[4]; + int fi[4]; + f[3] = (float)sc.y0; + for (int dy = dc.y0; dy < dc.y1; ++dy) + { + f[1] = f[3]; + f[3] = sc.y0 + (dy + 1 - dc.y0)*scale[1]; + if (f[3] >= sc.y1) f[3] = sc.y1 - 0.001f; //todo:1.f/dim should be enough + + f[2] = (float)sc.x0; + for (int dx = dc.x0; dx < dc.x1; ++dx) + { + f[0] = f[2]; + f[2] = sc.x0 + (dx + 1 - dc.x0)*scale[0]; + if (f[2] >= sc.x1) f[2] = sc.x1 - 0.001f; + + //accumulate linear color + sum[0] = 0.f; + sum[1] = 0.f; + sum[2] = 0.f; + sum[3] = 0.f; + + //sample border + fi[0] = (int)(f[0]); + fi[1] = (int)(f[1]); + fi[2] = (int)(f[2]); + fi[3] = (int)(f[3]); + + float w[2]; + for (int fy = fi[1]; fy <= fi[3]; ++fy) + { + w[1] = 1.f; + if (fy == fi[1]) w[1] -= f[1] - fy; + if (fy == fi[3]) w[1] -= fy + 1 - f[3]; + + for (int fx = fi[0]; fx <= fi[2]; ++fx) + { + w[0] = 1.f; + if (fx == fi[0]) w[0] -= f[0] - fx; + if (fx == fi[2]) w[0] -= fx + 1 - f[2]; + + const float ws = w[1] * w[0] * rs; + + switch (srcFormat) + { + case video::ECF_A1R5G5B5: sbgra = video::A1R5G5B5toA8R8G8B8(*(u16*)(srcData + (fy*src_clip.x1) * 2 + (fx * 2))); break; + case video::ECF_R5G6B5: sbgra = video::R5G6B5toA8R8G8B8(*(u16*)(srcData + (fy*src_clip.x1) * 2 + (fx * 2))); break; + case video::ECF_A8R8G8B8: sbgra = *(u32*)(srcData + (fy*src_clip.x1) * 4 + (fx * 4)); break; + case video::ECF_R8G8B8: + { + const u8* p = srcData + (fy*src_clip.x1) * 3 + (fx * 3); + sbgra = 0xFF000000 | p[0] << 16 | p[1] << 8 | p[2]; + } break; + default: break; + } + if (src_sRGB) + { + sum[0] += srgb_8bit_to_linear_float[(sbgra) & 0xFF] * ws; + sum[1] += srgb_8bit_to_linear_float[(sbgra >> 8) & 0xFF] * ws; + sum[2] += srgb_8bit_to_linear_float[(sbgra >> 16) & 0xFF] * ws; + sum[3] += ((sbgra >> 24) & 0xFF) * ws; + } + else + { + sum[0] += ((sbgra) & 0xFF) * ws; + sum[1] += ((sbgra >> 8) & 0xFF) * ws; + sum[2] += ((sbgra >> 16) & 0xFF) * ws; + sum[3] += ((sbgra >> 24) & 0xFF) * ws; + } + + } + } + switch (op) + { + case BLITTER_TEXTURE_ALPHA_BLEND: + case BLITTER_TEXTURE_ALPHA_COLOR_BLEND: + break; + default: + break; + } + if (dst_sRGB) + { + sbgra = linear_to_srgb_8bit(sum[0]) | + linear_to_srgb_8bit(sum[1]) << 8 | + linear_to_srgb_8bit(sum[2]) << 16 | + (u32)(sum[3]) << 24; + } + else + { + sbgra = (u32)(sum[0]) | + (u32)(sum[1]) << 8 | + (u32)(sum[2]) << 16 | + (u32)(sum[3]) << 24; + } + switch (dstFormat) + { + case video::ECF_A8R8G8B8: *(u32*)(dstData + (dy*dst_clip.x1) * 4 + (dx * 4)) = sbgra; break; + case video::ECF_R8G8B8: + { + u8* p = dstData + (dy*dst_clip.x1) * 3 + (dx * 3); + p[2] = (sbgra) & 0xFF; + p[1] = (sbgra >> 8) & 0xFF; + p[0] = (sbgra >> 16) & 0xFF; + } break; + case video::ECF_A1R5G5B5: *(u16*)(dstData + (dy*dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toA1R5G5B5(sbgra); break; + case video::ECF_R5G6B5: *(u16*)(dstData + (dy*dst_clip.x1) * 2 + (dx * 2)) = video::A8R8G8B8toR5G6B5(sbgra); break; + default: + break; + } + } + } + +} + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/CSoftwareTexture2.h b/source/Irrlicht/CSoftwareTexture2.h index ac3c1fc5..4f6be486 100644 --- a/source/Irrlicht/CSoftwareTexture2.h +++ b/source/Irrlicht/CSoftwareTexture2.h @@ -21,6 +21,14 @@ class CBurningVideoDriver; /*! interface for a Video Driver dependent Texture. */ +struct CSoftwareTexture2_Bound +{ + f32 w; // width - 0.5f; + f32 h; // height- 0.5f; + f32 cx; // texelcenter x 1.f/width*0.5f + f32 cy; // texelcenter y 1.f/height*0.5f +}; + class CSoftwareTexture2 : public ITexture { public: @@ -28,21 +36,34 @@ public: //! constructor enum eTex2Flags { - GEN_MIPMAP = 1, - IS_RENDERTARGET = 2, - NP2_SIZE = 4, + GEN_MIPMAP = 1, // has mipmaps + GEN_MIPMAP_AUTO = 2, // automatic mipmap generation + IS_RENDERTARGET = 4, + ALLOW_NPOT = 8, //allow non power of two + IMAGE_IS_LINEAR = 16, + TEXTURE_IS_LINEAR = 32, }; - CSoftwareTexture2(IImage* surface, const io::path& name, u32 flags); + CSoftwareTexture2(IImage* surface, const io::path& name, u32 flags /*eTex2Flags*/, CBurningVideoDriver* driver); //! destructor virtual ~CSoftwareTexture2(); + u32 getMipmapLevel(s32 newLevel) const + { + if ( newLevel < 0 ) newLevel = 0; + else if ( newLevel >= SOFTWARE_DRIVER_2_MIPMAPPING_MAX ) newLevel = SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1; + + while ( newLevel > 0 && MipMap[newLevel] == 0 ) newLevel -= 1; + return newLevel; + } + //! lock function virtual void* lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E_TEXTURE_LOCK_FLAGS lockFlags = ETLF_FLIP_Y_UP_RTT) _IRR_OVERRIDE_ { if (Flags & GEN_MIPMAP) { - MipMapLOD = mipmapLevel; + //called from outside. must test + MipMapLOD = getMipmapLevel(mipmapLevel); Size = MipMap[MipMapLOD]->getDimension(); Pitch = MipMap[MipMapLOD]->getPitch(); } @@ -55,14 +76,19 @@ public: { } - //! Returns the size of the largest mipmap. + //! compare the area drawn with the area of the texture f32 getLODFactor( const f32 texArea ) const { - return OrigImageDataSizeInPixels * texArea; + return MipMap0_Area[0]* MipMap0_Area[1] * 0.5f * texArea; //return MipMap[0]->getImageDataSizeInPixels () * texArea; } - //! returns unoptimized surface + const u32* getMipMap0_Area() const + { + return MipMap0_Area; + } + + //! returns unoptimized surface (misleading name. burning can scale down originalimage) virtual CImage* getImage() const { return MipMap[0]; @@ -74,16 +100,27 @@ public: return MipMap[MipMapLOD]; } + //precalculated dimx-1/dimx*0.5f + const CSoftwareTexture2_Bound& getTexBound() const + { + return TexBound[MipMapLOD]; + } + virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) _IRR_OVERRIDE_; + f32 get_lod_bias() const { return LodBIAS; } private: - f32 OrigImageDataSizeInPixels; + void calcDerivative(); - CImage * MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; + //! controls MipmapSelection. relation between drawn area and image size + u32 MipMapLOD; // 0 .. original Texture pot -SOFTWARE_DRIVER_2_MIPMAPPING_MAX + u32 Flags; //eTex2Flags + CBurningVideoDriver* Driver; - u32 MipMapLOD; - u32 Flags; - ECOLOR_FORMAT OriginalFormat; + CImage* MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; + CSoftwareTexture2_Bound TexBound[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; + u32 MipMap0_Area[2]; + f32 LodBIAS; }; /*! @@ -103,9 +140,9 @@ protected: CBurningVideoDriver* Driver; }; - } // end namespace video } // end namespace irr -#endif +#endif // __C_SOFTWARE_2_TEXTURE_H_INCLUDED__ + diff --git a/source/Irrlicht/CTRGouraud2.cpp b/source/Irrlicht/CTRGouraud2.cpp index 194cc68b..d0488b57 100644 --- a/source/Irrlicht/CTRGouraud2.cpp +++ b/source/Irrlicht/CTRGouraud2.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -83,13 +83,11 @@ public: CTRGouraud2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle (const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + //virtual bool canWireFrame () { return true; } - -private: - void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; +protected: + virtual void scanline_bilinear (); }; @@ -136,8 +134,8 @@ void CTRGouraud2::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -145,7 +143,7 @@ void CTRGouraud2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -182,6 +180,7 @@ void CTRGouraud2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -193,34 +192,31 @@ void CTRGouraud2::scanline_bilinear () #ifdef IPOL_C0 tFixPoint r0, g0, b0; -#ifdef INVERSE_W - f32 inversew; -#endif + f32 inversew = FIX_POINT_F32_MUL * COLOR_MAX; #endif for ( s32 i = 0; i <= dx; ++i ) { + //if test active only first pixel + if ( (0 == EdgeTestPass) & i ) break; #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W - if ( line.w[0] >= z[i] ) + if (line.w[0] >= z[i] ) #endif { #ifdef IPOL_C0 + #ifdef INVERSE_W - inversew = core::reciprocal ( line.w[0] ); - - getSample_color ( r0, g0, b0, line.c[0][0] * inversew ); -#else - getSample_color ( r0, g0, b0, line.c[0][0] ); + inversew = fix_inverse32_color(line.w[0]); #endif - - dst[i] = fix_to_color ( r0, g0, b0 ); + vec4_to_fix( r0, g0, b0, line.c[0][0],inversew ); + dst[i] = fix_to_sample( r0, g0, b0 ); #else - dst[i] = COLOR_BRIGHT_WHITE; + dst[i] = PrimitiveColor; #endif #ifdef WRITE_Z @@ -251,7 +247,7 @@ void CTRGouraud2::scanline_bilinear () } -void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); @@ -262,10 +258,10 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_edge( ca ); + scan.invDeltaY[1] = reciprocal_edge( ba ); + scan.invDeltaY[2] = reciprocal_edge( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -351,8 +347,8 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -421,6 +417,7 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D // render a scanline scanline_bilinear (); + if ( EdgeTestPass & edge_test_first_line ) break; scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -454,7 +451,7 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D } // rasterize lower sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[2] ) + if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) @@ -510,8 +507,8 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -581,6 +578,7 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D // render a scanline scanline_bilinear (); + if ( EdgeTestPass & edge_test_first_line ) break; scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -630,6 +628,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTriangleRendererGouraud2(CBurningVideoDriver* driver) { + // ETR_GOURAUD . no texture #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGouraud2(driver); #else diff --git a/source/Irrlicht/CTRGouraudAlpha2.cpp b/source/Irrlicht/CTRGouraudAlpha2.cpp index 837ab3e4..dd425f8b 100644 --- a/source/Irrlicht/CTRGouraudAlpha2.cpp +++ b/source/Irrlicht/CTRGouraudAlpha2.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -84,15 +84,12 @@ public: CTRGouraudAlpha2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle ( const s4DVertex* burning_restrict a,const s4DVertex* burning_restrict b,const s4DVertex* burning_restrict c ) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; - }; //! constructor @@ -142,8 +139,8 @@ void CTRGouraudAlpha2::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -151,7 +148,7 @@ void CTRGouraudAlpha2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -188,6 +185,7 @@ void CTRGouraudAlpha2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -198,9 +196,7 @@ void CTRGouraudAlpha2::scanline_bilinear () #ifdef IPOL_C0 -#ifdef INVERSE_W - f32 inversew; -#endif + f32 inversew = FIX_POINT_F32_MUL; tFixPoint a0; tFixPoint r0, g0, b0; @@ -220,22 +216,20 @@ void CTRGouraudAlpha2::scanline_bilinear () { #ifdef IPOL_C0 #ifdef INVERSE_W - inversew = core::reciprocal ( line.w[0] ); - - getSample_color ( a0, r0, g0, b0, line.c[0][0] * inversew ); -#else - getSample_color ( a0, r0, g0, b0, line.c[0][0] ); + inversew = reciprocal_zero_no ( line.w[0] ); #endif + vec4_to_fix( a0, r0, g0, b0, line.c[0][0],inversew ); color_to_fix ( r1, g1, b1, dst[i] ); + fix_color_norm(a0); r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); - dst[i] = fix_to_color ( r2, g2, b2 ); + dst[i] = fix4_to_sample( a0,r2, g2, b2 ); #else - dst[i] = COLOR_BRIGHT_WHITE; + dst[i] = PrimitiveColor; #endif #ifdef WRITE_Z z[i] = line.z[0]; @@ -265,7 +259,7 @@ void CTRGouraudAlpha2::scanline_bilinear () } -void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -276,9 +270,9 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -365,8 +359,8 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -524,8 +518,8 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -642,6 +636,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTriangleRendererGouraudAlpha2(CBurningVideoDriver* driver) { + // ETR_GOURAUD_ALPHA unused #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGouraudAlpha2(driver); #else diff --git a/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp b/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp index b5453df0..d921cb03 100644 --- a/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp +++ b/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -84,14 +84,11 @@ public: CTRGouraudAlphaNoZ2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle (const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; - }; //! constructor @@ -138,8 +135,8 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -147,7 +144,7 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -184,6 +181,7 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -192,11 +190,10 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () + f32 inversew = FIX_POINT_F32_MUL * COLOR_MAX; + #ifdef IPOL_C0 -#ifdef INVERSE_W - f32 inversew; -#endif tFixPoint a0; tFixPoint r0, g0, b0; @@ -224,22 +221,21 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () #ifdef IPOL_C0 #ifdef IPOL_W - inversew = core::reciprocal ( line.w[0] ); - - getSample_color ( a0, r0, g0, b0, line.c[0][0] * inversew ); -#else - getSample_color ( a0, r0, g0, b0, line.c[0][0] ); + inversew = fix_inverse32_color(line.w[0]); #endif + vec4_to_fix( a0, r0, g0, b0, line.c[0][0],inversew ); + color_to_fix ( r1, g1, b1, dst[i] ); + fix_color_norm(a0); r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); - dst[i] = fix_to_color ( r2, g2, b2 ); + dst[i] = fix_to_sample( r2, g2, b2 ); #else - dst[i] = COLOR_BRIGHT_WHITE; + dst[i] = PrimitiveColor; #endif @@ -264,7 +260,7 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () } -void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRGouraudAlphaNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -275,9 +271,9 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -363,8 +359,8 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -522,8 +518,8 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -640,6 +636,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRGouraudAlphaNoZ2(CBurningVideoDriver* driver) { + //ETR_GOURAUD_ALPHA_NOZ - draw2DRectangle Gradient #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGouraudAlphaNoZ2(driver); #else diff --git a/source/Irrlicht/CTRGouraudNoZ2.cpp b/source/Irrlicht/CTRGouraudNoZ2.cpp new file mode 100644 index 00000000..2e0bc393 --- /dev/null +++ b/source/Irrlicht/CTRGouraudNoZ2.cpp @@ -0,0 +1,641 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" +#include "IBurningShader.h" + +#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + +// compile flag for this file +#undef USE_ZBUFFER +#undef IPOL_Z +#undef CMP_Z +#undef WRITE_Z + +#undef IPOL_W +#undef CMP_W +#undef WRITE_W + +#undef SUBTEXEL +#undef INVERSE_W + +#undef IPOL_C0 +#undef IPOL_T0 +#undef IPOL_T1 + +// define render case +#define SUBTEXEL +#define INVERSE_W + +#define USE_ZBUFFER +#define IPOL_W +//#define CMP_W +//#define WRITE_W + +#define IPOL_C0 +//#define IPOL_T0 +//#define IPOL_T1 + +// apply global override +#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + #undef INVERSE_W +#endif + +#ifndef SOFTWARE_DRIVER_2_SUBTEXEL + #undef SUBTEXEL +#endif + +#if BURNING_MATERIAL_MAX_COLORS < 1 + #undef IPOL_C0 +#endif + +#if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) + #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + #undef IPOL_W + #endif + #define IPOL_Z + + #ifdef CMP_W + #undef CMP_W + #define CMP_Z + #endif + + #ifdef WRITE_W + #undef WRITE_W + #define WRITE_Z + #endif + +#endif + + +namespace irr +{ + +namespace video +{ + +class CTRGouraudNoZ2 : public IBurningShader +{ +public: + + //! constructor + CTRGouraudNoZ2(CBurningVideoDriver* driver); + + //! draws an indexed triangle list + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual bool canWireFrame () { return true; } + +protected: + virtual void scanline_bilinear (); +}; + +//! constructor +CTRGouraudNoZ2::CTRGouraudNoZ2(CBurningVideoDriver* driver) +: IBurningShader(driver) +{ + #ifdef _DEBUG + setDebugName("CTRGouraudNoZ2"); + #endif +} + + + +/*! +*/ +void CTRGouraudNoZ2::scanline_bilinear () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + //fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + //z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + +#ifdef IPOL_C0 + tFixPoint r0, g0, b0; + + f32 inversew = FIX_POINT_F32_MUL * COLOR_MAX; + +#endif + + for ( s32 i = 0; i <= dx; ++i ) + { + if ( (0 == EdgeTestPass) & i ) break; + +#ifdef CMP_Z + if ( line.z[0] < z[i] ) +#endif +#ifdef CMP_W + if (line.w[0] >= z[i] ) +#endif + + { +#ifdef IPOL_C0 +#ifdef INVERSE_W + inversew = fix_inverse32_color(line.w[0]); +#endif + vec4_to_fix(r0, g0, b0, line.c[0][0], inversew); + dst[i] = fix_to_sample(r0, g0, b0); +#else + dst[i] = PrimitiveColor; +#endif + +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + +} + +void CTRGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) +{ + // sort on height, y + if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); + if ( a->Pos.y > c->Pos.y ) swapVertexPointer(&a, &c); + if ( b->Pos.y > c->Pos.y ) swapVertexPointer(&b, &c); + + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; + + // calculate delta y of the edges + scan.invDeltaY[0] = reciprocal_edge( ca ); + scan.invDeltaY[1] = reciprocal_edge( ba ); + scan.invDeltaY[2] = reciprocal_edge( cb ); + + if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) + return; + + // find if the major edge is left or right aligned + f32 temp[4]; + + temp[0] = a->Pos.x - c->Pos.x; + temp[1] = -ca; + temp[2] = b->Pos.x - a->Pos.x; + temp[3] = ba; + + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; + scan.right = 1 - scan.left; + + // calculate slopes for the major edge + scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; + scan.x[0] = a->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; + scan.z[0] = a->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; + scan.w[0] = a->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; + scan.t[0][0] = a->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; + scan.t[1][0] = a->Tex[1]; +#endif + + // top left fill convention y run + s32 yStart; + s32 yEnd; + +#ifdef SUBTEXEL + f32 subPixel; +#endif + + + // rasterize upper sub-triangle + if ( (f32) 0.0 != scan.invDeltaY[1] ) + { + // calculate slopes for top edge + scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; + scan.x[1] = a->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; + scan.z[1] = a->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; + scan.w[1] = a->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; + scan.t[0][1] = a->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; + scan.t[1][1] = a->Tex[1]; +#endif + + // apply top-left fill convention, top part + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); + +#ifdef SUBTEXEL + subPixel = ( (f32) yStart ) - a->Pos.y; + + // correct to pixel center + scan.x[0] += scan.slopeX[0] * subPixel; + scan.x[1] += scan.slopeX[1] * subPixel; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0] * subPixel; + scan.z[1] += scan.slopeZ[1] * subPixel; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0] * subPixel; + scan.w[1] += scan.slopeW[1] * subPixel; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0] * subPixel; + scan.t[0][1] += scan.slopeT[0][1] * subPixel; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0] * subPixel; + scan.t[1][1] += scan.slopeT[1][1] * subPixel; +#endif + +#endif + + // rasterize the edge scanlines + for( line.y = yStart; line.y <= yEnd; ++line.y) + { + line.x[scan.left] = scan.x[0]; + line.x[scan.right] = scan.x[1]; + +#ifdef IPOL_Z + line.z[scan.left] = scan.z[0]; + line.z[scan.right] = scan.z[1]; +#endif + +#ifdef IPOL_W + line.w[scan.left] = scan.w[0]; + line.w[scan.right] = scan.w[1]; +#endif + +#ifdef IPOL_C0 + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; +#endif + +#ifdef IPOL_T0 + line.t[0][scan.left] = scan.t[0][0]; + line.t[0][scan.right] = scan.t[0][1]; +#endif + +#ifdef IPOL_T1 + line.t[1][scan.left] = scan.t[1][0]; + line.t[1][scan.right] = scan.t[1][1]; +#endif + + // render a scanline + scanline_bilinear (); + if ( EdgeTestPass & edge_test_first_line ) break; + + scan.x[0] += scan.slopeX[0]; + scan.x[1] += scan.slopeX[1]; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0]; + scan.z[1] += scan.slopeZ[1]; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0]; + scan.w[1] += scan.slopeW[1]; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0]; + scan.t[0][1] += scan.slopeT[0][1]; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0]; + scan.t[1][1] += scan.slopeT[1][1]; +#endif + } + } + + // rasterize lower sub-triangle + if ( (f32) 0.0 != scan.invDeltaY[2] ) + { + // advance to middle point + if( (f32) 0.0 != scan.invDeltaY[1] ) + { + temp[0] = b->Pos.y - a->Pos.y; // dy + + scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; +#ifdef IPOL_Z + scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; +#endif +#ifdef IPOL_W + scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; +#endif +#ifdef IPOL_C0 + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; +#endif +#ifdef IPOL_T0 + scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; +#endif +#ifdef IPOL_T1 + scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; +#endif + + } + + // calculate slopes for bottom edge + scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; + scan.x[1] = b->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; + scan.z[1] = b->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; + scan.w[1] = b->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; + scan.t[0][1] = b->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; + scan.t[1][1] = b->Tex[1]; +#endif + + // apply top-left fill convention, top part + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); + +#ifdef SUBTEXEL + + subPixel = ( (f32) yStart ) - b->Pos.y; + + // correct to pixel center + scan.x[0] += scan.slopeX[0] * subPixel; + scan.x[1] += scan.slopeX[1] * subPixel; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0] * subPixel; + scan.z[1] += scan.slopeZ[1] * subPixel; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0] * subPixel; + scan.w[1] += scan.slopeW[1] * subPixel; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0] * subPixel; + scan.t[0][1] += scan.slopeT[0][1] * subPixel; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0] * subPixel; + scan.t[1][1] += scan.slopeT[1][1] * subPixel; +#endif + +#endif + + // rasterize the edge scanlines + for( line.y = yStart; line.y <= yEnd; ++line.y) + { + line.x[scan.left] = scan.x[0]; + line.x[scan.right] = scan.x[1]; + +#ifdef IPOL_Z + line.z[scan.left] = scan.z[0]; + line.z[scan.right] = scan.z[1]; +#endif + +#ifdef IPOL_W + line.w[scan.left] = scan.w[0]; + line.w[scan.right] = scan.w[1]; +#endif + +#ifdef IPOL_C0 + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; +#endif + +#ifdef IPOL_T0 + line.t[0][scan.left] = scan.t[0][0]; + line.t[0][scan.right] = scan.t[0][1]; +#endif + +#ifdef IPOL_T1 + line.t[1][scan.left] = scan.t[1][0]; + line.t[1][scan.right] = scan.t[1][1]; +#endif + + // render a scanline + scanline_bilinear (); + if ( EdgeTestPass & edge_test_first_line ) break; + + scan.x[0] += scan.slopeX[0]; + scan.x[1] += scan.slopeX[1]; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0]; + scan.z[1] += scan.slopeZ[1]; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0]; + scan.w[1] += scan.slopeW[1]; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0]; + scan.t[0][1] += scan.slopeT[0][1]; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0]; + scan.t[1][1] += scan.slopeT[1][1]; +#endif + + } + } + +} + + +} // end namespace video +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ + +namespace irr +{ +namespace video +{ + +//! creates a flat triangle renderer +IBurningShader* createTriangleRendererGouraudNoZ2(CBurningVideoDriver* driver) +{ + //ETR_GOURAUD_NOZ - no texture no depth test no depth write + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + return new CTRGouraudNoZ2(driver); + #else + return 0; + #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ +} + + +} // end namespace video +} // end namespace irr + + + diff --git a/source/Irrlicht/CTRNormalMap.cpp b/source/Irrlicht/CTRNormalMap.cpp index bc72b75c..5df81c7a 100644 --- a/source/Irrlicht/CTRNormalMap.cpp +++ b/source/Irrlicht/CTRNormalMap.cpp @@ -21,6 +21,7 @@ #undef INVERSE_W #undef IPOL_C0 +#undef IPOL_C1 #undef IPOL_T0 #undef IPOL_T1 #undef IPOL_T2 @@ -36,6 +37,7 @@ #define WRITE_W #define IPOL_C0 +#define IPOL_C1 #define IPOL_T0 #define IPOL_T1 #define IPOL_L0 @@ -49,10 +51,18 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif +#if BURNING_MATERIAL_MAX_COLORS < 2 + #undef IPOL_C1 +#endif + +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT < 1 + #undef IPOL_L0 +#endif + #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W @@ -87,14 +97,11 @@ public: CTRNormalMap(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; - + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; private: - void scanline_bilinear (); - - sScanConvertData scan; - sScanLineData line; + void fragmentShader(); }; @@ -108,10 +115,13 @@ CTRNormalMap::CTRNormalMap(CBurningVideoDriver* driver) } +void CTRNormalMap::OnSetMaterial(const SBurningShaderMaterial& material) +{ +} /*! */ -void CTRNormalMap::scanline_bilinear () +void CTRNormalMap::fragmentShader() { tVideoSample *dst; @@ -135,18 +145,18 @@ void CTRNormalMap::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif #ifdef IPOL_L0 - sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT]; + sVec3Pack_unpack slopeL[BURNING_MATERIAL_MAX_LIGHT_TANGENT]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -154,7 +164,7 @@ void CTRNormalMap::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -165,6 +175,9 @@ void CTRNormalMap::scanline_bilinear () #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif +#ifdef IPOL_C1 + slopeC[1] = (line.c[1][1] - line.c[1][0]) * invDeltaX; +#endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif @@ -189,6 +202,9 @@ void CTRNormalMap::scanline_bilinear () #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1] * subPixel; +#endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif @@ -203,6 +219,7 @@ void CTRNormalMap::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -210,25 +227,33 @@ void CTRNormalMap::scanline_bilinear () #endif - f32 inversew; + f32 inversew = FIX_POINT_F32_MUL; - tFixPoint tx0, tx1; - tFixPoint ty0, ty1; + tFixPoint tx0, ty0; + +#ifdef IPOL_T1 + tFixPoint tx1, ty1; +#endif tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; +#ifdef IPOL_L0 tFixPoint lx, ly, lz; - tFixPoint ndotl; - - sVec3 light; +#endif + tFixPoint ndotl = FIX_POINT_ONE; #ifdef IPOL_C0 - tFixPoint r3, g3, b3; + tFixPoint a3,r3, g3, b3; #endif +#ifdef IPOL_C1 + tFixPoint aFog = FIX_POINT_ONE; +#endif + + for ( s32 i = 0; i <= dx; i++ ) { #ifdef CMP_Z @@ -240,88 +265,13 @@ void CTRNormalMap::scanline_bilinear () { #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - - tx0 = tofix ( line.t[0][0].x,inversew); - ty0 = tofix ( line.t[0][0].y,inversew); - tx1 = tofix ( line.t[1][0].x,inversew); - ty1 = tofix ( line.t[1][0].y,inversew); - +#endif #ifdef IPOL_C0 - r3 = tofix ( line.c[0][0].y ,inversew ); - g3 = tofix ( line.c[0][0].z ,inversew ); - b3 = tofix ( line.c[0][0].w ,inversew ); -#endif - -#else - inversew = FIX_POINT_F32_MUL; - tx0 = tofix(line.t[0][0].x, inversew); - ty0 = tofix(line.t[0][0].y, inversew); - tx1 = tofix(line.t[1][0].x, inversew); - ty1 = tofix(line.t[1][0].y, inversew); - -#ifdef IPOL_C0 - r3 = tofix ( line.c[0][0].y ); - g3 = tofix ( line.c[0][0].z ); - b3 = tofix ( line.c[0][0].w ); -#endif - -#endif - getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); - - // normal map - getSample_texture ( r1, g1, b1, &IT[1], tx1, ty1 ); - - r1 = ( r1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); - g1 = ( g1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); - b1 = ( b1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); - -/* - sVec3 l = line.l[0][0] * inversew; - l.setLength( 2.f ); - - lx = tofix ( l.x - 0.5f ); - ly = tofix ( l.y - 0.5f ); - lz = tofix ( l.z - 0.5f ); -*/ - - lx = tofix ( line.l[0][0].x, inversew ); - ly = tofix ( line.l[0][0].y, inversew ); - lz = tofix ( line.l[0][0].z, inversew ); - - // DOT 3 Normal Map light in tangent space - ndotl = saturateFix ( FIX_POINT_HALF_COLOR + (( imulFix ( r1, lx ) + imulFix ( g1, ly ) + imulFix ( b1, lz ) ) << (COLOR_MAX_LOG2-1)) ); - -#ifdef IPOL_C0 - - // N . L - r2 = imulFix ( imulFix_tex1 ( r0, ndotl ), r3 ); - g2 = imulFix ( imulFix_tex1 ( g0, ndotl ), g3 ); - b2 = imulFix ( imulFix_tex1 ( b0, ndotl ), b3 ); - -/* - // heightmap: (1 - neu ) + alt - 0.5, on_minus_srcalpha + add signed - // emboss bump map - a4 -= a1; - r2 = clampfix_maxcolor ( clampfix_mincolor ( imulFix ( r0 + a4, r3 ) ) ); - g2 = clampfix_maxcolor ( clampfix_mincolor ( imulFix ( g0 + a4, g3 ) ) ); - b2 = clampfix_maxcolor ( clampfix_mincolor ( imulFix ( b0 + a4, b3 ) ) ); -*/ - -/* - r2 = clampfix_maxcolor ( imulFix_tex1 ( r2, r1 ) ); - g2 = clampfix_maxcolor ( imulFix_tex1 ( g2, g1 ) ); - b2 = clampfix_maxcolor ( imulFix_tex1 ( b2, b1 ) ); -*/ -#else - r2 = clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ); - g2 = clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ); - b2 = clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ); -#endif - - - dst[i] = fix_to_color ( r2, g2, b2 ); - + //vertex alpha blend ( and omit depthwrite ,hacky..) + a3 = tofix(line.c[0][0].x, inversew); + if (a3 + 2 >= FIX_POINT_ONE) + { #ifdef WRITE_Z z[i] = line.z[0]; #endif @@ -329,6 +279,87 @@ void CTRNormalMap::scanline_bilinear () z[i] = line.w[0]; #endif } +#endif + +#ifdef IPOL_C1 + //complete inside fog + if (TL_Flag & TL_FOG) + { + aFog = tofix(line.c[1][0].a, inversew); + if (aFog <= 0) + { + dst[i] = fog_color_sample; + continue; + } + } +#endif + + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); + + // diffuse map + getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); + + // normal map ( same texcoord0 but different mipmapping) + getSample_texture ( r1, g1, b1, &IT[1], tx1, ty1 ); + + r1 = ( r1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); + g1 = ( g1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); + b1 = ( b1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); + +#ifdef IPOL_L0 + lx = tofix ( line.l[0][0].x, inversew ); + ly = tofix ( line.l[0][0].y, inversew ); + lz = tofix ( line.l[0][0].z, inversew ); + + // DOT 3 Normal Map light in tangent space + //max(dot(LightVector, Normal), 0.0); + ndotl = clampfix_mincolor( (imulFix_simple(r1,lx) + imulFix_simple(g1,ly) + imulFix_simple(b1,lz) ) ); +#endif + +#ifdef IPOL_C0 + + //LightColor[0] + r3 = tofix(line.c[0][0].y, inversew); + g3 = tofix(line.c[0][0].z, inversew); + b3 = tofix(line.c[0][0].w, inversew); + + // Lambert * LightColor[0] * Diffuse Texture; + r2 = imulFix (imulFix_simple( r3, ndotl ), r0 ); + g2 = imulFix (imulFix_simple( g3, ndotl ), g0 ); + b2 = imulFix (imulFix_simple( b3, ndotl ), b0 ); + + //vertex alpha blend ( and omit depthwrite ,hacky..) + if (a3 + 2 < FIX_POINT_ONE) + { + color_to_fix(r1, g1, b1, dst[i]); + r2 = r1 + imulFix(a3, r2 - r1); + g2 = g1 + imulFix(a3, g2 - g1); + b2 = b1 + imulFix(a3, b2 - b1); + } + +#ifdef IPOL_C1 + //mix with distance + if (aFog < FIX_POINT_ONE) + { + r2 = fog_color[1] + imulFix(aFog, r2 - fog_color[1]); + g2 = fog_color[2] + imulFix(aFog, g2 - fog_color[2]); + b2 = fog_color[3] + imulFix(aFog, b2 - fog_color[3]); + } +#endif + dst[i] = fix_to_sample(r2, g2, b2); + + +#else + r2 = imulFix_tex4 ( r0, r1 ); + g2 = imulFix_tex4 ( g0, g1 ); + b2 = imulFix_tex4 ( b0, b1 ); + dst[i] = fix_to_sample(r2, g2, b2); +#endif + + } #ifdef IPOL_Z line.z[0] += slopeZ; @@ -339,6 +370,9 @@ void CTRNormalMap::scanline_bilinear () #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1]; +#endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif @@ -355,7 +389,7 @@ void CTRNormalMap::scanline_bilinear () } -void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRNormalMap::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -366,9 +400,9 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -403,6 +437,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][0] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][0] = (c->Color[1] - a->Color[1]) * scan.invDeltaY[0]; + scan.c[1][0] = a->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; @@ -433,7 +472,6 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 // rasterize upper sub-triangle - //if ( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge @@ -455,6 +493,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][1] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (b->Color[1] - a->Color[1]) * scan.invDeltaY[1]; + scan.c[1][1] = a->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; @@ -476,8 +519,8 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -501,6 +544,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -544,6 +592,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -565,7 +618,7 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 #endif // render a scanline - scanline_bilinear (); + fragmentShader (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -585,6 +638,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -609,11 +667,9 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 } // rasterize lower sub-triangle - //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point - //if( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy @@ -628,6 +684,9 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif +#ifdef IPOL_C1 + scan.c[1][0] = a->Color[1] + scan.slopeC[1][0] * temp[0]; +#endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif @@ -638,7 +697,7 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.t[2][0] = a->Tex[2] + scan.slopeT[2][0] * temp[0]; #endif #ifdef IPOL_L0 - scan.l[0][0] = a->LightTangent[0] + scan.slopeL[0][0] * temp[0]; + scan.l[0][0] = sVec3Pack_unpack(a->LightTangent[0]) + scan.slopeL[0][0] * temp[0]; #endif } @@ -662,6 +721,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][1] = b->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (c->Color[1] - b->Color[1]) * scan.invDeltaY[2]; + scan.c[1][1] = b->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; @@ -683,8 +747,8 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -709,6 +773,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -752,6 +821,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -773,7 +847,7 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 #endif // render a scanline - scanline_bilinear (); + fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -793,6 +867,11 @@ void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4 scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; diff --git a/source/Irrlicht/CTRStencilShadow.cpp b/source/Irrlicht/CTRStencilShadow.cpp index 02ed525d..82b5ed3d 100644 --- a/source/Irrlicht/CTRStencilShadow.cpp +++ b/source/Irrlicht/CTRStencilShadow.cpp @@ -47,7 +47,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -84,19 +84,10 @@ public: CTRStencilShadow(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; - virtual void setParam ( u32 index, f32 value) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: - // fragment shader - typedef void (CTRStencilShadow::*tFragmentShader) (); - void fragment_zfail_decr (); - void fragment_zfail_incr (); - - tFragmentShader fragmentShader; - - sScanConvertData scan; - sScanLineData line; + void fragmentShader(); }; @@ -112,36 +103,14 @@ CTRStencilShadow::CTRStencilShadow(CBurningVideoDriver* driver) /*! */ -void CTRStencilShadow::setParam ( u32 index, f32 value) +void CTRStencilShadow::fragmentShader() { - u32 val = (u32) value; - - // glStencilOp (fail,zfail,zpass - if ( index == 1 && val == 1 ) - { - fragmentShader = &CTRStencilShadow::fragment_zfail_incr; - } - else - if ( index == 1 && val == 2 ) - { - fragmentShader = &CTRStencilShadow::fragment_zfail_decr; - } -} - -/*! -*/ -void CTRStencilShadow::fragment_zfail_decr () -{ - if (!Stencil) - return; - //tVideoSample *dst; - #ifdef USE_ZBUFFER fp24 *z; #endif #ifdef USE_SBUFFER - u32 *stencil; + tStencilSample *stencil; #endif s32 xStart; @@ -158,27 +127,19 @@ void CTRStencilShadow::fragment_zfail_decr () #ifdef IPOL_W fp24 slopeW; #endif -#ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; -#endif -#ifdef IPOL_T0 - sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; -#endif -#ifdef IPOL_L0 - sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT]; -#endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; - if ( dx < 0 ) return; + SOFTWARE_DRIVER_2_CLIPCHECK; + // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -186,21 +147,6 @@ void CTRStencilShadow::fragment_zfail_decr () #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif -#ifdef IPOL_C0 - slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; -#endif -#ifdef IPOL_T0 - slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; -#endif -#ifdef IPOL_T1 - slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; -#endif -#ifdef IPOL_T2 - slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX; -#endif -#ifdef IPOL_L0 - slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX; -#endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; @@ -210,23 +156,8 @@ void CTRStencilShadow::fragment_zfail_decr () #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif -#ifdef IPOL_C0 - line.c[0][0] += slopeC[0] * subPixel; #endif -#ifdef IPOL_T0 - line.t[0][0] += slopeT[0] * subPixel; -#endif -#ifdef IPOL_T1 - line.t[1][0] += slopeT[1] * subPixel; -#endif -#ifdef IPOL_T2 - line.t[2][0] += slopeT[2] * subPixel; -#endif -#ifdef IPOL_L0 - line.l[0][0] += slopeL[0] * subPixel; -#endif -#endif - + SOFTWARE_DRIVER_2_CLIPCHECK; //dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -234,30 +165,43 @@ void CTRStencilShadow::fragment_zfail_decr () #endif #ifdef USE_SBUFFER - stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + stencil = (tStencilSample*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W - f32 inversew; + f32 inversew = FIX_POINT_F32_MUL; #endif - -#ifdef IPOL_C0 - tFixPoint r3, g3, b3; -#endif - - for ( s32 i = 0; i <= dx; i++ ) + s32 i; + for (i = 0; i <= dx; i++) { #ifdef CMP_Z - if ( line.z[0] < z[i] ) + if (line.z[0] < z[i]) #endif #ifdef CMP_W - if ( line.w[0] < z[i] ) + if (line.w[0] > z[i]) #endif + { + // zpass + switch (stencilOp[2]) + { + case StencilOp_INCR: stencil[i] += 1; break; + case StencilOp_DECR: stencil[i] -= 1; break;// core::s32_max(0, stencil[i] - 1); break; + default: + case StencilOp_KEEP: break; + } + } + else { // zfail - stencil[i] -= 1; + switch (stencilOp[1]) + { + case StencilOp_INCR: stencil[i] += 1; break; + case StencilOp_DECR: stencil[i] -= 1; break;// core::s32_max(0, stencil[i] - 1); break; + default: + case StencilOp_KEEP: break; + } } #ifdef IPOL_Z @@ -265,181 +209,13 @@ void CTRStencilShadow::fragment_zfail_decr () #endif #ifdef IPOL_W line.w[0] += slopeW; -#endif -#ifdef IPOL_C0 - line.c[0][0] += slopeC[0]; -#endif -#ifdef IPOL_T0 - line.t[0][0] += slopeT[0]; -#endif -#ifdef IPOL_T1 - line.t[1][0] += slopeT[1]; -#endif -#ifdef IPOL_T2 - line.t[2][0] += slopeT[2]; -#endif -#ifdef IPOL_L0 - line.l[0][0] += slopeL[0]; #endif } + } -/*! -*/ -void CTRStencilShadow::fragment_zfail_incr() -{ - if (!Stencil) - return; - //tVideoSample *dst; -#ifdef USE_ZBUFFER - fp24 *z; -#endif - -#ifdef USE_SBUFFER - u32 *stencil; -#endif - - s32 xStart; - s32 xEnd; - s32 dx; - - -#ifdef SUBTEXEL - f32 subPixel; -#endif - -#ifdef IPOL_Z - f32 slopeZ; -#endif -#ifdef IPOL_W - fp24 slopeW; -#endif -#ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; -#endif -#ifdef IPOL_T0 - sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; -#endif -#ifdef IPOL_L0 - sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT]; -#endif - - // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; - - dx = xEnd - xStart; - - if ( dx < 0 ) - return; - - // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); - -#ifdef IPOL_Z - slopeZ = (line.z[1] - line.z[0]) * invDeltaX; -#endif -#ifdef IPOL_W - slopeW = (line.w[1] - line.w[0]) * invDeltaX; -#endif -#ifdef IPOL_C0 - slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; -#endif -#ifdef IPOL_T0 - slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; -#endif -#ifdef IPOL_T1 - slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; -#endif -#ifdef IPOL_T2 - slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX; -#endif -#ifdef IPOL_L0 - slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX; -#endif - -#ifdef SUBTEXEL - subPixel = ( (f32) xStart ) - line.x[0]; -#ifdef IPOL_Z - line.z[0] += slopeZ * subPixel; -#endif -#ifdef IPOL_W - line.w[0] += slopeW * subPixel; -#endif -#ifdef IPOL_C0 - line.c[0][0] += slopeC[0] * subPixel; -#endif -#ifdef IPOL_T0 - line.t[0][0] += slopeT[0] * subPixel; -#endif -#ifdef IPOL_T1 - line.t[1][0] += slopeT[1] * subPixel; -#endif -#ifdef IPOL_T2 - line.t[2][0] += slopeT[2] * subPixel; -#endif -#ifdef IPOL_L0 - line.l[0][0] += slopeL[0] * subPixel; -#endif -#endif - - //dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; - -#ifdef USE_ZBUFFER - z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; -#endif - -#ifdef USE_SBUFFER - stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; -#endif - -#ifdef INVERSE_W - f32 inversew; -#endif - -#ifdef IPOL_C0 - tFixPoint r3, g3, b3; -#endif - - for ( s32 i = 0; i <= dx; i++ ) - { -#ifdef CMP_Z - if ( line.z[0] < z[i] ) -#endif -#ifdef CMP_W - if ( line.w[0] < z[i] ) -#endif - { - // zfail - stencil[i] += 1; - } - -#ifdef IPOL_Z - line.z[0] += slopeZ; -#endif -#ifdef IPOL_W - line.w[0] += slopeW; -#endif -#ifdef IPOL_C0 - line.c[0][0] += slopeC[0]; -#endif -#ifdef IPOL_T0 - line.t[0][0] += slopeT[0]; -#endif -#ifdef IPOL_T1 - line.t[1][0] += slopeT[1]; -#endif -#ifdef IPOL_T2 - line.t[2][0] += slopeT[2]; -#endif -#ifdef IPOL_L0 - line.l[0][0] += slopeL[0]; -#endif - } -} - -void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRStencilShadow::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -450,9 +226,9 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -516,7 +292,6 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // rasterize upper sub-triangle - //if ( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge @@ -559,8 +334,8 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -648,7 +423,7 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // render a scanline - (this->*fragmentShader) (); + fragmentShader (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -766,8 +541,8 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -856,7 +631,7 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons #endif // render a scanline - (this->*fragmentShader) (); + fragmentShader (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -915,6 +690,7 @@ namespace video //! creates a triangle renderer IBurningShader* createTRStencilShadow(CBurningVideoDriver* driver) { + //ETR_STENCIL_SHADOW #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRStencilShadow(driver); #else diff --git a/source/Irrlicht/CTRTextureBlend.cpp b/source/Irrlicht/CTRTextureBlend.cpp index e3ba0791..da178eb1 100644 --- a/source/Irrlicht/CTRTextureBlend.cpp +++ b/source/Irrlicht/CTRTextureBlend.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -76,19 +76,32 @@ namespace irr namespace video { -class CTRTextureBlend : public IBurningShader -{ -public: + class CTRTextureBlend : public IBurningShader + { + public: - //! constructor - CTRTextureBlend(CBurningVideoDriver* driver); + //! constructor + CTRTextureBlend(CBurningVideoDriver* driver); - //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + //! draws an indexed triangle list + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; - virtual void setZCompareFunc ( u32 func) _IRR_OVERRIDE_; - virtual void setParam ( u32 index, f32 value) _IRR_OVERRIDE_; +#if defined(PATCH_SUPERTUX_8_0_1) + virtual void setZCompareFunc(u32 func) + { + depth_func = (E_COMPARISON_FUNC)func; + } + virtual void setParam(u32 index, f32 value) + { + SBurningShaderMaterial material; + material.org.ZBuffer = depth_func; + material.org.MaterialTypeParam = value; + OnSetMaterial(material); + } + +#endif private: // fragment shader @@ -102,12 +115,11 @@ private: void fragment_one_one_minus_src_alpha (); void fragment_one_minus_dst_alpha_one(); void fragment_src_alpha_one(); + void fragment_src_alpha_one_minus_src_alpha(); tFragmentShader fragmentShader; - sScanConvertData scan; - sScanLineData line; - u32 ZCompare; + E_COMPARISON_FUNC depth_func; }; //! constructor @@ -118,26 +130,23 @@ CTRTextureBlend::CTRTextureBlend(CBurningVideoDriver* driver) setDebugName("CTRTextureBlend"); #endif - ZCompare = 1; + depth_func = ECFN_LESSEQUAL; + fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; } /*! */ -void CTRTextureBlend::setZCompareFunc ( u32 func) +void CTRTextureBlend::OnSetMaterial(const SBurningShaderMaterial& material) { - ZCompare = func; -} + int showname = 0; -/*! -*/ -void CTRTextureBlend::setParam ( u32 index, f32 value) -{ - u8 showname = 0; + depth_func = (E_COMPARISON_FUNC)material.org.ZBuffer; + AlphaRef = 0; // tofix(material.org.MaterialTypeParam, FIXPOINT_COLOR_MAX); E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; u32 alphaSrc; - unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSrc, value ); + unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSrc, material.org.MaterialTypeParam); fragmentShader = 0; @@ -145,43 +154,39 @@ void CTRTextureBlend::setParam ( u32 index, f32 value) { fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; } - else - if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE ) + else if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE ) { fragmentShader = &CTRTextureBlend::fragment_dst_color_one; } - else - if ( srcFact == EBF_DST_COLOR && dstFact == EBF_SRC_ALPHA) + else if ( srcFact == EBF_DST_COLOR && dstFact == EBF_SRC_ALPHA) { fragmentShader = &CTRTextureBlend::fragment_dst_color_src_alpha; } - else - if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE_MINUS_DST_ALPHA) + else if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE_MINUS_DST_ALPHA) { fragmentShader = &CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha; } - else - if ( srcFact == EBF_ZERO && dstFact == EBF_ONE_MINUS_SRC_COLOR ) + else if ( srcFact == EBF_ZERO && dstFact == EBF_ONE_MINUS_SRC_COLOR ) { fragmentShader = &CTRTextureBlend::fragment_zero_one_minus_scr_color; } - else - if ( srcFact == EBF_ONE && dstFact == EBF_ONE_MINUS_SRC_ALPHA) + else if ( srcFact == EBF_ONE && dstFact == EBF_ONE_MINUS_SRC_ALPHA) { fragmentShader = &CTRTextureBlend::fragment_one_one_minus_src_alpha; } - else - if ( srcFact == EBF_ONE_MINUS_DST_ALPHA && dstFact == EBF_ONE ) + else if ( srcFact == EBF_ONE_MINUS_DST_ALPHA && dstFact == EBF_ONE ) { fragmentShader = &CTRTextureBlend::fragment_one_minus_dst_alpha_one; } - else - if ( srcFact == EBF_SRC_ALPHA && dstFact == EBF_ONE ) + else if ( srcFact == EBF_SRC_ALPHA && dstFact == EBF_ONE ) { fragmentShader = &CTRTextureBlend::fragment_src_alpha_one; } - else - if ( srcFact == EBF_SRC_COLOR && dstFact == EBF_SRC_ALPHA ) + else if (srcFact == EBF_SRC_ALPHA && dstFact == EBF_ONE_MINUS_SRC_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_src_alpha_one_minus_src_alpha; + } + else if ( srcFact == EBF_SRC_COLOR && dstFact == EBF_SRC_ALPHA ) { fragmentShader = &CTRTextureBlend::fragment_src_color_src_alpha; } @@ -213,7 +218,7 @@ void CTRTextureBlend::setParam ( u32 index, f32 value) { char buf[128]; snprintf_irr ( buf, 128, "missing shader: %s %s",n[srcFact], n[dstFact] ); - os::Printer::log( buf, ELL_INFORMATION ); + os::Printer::log( buf, ELL_WARNING); lsrcFact = srcFact; ldstFact = dstFact; @@ -248,15 +253,15 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -264,7 +269,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -301,6 +306,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -315,9 +321,10 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -342,7 +349,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); @@ -385,7 +392,7 @@ void CTRTextureBlend::fragment_dst_color_src_alpha () color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); @@ -432,23 +439,22 @@ void CTRTextureBlend::fragment_src_color_src_alpha () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; - if ( dx < 0 ) return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -485,6 +491,7 @@ void CTRTextureBlend::fragment_src_color_src_alpha () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -497,11 +504,16 @@ void CTRTextureBlend::fragment_src_color_src_alpha () tFixPoint a0, r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 + tFixPoint a2,r2, g2, b2; +#endif + s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -509,9 +521,9 @@ void CTRTextureBlend::fragment_src_color_src_alpha () #endif { - + //solves example 08. todo: depth_write. #ifdef WRITE_W - z[i] = line.w[0]; + //z[i] = line.w[0]; #endif #ifdef INVERSE_W @@ -519,13 +531,21 @@ void CTRTextureBlend::fragment_src_color_src_alpha () #endif getSample_texture ( a0, r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,iw), tofix ( line.t[0][0].y,iw) ); - color_to_fix ( r1, g1, b1, dst[i] ); -// u32 check = imulFix_tex1( r0, r1 ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1( r0, r1 ) + imulFix_tex1( r1, a0 ) ), - clampfix_maxcolor ( imulFix_tex1( g0, g1 ) + imulFix_tex1( g1, a0 ) ), - clampfix_maxcolor ( imulFix_tex1( b0, b1 ) + imulFix_tex1( b1, a0 ) ) +#ifdef IPOL_C0 + vec4_to_fix(a2,r2, g2, b2, line.c[0][0], iw); + //a0 = imulFix(a0, a2); why is vertex color enabled and not vertex_alpha? + r0 = imulFix_simple(r0, r2); + g0 = imulFix_simple(g0, g2); + b0 = imulFix_simple(b0, b2); +#endif + + color_to_fix ( r1, g1, b1, dst[i] ); + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex1( r0, r0 ) + imulFix_tex1( r1, a0 ) ), + clampfix_maxcolor ( imulFix_tex1( g0, g0 ) + imulFix_tex1( g1, a0 ) ), + clampfix_maxcolor ( imulFix_tex1( b0, b0 ) + imulFix_tex1( b1, a0 ) ) ); + } #ifdef IPOL_W @@ -565,7 +585,7 @@ void CTRTextureBlend::fragment_src_color_src_alpha () color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); @@ -582,6 +602,7 @@ void CTRTextureBlend::fragment_src_color_src_alpha () line.c[0][0] += slopeC[0]; #endif }break; + } // zcompare } @@ -612,15 +633,15 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -628,7 +649,7 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2 ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -665,6 +686,7 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -676,13 +698,15 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() tFixPoint a0,r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -704,16 +728,16 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), - imulFix ( g0 + imulFix ( g1, a0 ), g2 ), - imulFix ( b0 + imulFix ( b1, a0 ), b2 ) + dst[i] = fix_to_sample( imulFix ( r0 + imulFix_simple( r1, a0 ), r2 ), + imulFix ( g0 + imulFix_simple( g1, a0 ), g2 ), + imulFix ( b0 + imulFix_simple( b1, a0 ), b2 ) ); #else - dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), - g0 + imulFix ( g1, a0 ), - b0 + imulFix ( b1, a0 ) + dst[i] = fix_to_sample( r0 + imulFix_simple( r1, a0 ), + g0 + imulFix_simple( g1, a0 ), + b0 + imulFix_simple( b1, a0 ) ); #endif @@ -753,16 +777,16 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), - imulFix ( g0 + imulFix ( g1, a0 ), g2 ), - imulFix ( b0 + imulFix ( b1, a0 ), b2 ) + dst[i] = fix_to_sample( imulFix ( r0 + imulFix_simple( r1, a0 ), r2 ), + imulFix ( g0 + imulFix_simple( g1, a0 ), g2 ), + imulFix ( b0 + imulFix_simple( b1, a0 ), b2 ) ); #else - dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), - g0 + imulFix ( g1, a0 ), - b0 + imulFix ( b1, a0 ) + dst[i] = fix_to_sample( r0 + imulFix_simple( r1, a0 ), + g0 + imulFix_simple( g1, a0 ), + b0 + imulFix_simple( b1, a0 ) ); #endif @@ -779,6 +803,7 @@ void CTRTextureBlend::fragment_one_one_minus_src_alpha() line.c[0][0] += slopeC[0]; #endif }break; + } // zcompare } @@ -809,15 +834,15 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -825,7 +850,7 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -862,6 +887,7 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -873,13 +899,15 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () tFixPoint r0, g0, b0; tFixPoint a1, r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -899,17 +927,17 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; - dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), - imulFix ( imulFix ( g0, a1 ) + g1, g2 ), - imulFix ( imulFix ( b0, a1 ) + b1, b2 ) + dst[i] = fix_to_sample( imulFix (imulFix_simple( r0, a1 ) + r1, r2 ), + imulFix (imulFix_simple( g0, a1 ) + g1, g2 ), + imulFix (imulFix_simple( b0, a1 ) + b1, b2 ) ); #else - dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, - imulFix ( g0, a1) + g0, - imulFix ( b0, a1) + b0 + dst[i] = fix_to_sample(imulFix_simple( r0, a1) + r0, + imulFix_simple( g0, a1) + g0, + imulFix_simple( b0, a1) + b0 ); #endif @@ -948,17 +976,17 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; - dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), - imulFix ( imulFix ( g0, a1 ) + g1, g2 ), - imulFix ( imulFix ( b0, a1 ) + b1, b2 ) + dst[i] = fix_to_sample( imulFix (imulFix_simple( r0, a1 ) + r1, r2 ), + imulFix (imulFix_simple( g0, a1 ) + g1, g2 ), + imulFix (imulFix_simple( b0, a1 ) + b1, b2 ) ); #else - dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, - imulFix ( g0, a1) + g0, - imulFix ( b0, a1) + b0 + dst[i] = fix_to_sample(imulFix_simple( r0, a1) + r0, + imulFix_simple( g0, a1) + g0, + imulFix_simple( b0, a1) + b0 ); #endif @@ -975,6 +1003,7 @@ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () line.c[0][0] += slopeC[0]; #endif }break; + } // zcompare } @@ -1005,15 +1034,15 @@ void CTRTextureBlend::fragment_src_alpha_one () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -1021,7 +1050,7 @@ void CTRTextureBlend::fragment_src_alpha_one () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1058,6 +1087,7 @@ void CTRTextureBlend::fragment_src_alpha_one () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -1069,13 +1099,15 @@ void CTRTextureBlend::fragment_src_alpha_one () tFixPoint a0, r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -1092,32 +1124,32 @@ void CTRTextureBlend::fragment_src_alpha_one () getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); if ( a0 > 0 ) { - a0 >>= 8; + fix_color_norm(a0); color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix4_to_color ( a0, - clampfix_maxcolor ( imulFix (r0,a0 ) + r1), - clampfix_maxcolor ( imulFix (g0,a0 ) + g1), - clampfix_maxcolor ( imulFix (b0,a0 ) + b1) + dst[i] = fix4_to_sample( a0, + clampfix_maxcolor (imulFix_simple(r0,a0) + r1), + clampfix_maxcolor (imulFix_simple(g0,a0) + g1), + clampfix_maxcolor (imulFix_simple(b0,a0) + b1) ); /* - a0 >>= 8; - dst[i] = fix4_to_color ( a0, - imulFix ( imulFix ( r0, a0 ) + r1, r2 ), - imulFix ( imulFix ( g0, a0 ) + g1, g2 ), - imulFix ( imulFix ( b0, a0 ) + b1, b2 ) + fix_color_norm(a0); + dst[i] = fix4_to_sample ( a0, + imulFix ( imulFix_simple ( r0, a0 ) + r1, r2 ), + imulFix ( imulFix_simple ( g0, a0 ) + g1, g2 ), + imulFix ( imulFix_simple ( b0, a0 ) + b1, b2 ) ); */ #else - dst[i] = fix4_to_color ( a0, - clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), - clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), - clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) + dst[i] = fix4_to_sample( a0, + clampfix_maxcolor (imulFix_simple(r0,a0 ) + r1 ), + clampfix_maxcolor (imulFix_simple(g0,a0 ) + g1 ), + clampfix_maxcolor (imulFix_simple(b0,a0 ) + b1 ) ); #endif @@ -1156,32 +1188,32 @@ void CTRTextureBlend::fragment_src_alpha_one () getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); if ( a0 > 0 ) { - a0 >>= 8; + fix_color_norm(a0); color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix4_to_color ( a0, - clampfix_maxcolor ( imulFix ( imulFix (r0,a0 ) + r1, r2 ) ), - clampfix_maxcolor ( imulFix ( imulFix (g0,a0 ) + g1, g2 ) ), - clampfix_maxcolor ( imulFix ( imulFix (b0,a0 ) + b1, b2 ) ) + dst[i] = fix4_to_sample( a0, + clampfix_maxcolor ( imulFix (imulFix_simple(r0,a0 ) + r1, r2 ) ), + clampfix_maxcolor ( imulFix (imulFix_simple(g0,a0 ) + g1, g2 ) ), + clampfix_maxcolor ( imulFix (imulFix_simple(b0,a0 ) + b1, b2 ) ) ); /* - a0 >>= 8; - dst[i] = fix4_to_color ( a0, - imulFix ( imulFix ( r0, a0 ) + r1, r2 ), - imulFix ( imulFix ( g0, a0 ) + g1, g2 ), - imulFix ( imulFix ( b0, a0 ) + b1, b2 ) + fix_color_norm(a0); + dst[i] = fix4_to_sample ( a0, + imulFix ( imulFix_simple ( r0, a0 ) + r1, r2 ), + imulFix ( imulFix_simple ( g0, a0 ) + g1, g2 ), + imulFix ( imulFix_simple ( b0, a0 ) + b1, b2 ) ); */ #else - dst[i] = fix4_to_color ( a0, - clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), - clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), - clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) + dst[i] = fix4_to_sample( a0, + clampfix_maxcolor (imulFix_simple(r0,a0 ) + r1 ), + clampfix_maxcolor (imulFix_simple(g0,a0 ) + g1 ), + clampfix_maxcolor (imulFix_simple(b0,a0 ) + b1 ) ); #endif @@ -1201,6 +1233,160 @@ void CTRTextureBlend::fragment_src_alpha_one () line.c[0][0] += slopeC[0]; #endif }break; + + } // zcompare + +} + + +/*! +*/ +void CTRTextureBlend::fragment_src_alpha_one_minus_src_alpha() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left(line.x[0]); + xEnd = fill_convention_right(line.x[1]); + + dx = xEnd - xStart; + if (dx < 0) + return; + + // slopes + const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ((f32)xStart) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + (line.y * RenderTarget->getDimension().Width) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*)DepthBuffer->lock() + (line.y * RenderTarget->getDimension().Width) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint a0, r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint a2, r2, g2, b2; + + s32 i; + + switch (depth_func) + { + default: + case ECFN_LESSEQUAL: + for (i = 0; i <= dx; ++i) + { +#ifdef CMP_W + if (line.w[0] >= z[i]) +#endif + + { +#ifdef WRITE_W + //z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32(line.w[0]); +#endif + + getSample_texture(a0, r0, g0, b0, &IT[0], tofix(line.t[0][0].x, iw), tofix(line.t[0][0].y, iw)); + if (a0 > AlphaRef) + { +#ifdef IPOL_C0 + vec4_to_fix(a2, r2, g2, b2, line.c[0][0], iw); + //a0 = imulFix(a0, a2); why is vertex color enabled and not vertex_alpha? + r0 = imulFix_simple(r0, r2); + g0 = imulFix_simple(g0, g2); + b0 = imulFix_simple(b0, b2); +#endif + + color_to_fix(r1, g1, b1, dst[i]); + + fix_color_norm(a0); + + r2 = r1 + imulFix(a0, r0 - r1); + g2 = g1 + imulFix(a0, g0 - g1); + b2 = b1 + imulFix(a0, b0 - b1); + dst[i] = fix4_to_sample(a0, r2, g2, b2); + } + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + } // zcompare } @@ -1232,15 +1418,15 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -1248,7 +1434,7 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1285,6 +1471,7 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -1296,13 +1483,15 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () tFixPoint r0, g0, b0; tFixPoint a1, r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -1322,15 +1511,15 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; - dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), + dst[i] = fix_to_sample( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), imulFix ( imulFix ( g1, g0 + a1 ), g2 ), imulFix ( imulFix ( b1, b0 + a1 ), b2 ) ); #else - dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), + dst[i] = fix_to_sample( imulFix ( r1, r0 + a1 ), imulFix ( g1, g0 + a1 ), imulFix ( b1, b0 + a1 ) ); @@ -1371,15 +1560,15 @@ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; - dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), + dst[i] = fix_to_sample( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), imulFix ( imulFix ( g1, g0 + a1 ), g2 ), imulFix ( imulFix ( b1, b0 + a1 ), b2 ) ); #else - dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), + dst[i] = fix_to_sample( imulFix ( r1, r0 + a1 ), imulFix ( g1, g0 + a1 ), imulFix ( b1, b0 + a1 ) ); @@ -1428,15 +1617,15 @@ void CTRTextureBlend::fragment_dst_color_zero () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -1444,7 +1633,7 @@ void CTRTextureBlend::fragment_dst_color_zero () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1481,6 +1670,7 @@ void CTRTextureBlend::fragment_dst_color_zero () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -1492,13 +1682,15 @@ void CTRTextureBlend::fragment_dst_color_zero () tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -1519,15 +1711,15 @@ void CTRTextureBlend::fragment_dst_color_zero () color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), - imulFix ( imulFix ( g0, g1 ), g2 ), - imulFix ( imulFix ( b0, b1 ), b2 ) ); + dst[i] = fix_to_sample( imulFix (imulFix_simple( r0, r1 ), r2 ), + imulFix (imulFix_simple( g0, g1 ), g2 ), + imulFix (imulFix_simple( b0, b1 ), b2 ) ); #else - dst[i] = fix_to_color ( imulFix ( r0, r1 ), - imulFix ( g0, g1 ), - imulFix ( b0, b1 ) + dst[i] = fix_to_sample(imulFix_simple( r0, r1 ), + imulFix_simple( g0, g1 ), + imulFix_simple( b0, b1 ) ); #endif @@ -1566,16 +1758,16 @@ void CTRTextureBlend::fragment_dst_color_zero () color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), - imulFix ( imulFix ( g0, g1 ), g2 ), - imulFix ( imulFix ( b0, b1 ), b2 ) + dst[i] = fix_to_sample( imulFix (imulFix_simple( r0, r1 ), r2 ), + imulFix (imulFix_simple( g0, g1 ), g2 ), + imulFix (imulFix_simple( b0, b1 ), b2 ) ); #else - dst[i] = fix_to_color ( imulFix ( r0, r1 ), - imulFix ( g0, g1 ), - imulFix ( b0, b1 ) + dst[i] = fix_to_sample(imulFix_simple( r0, r1 ), + imulFix_simple( g0, g1 ), + imulFix_simple( b0, b1 ) ); #endif @@ -1622,15 +1814,15 @@ void CTRTextureBlend::fragment_dst_color_one () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -1638,7 +1830,7 @@ void CTRTextureBlend::fragment_dst_color_one () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1675,6 +1867,7 @@ void CTRTextureBlend::fragment_dst_color_one () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -1686,13 +1879,15 @@ void CTRTextureBlend::fragment_dst_color_one () tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -1712,15 +1907,15 @@ void CTRTextureBlend::fragment_dst_color_one () getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); #else - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); @@ -1761,15 +1956,15 @@ void CTRTextureBlend::fragment_dst_color_one () color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); #else - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); @@ -1819,15 +2014,15 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -1835,7 +2030,7 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -1872,6 +2067,7 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -1883,13 +2079,15 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 tFixPoint r2, g2, b2; - +#endif s32 i; - switch ( ZCompare ) + switch (depth_func) { - case 1: + default: + case ECFN_LESSEQUAL: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W @@ -1909,17 +2107,17 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), - imulFix ( FIX_POINT_ONE - g0, g1 ), - imulFix ( FIX_POINT_ONE - b0, b1 ) + dst[i] = fix_to_sample(imulFix( FIX_POINT_ONE - r0, r1 ), + imulFix( FIX_POINT_ONE - g0, g1 ), + imulFix( FIX_POINT_ONE - b0, b1 ) ); #else - dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), - imulFix ( FIX_POINT_ONE - g0, g1 ), - imulFix ( FIX_POINT_ONE - b0, b1 ) + dst[i] = fix_to_sample(imulFix( FIX_POINT_ONE - r0, r1 ), + imulFix( FIX_POINT_ONE - g0, g1 ), + imulFix( FIX_POINT_ONE - b0, b1 ) ); #endif @@ -1957,17 +2155,17 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 - getSample_color ( r2, g2, b2, line.c[0][0],iw ); + vec4_to_fix( r2, g2, b2, line.c[0][0],iw ); - dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), - imulFix ( FIX_POINT_ONE - g0, g1 ), - imulFix ( FIX_POINT_ONE - b0, b1 ) + dst[i] = fix_to_sample(imulFix( FIX_POINT_ONE - r0, r1 ), + imulFix( FIX_POINT_ONE - g0, g1 ), + imulFix( FIX_POINT_ONE - b0, b1 ) ); #else - dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), - imulFix ( FIX_POINT_ONE - g0, g1 ), - imulFix ( FIX_POINT_ONE - b0, b1 ) + dst[i] = fix_to_sample(imulFix( FIX_POINT_ONE - r0, r1 ), + imulFix( FIX_POINT_ONE - g0, g1 ), + imulFix( FIX_POINT_ONE - b0, b1 ) ); #endif @@ -1990,7 +2188,7 @@ void CTRTextureBlend::fragment_zero_one_minus_scr_color () -void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureBlend::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { if ( 0 == fragmentShader ) return; @@ -2004,9 +2202,9 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -2092,8 +2290,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -2251,8 +2449,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -2371,6 +2569,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRTextureBlend(CBurningVideoDriver* driver) { + // EMT_ONETEXTURE_BLEND #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureBlend(driver); #else diff --git a/source/Irrlicht/CTRTextureDetailMap2.cpp b/source/Irrlicht/CTRTextureDetailMap2.cpp index f5653ab5..3e75c2d9 100644 --- a/source/Irrlicht/CTRTextureDetailMap2.cpp +++ b/source/Irrlicht/CTRTextureDetailMap2.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -84,13 +84,11 @@ public: CTRTextureDetailMap2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual bool canWireFrame () { return true; } - -private: - void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; +protected: + virtual void scanline_bilinear (); }; @@ -138,8 +136,8 @@ void CTRTextureDetailMap2::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -147,7 +145,7 @@ void CTRTextureDetailMap2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -184,6 +182,7 @@ void CTRTextureDetailMap2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -203,6 +202,8 @@ void CTRTextureDetailMap2::scanline_bilinear () for ( s32 i = 0; i <= dx; ++i ) { + if ( (0 == EdgeTestPass) & i ) break; + #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif @@ -222,16 +223,13 @@ void CTRTextureDetailMap2::scanline_bilinear () getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); getSample_texture ( r1, g1, b1, &IT[1], tx1,ty1 ); - // bias half color - r1 += -FIX_POINT_HALF_COLOR; - g1 += -FIX_POINT_HALF_COLOR; - b1 += -FIX_POINT_HALF_COLOR; + // add signed - r2 = clampfix_mincolor ( clampfix_maxcolor ( r0 + r1 ) ); - g2 = clampfix_mincolor ( clampfix_maxcolor ( g0 + g1 ) ); - b2 = clampfix_mincolor ( clampfix_maxcolor ( b0 + b1 ) ); + r2 = clampfix_mincolor ( clampfix_maxcolor ( r0 + r1 - FIX_POINT_HALF_COLOR ) ); + g2 = clampfix_mincolor ( clampfix_maxcolor ( g0 + g1 - FIX_POINT_HALF_COLOR ) ); + b2 = clampfix_mincolor ( clampfix_maxcolor ( b0 + b1 - FIX_POINT_HALF_COLOR ) ); - dst[i] = fix_to_color ( r2, g2, b2 ); + dst[i] = fix_to_sample( r2, g2, b2 ); #ifdef WRITE_Z z[i] = line.z[0]; @@ -261,7 +259,7 @@ void CTRTextureDetailMap2::scanline_bilinear () } -void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureDetailMap2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -272,9 +270,9 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_edge( ca ); + scan.invDeltaY[1] = reciprocal_edge( ba ); + scan.invDeltaY[2] = reciprocal_edge( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -360,8 +358,8 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -519,8 +517,8 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL diff --git a/source/Irrlicht/CTRTextureGouraud2.cpp b/source/Irrlicht/CTRTextureGouraud2.cpp index 7bcc512b..ef864606 100644 --- a/source/Irrlicht/CTRTextureGouraud2.cpp +++ b/source/Irrlicht/CTRTextureGouraud2.cpp @@ -21,8 +21,11 @@ #undef INVERSE_W #undef IPOL_C0 +#undef IPOL_C1 +#undef IPOL_C2 #undef IPOL_T0 #undef IPOL_T1 +#undef IPOL_L0 // define render case #define SUBTEXEL @@ -34,8 +37,11 @@ #define WRITE_W #define IPOL_C0 +#define IPOL_C1 +//#define IPOL_C2 #define IPOL_T0 //#define IPOL_T1 +//#define IPOL_L0 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT @@ -46,10 +52,23 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif +#if BURNING_MATERIAL_MAX_COLORS < 2 + #undef IPOL_C1 +#endif + +#if BURNING_MATERIAL_MAX_COLORS < 3 +#undef IPOL_C2 +#endif + +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT < 1 + #undef IPOL_L0 +#endif + + #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W @@ -83,14 +102,12 @@ public: CTRTextureGouraud2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual bool canWireFrame () { return true; } private: - void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; - + void fragmentShader (); }; //! constructor @@ -106,7 +123,7 @@ CTRTextureGouraud2::CTRTextureGouraud2(CBurningVideoDriver* driver) /*! */ -void CTRTextureGouraud2::scanline_bilinear () +void CTRTextureGouraud2::fragmentShader () { tVideoSample *dst; @@ -130,15 +147,19 @@ void CTRTextureGouraud2::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif +#ifdef IPOL_L0 + sVec3Pack_unpack slopeL[BURNING_MATERIAL_MAX_LIGHT_TANGENT]; +#endif + // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -146,7 +167,7 @@ void CTRTextureGouraud2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -155,7 +176,13 @@ void CTRTextureGouraud2::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_C1 + slopeC[1] = (line.c[1][1] - line.c[1][0]) * invDeltaX; +#endif +#ifdef IPOL_C2 + slopeC[2] = (line.c[2][1] - line.c[2][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -163,6 +190,10 @@ void CTRTextureGouraud2::scanline_bilinear () #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif +#ifdef IPOL_L0 + slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX; +#endif + #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; @@ -173,7 +204,13 @@ void CTRTextureGouraud2::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0][0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1] * subPixel; +#endif +#ifdef IPOL_C2 + line.c[2][0] += slopeC[2] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -181,8 +218,12 @@ void CTRTextureGouraud2::scanline_bilinear () #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif +#ifdef IPOL_L0 + line.l[0][0] += slopeL[0] * subPixel; +#endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -195,18 +236,29 @@ void CTRTextureGouraud2::scanline_bilinear () tFixPoint tx0; tFixPoint ty0; - tFixPoint r0, g0, b0; - #ifdef IPOL_C0 + tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #endif -#ifdef BURNINGVIDEO_RENDERER_FAST +#ifdef IPOL_C1 + tFixPoint aFog = FIX_POINT_ONE; +#endif + + +#ifdef IPOL_C2 + tFixPoint r3, g3, b3; +#endif + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff u32 dIndex = ( line.y & 3 ) << 2; #endif for ( s32 i = 0; i <= dx; ++i ) { + //if test active only first pixel + if ( (0 == EdgeTestPass) & i ) break; + #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif @@ -221,41 +273,70 @@ void CTRTextureGouraud2::scanline_bilinear () z[i] = line.w[0]; #endif - #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); +#endif + +#ifdef IPOL_C1 + //complete inside fog + if (TL_Flag & TL_FOG) + { + aFog = tofix(line.c[1][0].a, inversew); + if (aFog <= 0) + { + dst[i] = fog_color_sample; + continue; + } + } +#endif tx0 = tofix ( line.t[0][0].x, inversew); ty0 = tofix ( line.t[0][0].y, inversew); + #ifdef IPOL_C0 - r1 = tofix ( line.c[0][0].y ,inversew ); - g1 = tofix ( line.c[0][0].z ,inversew ); - b1 = tofix ( line.c[0][0].w ,inversew ); + + getSample_texture(r0, g0, b0, &IT[0], tx0, ty0); + vec4_to_fix(r1, g1, b1, line.c[0][0], inversew); + + r0 = imulFix_simple(r0, r1); + g0 = imulFix_simple(g0, g1); + b0 = imulFix_simple(b0, b1); + +#ifdef IPOL_C1 + + //specular highlight + if (TL_Flag & TL_SPECULAR) + { + vec4_to_fix(r1, g1, b1, line.c[1][0], inversew*COLOR_MAX); + r0 = clampfix_maxcolor(r1 + r0); + g0 = clampfix_maxcolor(g1 + g0); + b0 = clampfix_maxcolor(b1 + b0); + } + //mix with distance + if (aFog < FIX_POINT_ONE) + { + r0 = fog_color[1] + imulFix(aFog, r0 - fog_color[1]); + g0 = fog_color[2] + imulFix(aFog, g0 - fog_color[2]); + b0 = fog_color[3] + imulFix(aFog, b0 - fog_color[3]); + } + dst[i] = fix_to_sample(r0, g0, b0); + +#else + dst[i] = fix_to_sample( + imulFix_simple(r0, r1), + imulFix_simple(g0, g1), + imulFix_simple(b0, b1) + ); #endif #else - tx0 = tofix(line.t[0][0].x, inversew); - ty0 = tofix(line.t[0][0].y, inversew); -#ifdef IPOL_C0 - getTexel_plain2 ( r1, g1, b1, line.c[0][0] ); -#endif -#endif -#ifdef IPOL_C0 - getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); - - dst[i] = fix_to_color ( imulFix ( r0, r1 ), - imulFix ( g0, g1 ), - imulFix ( b0, b1 ) - ); -#else - -#ifdef BURNINGVIDEO_RENDERER_FAST +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = getTexel_plain ( &IT[0], d + tx0, d + ty0 ); #else getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); - dst[i] = fix_to_color ( r0, g0, b0 ); + dst[i] = fix_to_sample( r0, g0, b0 ); #endif #endif @@ -269,19 +350,28 @@ void CTRTextureGouraud2::scanline_bilinear () line.w[0] += slopeW; #endif #ifdef IPOL_C0 - line.c[0][0] += slopeC; + line.c[0][0] += slopeC[0]; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1]; +#endif +#ifdef IPOL_C2 + line.c[2][0] += slopeC[2]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; +#endif +#ifdef IPOL_L0 + line.l[0][0] += slopeL[0]; #endif } } -void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureGouraud2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -292,9 +382,9 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -329,6 +419,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][0] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][0] = (c->Color[1] - a->Color[1]) * scan.invDeltaY[0]; + scan.c[1][0] = a->Color[1]; +#endif + +#ifdef IPOL_C2 + scan.slopeC[2][0] = (c->Color[2] - a->Color[2]) * scan.invDeltaY[0]; + scan.c[2][0] = a->Color[2]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; @@ -339,6 +439,11 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][0] = a->Tex[1]; #endif +#ifdef IPOL_L0 + scan.slopeL[0][0] = (c->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[0]; + scan.l[0][0] = a->LightTangent[0]; +#endif + // top left fill convention y run s32 yStart; s32 yEnd; @@ -348,7 +453,7 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co #endif // rasterize upper sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[1] ) + if ( F32_GREATER_0(scan.invDeltaY[1]) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; @@ -369,6 +474,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][1] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (b->Color[1] - a->Color[1]) * scan.invDeltaY[1]; + scan.c[1][1] = a->Color[1]; +#endif + +#ifdef IPOL_C2 + scan.slopeC[2][1] = (b->Color[2] - a->Color[2]) * scan.invDeltaY[1]; + scan.c[2][1] = a->Color[2]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; @@ -379,9 +494,14 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][1] = a->Tex[1]; #endif +#ifdef IPOL_L0 + scan.slopeL[0][1] = (b->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[1]; + scan.l[0][1] = a->LightTangent[0]; +#endif + // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -405,6 +525,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + +#ifdef IPOL_C2 + scan.c[2][0] += scan.slopeC[2][0] * subPixel; + scan.c[2][1] += scan.slopeC[2][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -415,6 +545,11 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif +#ifdef IPOL_L0 + scan.l[0][0] += scan.slopeL[0][0] * subPixel; + scan.l[0][1] += scan.slopeL[0][1] * subPixel; +#endif + #endif // rasterize the edge scanlines @@ -438,6 +573,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + +#ifdef IPOL_C2 + line.c[2][scan.left] = scan.c[2][0]; + line.c[2][scan.right] = scan.c[2][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -448,8 +593,15 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co line.t[1][scan.right] = scan.t[1][1]; #endif +#ifdef IPOL_L0 + line.l[0][scan.left] = scan.l[0][0]; + line.l[0][scan.right] = scan.l[0][1]; +#endif + // render a scanline - scanline_bilinear (); + fragmentShader (); + if ( EdgeTestPass & edge_test_first_line ) break; + scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -469,6 +621,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + +#ifdef IPOL_C2 + scan.c[2][0] += scan.slopeC[2][0]; + scan.c[2][1] += scan.slopeC[2][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -479,14 +641,19 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][1] += scan.slopeT[1][1]; #endif +#ifdef IPOL_L0 + scan.l[0][0] += scan.slopeL[0][0]; + scan.l[0][1] += scan.slopeL[0][1]; +#endif + } } // rasterize lower sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[2] ) + if (F32_GREATER_0(scan.invDeltaY[2]) ) { // advance to middle point - if( (f32) 0.0 != scan.invDeltaY[1] ) + if(F32_GREATER_0(scan.invDeltaY[1]) ) { temp[0] = b->Pos.y - a->Pos.y; // dy @@ -500,6 +667,12 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif +#ifdef IPOL_C1 + scan.c[1][0] = a->Color[1] + scan.slopeC[1][0] * temp[0]; +#endif +#ifdef IPOL_C2 + scan.c[2][0] = a->Color[2] + scan.slopeC[2][0] * temp[0]; +#endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif @@ -507,6 +680,9 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif +#ifdef IPOL_L0 + scan.l[0][0] = sVec3Pack_unpack(a->LightTangent[0]) + scan.slopeL[0][0] * temp[0]; +#endif } // calculate slopes for bottom edge @@ -528,6 +704,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][1] = b->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (c->Color[1] - b->Color[1]) * scan.invDeltaY[2]; + scan.c[1][1] = b->Color[1]; +#endif + +#ifdef IPOL_C2 + scan.slopeC[2][1] = (c->Color[2] - b->Color[2]) * scan.invDeltaY[2]; + scan.c[2][1] = b->Color[2]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; @@ -538,9 +724,14 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][1] = b->Tex[1]; #endif +#ifdef IPOL_L0 + scan.slopeL[0][1] = (c->LightTangent[0] - b->LightTangent[0]) * scan.invDeltaY[2]; + scan.l[0][1] = b->LightTangent[0]; +#endif + // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -565,6 +756,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + +#ifdef IPOL_C1 + scan.c[2][0] += scan.slopeC[2][0] * subPixel; + scan.c[2][1] += scan.slopeC[2][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -575,6 +776,11 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif +#ifdef IPOL_L0 + scan.l[0][0] += scan.slopeL[0][0] * subPixel; + scan.l[0][1] += scan.slopeL[0][1] * subPixel; +#endif + #endif // rasterize the edge scanlines @@ -598,6 +804,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + +#ifdef IPOL_C2 + line.c[2][scan.left] = scan.c[2][0]; + line.c[2][scan.right] = scan.c[2][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -608,8 +824,15 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co line.t[1][scan.right] = scan.t[1][1]; #endif +#ifdef IPOL_L0 + line.l[0][scan.left] = scan.l[0][0]; + line.l[0][scan.right] = scan.l[0][1]; +#endif + // render a scanline - scanline_bilinear ( ); + fragmentShader (); + if ( EdgeTestPass & edge_test_first_line ) break; + scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -629,6 +852,16 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + +#ifdef IPOL_C2 + scan.c[2][0] += scan.slopeC[2][0]; + scan.c[2][1] += scan.slopeC[2][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -639,6 +872,11 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co scan.t[1][1] += scan.slopeT[1][1]; #endif +#ifdef IPOL_L0 + scan.l[0][0] += scan.slopeL[0][0]; + scan.l[0][1] += scan.slopeL[0][1]; +#endif + } } @@ -657,6 +895,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureGouraud2(CBurningVideoDriver* driver) { + // ETR_TEXTURE_GOURAUD #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraud2(driver); #else diff --git a/source/Irrlicht/CTRTextureGouraudAdd2.cpp b/source/Irrlicht/CTRTextureGouraudAdd2.cpp index 0f54928f..040c83de 100644 --- a/source/Irrlicht/CTRTextureGouraudAdd2.cpp +++ b/source/Irrlicht/CTRTextureGouraudAdd2.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -84,13 +84,11 @@ public: CTRTextureGouraudAdd2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanLineData line; - }; //! constructor @@ -137,8 +135,8 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -146,7 +144,7 @@ void CTRTextureGouraudAdd2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -183,6 +181,7 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -193,9 +192,8 @@ void CTRTextureGouraudAdd2::scanline_bilinear () f32 inversew = FIX_POINT_F32_MUL; -#ifdef BURNINGVIDEO_RENDERER_FAST +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff u32 dIndex = ( line.y & 3 ) << 2; - #else tFixPoint tx0; tFixPoint ty0; @@ -216,32 +214,28 @@ void CTRTextureGouraudAdd2::scanline_bilinear () { +#ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); +#endif -#ifdef BURNINGVIDEO_RENDERER_FAST +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - -#ifdef INVERSE_W - inversew = fix_inverse32 ( line.w[0] ); -#endif - dst[i] = PixelAdd32 ( - dst[i], - getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), - d + tofix ( line.t[0][0].y,inversew) ) - ); + dst[i] = PixelAdd32 ( + dst[i], + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ) + ); #else -#ifdef INVERSE_W - inversew = fix_inverse32 ( line.w[0] ); -#endif tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( r1 + r0 ), + dst[i] = fix_to_sample( clampfix_maxcolor ( r1 + r0 ), clampfix_maxcolor ( g1 + g0 ), clampfix_maxcolor ( b1 + b0 ) ); @@ -275,10 +269,8 @@ void CTRTextureGouraudAdd2::scanline_bilinear () } -void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { - sScanConvertData scan; - // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); @@ -288,9 +280,9 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); // find if the major edge is left or right aligned f32 temp[4]; @@ -373,8 +365,8 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -532,8 +524,8 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -651,6 +643,8 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAdd2(CBurningVideoDriver* driver) { + //ETR_TEXTURE_GOURAUD_ADD + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAdd2(driver); #else diff --git a/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp b/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp index 1c7f586b..4a619530 100644 --- a/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp +++ b/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp @@ -33,38 +33,38 @@ #define CMP_W //#define WRITE_W -//#define IPOL_C0 +#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #undef INVERSE_W - #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #undef IPOL_W - #endif +#undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL - #undef SUBTEXEL +#undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - #undef IPOL_C0 +#if BURNING_MATERIAL_MAX_COLORS < 1 +#undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) - #define IPOL_Z +#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +#undef IPOL_W +#endif +#define IPOL_Z - #ifdef CMP_W - #undef CMP_W - #define CMP_Z - #endif +#ifdef CMP_W +#undef CMP_W +#define CMP_Z +#endif - #ifdef WRITE_W - #undef WRITE_W - #define WRITE_Z - #endif +#ifdef WRITE_W +#undef WRITE_W +#define WRITE_Z +#endif #endif @@ -83,13 +83,11 @@ public: CTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: - void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; + void fragmentShader(); }; @@ -106,7 +104,7 @@ CTRTextureGouraudAddNoZ2::CTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver) /*! */ -void CTRTextureGouraudAddNoZ2::scanline_bilinear () +void CTRTextureGouraudAddNoZ2::fragmentShader() { tVideoSample *dst; @@ -137,16 +135,15 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; - if ( dx < 0 ) return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -155,7 +152,7 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[1] - line.c[0]) * invDeltaX; + slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -173,7 +170,7 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0] += slopeC * subPixel; + line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -183,6 +180,7 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -198,6 +196,10 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; +#ifdef IPOL_C0 + tFixPoint r2, g2, b2; +#endif + for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z @@ -207,20 +209,30 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () if ( line.w[0] >= z[i] ) #endif { -#ifdef IPOL_W +#ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); #endif tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); - getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); + getSample_texture(r0, g0, b0, &IT[0], tx0, ty0); - color_to_fix ( r1, g1, b1, dst[i] ); - - dst[i] = fix_to_color ( clampfix_maxcolor ( r1 + (r0 >> 1 ) ), - clampfix_maxcolor ( g1 + (g0 >> 1 ) ), - clampfix_maxcolor ( b1 + (b0 >> 1) ) - ); +#ifdef IPOL_C0 + vec4_to_fix(r2, g2, b2, line.c[0][0], inversew); + r0 = imulFix(r2, r0); + g0 = imulFix(g2, g0); + b0 = imulFix(b2, b0); +#endif + + //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + if (r0 | g0 | b0) + { + color_to_fix(r1, g1, b1, dst[i]); + r1 = imulFix_tex1(r1, FIXPOINT_COLOR_MAX - r0); + g1 = imulFix_tex1(g1, FIXPOINT_COLOR_MAX - g0); + b1 = imulFix_tex1(b1, FIXPOINT_COLOR_MAX - b0); + dst[i] = fix_to_sample(r0+r1, g0+g1, b0+b1); + } #ifdef WRITE_Z z[i] = line.z[0]; @@ -237,7 +249,7 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () line.w[0] += slopeW; #endif #ifdef IPOL_C0 - line.c[0] += slopeC; + line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; @@ -249,8 +261,11 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () } -void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureGouraudAddNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { + //billboard discard + //if (a->Color[0].r <= 0.f) return; + // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); @@ -260,9 +275,9 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -293,8 +308,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; - scan.c[0] = a->Color[0]; + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -316,7 +331,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // rasterize upper sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[1] ) + if (F32_GREATER_0(scan.invDeltaY[1]) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; @@ -333,8 +348,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; - scan.c[1] = a->Color[0]; + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -348,8 +363,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -369,8 +384,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -402,8 +417,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -417,7 +432,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // render a scanline - scanline_bilinear (); + fragmentShader(); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -433,8 +448,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -451,10 +466,10 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex } // rasterize lower sub-triangle - if ( (f32) 0.0 != scan.invDeltaY[2] ) + if (F32_GREATER_0(scan.invDeltaY[2]) ) { // advance to middle point - if( (f32) 0.0 != scan.invDeltaY[1] ) + if(F32_GREATER_0(scan.invDeltaY[1]) ) { temp[0] = b->Pos.y - a->Pos.y; // dy @@ -466,7 +481,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 - scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; @@ -492,8 +507,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; - scan.c[1] = b->Color[0]; + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 @@ -507,8 +522,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -529,8 +544,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -562,8 +577,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -577,7 +592,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // render a scanline - scanline_bilinear ( ); + fragmentShader( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -593,8 +608,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -625,6 +640,20 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver) { + /* + ETR_TEXTURE_GOURAUD_ADD_NO_Z + + Irrlicht: + Material.MaterialType = EMT_TRANSPARENT_ADD_COLOR; + Material.ZBuffer = ECFN_DISABLED; + -> need Material.ZWriteEnable off + + OpenGL + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + */ + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAddNoZ2(driver); #else diff --git a/source/Irrlicht/CTRTextureGouraudAlpha.cpp b/source/Irrlicht/CTRTextureGouraudAlpha.cpp index 37bb477c..6e922359 100644 --- a/source/Irrlicht/CTRTextureGouraudAlpha.cpp +++ b/source/Irrlicht/CTRTextureGouraudAlpha.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -84,18 +84,12 @@ public: CTRTextureGouraudAlpha2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; - - virtual void setParam ( u32 index, f32 value) _IRR_OVERRIDE_; - + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; - - u32 AlphaRef; }; //! constructor @@ -105,19 +99,17 @@ CTRTextureGouraudAlpha2::CTRTextureGouraudAlpha2(CBurningVideoDriver* driver) #ifdef _DEBUG setDebugName("CTRTextureGouraudAlpha2"); #endif - - AlphaRef = 0; } /*! */ -void CTRTextureGouraudAlpha2::setParam ( u32 index, f32 value) +void CTRTextureGouraudAlpha2::OnSetMaterial(const SBurningShaderMaterial& material) { -#ifdef BURNINGVIDEO_RENDERER_FAST - AlphaRef = core::floor32_fast( value * 256.f ); +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + AlphaRef = core::floor32(material.org.MaterialTypeParam * 256.f); #else - AlphaRef = u32_to_fixPoint ( core::floor32_fast( value * 256.f ) ); + AlphaRef = tofix(material.org.MaterialTypeParam, FIXPOINT_COLOR_MAX); #endif } @@ -147,15 +139,15 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -163,7 +155,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -200,6 +192,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -209,17 +202,15 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () f32 inversew = FIX_POINT_F32_MUL; -#ifdef BURNINGVIDEO_RENDERER_FAST - u32 dIndex = ( line.y & 3 ) << 2; - +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + u32 dIndex = (line.y & 3) << 2; #else - tFixPoint a0; - tFixPoint r0, g0, b0; -#endif + tFixPoint a0, r0, g0, b0; #ifdef IPOL_C0 tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; +#endif #endif for ( s32 i = 0; i <= dx; ++i ) @@ -233,7 +224,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () { -#ifdef BURNINGVIDEO_RENDERER_FAST +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; @@ -245,7 +236,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () d + tofix ( line.t[0][0].y,inversew) ); - const u32 alpha = ( argb >> 24 ); + const tFixPoint alpha = ( argb >> 24 ); if ( alpha > AlphaRef ) { #ifdef WRITE_Z @@ -263,19 +254,14 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); +#endif getSample_texture ( a0,r0,g0,b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); -#else - getSample_texture ( a0,r0,g0,b0, - &IT[0], - tofix ( line.t[0][0].x), - tofix ( line.t[0][0].y) - ); -#endif - if ( (tFixPointu) a0 > AlphaRef ) + + if ( a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -284,30 +270,23 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef INVERSE_W - getSample_color ( r2, g2, b2, line.c[0][0], inversew ); -#else - getSample_color ( r2, g2, b2, line.c[0][0] ); -#endif - r0 = imulFix ( r0, r2 ); - g0 = imulFix ( g0, g2 ); - b0 = imulFix ( b0, b2 ); +#ifdef IPOL_C0 + + vec4_to_fix( r2, g2, b2, line.c[0][0], inversew ); + + r0 = imulFix_simple( r0, r2 ); + g0 = imulFix_simple( g0, g2 ); + b0 = imulFix_simple( b0, b2 ); color_to_fix ( r1, g1, b1, dst[i] ); - a0 >>= 8; + fix_color_norm(a0); r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); - dst[i] = fix4_to_color ( a0, r2, g2, b2 ); + dst[i] = fix4_to_sample( a0, r2, g2, b2 ); -/* - dst[i] = PixelBlend32 ( dst[i], - fix_to_color ( r0,g0, b0 ), - fixPointu_to_u32 ( a0 ) - ); -*/ /* getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); color_to_fix ( r1, g1, b1, dst[i] ); @@ -315,9 +294,14 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () r2 = r0 + imulFix ( a0, r1 - r0 ); g2 = g0 + imulFix ( a0, g1 - g0 ); b2 = b0 + imulFix ( a0, b1 - b0 ); - dst[i] = fix_to_color ( r2, g2, b2 ); + dst[i] = fix_to_sample ( r2, g2, b2 ); */ - +#else + dst[i] = PixelBlend32 ( dst[i], + fix_to_sample( r0,g0, b0 ), + fixPointu_to_u32 ( a0 ) + ); +#endif } #endif @@ -342,7 +326,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () } -void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureGouraudAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -353,9 +337,9 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -441,8 +425,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -600,8 +584,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -720,6 +704,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAlpha(CBurningVideoDriver* driver) { + //ETR_TEXTURE_GOURAUD_ALPHA #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAlpha2(driver); #else diff --git a/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp b/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp index 2830247e..6a550334 100644 --- a/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp +++ b/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp @@ -21,6 +21,7 @@ #undef INVERSE_W #undef IPOL_C0 +#undef IPOL_C1 #undef IPOL_T0 #undef IPOL_T1 @@ -34,6 +35,7 @@ //#define WRITE_W #define IPOL_C0 +//#define IPOL_C1 #define IPOL_T0 //#define IPOL_T1 @@ -46,10 +48,14 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif +#if BURNING_MATERIAL_MAX_COLORS < 2 + #undef IPOL_C1 +#endif + #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W @@ -84,18 +90,34 @@ public: CTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; - virtual void setParam ( u32 index, f32 value) _IRR_OVERRIDE_; +#if defined(PATCH_SUPERTUX_8_0_1) + SBurningShaderMaterial Material; + virtual void setMaterial(const SBurningShaderMaterial &material) + { + Material = material; + } + + virtual void setParam(u32 index, f32 value) + { + OnSetMaterial(Material); +} +#endif private: - void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; + // fragment shader + typedef void (CTRTextureGouraudAlphaNoZ::*tFragmentShader) (); + void fragment_linear(); + void fragment_linear_test(); + void fragment_point_noz(); + + tFragmentShader fragmentShader; + - u32 AlphaRef; }; //! constructor @@ -106,24 +128,37 @@ CTRTextureGouraudAlphaNoZ::CTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver setDebugName("CTRTextureGouraudAlphaNoZ"); #endif - AlphaRef = 0; + fragmentShader = &CTRTextureGouraudAlphaNoZ::fragment_linear; } /*! */ -void CTRTextureGouraudAlphaNoZ::setParam ( u32 index, f32 value) +void CTRTextureGouraudAlphaNoZ::OnSetMaterial(const SBurningShaderMaterial& material) { -#ifdef BURNINGVIDEO_RENDERER_FAST - AlphaRef = core::floor32_fast( value * 256.f ); +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + AlphaRef = core::floor32(material.org.MaterialTypeParam * 256.f); #else - AlphaRef = u32_to_fixPoint ( core::floor32_fast( value * 256.f ) ); + AlphaRef = tofix(material.org.MaterialTypeParam, FIXPOINT_COLOR_MAX); #endif + + //check triangle on w = 1.f instead.. +#ifdef SOFTWARE_DRIVER_2_BILINEAR + if (material.Fallback_MaterialType == EMT_TRANSPARENT_ALPHA_CHANNEL_REF) + fragmentShader = &CTRTextureGouraudAlphaNoZ::fragment_linear_test; + else + if ( material.org.TextureLayer[0].BilinearFilter ) + fragmentShader = &CTRTextureGouraudAlphaNoZ::fragment_linear; + else + +#endif + fragmentShader = &CTRTextureGouraudAlphaNoZ::fragment_point_noz; + } /*! */ -void CTRTextureGouraudAlphaNoZ::scanline_bilinear () +void CTRTextureGouraudAlphaNoZ::fragment_linear() { tVideoSample *dst; @@ -147,15 +182,15 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC[MATERIAL_MAX_COLORS]; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -163,7 +198,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -174,6 +209,9 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif +#ifdef IPOL_C1 + slopeC[1] = (line.c[1][1] - line.c[1][0]) * invDeltaX; +#endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif @@ -192,6 +230,9 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1] * subPixel; +#endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif @@ -200,6 +241,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -209,7 +251,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () f32 inversew = FIX_POINT_F32_MUL; -#ifdef BURNINGVIDEO_RENDERER_FAST +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff u32 dIndex = ( line.y & 3 ) << 2; #else @@ -219,7 +261,11 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #ifdef IPOL_C0 tFixPoint r1, g1, b1; - tFixPoint r2, g2, b2; + tFixPoint a2,r2, g2, b2; +#endif + +#ifdef IPOL_C1 + tFixPoint a3,r3, g3, b3; #endif for ( s32 i = 0; i <= dx; ++i ) @@ -233,7 +279,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () { -#ifdef BURNINGVIDEO_RENDERER_FAST +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; @@ -244,7 +290,7 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () d + tofix ( line.t[0][0].y,inversew) ); - const u32 alpha = ( argb >> 24 ); + const tFixPoint alpha = ( argb >> 24 ); if ( alpha > AlphaRef ) { #ifdef WRITE_Z @@ -262,19 +308,14 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); +#endif getSample_texture ( a0, r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); -#else - getSample_texture ( a0, r0, g0,b0, - &IT[0], - tofix ( line.t[0][0].x), - tofix ( line.t[0][0].y) - ); -#endif - if ( (tFixPointu) a0 > AlphaRef ) + + if ( a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -283,39 +324,30 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef INVERSE_W - getSample_color ( r2, g2, b2, line.c[0][0], inversew ); -#else - getSample_color ( r2, g2, b2, line.c[0][0] ); -#endif - r0 = imulFix ( r0, r2 ); - g0 = imulFix ( g0, g2 ); - b0 = imulFix ( b0, b2 ); +#ifdef IPOL_C0 + + vec4_to_fix( a2,r2, g2, b2, line.c[0][0], inversew ); + + //a0 = imulFix(a0, a2); //2D uses vertexalpha*texelalpha + r0 = imulFix_simple( r0, r2 ); + g0 = imulFix_simple( g0, g2 ); + b0 = imulFix_simple( b0, b2 ); color_to_fix ( r1, g1, b1, dst[i] ); - a0 >>= 8; + fix_color_norm(a0); r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); - dst[i] = fix4_to_color ( a0, r2, g2, b2 ); + dst[i] = fix4_to_sample( a0, r2, g2, b2 ); -/* +#else dst[i] = PixelBlend32 ( dst[i], - fix_to_color ( r0,g0, b0 ), + fix_to_sample( r0,g0, b0 ), fixPointu_to_u32 ( a0 ) ); -*/ -/* - getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); - color_to_fix ( r1, g1, b1, dst[i] ); - - r2 = r0 + imulFix ( a0, r1 - r0 ); - g2 = g0 + imulFix ( a0, g1 - g0 ); - b2 = b0 + imulFix ( a0, b1 - b0 ); - dst[i] = fix_to_color ( r2, g2, b2 ); -*/ +#endif } #endif @@ -331,6 +363,9 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1]; +#endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif @@ -341,7 +376,447 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () } -void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +/*! +*/ +void CTRTextureGouraudAlphaNoZ::fragment_linear_test() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left(line.x[0]); + xEnd = fill_convention_right(line.x[1]); + + dx = xEnd - xStart; + + if (dx < 0) + return; + + // slopes + const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_C1 + slopeC[1] = (line.c[1][1] - line.c[1][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ((f32)xStart) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + (line.y * RenderTarget->getDimension().Width) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*)DepthBuffer->lock() + (line.y * RenderTarget->getDimension().Width) + xStart; +#endif + + + f32 inversew = FIX_POINT_F32_MUL; + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + u32 dIndex = (line.y & 3) << 2; + +#else + tFixPoint a0; + tFixPoint r0, g0, b0; +#endif + +#ifdef IPOL_C0 + tFixPoint r1, g1, b1; + tFixPoint a2, r2, g2, b2; +#endif + +#ifdef IPOL_C1 + tFixPoint a3, r3, g3, b3; +#endif + + for (s32 i = 0; i <= dx; ++i) + { +#ifdef CMP_Z + if (line.z[0] < z[i]) +#endif +#ifdef CMP_W + if (line.w[0] >= z[i]) +#endif + + { + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + + const tFixPointu d = dithermask[dIndex | (i) & 3]; + +#ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); +#endif + u32 argb = getTexel_plain(&IT[0], d + tofix(line.t[0][0].x, inversew), + d + tofix(line.t[0][0].y, inversew) + ); + + const tFixPoint alpha = (argb >> 24); + if (alpha > AlphaRef) + { +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + + dst[i] = PixelBlend32(dst[i], argb, alpha); + } + + +#else + +#ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); +#endif + getSample_texture(a0, r0, g0, b0, + &IT[0], + tofix(line.t[0][0].x, inversew), + tofix(line.t[0][0].y, inversew) + ); + + if (a0 > AlphaRef) + { +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef IPOL_C0 + + vec4_to_fix(a2, r2, g2, b2, line.c[0][0], inversew); + + a0 = imulFix(a0, a2); //2D uses vertexalpha*texelalpha + r0 = imulFix(r0, r2); + g0 = imulFix(g0, g2); + b0 = imulFix(b0, b2); + + color_to_fix(r1, g1, b1, dst[i]); + + fix_color_norm(a0); + + r2 = r1 + imulFix(a0, r0 - r1); + g2 = g1 + imulFix(a0, g0 - g1); + b2 = b1 + imulFix(a0, b0 - b1); + dst[i] = fix4_to_sample(a0, r2, g2, b2); + +#else + dst[i] = PixelBlend32(dst[i], + fix_to_sample(r0, g0, b0), + fixPointu_to_u32(a0) + ); +#endif + + } +#endif + + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1]; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + +} + + +/*! +*/ +void CTRTextureGouraudAlphaNoZ::fragment_point_noz() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + //fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left(line.x[0]); + xEnd = fill_convention_right(line.x[1]); + + dx = xEnd - xStart; + + if (dx < 0) + return; + + // slopes + const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_C1 + slopeC[1] = (line.c[1][1] - line.c[1][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ((f32)xStart) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + (line.y * RenderTarget->getDimension().Width) + xStart; + +#ifdef USE_ZBUFFER + //z = (fp24*)DepthBuffer->lock() + (line.y * RenderTarget->getDimension().Width) + xStart; +#endif + + + f32 inversew = FIX_POINT_F32_MUL; + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + u32 dIndex = (line.y & 3) << 2; + +#else + tFixPoint a0; + tFixPoint r0, g0, b0; +#endif + +#ifdef IPOL_C0 + tFixPoint r1, g1, b1; + tFixPoint a2,r2, g2, b2; +#endif + +#ifdef IPOL_C1 + tFixPoint a3, r3, g3, b3; +#endif + for (s32 i = 0; i <= dx; ++i) + { +#ifdef CMP_Z + if (line.z[0] < z[i]) +#endif +#ifdef CMP_W +// if (line.w[0] >= z[i]) +#endif + + { + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + + const tFixPointu d = dithermask[dIndex | (i) & 3]; + +#ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); +#endif + u32 argb = getTexel_plain(&IT[0], d + tofix(line.t[0][0].x, inversew), + d + tofix(line.t[0][0].y, inversew) + ); + + const tFixPoint alpha = (argb >> 24); + if (alpha > AlphaRef) + { +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + + dst[i] = PixelBlend32(dst[i], argb, alpha); + } + + +#else + +#ifdef INVERSE_W + //inversew = fix_inverse32(line.w[0]); +#endif + getTexel_fix(a0, r0, g0, b0, + &IT[0], + tofix(line.t[0][0].x, inversew), + tofix(line.t[0][0].y, inversew) + ); + + if (a0 > AlphaRef) + { +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + //z[i] = line.w[0]; +#endif + +#ifdef IPOL_C0 + + vec4_to_fix(a2,r2, g2, b2, line.c[0][0], inversew); + + a0 = imulFix(a0, a2); //2D uses vertexalpha*texelalpha + r0 = imulFix(r0, r2); + g0 = imulFix(g0, g2); + b0 = imulFix(b0, b2); + + color_to_fix(r1, g1, b1, dst[i]); + + fix_color_norm(a0); + + r2 = r1 + imulFix(a0, r0 - r1); + g2 = g1 + imulFix(a0, g0 - g1); + b2 = b1 + imulFix(a0, b0 - b1); + dst[i] = fix4_to_sample(a0, r2, g2, b2); + +#else + dst[i] = PixelBlend32(dst[i], + fix_to_sample(r0, g0, b0), + fixPointu_to_u32(a0) + ); +#endif + + } +#endif + + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + //line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1]; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + +} + +void CTRTextureGouraudAlphaNoZ::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -352,9 +827,9 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -389,6 +864,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][0] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][0] = (c->Color[1] - a->Color[1]) * scan.invDeltaY[0]; + scan.c[1][0] = a->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; @@ -429,6 +909,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][1] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (b->Color[1] - a->Color[1]) * scan.invDeltaY[1]; + scan.c[1][1] = a->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; @@ -440,8 +925,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -465,6 +950,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -498,6 +988,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -509,7 +1004,7 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif // render a scanline - scanline_bilinear ( ); + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -529,6 +1024,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -560,6 +1060,10 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif +#ifdef IPOL_C1 + scan.c[1][0] = a->Color[1] + scan.slopeC[1][0] * temp[0]; +#endif + #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif @@ -588,6 +1092,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][1] = b->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (c->Color[1] - b->Color[1]) * scan.invDeltaY[2]; + scan.c[1][1] = b->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; @@ -599,8 +1108,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -625,6 +1134,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -658,6 +1172,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -669,7 +1188,7 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte #endif // render a scanline - scanline_bilinear ( ); + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -689,6 +1208,11 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -720,6 +1244,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver) { + // ETR_TEXTURE_GOURAUD_ALPHA_NOZ #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAlphaNoZ(driver); #else @@ -728,6 +1253,7 @@ IBurningShader* createTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver) } + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/CTRTextureGouraudNoZ2.cpp b/source/Irrlicht/CTRTextureGouraudNoZ2.cpp index 6abc6e11..c2b4625d 100644 --- a/source/Irrlicht/CTRTextureGouraudNoZ2.cpp +++ b/source/Irrlicht/CTRTextureGouraudNoZ2.cpp @@ -42,7 +42,7 @@ #define IPOL_T0 //#define IPOL_T1 -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -88,13 +88,11 @@ public: CTRTextureGouraudNoZ2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; }; @@ -142,8 +140,8 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -151,7 +149,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -188,6 +186,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -199,7 +198,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) tFixPoint tx0; tFixPoint ty0; - + tFixPoint r0, g0, b0; for ( s32 i = 0; i <= dx; ++i ) { @@ -216,12 +215,12 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #endif tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); - dst[i] = getTexel_plain ( &IT[0], tx0, ty0 ); + //skybox + //dst[i] = getTexel_plain ( &IT[0], tx0, ty0 ); + + getSample_texture ( r0, g0, b0, IT+0, tx0, ty0 ); + dst[i] = fix_to_sample( r0, g0, b0 ); -/* - getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); - dst[i] = fix_to_color ( r0, g0, b0 ); -*/ #ifdef WRITE_Z z[i] = line.z[0]; #endif @@ -249,7 +248,7 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) } -void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureGouraudNoZ2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -260,9 +259,9 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -348,8 +347,8 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -507,8 +506,8 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -626,6 +625,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudNoZ2(CBurningVideoDriver* driver) { + // ETR_TEXTURE_GOURAUD_NOZ #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudNoZ2( driver ); #else diff --git a/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp b/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp index 8da8e872..4b9c4c20 100644 --- a/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp +++ b/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp @@ -21,6 +21,7 @@ #undef INVERSE_W #undef IPOL_C0 +#undef IPOL_C1 #undef IPOL_T0 #undef IPOL_T1 @@ -34,6 +35,7 @@ //#define WRITE_W #define IPOL_C0 +#define IPOL_C1 #define IPOL_T0 //#define IPOL_T1 @@ -46,10 +48,15 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif +#if BURNING_MATERIAL_MAX_COLORS < 2 + #undef IPOL_C1 +#endif + + #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W @@ -82,13 +89,11 @@ public: CTRTextureVertexAlpha2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; }; @@ -129,15 +134,15 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -145,7 +150,7 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -154,7 +159,10 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_C1 + slopeC[1] = (line.c[1][1] - line.c[1][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -172,8 +180,12 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0][0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; #endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1] * subPixel; +#endif + #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif @@ -182,6 +194,7 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -191,22 +204,18 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) f32 inversew = FIX_POINT_F32_MUL; -//#define __TEST_THIS - -#ifdef __TEST_THIS - -#else tFixPoint tx0; tFixPoint ty0; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; - tFixPoint r2, g2, b2; -#endif - #ifdef IPOL_C0 - tFixPoint a3; + tFixPoint a2,r2, g2, b2; +#endif + +#ifdef IPOL_C1 + tFixPoint aFog = FIX_POINT_ONE; #endif @@ -220,50 +229,74 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #endif { -#ifdef __TEST_THIS - - inversew = fix_inverse32 ( line.w[0] ); - - dst[i] = PixelAdd32 ( - dst[i], - getTexel_plain ( &IT[0], tofix ( line.t[0][0].x,inversew), - tofix ( line.t[0][0].y,inversew) ) - ); - -#else - -#ifdef INVERSE_W - inversew = fix_inverse32 ( line.w[0] ); -#endif - tx0 = tofix ( line.t[0][0].x,inversew); - ty0 = tofix ( line.t[0][0].y,inversew); - -#ifdef IPOL_C0 - a3 = tofix ( line.c[0][0].y,inversew ); -#endif - - getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); - color_to_fix ( r1, g1, b1, dst[i] ); - -#ifdef IPOL_C0 - r2 = clampfix_maxcolor ( r1 + imulFix ( r0, a3 ) ); - g2 = clampfix_maxcolor ( g1 + imulFix ( g0, a3 ) ); - b2 = clampfix_maxcolor ( b1 + imulFix ( b0, a3 ) ); -#else - r2 = clampfix_maxcolor ( r1 + r0 ); - g2 = clampfix_maxcolor ( g1 + g0 ); - b2 = clampfix_maxcolor ( b1 + b0 ); -#endif - - dst[i] = fix_to_color ( r2, g2, b2 ); - #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif + +#ifdef INVERSE_W + inversew = fix_inverse32 ( line.w[0] ); #endif +#ifdef IPOL_C1 + //complete inside fog + if (TL_Flag & TL_FOG) + { + aFog = tofix(line.c[1][0].a, inversew); + if (aFog <= 0) + { + dst[i] = fog_color_sample; + continue; + } + } +#endif + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + + getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + vec4_to_fix(a2,r2, g2, b2, line.c[0][0], inversew); + + r0 = imulFix_simple(r0, r2); + g0 = imulFix_simple(g0, g2); + b0 = imulFix_simple(b0, b2); + +#ifdef IPOL_C1 + //specular highlight + if (TL_Flag & TL_SPECULAR) + { + vec4_to_fix(r2, g2, b2, line.c[1][0], inversew*COLOR_MAX); + r0 = clampfix_maxcolor(r2 + r0); + g0 = clampfix_maxcolor(g2 + g0); + b0 = clampfix_maxcolor(b2 + b0); + } +#endif + //blend background + r0 = r1 + imulFix(a2, r0 - r1); + g0 = g1 + imulFix(a2, g0 - g1); + b0 = b1 + imulFix(a2, b0 - b1); + +#ifdef IPOL_C1 + //mix with distance + if (aFog < FIX_POINT_ONE) //TL_Flag & TL_FOG) + { + r0 = fog_color[1] + imulFix(aFog, r0 - fog_color[1]); + g0 = fog_color[2] + imulFix(aFog, g0 - fog_color[2]); + b0 = fog_color[3] + imulFix(aFog, b0 - fog_color[3]); + } +#endif + +#else + r0 = clampfix_maxcolor ( r1 + r0 ); + g0 = clampfix_maxcolor ( g1 + g0 ); + b0 = clampfix_maxcolor ( b1 + b0 ); +#endif + + dst[i] = fix_to_sample( r0, g0, b0 ); + } #ifdef IPOL_Z @@ -273,7 +306,10 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) line.w[0] += slopeW; #endif #ifdef IPOL_C0 - line.c[0][0] += slopeC; + line.c[0][0] += slopeC[0]; +#endif +#ifdef IPOL_C1 + line.c[1][0] += slopeC[1]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; @@ -285,7 +321,7 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) } -void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureVertexAlpha2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -296,9 +332,9 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -333,6 +369,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][0] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][0] = (c->Color[1] - a->Color[1]) * scan.invDeltaY[0]; + scan.c[1][0] = a->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; @@ -373,6 +414,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][1] = a->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (b->Color[1] - a->Color[1]) * scan.invDeltaY[1]; + scan.c[1][1] = a->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; @@ -384,8 +430,8 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -409,6 +455,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -442,6 +493,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -473,6 +529,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -504,6 +565,9 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif +#ifdef IPOL_C1 + scan.c[1][0] = a->Color[1] + scan.slopeC[1][0] * temp[0]; +#endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif @@ -532,6 +596,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][1] = b->Color[0]; #endif +#ifdef IPOL_C1 + scan.slopeC[1][1] = (c->Color[1] - b->Color[1]) * scan.invDeltaY[2]; + scan.c[1][1] = b->Color[1]; +#endif + #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; @@ -543,8 +612,8 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -569,6 +638,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0] * subPixel; + scan.c[1][1] += scan.slopeC[1][1] * subPixel; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; @@ -602,6 +676,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * line.c[0][scan.right] = scan.c[0][1]; #endif +#ifdef IPOL_C1 + line.c[1][scan.left] = scan.c[1][0]; + line.c[1][scan.right] = scan.c[1][1]; +#endif + #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; @@ -633,6 +712,11 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * scan.c[0][1] += scan.slopeC[0][1]; #endif +#ifdef IPOL_C1 + scan.c[1][0] += scan.slopeC[1][0]; + scan.c[1][1] += scan.slopeC[1][1]; +#endif + #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; @@ -662,6 +746,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureVertexAlpha2(CBurningVideoDriver* driver) { + /* ETR_TEXTURE_GOURAUD_VERTEX_ALPHA */ #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureVertexAlpha2(driver); #else diff --git a/source/Irrlicht/CTRTextureLightMap2_Add.cpp b/source/Irrlicht/CTRTextureLightMap2_Add.cpp index db49d530..d5cc7e32 100644 --- a/source/Irrlicht/CTRTextureLightMap2_Add.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_Add.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -82,15 +82,12 @@ public: CTRTextureLightMap2_Add(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; - }; //! constructor @@ -137,8 +134,8 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -146,7 +143,7 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -183,6 +180,7 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -190,11 +188,10 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #endif -#ifdef BURNINGVIDEO_RENDERER_FAST f32 inversew = FIX_POINT_F32_MUL; + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff u32 dIndex = ( line.y & 3 ) << 2; - - #else // tFixPoint r0, g0, b0; @@ -219,11 +216,12 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef BURNINGVIDEO_RENDERER_FAST - #ifdef INVERSE_W - inversew = fix_inverse32 ( line.w[0] ); + inversew = fix_inverse32(line.w[0]); #endif + +#if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff + const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( @@ -234,12 +232,11 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () ); #else - const f32 inversew = fix_inverse32 ( line.w[0] ); getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[0][1].x,inversew), tofix ( line.t[0][1].y,inversew) ); - dst[i] = fix_to_color ( clampfix_maxcolor ( r0 + r1 ), + dst[i] = fix_to_sample( clampfix_maxcolor ( r0 + r1 ), clampfix_maxcolor ( g0 + g1 ), clampfix_maxcolor ( b0 + b1 ) ); @@ -266,7 +263,7 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () } -void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -277,9 +274,9 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -365,8 +362,8 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -524,8 +521,8 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL diff --git a/source/Irrlicht/CTRTextureLightMap2_M1.cpp b/source/Irrlicht/CTRTextureLightMap2_M1.cpp index 71952749..1295d3c7 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M1.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M1.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -82,14 +82,12 @@ public: CTRTextureLightMap2_M1(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear2 (); - sScanLineData line; - }; //! constructor @@ -115,15 +113,15 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; if ( dx < 0 ) return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -170,6 +168,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () line.z[0] = a; line.z[1] = b; #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -226,7 +225,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () #endif - dst[i] = fix_to_color ( imulFix_tex1 ( r0, r1 ), + dst[i] = fix_to_sample( imulFix_tex1 ( r0, r1 ), imulFix_tex1 ( g0, g1 ), imulFix_tex1 ( b0, b1 ) ); @@ -244,9 +243,8 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () } -void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_M1::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { - sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -257,9 +255,9 @@ void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex * const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -345,8 +343,8 @@ void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -505,8 +503,8 @@ void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -626,6 +624,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_M1(CBurningVideoDriver* driver) { + //ETR_TEXTURE_GOURAUD_LIGHTMAP_M1 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureLightMap2_M1(driver); #else diff --git a/source/Irrlicht/CTRTextureLightMap2_M2.cpp b/source/Irrlicht/CTRTextureLightMap2_M2.cpp index f748990b..5976cfb8 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M2.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M2.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -82,14 +82,12 @@ public: CTRTextureLightMap2_M2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear2 (); - sScanLineData line; - }; //! constructor @@ -115,15 +113,15 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; if ( dx < 0 ) return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -170,6 +168,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () line.z[0] = a; line.z[1] = b; #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -226,7 +225,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () #endif - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + dst[i] = fix_to_sample( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); @@ -244,10 +243,8 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () } -void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_M2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { - sScanConvertData scan; - // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); @@ -257,9 +254,9 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -345,8 +342,8 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -505,8 +502,8 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL diff --git a/source/Irrlicht/CTRTextureLightMap2_M4.cpp b/source/Irrlicht/CTRTextureLightMap2_M4.cpp index 3fd726cf..b33a0e0c 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M4.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M4.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -82,19 +82,21 @@ public: CTRTextureLightMap2_M4(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: - void drawTriangle_Min ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); - void drawTriangle_Mag ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); - - void scanline_bilinear (); +#if defined(SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN) + void drawTriangle_Min ( const s4DVertex* burning_restrict a,const s4DVertex* burning_restrict b,const s4DVertex* burning_restrict c ); + void drawTriangle_Mag ( const s4DVertex* burning_restrict a,const s4DVertex* burning_restrict b,const s4DVertex* burning_restrict c ); void scanline_bilinear2_mag (); void scanline_bilinear2_min (); +#else + #define scanline_bilinear2_mag scanline_bilinear +#endif - sScanLineData line; + void scanline_bilinear (); }; @@ -109,14 +111,14 @@ CTRTextureLightMap2_M4::CTRTextureLightMap2_M4(CBurningVideoDriver* driver) /*! */ -REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () +void CTRTextureLightMap2_M4::scanline_bilinear2_mag () { tVideoSample *dst; fp24 *z; // apply top-left fill-convention, left - const s32 xStart = irr::core::ceil32_fast( line.x[0] ); - const s32 xEnd = irr::core::ceil32_fast( line.x[1] ) - 1; + const s32 xStart = fill_convention_left(line.x[0]); + const s32 xEnd = fill_convention_right(line.x[1]); s32 dx; s32 i; @@ -125,8 +127,10 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () if ( dx < 0 ) return; + SOFTWARE_DRIVER_2_CLIPCHECK; + // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel i = ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -229,11 +233,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif - - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) - ); + dst[i] = fix_to_sample(imulFix_tex4(r0, r1), imulFix_tex4(g0, g1), imulFix_tex4(b0, b1)); } #ifdef IPOL_W @@ -248,7 +248,8 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () } -REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () +#if defined (SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN) +void CTRTextureLightMap2_M4::scanline_bilinear2_min () { tVideoSample *dst; fp24 *z; @@ -260,15 +261,17 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left(line.x[0]); + xEnd = fill_convention_right(line.x[1]); dx = xEnd - xStart; if ( dx < 0 ) return; + SOFTWARE_DRIVER_2_CLIPCHECK; + // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; @@ -315,6 +318,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () line.z[0] = a; line.z[1] = b; #endif + dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -352,10 +356,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () getTexel_fix ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getTexel_fix ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) - ); + dst[i] = fix_to_sample(imulFix_tex4(r0, r1), imulFix_tex4(g0, g1), imulFix_tex4(b0, b1)); } #ifdef IPOL_W @@ -369,21 +370,20 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () } -//#ifdef BURNINGVIDEO_RENDERER_FAST -#if 1 - -void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { - if ( IT[0].lodLevel <= 2 ) - drawTriangle_Mag ( a, b, c ); + if (IT[0].lodFactor < 4) + { + drawTriangle_Mag(a, b, c); + } else - drawTriangle_Min ( a, b, c ); + { + drawTriangle_Min(a, b, c); + } } -void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex* burning_restrict a,const s4DVertex* burning_restrict b,const s4DVertex* burning_restrict c ) { - sScanConvertData scan; - // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); @@ -393,9 +393,9 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; @@ -481,8 +481,8 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -641,8 +641,8 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -746,16 +746,15 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert } -void CTRTextureLightMap2_M4::drawTriangle_Mag ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_M4::drawTriangle_Mag ( const s4DVertex* burning_restrict a,const s4DVertex* burning_restrict b,const s4DVertex* burning_restrict c ) -#else +#else //#if defined (SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN) -void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) #endif { - sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -765,14 +764,18 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; - // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); - if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) + if ( F32_LOWER_EQUAL_0 ( ca ) ) return; + // calculate delta y of the edges + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); + + //if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) + // return; + // find if the major edge is left or right aligned f32 temp[4]; @@ -855,8 +858,8 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -1015,8 +1018,8 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL @@ -1120,6 +1123,8 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * } +#undef scanline_bilinear2_mag + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp b/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp index 64a14ab4..55e7ffc0 100644 --- a/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp +++ b/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp @@ -46,7 +46,7 @@ #undef SUBTEXEL #endif -#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#if BURNING_MATERIAL_MAX_COLORS < 1 #undef IPOL_C0 #endif @@ -82,15 +82,12 @@ public: CTRGTextureLightMap2_M4(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; private: void scanline_bilinear (); - sScanConvertData scan; - sScanLineData line; - }; //! constructor @@ -137,8 +134,8 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () #endif // apply top-left fill-convention, left - xStart = core::ceil32_fast( line.x[0] ); - xEnd = core::ceil32_fast( line.x[1] ) - 1; + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); dx = xEnd - xStart; @@ -146,7 +143,7 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () return; // slopes - const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; @@ -183,6 +180,7 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () #endif #endif + SOFTWARE_DRIVER_2_CLIPCHECK; dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER @@ -230,26 +228,22 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () getSample_texture ( r1, g1, b1, &IT[1], tx1, ty1 ); #ifdef IPOL_C0 - r2 = imulFix ( r0, r3 ); - g2 = imulFix ( g0, g3 ); - b2 = imulFix ( b0, b3 ); + r2 = imulFix_simple( r0, r3 ); + g2 = imulFix_simple( g0, g3 ); + b2 = imulFix_simple( b0, b3 ); + + r2 = imulFix_tex4 ( r2, r1 ); + g2 = imulFix_tex4 ( g2, g1 ); + b2 = imulFix_tex4 ( b2, b1 ); - r2 = clampfix_maxcolor ( imulFix_tex4 ( r2, r1 ) ); - g2 = clampfix_maxcolor ( imulFix_tex4 ( g2, g1 ) ); - b2 = clampfix_maxcolor ( imulFix_tex4 ( b2, b1 ) ); -/* - r2 = r3 << 8; - g2 = g3 << 8; - b2 = b3 << 8; -*/ #else - r2 = clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ); - g2 = clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ); - b2 = clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ); + r2 = imulFix_tex4 ( r0, r1 ); + g2 = imulFix_tex4 ( g0, g1 ); + b2 = imulFix_tex4 ( b0, b1 ); #endif - dst[i] = fix_to_color ( r2, g2, b2 ); + dst[i] = fix_to_sample( r2, g2, b2 ); #ifdef WRITE_Z z[i] = line.z[0]; @@ -278,7 +272,7 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () } -void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRGTextureLightMap2_M4::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); @@ -289,9 +283,9 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges - scan.invDeltaY[0] = core::reciprocal( ca ); - scan.invDeltaY[1] = core::reciprocal( ba ); - scan.invDeltaY[2] = core::reciprocal( cb ); + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); if ( F32_LOWER_0 ( scan.invDeltaY[0] ) ) return; @@ -379,8 +373,8 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( a->Pos.y ); - yEnd = core::ceil32_fast( b->Pos.y ) - 1; + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; @@ -540,8 +534,8 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex #endif // apply top-left fill convention, top part - yStart = core::ceil32_fast( b->Pos.y ); - yEnd = core::ceil32_fast( c->Pos.y ) - 1; + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); #ifdef SUBTEXEL diff --git a/source/Irrlicht/CTRTextureWire2.cpp b/source/Irrlicht/CTRTextureWire2.cpp index e1bb8ba6..b77b788f 100644 --- a/source/Irrlicht/CTRTextureWire2.cpp +++ b/source/Irrlicht/CTRTextureWire2.cpp @@ -28,14 +28,14 @@ #define SUBTEXEL #define INVERSE_W -#define USE_ZBUFFER +//#define USE_ZBUFFER #define IPOL_W -#define CMP_W -#define WRITE_W +//#define CMP_W +//#define WRITE_W -//#define IPOL_C0 -#define IPOL_T0 +#define IPOL_C0 +//#define IPOL_T0 //#define IPOL_T1 // apply global override @@ -47,6 +47,10 @@ #undef SUBTEXEL #endif +#if BURNING_MATERIAL_MAX_COLORS < 1 + #undef IPOL_C0 +#endif + #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W @@ -80,14 +84,17 @@ public: CTRTextureWire2(CBurningVideoDriver* driver); //! draws an indexed triangle list - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_; + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; virtual void drawLine ( const s4DVertex *a,const s4DVertex *b) _IRR_OVERRIDE_; + virtual void drawPoint( const s4DVertex *a) _IRR_OVERRIDE_; + virtual bool canWireFrame () _IRR_OVERRIDE_ { return true; } + virtual bool canPointCloud() _IRR_OVERRIDE_ { return true; } +protected: + virtual void scanline_bilinear (); - -private: void renderAlphaLine ( const s4DVertex *a,const s4DVertex *b ) const; - void renderLine ( const s4DVertex *a,const s4DVertex *b ) const; + void renderLine ( const s4DVertex *a,const s4DVertex *b, int renderZero = 0 ) const; }; @@ -101,26 +108,22 @@ CTRTextureWire2::CTRTextureWire2(CBurningVideoDriver* driver) } -// swap integer with xor -static inline void swap_xor ( s32 &a, s32 &b ) -{ - a ^= b; - b ^= a; - a ^= b; -} - /*! + 2d line */ -void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const +void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b, int renderZero) const { int pitch0 = RenderTarget->getDimension().Width << VIDEO_SAMPLE_GRANULARITY; +#ifdef USE_ZBUFFER int pitch1 = RenderTarget->getDimension().Width << 2; +#endif - int aposx = (int) a->Pos.x; - int aposy = (int) a->Pos.y; - int bposx = (int) b->Pos.x; - int bposy = (int) b->Pos.y; + //todo:! + int aposx = fill_convention_none(a->Pos.x); + int aposy = fill_convention_none(a->Pos.y); + int bposx = fill_convention_none(b->Pos.x); + int bposy = fill_convention_none(b->Pos.y); int dx = bposx - aposx; int dy = bposy - aposy; @@ -138,37 +141,39 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const int xInc0 = 1 << VIDEO_SAMPLE_GRANULARITY; int yInc0 = pitch0; +#ifdef USE_ZBUFFER int xInc1 = 4; int yInc1 = pitch1; - - tVideoSample color; - -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - tFixPoint r0, g0, b0; - getSample_color ( r0, g0, b0, a->Color[0] ); - color = fix_to_color ( r0, g0, b0 ); -#else - color = (tVideoSample) 0xFFFFFFFF; #endif if ( dx < 0 ) { xInc0 = - ( 1 << VIDEO_SAMPLE_GRANULARITY); +#ifdef USE_ZBUFFER xInc1 = -4; +#endif dx = -dx; } if ( dy > dx ) { - swap_xor ( dx, dy ); - swap_xor ( xInc0, yInc0 ); - swap_xor ( xInc1, yInc1 ); + //swap + register s32 t; + t = dx;dx=dy;dy=t; + t = xInc0;xInc0=yInc0;yInc0=t; +#ifdef USE_ZBUFFER + t = xInc1;xInc1=yInc1;yInc1=t; +#endif } - if ( 0 == dx ) - return; + if (0 == dx) + { + if (!renderZero) return; + dx = 1; + } - dst = (tVideoSample*) ( (u8*) (tVideoSample*)RenderTarget->getData() + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) ); + SOFTWARE_DRIVER_2_CLIPCHECK_WIRE; + dst = (tVideoSample*) ( (u8*) RenderTarget->getData() + ( aposy * pitch0 ) + (aposx* (1<< VIDEO_SAMPLE_GRANULARITY) ) ); #ifdef USE_ZBUFFER z = (fp24*) ( (u8*) (fp24*) DepthBuffer->lock() + ( aposy * pitch1 ) + (aposx << 2 ) ); #endif @@ -176,16 +181,43 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const c = dx << 1; m = dy << 1; + // slopes + const f32 invDeltaX = reciprocal_zero2( (f32)dx ); + #ifdef IPOL_Z - f32 slopeZ = (b->Pos.z - a->Pos.z) / f32(dx); + f32 slopeZ = (b->Pos.z - a->Pos.z) * invDeltaX; f32 dataZ = a->Pos.z; #endif #ifdef IPOL_W - fp24 slopeW = (b->Pos.w - a->Pos.w) / f32( dx ); + fp24 slopeW = (b->Pos.w - a->Pos.w) * invDeltaX; fp24 dataW = a->Pos.w; #endif + f32 inversew = FIX_POINT_F32_MUL; + + tVideoSample color; +#if BURNING_MATERIAL_MAX_COLORS > 0 + tFixPoint r0, g0, b0; +#ifdef IPOL_C0 + sVec4 slopeC; + sVec4 C; + slopeC = (b->Color[0] - a->Color[0]) * invDeltaX; + C = a->Color[0]; +#endif + +#ifdef INVERSE_W + inversew = fix_inverse32_color(dataW); +#endif + + vec4_to_fix( r0, g0, b0, a->Color[0], inversew); + color = fix_to_sample( r0, g0, b0 ); + +#else + color = (tVideoSample) 0xFFFFFFFF; +#endif + + run = dx; while ( run ) { @@ -203,15 +235,22 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const *z = dataW; #endif - *dst = color; +#ifdef IPOL_C0 +#ifdef INVERSE_W + inversew = fix_inverse32_color(dataW); +#endif + vec4_to_fix(r0, g0, b0, C,inversew); + color = fix_to_sample( r0, g0, b0 ); +#endif + *dst = color; } dst = (tVideoSample*) ( (u8*) dst + xInc0 ); // x += xInc -#ifdef IPOL_Z +#ifdef CMP_Z z = (fp24*) ( (u8*) z + xInc1 ); #endif -#ifdef IPOL_W +#ifdef CMP_W z = (fp24*) ( (u8*) z + xInc1 ); #endif @@ -219,10 +258,10 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const if ( d > dx ) { dst = (tVideoSample*) ( (u8*) dst + yInc0 ); // y += yInc -#ifdef IPOL_Z +#ifdef CMP_Z z = (fp24*) ( (u8*) z + yInc1 ); #endif -#ifdef IPOL_W +#ifdef CMP_W z = (fp24*) ( (u8*) z + yInc1 ); #endif @@ -235,15 +274,21 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const #ifdef IPOL_W dataW += slopeW; #endif +#ifdef IPOL_C0 + C += slopeC; +#endif + } } -void CTRTextureWire2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +void CTRTextureWire2::scanline_bilinear() { - sScanLineData line; +} +void CTRTextureWire2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) +{ // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); @@ -258,14 +303,17 @@ void CTRTextureWire2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const void CTRTextureWire2::drawLine ( const s4DVertex *a,const s4DVertex *b) { - // query access to TexMaps // sort on height, y - if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); + if (F32_A_GREATER_B(a->Pos.y,b->Pos.y )) swapVertexPointer(&a, &b); renderLine ( a, b ); +} +void CTRTextureWire2::drawPoint(const s4DVertex *a) +{ + if ( (a->flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE ) renderLine(a, a,1); } @@ -283,6 +331,7 @@ namespace video //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureGouraudWire2(CBurningVideoDriver* driver) { + //ETR_TEXTURE_GOURAUD_WIRE #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureWire2(driver); #else diff --git a/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp b/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp new file mode 100644 index 00000000..8fb92140 --- /dev/null +++ b/source/Irrlicht/CTR_transparent_reflection_2_layer.cpp @@ -0,0 +1,729 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" +#include "IBurningShader.h" + +#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + +// compile flag for this file +#undef USE_ZBUFFER +#undef IPOL_Z +#undef CMP_Z +#undef WRITE_Z + +#undef IPOL_W +#undef CMP_W +#undef WRITE_W + +#undef SUBTEXEL +#undef INVERSE_W + +#undef IPOL_C0 +#undef IPOL_T0 +#undef IPOL_T1 + +// define render case +#define SUBTEXEL +#define INVERSE_W + +#define USE_ZBUFFER +#define IPOL_W +#define CMP_W +#define WRITE_W + +#define IPOL_C0 +#define IPOL_T0 +#define IPOL_T1 + +// apply global override +#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + #undef INVERSE_W +#endif + +#ifndef SOFTWARE_DRIVER_2_SUBTEXEL + #undef SUBTEXEL +#endif + +#if BURNING_MATERIAL_MAX_COLORS < 1 + #undef IPOL_C0 +#endif + +#if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) + #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + #undef IPOL_W + #endif + #define IPOL_Z + + #ifdef CMP_W + #undef CMP_W + #define CMP_Z + #endif + + #ifdef WRITE_W + #undef WRITE_W + #define WRITE_Z + #endif + +#endif + +namespace irr +{ + +namespace video +{ + +class CTR_transparent_reflection_2_layer : public IBurningShader +{ +public: + + //! constructor + CTR_transparent_reflection_2_layer(CBurningVideoDriver* driver); + + //! draws an indexed triangle list + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; + +private: + void fragmentShader(); + + E_MATERIAL_TYPE MaterialType; + +}; + +//! constructor +CTR_transparent_reflection_2_layer::CTR_transparent_reflection_2_layer(CBurningVideoDriver* driver) +: IBurningShader(driver) +{ + #ifdef _DEBUG + setDebugName("CTR_transparent_reflection_2_layer"); + #endif +} + +void CTR_transparent_reflection_2_layer::OnSetMaterial(const SBurningShaderMaterial& material) +{ + MaterialType = material.org.MaterialType; + +} + +/*! +*/ +void CTR_transparent_reflection_2_layer::fragmentShader() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left( line.x[0] ); + xEnd = fill_convention_right( line.x[1] ); + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 inversew = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + +#ifdef IPOL_C0 + tFixPoint a1; +#endif + + switch(MaterialType) { + default: + case EMT_REFLECTION_2_LAYER: + for (s32 i = 0; i <= dx; ++i) + { +#ifdef CMP_Z + if (line.z[0] < z[i]) +#endif +#ifdef CMP_W + if (line.w[0] >= z[i]) +#endif + { + +#ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); +#endif + + getSample_texture(r0, g0, b0, &IT[0], tofix(line.t[0][0].x, inversew), tofix(line.t[0][0].y, inversew)); + getSample_texture(r1, g1, b1, &IT[1], tofix(line.t[1][0].x, inversew), tofix(line.t[1][0].y, inversew)); + + r0 = imulFix_tex1(r0, r1); + g0 = imulFix_tex1(g0, g1); + b0 = imulFix_tex1(b0, b1); + +#ifdef IPOL_C0 + vec4_to_fix(r1, g1, b1, line.c[0][0], inversew); + r0 = imulFix_simple(r1, r0); + g0 = imulFix_simple(g1, g0); + b0 = imulFix_simple(b1, b0); +#endif + + dst[i] = fix_to_sample(r0, g0, b0); + +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + break; + + case EMT_TRANSPARENT_REFLECTION_2_LAYER: + for (s32 i = 0; i <= dx; ++i) + { +#ifdef CMP_Z + if (line.z[0] < z[i]) +#endif +#ifdef CMP_W + if (line.w[0] >= z[i]) +#endif + { + +#ifdef INVERSE_W + inversew = fix_inverse32(line.w[0]); +#endif + + getSample_texture(r0, g0, b0, &IT[0], tofix(line.t[0][0].x, inversew), tofix(line.t[0][0].y, inversew)); + getSample_texture(r1, g1, b1, &IT[1], tofix(line.t[1][0].x, inversew), tofix(line.t[1][0].y, inversew)); + + r0 = imulFix_tex1(r0, r1); + g0 = imulFix_tex1(g0, g1); + b0 = imulFix_tex1(b0, b1); + +#ifdef IPOL_C0 + vec4_to_fix(a1, r1, g1, b1, line.c[0][0], inversew); + r0 = imulFix_simple(r1, r0); + g0 = imulFix_simple(g1, g0); + b0 = imulFix_simple(b1, b0); + + //vertex alpha blend EMT_TRANSPARENT_REFLECTION_2_LAYER + if (a1 + 2 < FIX_POINT_ONE) + { + color_to_fix(r1, g1, b1, dst[i]); + r0 = r1 + imulFix(a1, r0 - r1); + g0 = g1 + imulFix(a1, g0 - g1); + b0 = b1 + imulFix(a1, b0 - b1); + } +#endif + + dst[i] = fix_to_sample(r0, g0, b0); + +#ifdef WRITE_Z + //z[i] = line.z[0]; +#endif +#ifdef WRITE_W + //z[i] = line.w[0]; +#endif + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + break; + + } + + +} + +void CTR_transparent_reflection_2_layer::drawTriangle ( const s4DVertex* burning_restrict a,const s4DVertex* burning_restrict b,const s4DVertex* burning_restrict c ) +{ + // sort on height, y + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); + if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); + + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; + // calculate delta y of the edges + scan.invDeltaY[0] = reciprocal_zero( ca ); + scan.invDeltaY[1] = reciprocal_zero( ba ); + scan.invDeltaY[2] = reciprocal_zero( cb ); + + if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) + return; + + // find if the major edge is left or right aligned + f32 temp[4]; + + temp[0] = a->Pos.x - c->Pos.x; + temp[1] = -ca; + temp[2] = b->Pos.x - a->Pos.x; + temp[3] = ba; + + scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; + scan.right = 1 - scan.left; + + // calculate slopes for the major edge + scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; + scan.x[0] = a->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; + scan.z[0] = a->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; + scan.w[0] = a->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; + scan.t[0][0] = a->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; + scan.t[1][0] = a->Tex[1]; +#endif + + // top left fill convention y run + s32 yStart; + s32 yEnd; + +#ifdef SUBTEXEL + f32 subPixel; +#endif + + // rasterize upper sub-triangle + if ( F32_GREATER_0(scan.invDeltaY[1]) ) + { + // calculate slopes for top edge + scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; + scan.x[1] = a->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; + scan.z[1] = a->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; + scan.w[1] = a->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; + scan.t[0][1] = a->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; + scan.t[1][1] = a->Tex[1]; +#endif + + // apply top-left fill convention, top part + yStart = fill_convention_left( a->Pos.y ); + yEnd = fill_convention_right( b->Pos.y ); + +#ifdef SUBTEXEL + subPixel = ( (f32) yStart ) - a->Pos.y; + + // correct to pixel center + scan.x[0] += scan.slopeX[0] * subPixel; + scan.x[1] += scan.slopeX[1] * subPixel; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0] * subPixel; + scan.z[1] += scan.slopeZ[1] * subPixel; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0] * subPixel; + scan.w[1] += scan.slopeW[1] * subPixel; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0] * subPixel; + scan.t[0][1] += scan.slopeT[0][1] * subPixel; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0] * subPixel; + scan.t[1][1] += scan.slopeT[1][1] * subPixel; +#endif + +#endif + + // rasterize the edge scanlines + for( line.y = yStart; line.y <= yEnd; ++line.y) + { + line.x[scan.left] = scan.x[0]; + line.x[scan.right] = scan.x[1]; + +#ifdef IPOL_Z + line.z[scan.left] = scan.z[0]; + line.z[scan.right] = scan.z[1]; +#endif + +#ifdef IPOL_W + line.w[scan.left] = scan.w[0]; + line.w[scan.right] = scan.w[1]; +#endif + +#ifdef IPOL_C0 + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; +#endif + +#ifdef IPOL_T0 + line.t[0][scan.left] = scan.t[0][0]; + line.t[0][scan.right] = scan.t[0][1]; +#endif + +#ifdef IPOL_T1 + line.t[1][scan.left] = scan.t[1][0]; + line.t[1][scan.right] = scan.t[1][1]; +#endif + + // render a scanline + fragmentShader(); + + scan.x[0] += scan.slopeX[0]; + scan.x[1] += scan.slopeX[1]; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0]; + scan.z[1] += scan.slopeZ[1]; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0]; + scan.w[1] += scan.slopeW[1]; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0]; + scan.t[0][1] += scan.slopeT[0][1]; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0]; + scan.t[1][1] += scan.slopeT[1][1]; +#endif + + } + } + + // rasterize lower sub-triangle + if ( F32_GREATER_0(scan.invDeltaY[2]) ) + { + // advance to middle point + if( F32_GREATER_0(scan.invDeltaY[1]) ) + { + temp[0] = b->Pos.y - a->Pos.y; // dy + + scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; +#ifdef IPOL_Z + scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; +#endif +#ifdef IPOL_W + scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; +#endif +#ifdef IPOL_C0 + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; +#endif +#ifdef IPOL_T0 + scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; +#endif +#ifdef IPOL_T1 + scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; +#endif + + } + + // calculate slopes for bottom edge + scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; + scan.x[1] = b->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; + scan.z[1] = b->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; + scan.w[1] = b->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; + scan.t[0][1] = b->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; + scan.t[1][1] = b->Tex[1]; +#endif + + // apply top-left fill convention, top part + yStart = fill_convention_left( b->Pos.y ); + yEnd = fill_convention_right( c->Pos.y ); + +#ifdef SUBTEXEL + + subPixel = ( (f32) yStart ) - b->Pos.y; + + // correct to pixel center + scan.x[0] += scan.slopeX[0] * subPixel; + scan.x[1] += scan.slopeX[1] * subPixel; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0] * subPixel; + scan.z[1] += scan.slopeZ[1] * subPixel; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0] * subPixel; + scan.w[1] += scan.slopeW[1] * subPixel; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0] * subPixel; + scan.t[0][1] += scan.slopeT[0][1] * subPixel; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0] * subPixel; + scan.t[1][1] += scan.slopeT[1][1] * subPixel; +#endif + +#endif + + // rasterize the edge scanlines + for( line.y = yStart; line.y <= yEnd; ++line.y) + { + line.x[scan.left] = scan.x[0]; + line.x[scan.right] = scan.x[1]; + +#ifdef IPOL_Z + line.z[scan.left] = scan.z[0]; + line.z[scan.right] = scan.z[1]; +#endif + +#ifdef IPOL_W + line.w[scan.left] = scan.w[0]; + line.w[scan.right] = scan.w[1]; +#endif + +#ifdef IPOL_C0 + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; +#endif + +#ifdef IPOL_T0 + line.t[0][scan.left] = scan.t[0][0]; + line.t[0][scan.right] = scan.t[0][1]; +#endif + +#ifdef IPOL_T1 + line.t[1][scan.left] = scan.t[1][0]; + line.t[1][scan.right] = scan.t[1][1]; +#endif + + // render a scanline + fragmentShader(); + + scan.x[0] += scan.slopeX[0]; + scan.x[1] += scan.slopeX[1]; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0]; + scan.z[1] += scan.slopeZ[1]; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0]; + scan.w[1] += scan.slopeW[1]; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0]; + scan.t[0][1] += scan.slopeT[0][1]; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0]; + scan.t[1][1] += scan.slopeT[1][1]; +#endif + + } + } + +} + + +} // end namespace video +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ + +namespace irr +{ +namespace video +{ + +//! creates a flat triangle renderer +IBurningShader* createTriangleRendererTexture_transparent_reflection_2_layer(CBurningVideoDriver* driver) +{ + /* + ETR_TRANSPARENT_REFLECTION_2_LAYER + Irrlicht EMT_REFLECTION_2_LAYER,EMT_TRANSPARENT_REFLECTION_2_LAYER + */ + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + return new CTR_transparent_reflection_2_layer(driver); + #else + return 0; + #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ +} + + +} // end namespace video +} // end namespace irr + + + diff --git a/source/Irrlicht/CXMeshFileLoader.cpp b/source/Irrlicht/CXMeshFileLoader.cpp index 89c2c77a..feddb408 100644 --- a/source/Irrlicht/CXMeshFileLoader.cpp +++ b/source/Irrlicht/CXMeshFileLoader.cpp @@ -912,6 +912,12 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) s16 uv2type = -1; s16 tangenttype = -1; s16 binormaltype = -1; + + (void)tangentpos; // disable unused variable warnings + (void)binormalpos; // disable unused variable warnings + (void)tangenttype; // disable unused variable warnings + (void)binormaltype; // disable unused variable warnings + for (j=0; jgetDepthBuffer (); - if ( DepthBuffer ) - DepthBuffer->grab(); - - Stencil = (CStencilBuffer*) driver->getStencilBuffer (); - if ( Stencil ) - Stencil->grab(); - + IT[i].Texture = 0; } + Driver = driver; + CallBack = 0; - //! destructor - IBurningShader::~IBurningShader() + RenderTarget = 0; + ColorMask = COLOR_BRIGHT_WHITE; + DepthBuffer = (CDepthBuffer*) driver->getDepthBuffer (); + if ( DepthBuffer ) + DepthBuffer->grab(); + + Stencil = (CStencilBuffer*) driver->getStencilBuffer (); + if ( Stencil ) + Stencil->grab(); + + stencilOp[0] = StencilOp_KEEP; + stencilOp[1] = StencilOp_KEEP; + stencilOp[2] = StencilOp_KEEP; + AlphaRef = 0; + RenderPass_ShaderIsTransparent = 0; + PrimitiveColor = COLOR_BRIGHT_WHITE; + TL_Flag = 0; +} + +IBurningShader::IBurningShader(CBurningVideoDriver* driver) +{ + constructor_IBurningShader(driver); +} + +//! Constructor +IBurningShader::IBurningShader( + CBurningVideoDriver* driver, + s32& outMaterialTypeNr, + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram , + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, + scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) +{ + constructor_IBurningShader(driver); + BaseMaterial = baseMaterial; + CallBack = callback; + if (CallBack) + CallBack->grab(); + + // register myself as new material + outMaterialTypeNr = Driver->addMaterialRenderer(this); +} + + +//! destructor +IBurningShader::~IBurningShader() +{ + if (RenderTarget) + RenderTarget->drop(); + + if (DepthBuffer) + DepthBuffer->drop(); + + if (Stencil) + Stencil->drop(); + + for ( u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i ) { - if (RenderTarget) - RenderTarget->drop(); - - if (DepthBuffer) - DepthBuffer->drop(); - - if (Stencil) - Stencil->drop(); - - for ( u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i ) - { - if ( IT[i].Texture ) - IT[i].Texture->drop(); - } + if ( IT[i].Texture ) + IT[i].Texture->drop(); } - //! sets a render target - void IBurningShader::setRenderTarget(video::IImage* surface, const core::rect& viewPort) + if (CallBack) + CallBack->drop(); + +} + +//! sets a render target +void IBurningShader::setRenderTarget(video::IImage* surface, const core::rect& viewPort) +{ + if (RenderTarget) + RenderTarget->drop(); + + RenderTarget = (video::CImage* ) surface; + + if (RenderTarget) { - if (RenderTarget) - RenderTarget->drop(); + RenderTarget->grab(); - RenderTarget = (video::CImage* ) surface; + //(fp24*) DepthBuffer->lock() = DepthBuffer->lock(); + } +} - if (RenderTarget) - { - RenderTarget->grab(); - //(fp24*) DepthBuffer->lock() = DepthBuffer->lock(); - } +//! sets the Texture +void IBurningShader::setTextureParam( const size_t stage, video::CSoftwareTexture2* texture, s32 lodFactor) +{ + sInternalTexture *it = &IT[stage]; + + if ( it->Texture) + it->Texture->drop(); + + it->Texture = texture; + + if ( it->Texture) + { + it->Texture->grab(); + + // select mignify and magnify + it->lodFactor = lodFactor; + + //only mipmap chain (means positive lodFactor) + u32 existing_level = it->Texture->getMipmapLevel(lodFactor); + it->data = (tVideoSample*) it->Texture->lock(ETLM_READ_ONLY, existing_level, 0); + + // prepare for optimal fixpoint + it->pitchlog2 = s32_log2_s32 ( it->Texture->getPitch() ); + + const core::dimension2d &dim = it->Texture->getSize(); + it->textureXMask = s32_to_fixPoint ( dim.Width - 1 ) & FIX_POINT_UNSIGNED_MASK; + it->textureYMask = s32_to_fixPoint ( dim.Height - 1 ) & FIX_POINT_UNSIGNED_MASK; + } +} + +//emulate a line with degenerate triangle and special shader mode (not perfect...) +void IBurningShader::drawLine ( const s4DVertex *a,const s4DVertex *b) +{ + sVec2 d; + d.x = b->Pos.x - a->Pos.x; d.x *= d.x; + d.y = b->Pos.y - a->Pos.y; d.y *= d.y; + //if ( d.x * d.y < 0.001f ) return; + + if ( a->Pos.x > b->Pos.x ) swapVertexPointer(&a, &b); + + s4DVertex c = *a; + + const f32 w = (f32)RenderTarget->getDimension().Width-1; + const f32 h = (f32)RenderTarget->getDimension().Height-1; + + if ( d.x < 2.f ) { c.Pos.x = b->Pos.x + 1.f + d.y; if ( c.Pos.x > w ) c.Pos.x = w; } + else c.Pos.x = b->Pos.x; + if ( d.y < 2.f ) { c.Pos.y = b->Pos.y + 1.f; if ( c.Pos.y > h ) c.Pos.y = h; EdgeTestPass |= edge_test_first_line; } + + drawTriangle ( a,b,&c ); + EdgeTestPass &= ~edge_test_first_line; + +} + +void IBurningShader::drawPoint(const s4DVertex *a) +{ +} + +void IBurningShader::drawWireFrameTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) +{ + if ( EdgeTestPass & edge_test_pass ) drawTriangle(a, b, c); + else if (EdgeTestPass & edge_test_point) + { + drawPoint(a); + drawPoint(b); + drawPoint(c); + } + else + { + drawLine(a, b); + drawLine(b, c); + drawLine(a, c); + } +} + + +void IBurningShader::OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) +{ + if (Driver) + Driver->setFallback_Material(BaseMaterial); + services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + if (CallBack) + CallBack->OnSetMaterial(material); + +} + +void IBurningShader::OnUnsetMaterial() +{ +} + +bool IBurningShader::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) +{ + // call callback to set shader constants + if (CallBack) + CallBack->OnSetConstants(this, UserData); + return true; +} + + +//! Returns if the material is transparent. +bool IBurningShader::isTransparent() const +{ + return RenderPass_ShaderIsTransparent != 0; +} + +//! Access the callback provided by the users when creating shader materials +IShaderConstantSetCallBack* IBurningShader::getShaderConstantSetCallBack() const +{ + return CallBack; +} + +// implementations for the render services +void IBurningShader::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) +{ + // forward + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); +} + +s32 IBurningShader::getShaderConstantID(EBurningUniformFlags flags,const c8* name) +{ + if (!name || !name[0]) + return -1; + + BurningUniform add; + tiny_strcpy(add.name, name); + add.type = flags; + + s32 index = UniformInfo.linear_search(add); + if (index < 0) + { + UniformInfo.push_back(add); + index = UniformInfo.size() - 1; } + return index; +} - //! sets the Texture - void IBurningShader::setTextureParam( u32 stage, video::CSoftwareTexture2* texture, s32 lodLevel) +const char* tiny_itoa(s32 value, int base) +{ + static char b[32]; + int p = 31; + + //int sign = 0; + //if (value < 0) { sign = 1; value = -value; } + + b[p] = '\0'; + do { + b[--p] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[value%base]; + value /= base; + } while (value && p > 0); + + //if (sign && p > 0) { b[--p] = '-'; } + + return b + p; +} + +bool IBurningShader::setShaderConstantID(EBurningUniformFlags flags, s32 index, const void* data, size_t u32_count) +{ + if ((u32)index >= UniformInfo.size()) + return false; +#if 0 + BurningUniform add; + while ((u32)index >= UniformInfo.size()) { - sInternalTexture *it = &IT[stage]; - - if ( it->Texture) - it->Texture->drop(); - - it->Texture = texture; - - if ( it->Texture) - { - it->Texture->grab(); - - // select mignify and magnify ( lodLevel ) - //SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS - it->lodLevel = lodLevel; - it->data = (tVideoSample*) it->Texture->lock(ETLM_READ_ONLY, - core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 ), 0); - - // prepare for optimal fixpoint - it->pitchlog2 = s32_log2_s32 ( it->Texture->getPitch() ); - - const core::dimension2d &dim = it->Texture->getSize(); - it->textureXMask = s32_to_fixPoint ( dim.Width - 1 ) & FIX_POINT_UNSIGNED_MASK; - it->textureYMask = s32_to_fixPoint ( dim.Height - 1 ) & FIX_POINT_UNSIGNED_MASK; - } + tiny_strcpy(add.name, tiny_itoa(UniformInfo.size(),10)); + add.type = flags; + UniformInfo.push_back(add); } +#endif + + BurningUniform& use = UniformInfo[index]; + use.type = flags; + + const u32* s = (u32*)data; + u32* d = (u32*)use.data; + + if (!s) u32_count = 0; + if (u32_count > array_size(use.data)) u32_count = array_size(use.data); + for (size_t i = 0; i < u32_count; ++i) + { + d[i] = s[i]; + } + + return true; +} + + +s32 IBurningShader::getVertexShaderConstantID(const c8* name) +{ + return getShaderConstantID(BL_VERTEX_PROGRAM, name); +} + +s32 IBurningShader::getPixelShaderConstantID(const c8* name) +{ + return getShaderConstantID(BL_FRAGMENT_PROGRAM, name); +} + +void IBurningShader::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ + c8 name[BL_ACTIVE_UNIFORM_MAX_LENGTH]; + tiny_strcpy(name, tiny_itoa(startRegister, 10)); + + setShaderConstantID(BL_VERTEX_FLOAT, getShaderConstantID(BL_VERTEX_PROGRAM,name), data, constantAmount); +} + +void IBurningShader::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ + c8 name[BL_ACTIVE_UNIFORM_MAX_LENGTH]; + tiny_strcpy(name, tiny_itoa(startRegister, 10)); + + setShaderConstantID(BL_FRAGMENT_FLOAT, getShaderConstantID(BL_FRAGMENT_PROGRAM, name), data, constantAmount); +} + +bool IBurningShader::setVertexShaderConstant(s32 index, const f32* floats, int count) +{ + return setShaderConstantID(BL_VERTEX_FLOAT, index, floats, count); +} + +bool IBurningShader::setVertexShaderConstant(s32 index, const s32* ints, int count) +{ + return setShaderConstantID(BL_VERTEX_INT, index, ints, count); +} + +bool IBurningShader::setVertexShaderConstant(s32 index, const u32* ints, int count) +{ + return setShaderConstantID(BL_VERTEX_UINT, index, ints, count); +} + +bool IBurningShader::setPixelShaderConstant(s32 index, const f32* floats, int count) +{ + return setShaderConstantID(BL_FRAGMENT_FLOAT, index, floats, count); +} + +bool IBurningShader::setPixelShaderConstant(s32 index, const s32* ints, int count) +{ + return setShaderConstantID(BL_FRAGMENT_INT, index, ints, count); +} + +bool IBurningShader::setPixelShaderConstant(s32 index, const u32* ints, int count) +{ + return setShaderConstantID(BL_FRAGMENT_UINT, index, ints, count); +} + +void IBurningShader::setStencilOp(eBurningStencilOp sfail, eBurningStencilOp dpfail, eBurningStencilOp dppass) +{ + stencilOp[0] = sfail; + stencilOp[1] = dpfail; + stencilOp[2] = dppass; +} + + +IVideoDriver* IBurningShader::getVideoDriver() +{ + return Driver; +} } // end namespace video diff --git a/source/Irrlicht/IBurningShader.h b/source/Irrlicht/IBurningShader.h index 0fffff7c..8a9a8180 100644 --- a/source/Irrlicht/IBurningShader.h +++ b/source/Irrlicht/IBurningShader.h @@ -18,7 +18,9 @@ #include "SLight.h" #include "SMaterial.h" #include "os.h" - +#include "IMaterialRenderer.h" +#include "IMaterialRendererServices.h" +#include "IGPUProgrammingServices.h" namespace irr { @@ -29,56 +31,109 @@ namespace video struct SBurningShaderLight { //SLight org; - bool LightIsOn; + + sVec4 pos; //light position input + sVec4 pos4; //light position Model*View (Identity*View) E_LIGHT_TYPE Type; - f32 radius; f32 linearAttenuation; f32 constantAttenuation; f32 quadraticAttenuation; - sVec4 pos; - sVec3 AmbientColor; - sVec3 DiffuseColor; - sVec3 SpecularColor; - sVec4 pos_objectspace; + sVec4 spotDirection; + sVec4 spotDirection4; + f32 spotCosCutoff; + f32 spotCosInnerCutoff; + f32 spotExponent; + bool LightIsOn; + + sVec3Color AmbientColor; + sVec3Color DiffuseColor; + sVec3Color SpecularColor; }; - enum eLightFlags + enum eTransformLightFlags { - ENABLED = 0x01, - POINTLIGHT = 0x02, - SPECULAR = 0x04, - FOG = 0x08, - NORMALIZE = 0x10, - VERTEXTRANSFORM = 0x20, + //ENABLED = 0x01, + TL_SCISSOR = 0x02, + TL_LIGHT = 0x04, + TL_SPECULAR = 0x08, + TL_FOG = 0x10, + TL_NORMALIZE_NORMALS = 0x20, + TL_TEXTURE_TRANSFORM = 0x40, + TL_LIGHT_LOCAL_VIEWER = 0x80, + TL_LIGHT0_IS_NORMAL_MAP = 0x100 //sVec4 Light Vector is used as normal or specular }; - struct SBurningShaderLightSpace + struct SBurningShaderEyeSpace { + SBurningShaderEyeSpace() {} + virtual ~SBurningShaderEyeSpace() {} void reset () { Light.set_used ( 0 ); - Global_AmbientLight.set ( 0.f, 0.f, 0.f ); - Flags = 0; + Global_AmbientLight.set ( 0.f ); + + TL_Flag = TL_LIGHT_LOCAL_VIEWER; } + void resetFog() + { + fog_scale = 0.f; + //cam_distance = 0.f; + } + core::array Light; - sVec3 Global_AmbientLight; - sVec4 FogColor; - sVec4 campos; - sVec4 vertex; - sVec4 normal; - u32 Flags; + sVec3Color Global_AmbientLight; + + //sVec4 cam_eye_pos; //Camera Position in eye Space (0,0,-1) + //sVec4 cam_world_pos; //Camera Position in world Space + //sVec4 vertex4; //eye coordinate position of vertex + sVec4 normal; //transformed normal + sVec4 vertex; //eye coordinate position of vertex projected + + //derivative of vertex + //f32 cam_distance; // vertex.length(); + sVec4 cam_dir; //vertex.normalize(); + + f32 fog_scale; // 1 / (fog.end-fog.start) + + size_t TL_Flag; // eTransformLightFlags + }; + + enum eBurningCullFlag + { + CULL_FRONT = 1, + CULL_BACK = 2, + CULL_INVISIBLE = 4, //primitive smaller than a pixel (AreaMinDrawSize) + CULL_FRONT_AND_BACK = 8, + }; + + enum eBurningStencilOp + { + StencilOp_KEEP = 0x1E00, + StencilOp_INCR = 0x1E02, + StencilOp_DECR = 0x1E03 }; struct SBurningShaderMaterial { SMaterial org; + SMaterial lastMaterial; + bool resetRenderStates; - sVec3 AmbientColor; - sVec3 DiffuseColor; - sVec3 SpecularColor; - sVec3 EmissiveColor; + E_MATERIAL_TYPE Fallback_MaterialType; + + SMaterial mat2D; + //SMaterial save3D; + + size_t CullFlag; //eCullFlag + u32 depth_write; + u32 depth_test; + + sVec3Color AmbientColor; + sVec3Color DiffuseColor; + sVec3Color SpecularColor; + sVec3Color EmissiveColor; }; @@ -106,29 +161,88 @@ namespace video ETR_TEXTURE_GOURAUD_DETAIL_MAP, ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD, - ETR_GOURAUD_ALPHA, + ETR_GOURAUD_NOZ, + //ETR_GOURAUD_ALPHA, ETR_GOURAUD_ALPHA_NOZ, ETR_TEXTURE_GOURAUD_ALPHA, ETR_TEXTURE_GOURAUD_ALPHA_NOZ, + ETR_TEXTURE_GOURAUD_ALPHA_NOZ_NOPERSPECTIVE_CORRECT, ETR_NORMAL_MAP_SOLID, ETR_STENCIL_SHADOW, ETR_TEXTURE_BLEND, - ETR_REFERENCE, + ETR_TRANSPARENT_REFLECTION_2_LAYER, + + ETR_COLOR, + + //ETR_REFERENCE, ETR_INVALID, ETR2_COUNT }; + typedef enum + { + BL_VERTEX_PROGRAM = 1, + BL_FRAGMENT_PROGRAM = 2, + BL_TYPE_FLOAT = 4, + BL_TYPE_INT = 8, + BL_TYPE_UINT = 16, + + BL_VERTEX_FLOAT = (BL_VERTEX_PROGRAM | BL_TYPE_FLOAT), + BL_VERTEX_INT = (BL_VERTEX_PROGRAM | BL_TYPE_INT), + BL_VERTEX_UINT = (BL_VERTEX_PROGRAM | BL_TYPE_UINT), + BL_FRAGMENT_FLOAT = (BL_FRAGMENT_PROGRAM | BL_TYPE_FLOAT), + BL_FRAGMENT_INT = (BL_FRAGMENT_PROGRAM | BL_TYPE_INT), + BL_FRAGMENT_UINT = (BL_FRAGMENT_PROGRAM | BL_TYPE_UINT), + + BL_ACTIVE_UNIFORM_MAX_LENGTH = 28 + } EBurningUniformFlags; + + struct BurningUniform + { + c8 name[BL_ACTIVE_UNIFORM_MAX_LENGTH]; + u32 type; //EBurningUniformFlags + //int location; // UniformLocation is index + f32 data[16]; // simple LocalParameter + + bool operator==(const BurningUniform& other) const + { + return tiny_istoken(name, other.name); + } + + }; + class CBurningVideoDriver; - class IBurningShader : public virtual IReferenceCounted + class IBurningShader : public IMaterialRenderer, public IMaterialRendererServices { public: + //! Constructor IBurningShader(CBurningVideoDriver* driver); + //! Constructor + IBurningShader( + CBurningVideoDriver* driver, + s32& outMaterialTypeNr, + const c8* vertexShaderProgram = 0, + const c8* vertexShaderEntryPointName = 0, + E_VERTEX_SHADER_TYPE vsCompileTarget = video::EVST_VS_1_1, + const c8* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = 0, + E_PIXEL_SHADER_TYPE psCompileTarget = video::EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = EMT_SOLID, + s32 userData = 0); + //! destructor virtual ~IBurningShader(); @@ -136,27 +250,121 @@ namespace video virtual void setRenderTarget(video::IImage* surface, const core::rect& viewPort); //! sets the Texture - virtual void setTextureParam( u32 stage, video::CSoftwareTexture2* texture, s32 lodLevel); - virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) = 0; - virtual void drawLine ( const s4DVertex *a,const s4DVertex *b) {}; + virtual void setTextureParam( const size_t stage, video::CSoftwareTexture2* texture, s32 lodFactor); + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) {}; + virtual void drawLine ( const s4DVertex *a,const s4DVertex *b); + virtual void drawPoint(const s4DVertex *a); - virtual void setParam ( u32 index, f32 value) {}; - virtual void setZCompareFunc ( u32 func) {}; + void drawWireFrameTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); - virtual void setMaterial ( const SBurningShaderMaterial &material ) {}; + virtual void OnSetMaterial( const SBurningShaderMaterial& material ) {}; + + void pushEdgeTest(const int wireFrame,const int point,int save) + { + if ( save ) EdgeTestPass_stack = EdgeTestPass; + EdgeTestPass = point ? edge_test_point : wireFrame ? edge_test_left : edge_test_pass; + } + void popEdgeTest() { EdgeTestPass = EdgeTestPass_stack; } + virtual bool canWireFrame () { return false; } + virtual bool canPointCloud() { return false; } + + void setStencilOp(eBurningStencilOp sfail, eBurningStencilOp dpfail, eBurningStencilOp dppass); + + //IMaterialRenderer + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_; + + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) _IRR_OVERRIDE_; + + virtual void OnUnsetMaterial() _IRR_OVERRIDE_; + + //! Returns if the material is transparent. + virtual bool isTransparent() const _IRR_OVERRIDE_; + + //! Access the callback provided by the users when creating shader materials + virtual IShaderConstantSetCallBack* getShaderConstantSetCallBack() const _IRR_OVERRIDE_; + + // implementations for the render services + virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) _IRR_OVERRIDE_; + virtual s32 getVertexShaderConstantID(const c8* name) _IRR_OVERRIDE_; + virtual s32 getPixelShaderConstantID(const c8* name) _IRR_OVERRIDE_; + virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1) _IRR_OVERRIDE_; + virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1) _IRR_OVERRIDE_; + virtual bool setVertexShaderConstant(s32 index, const f32* floats, int count) _IRR_OVERRIDE_; + virtual bool setVertexShaderConstant(s32 index, const s32* ints, int count) _IRR_OVERRIDE_; + virtual bool setVertexShaderConstant(s32 index, const u32* ints, int count) _IRR_OVERRIDE_; + virtual bool setPixelShaderConstant(s32 index, const f32* floats, int count) _IRR_OVERRIDE_; + virtual bool setPixelShaderConstant(s32 index, const s32* ints, int count) _IRR_OVERRIDE_; + virtual bool setPixelShaderConstant(s32 index, const u32* ints, int count) _IRR_OVERRIDE_; + virtual IVideoDriver* getVideoDriver() _IRR_OVERRIDE_; + + //used if no color interpolation is defined + void setPrimitiveColor(const video::SColor& color) + { + #if BURNINGSHADER_COLOR_FORMAT == ECF_A8R8G8B8 + PrimitiveColor = color.color; + #else + PrimitiveColor = color.toA1R5G5B5(); + #endif + } + void setTLFlag(size_t in /*eTransformLightFlags*/) + { + TL_Flag = in; + } + void setFog(SColor color_fog) + { +#if BURNINGSHADER_COLOR_FORMAT == ECF_A8R8G8B8 + fog_color_sample = color_fog.color; +#else + fog_color_sample = color_fog.toA1R5G5B5(); +#endif + color_to_fix(fog_color, fog_color_sample); + } + void setScissor(const AbsRectangle& scissor) + { + Scissor = scissor; + } protected: + void constructor_IBurningShader(CBurningVideoDriver* driver); + CBurningVideoDriver *Driver; + IShaderConstantSetCallBack* CallBack; + E_MATERIAL_TYPE BaseMaterial; + s32 UserData; + + core::array UniformInfo; + s32 getShaderConstantID(EBurningUniformFlags program, const c8* name); + bool setShaderConstantID(EBurningUniformFlags flags, s32 index, const void* data, size_t u32_count); video::CImage* RenderTarget; CDepthBuffer* DepthBuffer; - CStencilBuffer * Stencil; + CStencilBuffer* Stencil; tVideoSample ColorMask; sInternalTexture IT[ BURNING_MATERIAL_MAX_TEXTURES ]; static const tFixPointu dithermask[ 4 * 4]; + + //draw degenerate triangle as line (left edge) drawTriangle -> holes,drawLine dda/bresenham + int EdgeTestPass; //edge_test_flag + int EdgeTestPass_stack; + + eBurningStencilOp stencilOp[4]; + tFixPoint AlphaRef; + int RenderPass_ShaderIsTransparent; + + sScanConvertData scan; + sScanLineData line; + tVideoSample PrimitiveColor; //used if no color interpolation is defined + + size_t /*eTransformLightFlags*/ TL_Flag; + tFixPoint fog_color[4]; + tVideoSample fog_color_sample; + + AbsRectangle Scissor; }; @@ -172,6 +380,7 @@ namespace video IBurningShader* createTriangleRendererTextureGouraudWire2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGouraud2(CBurningVideoDriver* driver); + IBurningShader* createTriangleRendererGouraudNoZ2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGouraudAlpha2(CBurningVideoDriver* driver); IBurningShader* createTRGouraudAlphaNoZ2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGouraudWire2(CBurningVideoDriver* driver); @@ -192,8 +401,9 @@ namespace video IBurningShader* createTRStencilShadow(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererReference(CBurningVideoDriver* driver); + IBurningShader* createTriangleRendererTexture_transparent_reflection_2_layer(CBurningVideoDriver* driver); - + IBurningShader* create_burning_shader_color(CBurningVideoDriver* driver); } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/IDepthBuffer.h b/source/Irrlicht/IDepthBuffer.h index 719d9f17..89f604f3 100644 --- a/source/Irrlicht/IDepthBuffer.h +++ b/source/Irrlicht/IDepthBuffer.h @@ -21,7 +21,7 @@ namespace video virtual ~IDepthBuffer() {}; //! clears the zbuffer - virtual void clear() = 0; + virtual void clear(f32 value) = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; @@ -51,29 +51,29 @@ namespace video //! destructor virtual ~IStencilBuffer() {}; - //! clears the zbuffer - virtual void clear() = 0; + //! clears the stencil buffer + virtual void clear(u8 value) = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; - //! returns the size of the zbuffer + //! returns the size of the stencil buffer virtual const core::dimension2d& getSize() const = 0; - //! locks the zbuffer + //! locks the stencil buffer virtual void* lock() = 0; - //! unlocks the zbuffer + //! unlocks the stencil buffer virtual void unlock() = 0; - //! returns pitch of depthbuffer (in bytes) + //! returns pitch of stencil buffer (in bytes) virtual u32 getPitch() const = 0; }; //! creates a Stencil Buffer - IStencilBuffer* createStencilBuffer(const core::dimension2d& size); + IStencilBuffer* createStencilBuffer(const core::dimension2d& size, u32 bit); } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/Irrlicht-gcc.cbp b/source/Irrlicht/Irrlicht-gcc.cbp index 3e8d0ad0..a1dbf210 100644 --- a/source/Irrlicht/Irrlicht-gcc.cbp +++ b/source/Irrlicht/Irrlicht-gcc.cbp @@ -972,6 +972,7 @@ + @@ -997,6 +998,7 @@ + @@ -1068,6 +1070,14 @@ + + + + + + + + diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj b/source/Irrlicht/Irrlicht10.0.vcxproj index 78c279ca..b61cdc0c 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj +++ b/source/Irrlicht/Irrlicht10.0.vcxproj @@ -1005,6 +1005,13 @@ + + + + + + + @@ -1271,6 +1278,7 @@ + @@ -1322,6 +1330,8 @@ + + diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj.filters b/source/Irrlicht/Irrlicht10.0.vcxproj.filters index 6269a9c5..618fb881 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht10.0.vcxproj.filters @@ -1389,6 +1389,27 @@ include\scene + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video @@ -2356,6 +2377,15 @@ Irrlicht\video\OpenGL Context + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video diff --git a/source/Irrlicht/Irrlicht11.0.vcxproj b/source/Irrlicht/Irrlicht11.0.vcxproj index 791a36a0..e6b828e4 100644 --- a/source/Irrlicht/Irrlicht11.0.vcxproj +++ b/source/Irrlicht/Irrlicht11.0.vcxproj @@ -1004,6 +1004,13 @@ + + + + + + + @@ -1270,6 +1277,7 @@ + @@ -1321,6 +1329,8 @@ + + diff --git a/source/Irrlicht/Irrlicht11.0.vcxproj.filters b/source/Irrlicht/Irrlicht11.0.vcxproj.filters index f61a3f95..1cffa753 100644 --- a/source/Irrlicht/Irrlicht11.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht11.0.vcxproj.filters @@ -1390,6 +1390,27 @@ include\scene + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + @@ -2357,6 +2378,15 @@ Irrlicht\video\OpenGL Context + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + diff --git a/source/Irrlicht/Irrlicht12.0.vcxproj b/source/Irrlicht/Irrlicht12.0.vcxproj index 7b01c746..9581357a 100644 --- a/source/Irrlicht/Irrlicht12.0.vcxproj +++ b/source/Irrlicht/Irrlicht12.0.vcxproj @@ -1321,6 +1321,8 @@ + + diff --git a/source/Irrlicht/Irrlicht12.0.vcxproj.filters b/source/Irrlicht/Irrlicht12.0.vcxproj.filters index 7e94d188..0623a911 100644 --- a/source/Irrlicht/Irrlicht12.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht12.0.vcxproj.filters @@ -2357,6 +2357,12 @@ Irrlicht\video\OpenGL Context + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + diff --git a/source/Irrlicht/Irrlicht14.0.vcxproj b/source/Irrlicht/Irrlicht14.0.vcxproj index 22385f15..47f07a3a 100644 --- a/source/Irrlicht/Irrlicht14.0.vcxproj +++ b/source/Irrlicht/Irrlicht14.0.vcxproj @@ -1015,7 +1015,15 @@ + + + + + + + + @@ -1281,6 +1289,7 @@ + @@ -1332,6 +1341,8 @@ + + diff --git a/source/Irrlicht/Irrlicht14.0.vcxproj.filters b/source/Irrlicht/Irrlicht14.0.vcxproj.filters index ed8c285b..077634de 100644 --- a/source/Irrlicht/Irrlicht14.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht14.0.vcxproj.filters @@ -1390,6 +1390,30 @@ include\scene + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Null + @@ -2357,6 +2381,15 @@ Irrlicht\video\OpenGL Context + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + diff --git a/source/Irrlicht/Irrlicht15.0.vcxproj b/source/Irrlicht/Irrlicht15.0.vcxproj index 3e766078..4ae8670c 100644 --- a/source/Irrlicht/Irrlicht15.0.vcxproj +++ b/source/Irrlicht/Irrlicht15.0.vcxproj @@ -1014,6 +1014,13 @@ + + + + + + + @@ -1268,6 +1275,7 @@ + @@ -1309,6 +1317,8 @@ + + diff --git a/source/Irrlicht/Irrlicht15.0.vcxproj.filters b/source/Irrlicht/Irrlicht15.0.vcxproj.filters index 7230ff84..16c0835f 100644 --- a/source/Irrlicht/Irrlicht15.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht15.0.vcxproj.filters @@ -1342,6 +1342,27 @@ include\video + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + @@ -2280,6 +2301,15 @@ Irrlicht\video\OpenGL Context + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + + + Irrlicht\video\Burning Video + diff --git a/source/Irrlicht/Makefile b/source/Irrlicht/Makefile index 37b14fb3..c967d247 100644 --- a/source/Irrlicht/Makefile +++ b/source/Irrlicht/Makefile @@ -47,7 +47,13 @@ IRRDRVROBJ = CNullDriver.o COpenGLCacheHandler.o COpenGLDriver.o COpenGLNormalMa IRRIMAGEOBJ = CColorConverter.o CImage.o CImageLoaderBMP.o CImageLoaderDDS.o CImageLoaderJPG.o CImageLoaderPCX.o CImageLoaderPNG.o CImageLoaderPSD.o CImageLoaderPVR.o CImageLoaderTGA.o CImageLoaderPPM.o CImageLoaderWAL.o CImageLoaderRGB.o \ CImageWriterBMP.o CImageWriterJPG.o CImageWriterPCX.o CImageWriterPNG.o CImageWriterPPM.o CImageWriterPSD.o CImageWriterTGA.o IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ) -IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRNormalMap.o CTRStencilShadow.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o CTRTextureGouraudVertexAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o CTRGouraud2.o CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o +IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRNormalMap.o \ + CTRStencilShadow.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o \ + CTRTextureGouraudWire.o CZBuffer.o CTRTextureGouraudVertexAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o \ + CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o CTRGouraud2.o \ + CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o \ + CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o \ + CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o CTR_transparent_reflection_2_layer.o CTRGouraudNoZ2.o burning_shader_color.o IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CWADReader.o CZipReader.o CPakReader.o CNPKReader.o CTarReader.o CMountPointReader.o irrXML.o CAttributes.o lzma/LzmaDec.o IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CIrrDeviceFB.o CLogger.o COSOperator.o Irrlicht.o os.o leakHunter.o CProfiler.o utf8.o IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o CGUIProfiler.o diff --git a/source/Irrlicht/S4DVertex.h b/source/Irrlicht/S4DVertex.h index 7ad6b83d..92abbb26 100644 --- a/source/Irrlicht/S4DVertex.h +++ b/source/Irrlicht/S4DVertex.h @@ -9,6 +9,7 @@ #include "SoftwareDriver2_compile_config.h" #include "SoftwareDriver2_helper.h" #include "irrAllocator.h" +#include "EPrimitiveTypes.h" namespace irr { @@ -16,6 +17,7 @@ namespace irr namespace video { +//! sVec2 used in BurningShader texture coordinates struct sVec2 { f32 x; @@ -34,10 +36,10 @@ struct sVec2 } // f = a * t + b * ( 1 - t ) - void interpolate(const sVec2& a, const sVec2& b, const f32 t) + void interpolate(const sVec2& burning_restrict a, const sVec2& burning_restrict b, const ipoltype t) { - x = b.x + ( ( a.x - b.x ) * t ); - y = b.y + ( ( a.y - b.y ) * t ); + x = (f32)(b.x + ( ( a.x - b.x ) * t )); + y = (f32)(b.y + ( ( a.y - b.y ) * t )); } sVec2 operator-(const sVec2& other) const @@ -75,126 +77,79 @@ struct sVec2 }; -// A8R8G8B8 -struct sVec4; -struct sCompressedVec4 +#include "irrpack.h" + +//! sVec3Pack used in BurningShader, packed direction +struct sVec3Pack { - u32 argb; + f32 x, y, z; + //f32 _can_pack; - void setA8R8G8B8 ( u32 value ) - { - argb = value; - } - - void setColorf ( const video::SColorf & color ) - { - argb = core::floor32_fast( color.a * 255.f ) << 24 | - core::floor32_fast( color.r * 255.f ) << 16 | - core::floor32_fast( color.g * 255.f ) << 8 | - core::floor32_fast( color.b * 255.f ); - } - - void setVec4 ( const sVec4 & v ); + sVec3Pack() {} + sVec3Pack(f32 _x, f32 _y, f32 _z) + : x(_x), y(_y), z(_z) {} // f = a * t + b * ( 1 - t ) - void interpolate(const sCompressedVec4& a, const sCompressedVec4& b, const f32 t) + void interpolate(const sVec3Pack& burning_restrict v0, const sVec3Pack& burning_restrict v1, const ipoltype t) { - argb = PixelBlend32 ( b.argb, a.argb, core::floor32_fast( t * 256.f ) ); + x = (f32)(v1.x + ((v0.x - v1.x) * t)); + y = (f32)(v1.y + ((v0.y - v1.y) * t)); + z = (f32)(v1.z + ((v0.z - v1.z) * t)); } + sVec3Pack operator-(const sVec3Pack& other) const + { + return sVec3Pack(x - other.x, y - other.y, z - other.z); + } -}; + sVec3Pack operator+(const sVec3Pack& other) const + { + return sVec3Pack(x + other.x, y + other.y, z + other.z); + } + sVec3Pack operator*(const f32 s) const + { + return sVec3Pack(x * s, y * s, z * s); + } + void operator+=(const sVec3Pack& other) + { + x += other.x; + y += other.y; + z += other.z; + } + + void operator=(const sVec3Pack& other) + { + x = other.x; + y = other.y; + z = other.z; + } + +} PACK_STRUCT; + +#include "irrunpack.h" + +//! sVec4 used in Driver,BurningShader, direction/color struct sVec4 { union { struct { f32 x, y, z, w; }; struct { f32 a, r, g, b; }; -// struct { sVec2 xy, zw; }; // sorry, this does not compile with gcc }; - - sVec4 () {} - - sVec4 ( f32 s) : x ( s ), y ( s ), z ( s ), w ( s ) {} - sVec4 ( f32 _x, f32 _y, f32 _z, f32 _w ) : x ( _x ), y ( _y ), z( _z ), w ( _w ){} - void set ( f32 _x, f32 _y, f32 _z, f32 _w ) - { - x = _x; - y = _y; - z = _z; - w = _w; - } - - void setA8R8G8B8 ( u32 argb ) - { - x = ( ( argb & 0xFF000000 ) >> 24 ) * ( 1.f / 255.f ); - y = ( ( argb & 0x00FF0000 ) >> 16 ) * ( 1.f / 255.f ); - z = ( ( argb & 0x0000FF00 ) >> 8 ) * ( 1.f / 255.f ); - w = ( ( argb & 0x000000FF ) ) * ( 1.f / 255.f ); - } - - - void setColorf ( const video::SColorf & color ) - { - x = color.a; - y = color.r; - z = color.g; - w = color.b; - } - - // f = a * t + b * ( 1 - t ) - void interpolate(const sVec4& a, const sVec4& b, const f32 t) + void interpolate(const sVec4& burning_restrict a, const sVec4& burning_restrict b, const ipoltype t) { - x = b.x + ( ( a.x - b.x ) * t ); - y = b.y + ( ( a.y - b.y ) * t ); - z = b.z + ( ( a.z - b.z ) * t ); - w = b.w + ( ( a.w - b.w ) * t ); - } - - - f32 dotProduct(const sVec4& other) const - { - return x*other.x + y*other.y + z*other.z + w*other.w; - } - - f32 dot_xyz( const sVec4& other) const - { - return x*other.x + y*other.y + z*other.z; - } - - f32 get_length_xyz_square () const - { - return x * x + y * y + z * z; - } - - f32 get_length_xyz () const - { - return core::squareroot ( x * x + y * y + z * z ); - } - - void normalize_xyz () - { - const f32 l = core::reciprocal_squareroot ( x * x + y * y + z * z ); - - x *= l; - y *= l; - z *= l; - } - - void project_xyz () - { - w = core::reciprocal ( w ); - x *= w; - y *= w; - z *= w; + x = (f32)(b.x + ( ( a.x - b.x ) * t )); + y = (f32)(b.y + ( ( a.y - b.y ) * t )); + z = (f32)(b.z + ( ( a.z - b.z ) * t )); + w = (f32)(b.w + ( ( a.w - b.w ) * t )); } sVec4 operator-(const sVec4& other) const @@ -225,32 +180,6 @@ struct sVec4 return sVec4(x * other.x , y * other.y, z * other.z,w * other.w); } - void mulReciprocal ( f32 s ) - { - const f32 i = core::reciprocal ( s ); - x = (f32) ( x * i ); - y = (f32) ( y * i ); - z = (f32) ( z * i ); - w = (f32) ( w * i ); - } - - void mul ( const f32 s ) - { - x *= s; - y *= s; - z *= s; - w *= s; - } - -/* - void operator*=(f32 s) - { - x *= s; - y *= s; - z *= s; - w *= s; - } -*/ void operator*=(const sVec4 &other) { x *= other.x; @@ -266,142 +195,180 @@ struct sVec4 z = other.z; w = other.w; } + + //outside shader + void set(f32 _x, f32 _y, f32 _z, f32 _w) + { + x = _x; + y = _y; + z = _z; + w = _w; + } + void setA8R8G8B8(const u32 argb) + { + a = ((argb & 0xFF000000) >> 24) * (1.f / 255.f); + r = ((argb & 0x00FF0000) >> 16) * (1.f / 255.f); + g = ((argb & 0x0000FF00) >> 8 ) * (1.f / 255.f); + b = ((argb & 0x000000FF) ) * (1.f / 255.f); + } + + REALINLINE ipoltype dot_xyzw(const sVec4& other) const + { + return (ipoltype)x * other.x + (ipoltype)y * other.y + (ipoltype)z * other.z + (ipoltype)w * other.w; + } + + REALINLINE f32 dot_xyz(const sVec4& other) const + { + return x * other.x + y * other.y + z * other.z; + } + + REALINLINE f32 dot_minus_xyz(const sVec4& other) const + { + return -x * other.x + -y * other.y + -z * other.z; + } + + void mul_xyz(const f32 s) + { + x *= s; + y *= s; + z *= s; + } + + f32 length_xyz() const + { + return sqrtf(x * x + y * y + z * z); + } + + void normalize_dir_xyz() + { + //const f32 l = core::reciprocal_squareroot(x * x + y * y + z * z); + f32 l = x * x + y * y + z * z; + l = l > 0.0000001f ? 1.f / sqrtf(l) : 1.f; + x *= l; + y *= l; + z *= l; + } + + + //unpack sVec3 to aligned during runtime + sVec4(const sVec3Pack& other) + { + x = other.x; + y = other.y; + z = other.z; + w = 0.f; + } + + void normalize_pack_xyz(sVec3Pack& out, const f32 len, const f32 ofs) const + { + //const f32 l = len * core::reciprocal_squareroot ( r * r + g * g + b * b ); + f32 l = x * x + y * y + z * z; + + l = l > 0.0000001f ? len / sqrtf(l) : 0.f; + out.x = (x*l) + ofs; + out.y = (y*l) + ofs; + out.z = (z*l) + ofs; + } + }; -struct sVec3 +//!during runtime sVec3Pack +typedef sVec4 sVec3Pack_unpack; + +//!sVec4 is argb. sVec3Color is rgba +struct sVec3Color { - union + f32 r, g, b,a; + + void set(const f32 s) { - struct { f32 r, g, b; }; - struct { f32 x, y, z; }; - }; - - - sVec3 () {} - sVec3 ( f32 _x, f32 _y, f32 _z ) - : r ( _x ), g ( _y ), b( _z ) {} - - sVec3 ( const sVec4 &v ) - : r ( v.x ), g ( v.y ), b( v.z ) {} - - void set ( f32 _r, f32 _g, f32 _b ) - { - r = _r; - g = _g; - b = _b; + r = s; + g = s; + b = s; + a = s; } - void setR8G8B8 ( u32 argb ) + void setA8R8G8B8(const u32 argb) { - r = ( ( argb & 0x00FF0000 ) >> 16 ) * ( 1.f / 255.f ); - g = ( ( argb & 0x0000FF00 ) >> 8 ) * ( 1.f / 255.f ); - b = ( ( argb & 0x000000FF ) ) * ( 1.f / 255.f ); + r = ((argb & 0x00FF0000) >> 16) * (1.f / 255.f); + g = ((argb & 0x0000FF00) >> 8 ) * (1.f / 255.f); + b = ((argb & 0x000000FF) ) * (1.f / 255.f); + a = ((argb & 0xFF000000) >> 24) * (1.f / 255.f); } - void setColorf ( const video::SColorf & color ) + void setColorf(const video::SColorf & color) { r = color.r; g = color.g; b = color.b; + a = color.a; } - void add (const sVec3& other) + void add_rgb(const sVec3Color& other) { r += other.r; g += other.g; b += other.b; } - void mulAdd(const sVec3& other, const f32 v) + void mad_rgb(const sVec3Color& other, const f32 v) { r += other.r * v; g += other.g * v; b += other.b * v; } - void mulAdd(const sVec3& v0, const sVec3& v1) + void mad_rgbv(const sVec3Color& v0, const sVec3Color& v1) { r += v0.r * v1.r; g += v0.g * v1.g; b += v0.b * v1.b; } - void saturate ( sVec4 &dest, u32 argb ) + //sVec4 is a,r,g,b, alpha pass + void sat(sVec4 &dest, const u32 argb) const { - dest.x = ( ( argb & 0xFF000000 ) >> 24 ) * ( 1.f / 255.f ); - dest.y = core::min_ ( r, 1.f ); - dest.z = core::min_ ( g, 1.f ); - dest.w = core::min_ ( b, 1.f ); + dest.a = ((argb & 0xFF000000) >> 24) * (1.f / 255.f); + dest.r = r <= 1.f ? r : 1.f; + dest.g = g <= 1.f ? g : 1.f; + dest.b = b <= 1.f ? b : 1.f; } - // f = a * t + b * ( 1 - t ) - void interpolate(const sVec3& v0, const sVec3& v1, const f32 t) + void sat_xyz(sVec3Pack &dest, const sVec3Color& v1) const { - r = v1.r + ( ( v0.r - v1.r ) * t ); - g = v1.g + ( ( v0.g - v1.g ) * t ); - b = v1.b + ( ( v0.b - v1.b ) * t ); + f32 v; + v = r * v1.r; dest.x = v < 1.f ? v : 1.f; + v = g * v1.g; dest.y = v < 1.f ? v : 1.f; + v = b * v1.b; dest.z = v < 1.f ? v : 1.f; } - sVec3 operator-(const sVec3& other) const + void sat_xyz(sVec4 &dest, const sVec3Color& v1) const { - return sVec3(r - other.r, b - other.b, g - other.g); + f32 v; + dest.a = 1.f; + v = r * v1.r; dest.r = v < 1.f ? v : 1.f; + v = g * v1.g; dest.g = v < 1.f ? v : 1.f; + v = b * v1.b; dest.b = v < 1.f ? v : 1.f; } - sVec3 operator+(const sVec3& other) const - { - return sVec3(r + other.r, g + other.g, b + other.b); - } - - sVec3 operator*(const f32 s) const - { - return sVec3(r * s , g * s, b * s); - } - - sVec3 operator/(const f32 s) const - { - f32 inv = 1.f / s; - return sVec3(r * inv , g * inv, b * inv); - } - - sVec3 operator*(const sVec3 &other) const - { - return sVec3(r * other.r , b * other.b, g * other.g); - } - - void operator+=(const sVec3& other) - { - r += other.r; - g += other.g; - b += other.b; - } - - void setLength ( f32 len ) - { - const f32 l = len * core::reciprocal_squareroot ( r * r + g * g + b * b ); - - r *= l; - g *= l; - b *= l; - } }; - - -inline void sCompressedVec4::setVec4 ( const sVec4 & v ) -{ - argb = core::floor32_fast( v.x * 255.f ) << 24 | - core::floor32_fast( v.y * 255.f ) << 16 | - core::floor32_fast( v.z * 255.f ) << 8 | - core::floor32_fast( v.w * 255.f ); -} - - +//internal BurningShaderFlag for a Vertex enum e4DVertexFlag { - VERTEX4D_INSIDE = 0x0000003F, - VERTEX4D_CLIPMASK = 0x0000003F, - VERTEX4D_PROJECTED = 0x00000100, + VERTEX4D_CLIPMASK = 0x0000003F, + VERTEX4D_CLIP_NEAR = 0x00000001, + VERTEX4D_CLIP_FAR = 0x00000002, + VERTEX4D_CLIP_LEFT = 0x00000004, + VERTEX4D_CLIP_RIGHT = 0x00000008, + VERTEX4D_CLIP_BOTTOM = 0x00000010, + VERTEX4D_CLIP_TOP = 0x00000020, + VERTEX4D_INSIDE = 0x0000003F, + + VERTEX4D_PROJECTED = 0x00000100, + VERTEX4D_VAL_ZERO = 0x00000200, + VERTEX4D_VAL_ONE = 0x00000400, VERTEX4D_FORMAT_MASK = 0xFFFF0000, @@ -413,62 +380,126 @@ enum e4DVertexFlag VERTEX4D_FORMAT_MASK_COLOR = 0x00F00000, VERTEX4D_FORMAT_COLOR_1 = 0x00100000, - VERTEX4D_FORMAT_COLOR_2 = 0x00200000, + VERTEX4D_FORMAT_COLOR_2_FOG = 0x00200000, + VERTEX4D_FORMAT_COLOR_3 = 0x00300000, + VERTEX4D_FORMAT_COLOR_4 = 0x00400000, - VERTEX4D_FORMAT_MASK_BUMP = 0x0F000000, - VERTEX4D_FORMAT_BUMP_DOT3 = 0x01000000, + VERTEX4D_FORMAT_MASK_LIGHT = 0x0F000000, + VERTEX4D_FORMAT_LIGHT_1 = 0x01000000, + VERTEX4D_FORMAT_LIGHT_2 = 0x02000000, + + VERTEX4D_FORMAT_MASK_TANGENT = 0xF0000000, + VERTEX4D_FORMAT_BUMP_DOT3 = 0x10000000, + VERTEX4D_FORMAT_SPECULAR = 0x20000000, }; -const u32 MATERIAL_MAX_COLORS = 1; -const u32 BURNING_MATERIAL_MAX_TEXTURES = 2; -const u32 BURNING_MATERIAL_MAX_TANGENT = 1; +//! vertex layout +enum e4DVertexType +{ + E4VT_STANDARD = 0, // EVT_STANDARD, video::S3DVertex. + E4VT_2TCOORDS = 1, // EVT_2TCOORDS, video::S3DVertex2TCoords. + E4VT_TANGENTS = 2, // EVT_TANGENTS, video::S3DVertexTangents + E4VT_REFLECTION_MAP = 3, + E4VT_SHADOW = 4, // float * 3 + E4VT_NO_TEXTURE = 5, // runtime if texture missing + E4VT_LINE = 6, + + E4VT_COUNT +}; + +enum e4DIndexType +{ + E4IT_16BIT = 1, // EIT_16BIT, + E4IT_32BIT = 2, // EIT_32BIT, + E4IT_NONE = 4, // +}; + +#ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL + #define BURNING_MATERIAL_MAX_TEXTURES 4 + #define BURNING_MATERIAL_MAX_COLORS 4 + #define BURNING_MATERIAL_MAX_LIGHT_TANGENT 1 + + //ensure handcrafted sizeof(s4DVertex) + #define sizeof_s4DVertex 128 + +#else + #define BURNING_MATERIAL_MAX_TEXTURES 2 + #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR + #define BURNING_MATERIAL_MAX_COLORS 1 + #else + #define BURNING_MATERIAL_MAX_COLORS 0 + #endif + #define BURNING_MATERIAL_MAX_LIGHT_TANGENT 1 + + //ensure handcrafted sizeof(s4DVertex) + #define sizeof_s4DVertex 64 +#endif // dummy Vertex. used for calculation vertex memory size struct s4DVertex_proxy { - u32 flag; sVec4 Pos; +#if BURNING_MATERIAL_MAX_TEXTURES > 0 sVec2 Tex[BURNING_MATERIAL_MAX_TEXTURES]; - -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - sVec4 Color[MATERIAL_MAX_COLORS]; #endif - - sVec3 LightTangent[BURNING_MATERIAL_MAX_TANGENT]; +#if BURNING_MATERIAL_MAX_COLORS > 0 + sVec4 Color[BURNING_MATERIAL_MAX_COLORS]; +#endif +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + sVec3Pack LightTangent[BURNING_MATERIAL_MAX_LIGHT_TANGENT]; +#endif + u32 flag; // e4DVertexFlag }; -#define SIZEOF_SVERTEX 64 -#define SIZEOF_SVERTEX_LOG2 6 /*! Internal BurningVideo Vertex */ struct s4DVertex { - u32 flag; - sVec4 Pos; +#if BURNING_MATERIAL_MAX_TEXTURES > 0 sVec2 Tex[ BURNING_MATERIAL_MAX_TEXTURES ]; - -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - sVec4 Color[ MATERIAL_MAX_COLORS ]; +#endif +#if BURNING_MATERIAL_MAX_COLORS > 0 + sVec4 Color[ BURNING_MATERIAL_MAX_COLORS ]; +#endif +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + sVec3Pack LightTangent[BURNING_MATERIAL_MAX_LIGHT_TANGENT]; #endif - sVec3 LightTangent[BURNING_MATERIAL_MAX_TANGENT]; + u32 flag; // e4DVertexFlag - //u8 fill [ SIZEOF_SVERTEX - sizeof (s4DVertex_proxy) ]; + +#if BURNING_MATERIAL_MAX_COLORS < 1 || BURNING_MATERIAL_MAX_LIGHT_TANGENT < 1 + u8 __align [sizeof_s4DVertex - sizeof (s4DVertex_proxy) ]; +#endif // f = a * t + b * ( 1 - t ) - void interpolate(const s4DVertex& b, const s4DVertex& a, const f32 t) + void interpolate(const s4DVertex& burning_restrict b, const s4DVertex& burning_restrict a, const ipoltype t) { - u32 i; - u32 size; - Pos.interpolate ( a.Pos, b.Pos, t ); +#if 0 + Tex[0].interpolate(a.Tex[0], b.Tex[0], t); + Tex[1].interpolate(a.Tex[1], b.Tex[1], t); + Color[0].interpolate(a.Color[0], b.Color[0], t); + LightTangent[0].interpolate(a.LightTangent[0], b.LightTangent[0], t); +#endif -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR + size_t i; + size_t size; + +#if BURNING_MATERIAL_MAX_TEXTURES > 0 + size = (flag & VERTEX4D_FORMAT_MASK_TEXTURE) >> 16; + for ( i = 0; i!= size; ++i ) + { + Tex[i].interpolate ( a.Tex[i], b.Tex[i], t ); + } +#endif + +#if BURNING_MATERIAL_MAX_COLORS > 0 size = (flag & VERTEX4D_FORMAT_MASK_COLOR) >> 20; for ( i = 0; i!= size; ++i ) { @@ -476,50 +507,164 @@ struct s4DVertex } #endif - size = (flag & VERTEX4D_FORMAT_MASK_TEXTURE) >> 16; - for ( i = 0; i!= size; ++i ) - { - Tex[i].interpolate ( a.Tex[i], b.Tex[i], t ); - } - - size = (flag & VERTEX4D_FORMAT_MASK_BUMP) >> 24; +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + size = (flag & VERTEX4D_FORMAT_MASK_LIGHT) >> 24; for ( i = 0; i!= size; ++i ) { LightTangent[i].interpolate ( a.LightTangent[i], b.LightTangent[i], t ); } +#endif } }; // ----------------- Vertex Cache --------------------------- -struct SAlignedVertex +// Buffer is used as pairs of S4DVertex (0 ... ndc, 1 .. dc and projected) +typedef s4DVertex s4DVertexPair; +#define sizeof_s4DVertexPairRel 2 +#define s4DVertex_ofs(index) ((index)*sizeof_s4DVertexPairRel) +#define s4DVertex_proj(index) ((index)*sizeof_s4DVertexPairRel) + 1 + +struct SAligned4DVertex { - SAlignedVertex ( u32 element, u32 aligned ) - : ElementSize ( element ) + SAligned4DVertex() + :data(0),mem(0), ElementSize(0) {} + + virtual ~SAligned4DVertex () { - u32 byteSize = (ElementSize << SIZEOF_SVERTEX_LOG2 ) + aligned; - mem = new u8 [ byteSize ]; - data = (s4DVertex*) mem; + if (mem) + { + delete[] mem; + mem = 0; + } } - virtual ~SAlignedVertex () + void resize(size_t element) { - delete [] mem; + if (element > ElementSize) + { + if (mem) delete[] mem; + size_t byteSize = align_next(element * sizeof_s4DVertex, 4096); + mem = new u8[byteSize]; + } + ElementSize = element; + data = (s4DVertex*)mem; } - s4DVertex *data; - u8 *mem; - u32 ElementSize; + s4DVertex* data; //align to 16 byte + u8* mem; + size_t ElementSize; }; +//#define memcpy_s4DVertexPair(dst,src) memcpy(dst,src,sizeof_s4DVertex * 2) +static REALINLINE void memcpy_s4DVertexPair(void* burning_restrict dst, const void* burning_restrict src) +{ + //test alignment -> if already in aligned data +#if 0 + if (((size_t)dst & 0xC) | ((size_t)src & 0xC)) + { + int g = 1; + } +#endif -// hold info for different Vertex Types +#if defined(ENV64BIT) && (sizeof_s4DVertex * sizeof_s4DVertexPairRel == 128) + u64* burning_restrict dst64 = (u64*)dst; + const u64* burning_restrict src64 = (const u64*)src; + + dst64[0] = src64[0]; + dst64[1] = src64[1]; + dst64[2] = src64[2]; + dst64[3] = src64[3]; + dst64[4] = src64[4]; + dst64[5] = src64[5]; + dst64[6] = src64[6]; + dst64[7] = src64[7]; + + dst64[8] = src64[8]; + dst64[9] = src64[9]; + dst64[10] = src64[10]; + dst64[11] = src64[11]; + dst64[12] = src64[12]; + dst64[13] = src64[13]; + dst64[14] = src64[14]; + dst64[15] = src64[15]; + +#elif defined(ENV64BIT) && (sizeof_s4DVertex * sizeof_s4DVertexPairRel == 256) + u64* burning_restrict dst64 = (u64*)dst; + const u64* burning_restrict src64 = (const u64*)src; + + dst64[0] = src64[0]; + dst64[1] = src64[1]; + dst64[2] = src64[2]; + dst64[3] = src64[3]; + dst64[4] = src64[4]; + dst64[5] = src64[5]; + dst64[6] = src64[6]; + dst64[7] = src64[7]; + + dst64[8] = src64[8]; + dst64[9] = src64[9]; + dst64[10] = src64[10]; + dst64[11] = src64[11]; + dst64[12] = src64[12]; + dst64[13] = src64[13]; + dst64[14] = src64[14]; + dst64[15] = src64[15]; + + dst64[16] = src64[16]; + dst64[17] = src64[17]; + dst64[18] = src64[18]; + dst64[19] = src64[19]; + dst64[20] = src64[20]; + dst64[21] = src64[21]; + dst64[22] = src64[22]; + dst64[23] = src64[23]; + + dst64[24] = src64[24]; + dst64[25] = src64[25]; + dst64[26] = src64[26]; + dst64[27] = src64[27]; + dst64[28] = src64[28]; + dst64[29] = src64[29]; + dst64[30] = src64[30]; + dst64[31] = src64[31]; + +#else + u32* dst32 = (u32*)dst; + const u32* src32 = (const u32*)src; + + size_t len = sizeof_s4DVertex * sizeof_s4DVertexPairRel; + while (len >= 32) + { + *dst32++ = *src32++; + *dst32++ = *src32++; + *dst32++ = *src32++; + *dst32++ = *src32++; + *dst32++ = *src32++; + *dst32++ = *src32++; + *dst32++ = *src32++; + *dst32++ = *src32++; + len -= 32; + } +/* + while (len >= 4) + { + *dst32++ = *src32++; + len -= 4; + } +*/ +#endif +} + + +//! hold info for different Vertex Types struct SVSize { - u32 Format; - u32 Pitch; - u32 TexSize; + size_t Format; // e4DVertexFlag VERTEX4D_FORMAT_MASK_TEXTURE + size_t Pitch; // sizeof Vertex + size_t TexSize; // amount Textures + size_t TexCooSize; // sizeof TextureCoordinates }; @@ -530,18 +675,24 @@ struct SCacheInfo u32 hit; }; -#define VERTEXCACHE_ELEMENT 16 +//must at least hold all possible (clipped) vertices of primitive. +#define VERTEXCACHE_ELEMENT 16 #define VERTEXCACHE_MISS 0xFFFFFFFF struct SVertexCache { - SVertexCache (): mem ( VERTEXCACHE_ELEMENT * 2, 128 ) {} + SVertexCache () {} + ~SVertexCache() {} + + //VertexType + SVSize vSize[E4VT_COUNT]; SCacheInfo info[VERTEXCACHE_ELEMENT]; + SCacheInfo info_temp[VERTEXCACHE_ELEMENT]; // Transformed and lite, clipping state // + Clipped, Projected - SAlignedVertex mem; + SAligned4DVertex mem; // source const void* vertices; @@ -550,15 +701,15 @@ struct SVertexCache const void* indices; u32 indexCount; u32 indicesIndex; - u32 indicesRun; + u32 indicesPitch; // primitives consist of x vertices - u32 primitivePitch; + size_t primitiveHasVertex; - u32 vType; //E_VERTEX_TYPE - u32 pType; //scene::E_PRIMITIVE_TYPE - u32 iType; //E_INDEX_TYPE iType + e4DVertexType vType; //E_VERTEX_TYPE + scene::E_PRIMITIVE_TYPE pType; //scene::E_PRIMITIVE_TYPE + e4DIndexType iType; //E_INDEX_TYPE iType }; @@ -579,10 +730,11 @@ REALINLINE void swapVertexPointer(const s4DVertex** v1, const s4DVertex** v2) // internal scan convert struct sScanConvertData { - u8 left; // major edge left/right - u8 right; // !left + u32 left; // major edge left/right + u32 right; // !left + u32 _unused_pack[2]; - f32 invDeltaY[3]; // inverse edge delta y + f32 invDeltaY[4]; // inverse edge delta for screen space sorted triangle f32 x[2]; // x coordinate f32 slopeX[2]; // x slope along edges @@ -595,20 +747,27 @@ struct sScanConvertData f32 slopeZ[2]; // z slope along edges #endif - sVec4 c[MATERIAL_MAX_COLORS][2]; // color - sVec4 slopeC[MATERIAL_MAX_COLORS][2]; // color slope along edges +#if BURNING_MATERIAL_MAX_COLORS > 0 + sVec4 c[BURNING_MATERIAL_MAX_COLORS][2]; // color + sVec4 slopeC[BURNING_MATERIAL_MAX_COLORS][2]; // color slope along edges +#endif +#if BURNING_MATERIAL_MAX_TEXTURES > 0 sVec2 t[BURNING_MATERIAL_MAX_TEXTURES][2]; // texture sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES][2]; // texture slope along edges +#endif - sVec3 l[BURNING_MATERIAL_MAX_TANGENT][2]; // Light Tangent - sVec3 slopeL[BURNING_MATERIAL_MAX_TEXTURES][2]; // tanget slope along edges +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + sVec3Pack_unpack l[BURNING_MATERIAL_MAX_LIGHT_TANGENT][2]; // Light Tangent + sVec3Pack_unpack slopeL[BURNING_MATERIAL_MAX_LIGHT_TANGENT][2]; // tanget slope along edges +#endif }; // passed to scan Line struct sScanLineData { s32 y; // y position of scanline + u32 _unused_pack[1]; f32 x[2]; // x start, x end of scanline #if defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) || defined ( SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT ) @@ -617,12 +776,19 @@ struct sScanLineData f32 z[2]; // z start, z end of scanline #endif -#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - sVec4 c[MATERIAL_MAX_COLORS][2]; // color start, color end of scanline + u32 _unused_pack_1[2]; + +#if BURNING_MATERIAL_MAX_COLORS > 0 + sVec4 c[BURNING_MATERIAL_MAX_COLORS][2]; // color start, color end of scanline #endif +#if BURNING_MATERIAL_MAX_TEXTURES > 0 sVec2 t[BURNING_MATERIAL_MAX_TEXTURES][2]; // texture start, texture end of scanline - sVec3 l[BURNING_MATERIAL_MAX_TANGENT][2]; // Light Tangent start, end +#endif + +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT > 0 + sVec3Pack_unpack l[BURNING_MATERIAL_MAX_LIGHT_TANGENT][2]; // Light Tangent start, end +#endif }; // passed to pixel Shader @@ -640,51 +806,56 @@ struct sPixelShaderData /* load a color value */ -inline void getTexel_plain2 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sVec4 &v - ) +REALINLINE void getTexel_plain2 ( tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v ) { - r = tofix(v.y, FIX_POINT_F32_MUL); - g = tofix(v.z, FIX_POINT_F32_MUL); - b = tofix(v.w, FIX_POINT_F32_MUL); + r = tofix(v.r, FIX_POINT_F32_MUL); + g = tofix(v.g, FIX_POINT_F32_MUL); + b = tofix(v.b, FIX_POINT_F32_MUL); +} + +#if 0 +/* + load a color value +*/ +REALINLINE void getSample_color ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const sVec4 &v ) +{ + a = tofix ( v.a, FIX_POINT_F32_MUL); + r = tofix ( v.r, COLOR_MAX * FIX_POINT_F32_MUL); + g = tofix ( v.g, COLOR_MAX * FIX_POINT_F32_MUL); + b = tofix ( v.b, COLOR_MAX * FIX_POINT_F32_MUL); } /* load a color value */ -inline void getSample_color ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sVec4 &v - ) +REALINLINE void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v ) { - a = tofix(v.x, FIX_POINT_F32_MUL); - r = tofix ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); - g = tofix ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); - b = tofix ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); + r = tofix ( v.r, COLOR_MAX * FIX_POINT_F32_MUL); + g = tofix ( v.g, COLOR_MAX * FIX_POINT_F32_MUL); + b = tofix ( v.b, COLOR_MAX * FIX_POINT_F32_MUL); } +#endif /* - load a color value + load a color value. mulby controls [0;1] or [0;ColorMax] + aka getSample_color */ -inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v ) +REALINLINE void vec4_to_fix(tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v, const f32 mulby ) { - r = tofix ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); - g = tofix ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); - b = tofix ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); + r = tofix(v.r, mulby); + g = tofix(v.g, mulby); + b = tofix(v.b, mulby); } -/* - load a color value -*/ -inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sVec4 &v, const f32 mulby ) +REALINLINE void vec4_to_fix(tFixPoint &a,tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v, const f32 mulby) { - r = tofix ( v.y, mulby); - g = tofix ( v.z, mulby); - b = tofix ( v.w, mulby); + a = tofix(v.a, mulby); + r = tofix(v.r, mulby); + g = tofix(v.g, mulby); + b = tofix(v.b, mulby); } - } } diff --git a/source/Irrlicht/SoftwareDriver2_compile_config.h b/source/Irrlicht/SoftwareDriver2_compile_config.h index a4713181..725ba1a9 100644 --- a/source/Irrlicht/SoftwareDriver2_compile_config.h +++ b/source/Irrlicht/SoftwareDriver2_compile_config.h @@ -7,10 +7,28 @@ #include "IrrCompileConfig.h" - // Generic Render Flags for burning's video rasterizer // defined now in irrlicht compile config +#if defined(PATCH_SUPERTUX_8_0_1) + #undef BURNINGVIDEO_RENDERER_BEAUTIFUL + + //#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT + #define SOFTWARE_DRIVER_2_SUBTEXEL + //#define SOFTWARE_DRIVER_2_BILINEAR + #define SOFTWARE_DRIVER_2_LIGHTING + #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR + #define SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR + #define SOFTWARE_DRIVER_2_32BIT + #define SOFTWARE_DRIVER_2_MIPMAPPING + #define SOFTWARE_DRIVER_2_USE_WBUFFER + #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 256 + #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN + #define SOFTWARE_DRIVER_2_CLIPPING + #define SOFTWARE_DRIVER_2_2D_AS_2D +#endif + #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT @@ -18,11 +36,15 @@ #define SOFTWARE_DRIVER_2_BILINEAR #define SOFTWARE_DRIVER_2_LIGHTING #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR + #define SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR #define SOFTWARE_DRIVER_2_32BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 + #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN + #define SOFTWARE_DRIVER_2_CLIPPING + #define SOFTWARE_DRIVER_2_2D_AS_3D #endif //! Set Flags for Windows Mobile @@ -36,7 +58,10 @@ #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER //#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 128 + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 64 + #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN + //#define SOFTWARE_DRIVER_2_CLIPPING + #define SOFTWARE_DRIVER_2_2D_AS_2D #endif #ifdef BURNINGVIDEO_RENDERER_FAST @@ -44,25 +69,34 @@ #define SOFTWARE_DRIVER_2_SUBTEXEL //#define SOFTWARE_DRIVER_2_BILINEAR //#define SOFTWARE_DRIVER_2_LIGHTING - //#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - #define SOFTWARE_DRIVER_2_32BIT + #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR + //#define SOFTWARE_DRIVER_2_32BIT + #define SOFTWARE_DRIVER_2_16BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 256 + #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN + #define SOFTWARE_DRIVER_2_CLIPPING + #define SOFTWARE_DRIVER_2_2D_AS_2D #endif #ifdef BURNINGVIDEO_RENDERER_ULTRA_FAST #define BURNINGVIDEO_RENDERER_FAST //#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT - #define SOFTWARE_DRIVER_2_SUBTEXEL + //#define SOFTWARE_DRIVER_2_SUBTEXEL //#define SOFTWARE_DRIVER_2_BILINEAR //#define SOFTWARE_DRIVER_2_LIGHTING - //#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR + #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR //#define SOFTWARE_DRIVER_2_32BIT - #define SOFTWARE_DRIVER_2_MIPMAPPING - #define SOFTWARE_DRIVER_2_USE_WBUFFER - #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 + #define SOFTWARE_DRIVER_2_16BIT + //#define SOFTWARE_DRIVER_2_MIPMAPPING + //#define SOFTWARE_DRIVER_2_USE_WBUFFER + //#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 128 + #define SOFTWARE_DRIVER_2_SCANLINE_MAG_MIN + //#define SOFTWARE_DRIVER_2_CLIPPING + #define SOFTWARE_DRIVER_2_2D_AS_2D #endif // Derivate flags @@ -74,24 +108,24 @@ #define BURNINGSHADER_COLOR_FORMAT ECF_A1R5G5B5 #endif -// mip mapping +// mip mapping - precalculated texture filter #if defined ( SOFTWARE_DRIVER_2_MIPMAPPING ) #if defined( BURNINGVIDEO_RENDERER_BEAUTIFUL ) #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 16 - #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 + #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 #elif defined ( BURNINGVIDEO_RENDERER_CE ) #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 - #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 + #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 8 #else - #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 8 - #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 + #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 + #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 8 #endif #else #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 1 - #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 + #define SOFTWARE_DRIVER_2_MIPMAPPING_MIN_SIZE 1 #endif -#define SOFTWARE_DRIVER_2_MIPMAPPING_SCALE (16/SOFTWARE_DRIVER_2_MIPMAPPING_MAX) + #ifndef REALINLINE #ifdef _MSC_VER @@ -101,4 +135,155 @@ #endif #endif + +// null check necessary (burningvideo only) +#define reciprocal_zero(x) ((x) != 0.f ? 1.f / (x):0.f) +static inline float reciprocal_zero2(float x) { return x != 0.f ? 1.f / x : 0.f; } +#define reciprocal_one(x) ((x) != 0.f ? 1.f / (x):1.f) + +#define fill_convention_left(x) (s32) ceilf(x) +#define fill_convention_right(x) ((s32) ceilf(x))-1 +#define fill_convention_none(x) (s32) (x) +//#define fill_convention_left(x) 65536 - int(65536.0f - x) +//#define fill_convention_right(x) 65535 - int(65536.0f - x) + + +//Check coordinates are in render target/window space +//#define SOFTWARE_DRIVER_2_DO_CLIPCHECK +#if defined (SOFTWARE_DRIVER_2_DO_CLIPCHECK) && defined(_WIN32) +#define SOFTWARE_DRIVER_2_CLIPCHECK if( xStart < 0 || xStart + dx >= (s32)RenderTarget->getDimension().Width || line.y < 0 || line.y >= (s32) RenderTarget->getDimension().Height ) __debugbreak() +#define SOFTWARE_DRIVER_2_CLIPCHECK_REF if( pShader.xStart < 0 || pShader.xStart + pShader.dx >= (s32)RenderTarget->getDimension().Width || line.y < 0 || line.y >= (s32) RenderTarget->getDimension().Height ) __debugbreak() +#define SOFTWARE_DRIVER_2_CLIPCHECK_WIRE if( aposx < 0 || aposx >= (s32)RenderTarget->getDimension().Width || aposy < 0 || aposy >= (s32) RenderTarget->getDimension().Height ) __debugbreak() + +inline float reciprocal_zero_no(const float x) +{ + if (x*x <= 0.00001f) __debugbreak(); + return 1.f / x; +} +#else +#define SOFTWARE_DRIVER_2_CLIPCHECK +#define SOFTWARE_DRIVER_2_CLIPCHECK_REF +#define SOFTWARE_DRIVER_2_CLIPCHECK_WIRE + +#define reciprocal_zero_no(x) 1.f/x #endif + +//!scanline renderer emulate line +enum edge_test_flag +{ + edge_test_pass = 1, //! not wireframe + edge_test_left = 0, + edge_test_first_line = 2, + edge_test_point = 4 +}; +//if any edge test flag is set result=1 else 0. ( pass height test for degenerate triangle ) +#define reciprocal_edge(x) ((x) != 0.f ? 1.f / (x):(~EdgeTestPass)&1) + +//! normalize from fixed point Color Max to fixed point [0;1] +#define fix_color_norm(x) x = (x+1) >> COLOR_MAX_LOG2 + +//! from 1 bit to 5 bit +#ifdef SOFTWARE_DRIVER_2_32BIT + #define fix_alpha_color_max(x) +#else + #define fix_alpha_color_max(x) if (x) x = (x << COLOR_MAX_LOG2) - 1 +#endif + +// Check windows +#if _WIN32 || _WIN64 +#if _WIN64 + #define ENV64BIT +#else + #define ENV32BIT +#endif +#endif + +// Check GCC +#if __GNUC__ +#if __x86_64__ || __ppc64__ + #define ENV64BIT +#else + #define ENV32BIT +#endif +#endif + +#if defined(ENV64BIT) && defined(BURNINGVIDEO_RENDERER_BEAUTIFUL) + typedef float ipoltype; +#else + typedef float ipoltype; +#endif + +#define ipol_lower_equal_0(n) ((n) <= (ipoltype)0.0) +#define ipol_greater_0(n) ((n) > (ipoltype)0.0) + +#if (_MSC_VER > 1700 ) + #define burning_restrict __restrict +#else + #define burning_restrict +#endif + +/* + if (condition) state |= mask; else state &= ~mask; +*/ +static inline void burning_setbit(size_t &state, int condition, size_t mask) +{ + if (condition) state |= mask; + else state &= ~mask; +} + +/* + if (condition) state |= m; else state &= ~m; +*/ +REALINLINE void burning_setbit32(unsigned int &state, int condition, const unsigned int mask) +{ + // 0, or any positive to mask + //s32 conmask = -condition >> 31; + state ^= ((-condition >> 31) ^ state) & mask; +} + +#define burning_stringify(s) #s +#define burning_create_indirect(s) create_##s +#define burning_create(s) burning_create_indirect(s) + + +#if defined(PATCH_SUPERTUX_8_0_1) +#define getData lock +#define snprintf_irr sprintf_s + +#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR +#ifdef SOFTWARE_DRIVER_2_USE_SEPARATE_SPECULAR_COLOR +#define BURNING_MATERIAL_MAX_COLORS 2 +#else +#define BURNING_MATERIAL_MAX_COLORS 1 +#endif +#else +#define BURNING_MATERIAL_MAX_COLORS 0 +#endif + +#ifndef _IRR_OVERRIDE_ +#define _IRR_OVERRIDE_ /**/ +#endif + +#define fix_to_color fix_to_sample +#define fix4_to_color fix4_to_sample +#define vec4_to_fix getSample_color +#define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 + +namespace irr { + + REALINLINE void memcpy32_small(void * dest, const void *source, size_t bytesize) + { + size_t c = bytesize >> 2; + + do + { + ((unsigned int *)dest)[c - 1] = ((unsigned int *)source)[c - 1]; + } while (--c); + + } + +} // namespace irr +#endif // #if defined(PATCH_SUPERTUX_8_0_1) + + +#endif // __S_VIDEO_2_SOFTWARE_COMPILE_CONFIG_H_INCLUDED__ diff --git a/source/Irrlicht/SoftwareDriver2_helper.h b/source/Irrlicht/SoftwareDriver2_helper.h index 01e2f4f7..59a91b85 100644 --- a/source/Irrlicht/SoftwareDriver2_helper.h +++ b/source/Irrlicht/SoftwareDriver2_helper.h @@ -24,40 +24,42 @@ namespace irr #ifdef SOFTWARE_DRIVER_2_32BIT typedef u32 tVideoSample; + typedef u32 tStencilSample; #define MASK_A 0xFF000000 #define MASK_R 0x00FF0000 #define MASK_G 0x0000FF00 #define MASK_B 0x000000FF - #define SHIFT_A 24 - #define SHIFT_R 16 - #define SHIFT_G 8 - #define SHIFT_B 0 + #define SHIFT_A (unsigned)24 + #define SHIFT_R (unsigned)16 + #define SHIFT_G (unsigned)8 + #define SHIFT_B (unsigned)0 #define COLOR_MAX 0xFF #define COLOR_MAX_LOG2 8 #define COLOR_BRIGHT_WHITE 0xFFFFFFFF - #define VIDEO_SAMPLE_GRANULARITY 2 + #define VIDEO_SAMPLE_GRANULARITY (unsigned)2 #else typedef u16 tVideoSample; + typedef u8 tStencilSample; #define MASK_A 0x8000 #define MASK_R 0x7C00 #define MASK_G 0x03E0 #define MASK_B 0x001F - #define SHIFT_A 15 - #define SHIFT_R 10 - #define SHIFT_G 5 - #define SHIFT_B 0 + #define SHIFT_A (unsigned)15 + #define SHIFT_R (unsigned)10 + #define SHIFT_G (unsigned)5 + #define SHIFT_B (unsigned)0 #define COLOR_MAX 0x1F #define COLOR_MAX_LOG2 5 #define COLOR_BRIGHT_WHITE 0xFFFF - #define VIDEO_SAMPLE_GRANULARITY 1 + #define VIDEO_SAMPLE_GRANULARITY (unsigned)1 #endif @@ -65,14 +67,16 @@ namespace irr // ----------------------- Generic ---------------------------------- +//! align_next - align to next upper 2^n +#define align_next(num,to) (((num) + (to-1)) & (~(to-1))) -//! a more useful memset for pixel +//! a more useful memset for pixel. dest must be aligned at least to 4 byte // (standard memset only works with 8-bit values) -inline void memset32(void * dest, const u32 value, u32 bytesize) +inline void memset32(void * dest, const u32 value, size_t bytesize) { u32 * d = (u32*) dest; - u32 i; + size_t i; // loops unrolled to reduce the number of increments by factor ~8. i = bytesize >> (2 + 3); @@ -101,13 +105,13 @@ inline void memset32(void * dest, const u32 value, u32 bytesize) } } -//! a more useful memset for pixel +//! a more useful memset for pixel. dest must be aligned at least to 2 byte // (standard memset only works with 8-bit values) -inline void memset16(void * dest, const u16 value, u32 bytesize) +inline void memset16(void * dest, const u16 value, size_t bytesize) { u16 * d = (u16*) dest; - u32 i; + size_t i; // loops unrolled to reduce the number of increments by factor ~8. i = bytesize >> (1 + 3); @@ -136,35 +140,52 @@ inline void memset16(void * dest, const u16 value, u32 bytesize) } } -/* - use biased loop counter - --> 0 byte copy is forbidden -*/ -REALINLINE void memcpy32_small ( void * dest, const void *source, u32 bytesize ) -{ - u32 c = bytesize >> 2; - do - { - ((u32*) dest ) [ c-1 ] = ((u32*) source) [ c-1 ]; - } while ( --c ); +// byte-align structures +#include "irrpack.h" -} +//IEEE Standard for Floating - Point Arithmetic(IEEE 754) +typedef union { + float f; + unsigned int u; + struct { unsigned int frac:23; unsigned exp:8; unsigned int sign:1; } fields; + struct { unsigned int frac_exp:31; } abs; +} ieee754 PACK_STRUCT; +// Default alignment +#include "irrunpack.h" +// 0.5f as integer +#define ieee754_zero_dot_5 0x3f000000 +#define ieee754_one 0x3f800000 +#define ieee754_two 0x40000000 -// integer log2 of a float ieee 754. TODO: non ieee floating point +#if 0 +// integer log2 of a float ieee 754. [not used anymore] static inline s32 s32_log2_f32( f32 f) { - u32 x = IR ( f ); - return ((x & 0x7F800000) >> 23) - 127; + //u32 x = IR ( f ); return ((x & 0x7F800000) >> 23) - 127; + ieee754 _log2; + _log2.f = f; + return _log2.fields.exp ? _log2.fields.exp - 127 : 10000000; /*denormal very high number*/ } +#endif -static inline s32 s32_log2_s32(u32 x) +// integer log2 of an integer. returning 0 as denormal +static inline s32 s32_log2_s32(u32 in) { - return s32_log2_f32( (f32) x); + s32 ret = 0; + while (in > 1) + { + in >>= 1; + ret++; + } + return ret; + //return s32_log2_f32( (f32) x); + //ieee754 _log2;_log2.f = (f32) in; return _log2.fields.exp - 127; } +#if 0 static inline s32 s32_abs(s32 x) { s32 b = x >> 31; @@ -177,13 +198,14 @@ REALINLINE u32 if_mask_a_else_b ( const u32 mask, const u32 a, const u32 b ) { return ( mask & ( a ^ b ) ) ^ b; } +#endif // ------------------ Video--------------------------------------- /*! Pixel = dest * ( 1 - alpha ) + source * alpha alpha [0;256] */ -REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, u32 alpha ) +REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, const u32 alpha ) { u32 srcRB = c1 & 0x00FF00FF; u32 srcXG = c1 & 0x0000FF00; @@ -213,7 +235,7 @@ REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, u32 alpha ) Pixel = dest * ( 1 - alpha ) + source * alpha alpha [0;32] */ -inline u16 PixelBlend16 ( const u16 c2, const u32 c1, const u16 alpha ) +inline u16 PixelBlend16 ( const u16 c2, const u16 c1, const u16 alpha ) { const u16 srcRB = c1 & 0x7C1F; const u16 srcXG = c1 & 0x03E0; @@ -386,97 +408,45 @@ inline u32 PixelBlend32 ( const u32 c2, const u32 c1 ) return (c1 & 0xFF000000) | rb | xg; } -/*! - Pixel => - color = sourceAlpha > 0 ? source, else dest - alpha = max(destAlpha, sourceAlpha) -*/ -inline u16 PixelCombine16 ( const u16 c2, const u16 c1 ) -{ - if ( video::getAlpha(c1) > 0 ) - return c1; - else - return c2; -} - -/*! - Pixel => - color = dest * ( 1 - SourceAlpha ) + source * SourceAlpha, - alpha = destAlpha * ( 1 - SourceAlpha ) + sourceAlpha - - where "1" means "full scale" (255) -*/ -inline u32 PixelCombine32 ( const u32 c2, const u32 c1 ) -{ - // alpha test - u32 alpha = c1 & 0xFF000000; - - if ( 0 == alpha ) - return c2; - if ( 0xFF000000 == alpha ) - { - return c1; - } - - alpha >>= 24; - - // add highbit alpha, if ( alpha > 127 ) alpha += 1; - // stretches [0;255] to [0;256] to avoid division by 255. use division 256 == shr 8 - alpha += ( alpha >> 7); - - u32 srcRB = c1 & 0x00FF00FF; - u32 srcXG = c1 & 0x0000FF00; - - u32 dstRB = c2 & 0x00FF00FF; - u32 dstXG = c2 & 0x0000FF00; - - - u32 rb = srcRB - dstRB; - u32 xg = srcXG - dstXG; - - rb *= alpha; - xg *= alpha; - rb >>= 8; - xg >>= 8; - - rb += dstRB; - xg += dstXG; - - rb &= 0x00FF00FF; - xg &= 0x0000FF00; - - u32 sa = c1 >> 24; - u32 da = c2 >> 24; - u32 blendAlpha_fix8 = (sa*256 + da*(256-alpha))>>8; - return blendAlpha_fix8 << 24 | rb | xg; -} - // ------------------ Fix Point ---------------------------------- +#if defined(ENV64BIT) typedef s32 tFixPoint; typedef u32 tFixPointu; +#else +typedef s32 tFixPoint; +typedef u32 tFixPointu; +#endif -// Fix Point 12 +// Fix Point 12 (overflow on s32) #if 0 #define FIX_POINT_PRE 12 #define FIX_POINT_FRACT_MASK 0xFFF - #define FIX_POINT_SIGNED_MASK 0xFFFFF000 #define FIX_POINT_UNSIGNED_MASK 0x7FFFF000 #define FIX_POINT_ONE 0x1000 #define FIX_POINT_ZERO_DOT_FIVE 0x0800 #define FIX_POINT_F32_MUL 4096.f #endif +// Fix Point 11 (overflow on s32) +#if 0 + #define FIX_POINT_PRE 11 + #define FIX_POINT_FRACT_MASK 0x7FF + #define FIX_POINT_UNSIGNED_MASK 0xFFFFF800 + #define FIX_POINT_ONE 0x800 + #define FIX_POINT_ZERO_DOT_FIVE 0x400 + #define FIX_POINT_F32_MUL 2048.f +#endif + // Fix Point 10 #if 1 #define FIX_POINT_PRE 10 - #define FIX_POINT_FRACT_MASK 0x3FF - #define FIX_POINT_SIGNED_MASK 0xFFFFFC00 + #define FIX_POINT_FRACT_MASK 0x000003FF #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00 - #define FIX_POINT_ONE 0x400 - #define FIX_POINT_ZERO_DOT_FIVE 0x200 + #define FIX_POINT_ONE 0x00000400 + #define FIX_POINT_ZERO_DOT_FIVE 0x00000200 #define FIX_POINT_F32_MUL 1024.f #endif @@ -484,7 +454,6 @@ typedef u32 tFixPointu; #if 0 #define FIX_POINT_PRE 9 #define FIX_POINT_FRACT_MASK 0x1FF - #define FIX_POINT_SIGNED_MASK 0xFFFFFE00 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00 #define FIX_POINT_ONE 0x200 #define FIX_POINT_ZERO_DOT_FIVE 0x100 @@ -495,7 +464,6 @@ typedef u32 tFixPointu; #if 0 #define FIX_POINT_PRE 7 #define FIX_POINT_FRACT_MASK 0x7F - #define FIX_POINT_SIGNED_MASK 0xFFFFFF80 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFF80 #define FIX_POINT_ONE 0x80 #define FIX_POINT_ZERO_DOT_FIVE 0x40 @@ -503,7 +471,20 @@ typedef u32 tFixPointu; #endif #define FIXPOINT_COLOR_MAX ( COLOR_MAX << FIX_POINT_PRE ) -#define FIX_POINT_HALF_COLOR ( (tFixPoint) ( ((f32) COLOR_MAX / 2.f * FIX_POINT_F32_MUL ) ) ) + +#if FIX_POINT_PRE == 10 && COLOR_MAX == 255 + #define FIX_POINT_HALF_COLOR 0x1FE00 + #define FIX_POINT_COLOR_ERROR 4 +#elif FIX_POINT_PRE == 12 && COLOR_MAX == 255 + #define FIX_POINT_HALF_COLOR 0x7F800 + #define FIX_POINT_COLOR_ERROR 16 +#elif FIX_POINT_PRE == 10 && COLOR_MAX == 31 + #define FIX_POINT_HALF_COLOR 0x3E00 + #define FIX_POINT_COLOR_ERROR 32 +#else + #define FIX_POINT_HALF_COLOR ( (tFixPoint) ( ((f32) COLOR_MAX / 2.f * FIX_POINT_F32_MUL ) ) ) + #define FIX_POINT_COLOR_ERROR (1<<(FIX_POINT_PRE-COLOR_MAX_LOG2)) +#endif /* @@ -521,12 +502,13 @@ inline tFixPointu u32_to_fixPoint (const u32 x) inline u32 fixPointu_to_u32 (const tFixPointu x) { - return x >> FIX_POINT_PRE; + return (u32)(x >> FIX_POINT_PRE); } // 1/x * FIX_POINT #define fix_inverse32(x) (FIX_POINT_F32_MUL / (x)) +#define fix_inverse32_color(x) ((FIX_POINT_F32_MUL*COLOR_MAX) / (x)) /* @@ -535,38 +517,50 @@ inline u32 fixPointu_to_u32 (const tFixPointu x) hints: compileflag /QIfist for msvc7. msvc 8.0 has smth different others should use their favourite assembler.. */ +#if 0 static inline int f_round2(f32 f) { f += (3<<22); return IR(f) - 0x4b400000; } +#endif /* convert f32 to Fix Point. multiply is needed anyway, so scale mulby */ +/* REALINLINE tFixPoint tofix0 (const f32 x, const f32 mulby = FIX_POINT_F32_MUL ) { return (tFixPoint) (x * mulby); } +*/ #define tofix(x,y) (tFixPoint)(x * y) + /* Fix Point , Fix Point Multiply */ +/* REALINLINE tFixPointu imulFixu(const tFixPointu x, const tFixPointu y) { return (x * y) >> (tFixPointu) FIX_POINT_PRE; } +*/ +#define imulFixu(x,y) (((x) * (y)) >> (tFixPointu) FIX_POINT_PRE) + /* Fix Point , Fix Point Multiply */ REALINLINE tFixPoint imulFix(const tFixPoint x, const tFixPoint y) { - return ( x * y) >> ( FIX_POINT_PRE ); + return (x * y) >> FIX_POINT_PRE; } +#define imulFix_simple(x,y) ((x*y)>>FIX_POINT_PRE) + +#if 0 /* Fix Point , Fix Point Multiply x * y * 2 */ @@ -574,14 +568,18 @@ REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y) { return ( x * y) >> ( FIX_POINT_PRE -1 ); } - +#endif /* - Multiply x * y * 1 + Multiply x * y * 1 FIXPOINT_COLOR_MAX */ REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y) { - return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 4 ); +#ifdef SOFTWARE_DRIVER_2_32BIT + return (((tFixPointu)x >> 2)*(((tFixPointu)y + FIX_POINT_ONE) >> 2)) >> (tFixPointu) (FIX_POINT_PRE + 4); +#else + return (x * (y+ FIX_POINT_ONE)) >> (FIX_POINT_PRE + 5); +#endif } /* @@ -593,26 +591,42 @@ REALINLINE tFixPoint imulFix_tex2(const tFixPoint x, const tFixPoint y) } /* - Multiply x * y * 4 + Multiply x * y * 4 clamp */ + REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y) { #ifdef SOFTWARE_DRIVER_2_32BIT - return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 2 ); + register tFixPoint a = (((tFixPointu)x >> 2)*(((tFixPointu)y + FIX_POINT_ONE) >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 2); #else - return ( x * y) >> ( FIX_POINT_PRE + ( VIDEO_SAMPLE_GRANULARITY * 3 ) ); + register tFixPoint a = (x * (y + FIX_POINT_ONE)) >> (FIX_POINT_PRE + 3); #endif + register tFixPoint mask = (a - FIXPOINT_COLOR_MAX) >> 31; + return (a & mask) | (FIXPOINT_COLOR_MAX & ~mask); } + +#if 0 +#define imulFix_tex1(x,y) ((((tFixPointu)x >> 2) * ((tFixPointu)y >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 4)) +#define imulFix_tex2(x,y) ((((tFixPointu)x >> 2) * ((tFixPointu)y >> 2)) >> (tFixPointu)(FIX_POINT_PRE + 3)) + +#ifdef SOFTWARE_DRIVER_2_32BIT +#define imulFix_tex4(x,y) ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 2 ) +#else +#define imulFix_tex4(x,y) ( x * y) >> ( FIX_POINT_PRE + ( VIDEO_SAMPLE_GRANULARITY * 3 ) ) +#endif +#endif + /*! - clamp FixPoint to maxcolor in FixPoint, min(a,31) + clamp FixPoint to maxcolor in FixPoint, min(a,COLOR_MAX) */ REALINLINE tFixPoint clampfix_maxcolor ( const tFixPoint a) { - tFixPoint c = (a - FIXPOINT_COLOR_MAX) >> 31; + register tFixPoint c = (a - FIXPOINT_COLOR_MAX) >> 31; return (a & c) | ( FIXPOINT_COLOR_MAX & ~c); } + /*! clamp FixPoint to 0 in FixPoint, max(a,0) */ @@ -630,22 +644,24 @@ REALINLINE tFixPoint saturateFix ( const tFixPoint a) // rount fixpoint to int inline s32 roundFix ( const tFixPoint x ) { - return ( x + FIX_POINT_ZERO_DOT_FIVE ) >> FIX_POINT_PRE; + return (s32)(( x + FIX_POINT_ZERO_DOT_FIVE ) >> FIX_POINT_PRE); } // x in [0;1[ +#if 0 inline s32 f32_to_23Bits(const f32 x) { f32 y = x + 1.f; return IR(y) & 0x7FFFFF; // last 23 bits } +#endif /*! - return VideoSample from fixpoint + fixpoint in [0..Fixpoint_color] to VideoSample xrgb */ -REALINLINE tVideoSample fix_to_color ( const tFixPoint r, const tFixPoint g, const tFixPoint b ) +REALINLINE tVideoSample fix_to_sample ( const tFixPoint r, const tFixPoint g, const tFixPoint b ) { return ( FIXPOINT_COLOR_MAX & FIXPOINT_COLOR_MAX) << ( SHIFT_A - FIX_POINT_PRE ) | ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | @@ -655,9 +671,11 @@ REALINLINE tVideoSample fix_to_color ( const tFixPoint r, const tFixPoint g, con /*! - return VideoSample from fixpoint + fixpoint to VideoSample argb + a in [0;1] + rgb in [0;255] colormax */ -REALINLINE tVideoSample fix4_to_color ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b ) +REALINLINE tVideoSample fix4_to_sample ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b ) { return ( a & (FIX_POINT_FRACT_MASK - 1 )) << ( SHIFT_A - 1 ) | ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | @@ -666,7 +684,7 @@ REALINLINE tVideoSample fix4_to_color ( const tFixPoint a, const tFixPoint r, co } /*! - return fixpoint from VideoSample granularity COLOR_MAX + return fixpoint from VideoSample granularity FIXPOINT_COLOR_MAX */ inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { @@ -676,7 +694,7 @@ inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVide } /*! - return fixpoint from VideoSample granularity COLOR_MAX + return fixpoint from VideoSample granularity FIXPOINT_COLOR_MAX */ inline void color_to_fix ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { @@ -694,6 +712,11 @@ inline void color_to_fix1 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVid (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 ); + + //0..255 -> 0..256 | c += c >= 0.5 ? 1 : 0 + r += (r & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + g += (g & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + b += (b & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; } /*! @@ -705,11 +728,47 @@ inline void color_to_fix1 ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 ); + + //0..255 -> 0..256 | c += c >= 0.5 ? 1 : 0 + a += (a & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + r += (r & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + g += (g & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + b += (b & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + +} + +/*! + return fixpoint from VideoSample granularity FIXPOINT_COLOR_MAX +*/ +inline void color_to_fix(tFixPoint c[4], const tVideoSample t00) +{ + c[0] = (t00 & MASK_A) >> (SHIFT_A - FIX_POINT_PRE); + c[1] = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE); + c[2] = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G); + c[3] = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B); +} + +/*! + return fixpoint from VideoSample granularity 0..FIX_POINT_ONE +*/ +inline void color_to_fix1(tFixPoint c[4], const tVideoSample t00) +{ + c[0] = (t00 & MASK_A) >> (SHIFT_A + COLOR_MAX_LOG2 - FIX_POINT_PRE); + c[1] = (t00 & MASK_R) >> (SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE); + c[2] = (t00 & MASK_G) >> (SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE); + c[3] = (t00 & MASK_B) << (FIX_POINT_PRE - COLOR_MAX_LOG2); + + //0..255 -> 0..256 | c += c >= 0.5 ? 1 : 0 + c[0] += (c[0] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + c[1] += (c[1] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + c[2] += (c[2] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + c[3] += (c[3] & FIX_POINT_ZERO_DOT_FIVE) ? FIX_POINT_COLOR_ERROR : 0; + } -// ----- FP24 ---- floating point z-buffer +//! ----- FP24 1.23 fix point z-buffer #if 1 typedef f32 fp24; @@ -751,22 +810,23 @@ struct fp24 struct sInternalTexture { - u32 textureXMask; - u32 textureYMask; + //power-of-two + void* data; //tVideoSample* Texture->lock(miplevel) + size_t textureXMask; + size_t textureYMask; - u32 pitchlog2; - void *data; + size_t pitchlog2; video::CSoftwareTexture2 *Texture; - s32 lodLevel; + s32 lodFactor; // magnify/minify }; // get video sample plain -inline tVideoSample getTexel_plain ( const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) +static inline tVideoSample getTexel_plain ( const sInternalTexture* t, const tFixPointu tx, const tFixPointu ty ) { - u32 ofs; + register size_t ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); @@ -777,16 +837,16 @@ inline tVideoSample getTexel_plain ( const sInternalTexture * t, const tFixPoint // get video sample to fix inline void getTexel_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty + const sInternalTexture* t, const tFixPointu tx, const tFixPointu ty ) { - u32 ofs; + register size_t ofs; - ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + ofs = ( ((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; + ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel - tVideoSample t00; + register tVideoSample t00; t00 = *((tVideoSample*)( (u8*) t->data + ofs )); r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); @@ -795,14 +855,36 @@ inline void getTexel_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, } +// get video sample to fixpoint colormax +inline void getTexel_fix(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sInternalTexture* t, const tFixPointu tx, const tFixPointu ty +) +{ + register size_t ofs; + + ofs = (((ty+ FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; + ofs |= ((tx+ FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + + // texel + register tVideoSample t00; + t00 = *((tVideoSample*)((u8*)t->data + ofs)); + + a = (t00 & MASK_A) >> (SHIFT_A - FIX_POINT_PRE); + r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE); + g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G); + b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B); + +} + +#if 0 // get video sample to fixpoint -REALINLINE void getTexel_fix ( tFixPoint &a, +static REALINLINE void getTexel_fix ( tFixPoint &a, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty) { - u32 ofs; + size_t ofs; - ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + ofs = ( ((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; + ofs |= ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel tVideoSample t00; @@ -810,253 +892,289 @@ REALINLINE void getTexel_fix ( tFixPoint &a, a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE); } - - -inline void getSample_texture_dither ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty, - const u32 x, const u32 y - ) -{ - static const tFixPointu dithermask[] = - { - 0x00,0x80,0x20,0xa0, - 0xc0,0x40,0xe0,0x60, - 0x30,0xb0,0x10,0x90, - 0xf0,0x70,0xd0,0x50 - }; - - const u32 index = (y & 3 ) << 2 | (x & 3); - - const tFixPointu _ntx = (tx + dithermask [ index ] ) & t->textureXMask; - const tFixPointu _nty = (ty + dithermask [ index ] ) & t->textureYMask; - - u32 ofs; - ofs = ( ( _nty ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( _ntx ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); - - // texel - const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs )); - - (tFixPointu &) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); - (tFixPointu &) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); - (tFixPointu &) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); - -} +#endif /* load a sample from internal texture at position tx,ty to fixpoint */ -#ifndef SOFTWARE_DRIVER_2_BILINEAR +#if defined(SOFTWARE_DRIVER_2_BILINEAR) + +#if 0 +// texture2D in fixpoint color range bilinear +static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sInternalTexture* burning_restrict t, const tFixPointu tx, const tFixPointu ty +) +{ +#if 0 + if (t->lodFactor > 0) + { + register size_t ofs; + + ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + + // texel + tVideoSample t00; + t00 = *((tVideoSample*)((u8*)t->data + ofs)); + + r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE); + g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G); + b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B); + return; + } +#endif + + tFixPointu r00, g00, b00; + tFixPointu r01, g01, b01; + tFixPointu r10, g10, b10; + tFixPointu r11, g11, b11; + + size_t o0, o1, o2, o3; + register tVideoSample t00; + + //wraps positive (ignoring negative) + o0 = (((ty)& t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; + o1 = (((ty + FIX_POINT_ONE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; + o2 = ((tx)& t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + o3 = ((tx + FIX_POINT_ONE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + + t00 = *((tVideoSample*)((u8*)t->data + (o0 + o2))); + r00 = (t00 & MASK_R) >> SHIFT_R; + g00 = (t00 & MASK_G) >> SHIFT_G; + b00 = (t00 & MASK_B); + + t00 = *((tVideoSample*)((u8*)t->data + (o0 + o3))); + r10 = (t00 & MASK_R) >> SHIFT_R; + g10 = (t00 & MASK_G) >> SHIFT_G; + b10 = (t00 & MASK_B); + + t00 = *((tVideoSample*)((u8*)t->data + (o1 + o2))); + r01 = (t00 & MASK_R) >> SHIFT_R; + g01 = (t00 & MASK_G) >> SHIFT_G; + b01 = (t00 & MASK_B); + + t00 = *((tVideoSample*)((u8*)t->data + (o1 + o3))); + r11 = (t00 & MASK_R) >> SHIFT_R; + g11 = (t00 & MASK_G) >> SHIFT_G; + b11 = (t00 & MASK_B); + + + register tFixPointu fracx = tx & FIX_POINT_FRACT_MASK; + register tFixPointu fracy = ty & FIX_POINT_FRACT_MASK; + + //w00 w01 w10 w11 + tFixPointu w[4]; + w[0] = imulFixu(FIX_POINT_ONE - fracx, FIX_POINT_ONE - fracy); + w[1] = imulFixu(FIX_POINT_ONE - fracx, fracy); + w[2] = imulFixu(fracx, FIX_POINT_ONE - fracy); + w[3] = imulFixu(fracx, fracy); + + r = (r00 * w[0]) + + (r01 * w[1]) + + (r10 * w[2]) + + (r11 * w[3]); + + g = (g00 * w[0]) + + (g01 * w[1]) + + (g10 * w[2]) + + (g11 * w[3]); + + b = (b00 * w[0]) + + (b01 * w[1]) + + (b10 * w[2]) + + (b11 * w[3]); + +} + +#else + +// texture2D in fixpoint color range bilinear +static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sInternalTexture* burning_restrict tex, const tFixPointu tx, const tFixPointu ty +) +{ +#if 0 + if (tex->lodFactor > 1) + { + //nearest neighbor + register size_t ofs; + ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & tex->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + + register tVideoSample t00; + t00 = *((tVideoSample*)((u8*)tex->data + ofs)); + + r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE); + g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G); + b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B); + return; + } +#endif + //w00 w01 w10 w11 + tFixPointu w[4]; + { + register tFixPointu fracx = tx & FIX_POINT_FRACT_MASK; + register tFixPointu fracy = ty & FIX_POINT_FRACT_MASK; + w[0] = imulFixu(FIX_POINT_ONE - fracx, FIX_POINT_ONE - fracy); + w[1] = imulFixu(fracx, FIX_POINT_ONE - fracy); + w[2] = imulFixu(FIX_POINT_ONE - fracx, fracy); + w[3] = imulFixu(fracx, fracy); + } + + //wraps positive (ignoring negative) + tVideoSample t[4]; + { + register size_t o0, o1, o2, o3; + o0 = (((ty) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; + o1 = (((ty + FIX_POINT_ONE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; + o2 = ((tx)& tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (unsigned)(FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + + t[0] = *((tVideoSample*)((u8*)tex->data + (o0 + o2))); + t[1] = *((tVideoSample*)((u8*)tex->data + (o0 + o3))); + t[2] = *((tVideoSample*)((u8*)tex->data + (o1 + o2))); + t[3] = *((tVideoSample*)((u8*)tex->data + (o1 + o3))); + } + + r = (((t[0] & MASK_R) >> SHIFT_R) * w[0]) + + (((t[1] & MASK_R) >> SHIFT_R) * w[1]) + + (((t[2] & MASK_R) >> SHIFT_R) * w[2]) + + (((t[3] & MASK_R) >> SHIFT_R) * w[3]); + + g = (((t[0] & MASK_G) >> SHIFT_G) * w[0]) + + (((t[1] & MASK_G) >> SHIFT_G) * w[1]) + + (((t[2] & MASK_G) >> SHIFT_G) * w[2]) + + (((t[3] & MASK_G) >> SHIFT_G) * w[3]); + + b = ((t[0] & MASK_B) * w[0]) + + ((t[1] & MASK_B) * w[1]) + + ((t[2] & MASK_B) * w[2]) + + ((t[3] & MASK_B) * w[3]); +} + +#endif + +// get Sample bilinear +static REALINLINE void getSample_texture(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sInternalTexture* burning_restrict tex, const tFixPointu tx, const tFixPointu ty +) +{ + + tFixPointu a00, r00, g00, b00; + tFixPointu a01, r01, g01, b01; + tFixPointu a10, r10, g10, b10; + tFixPointu a11, r11, g11, b11; + + size_t o0, o1, o2, o3; + register tVideoSample t00; + + o0 = (((ty)& tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; + o1 = (((ty + FIX_POINT_ONE) & tex->textureYMask) >> FIX_POINT_PRE) << tex->pitchlog2; + o2 = ((tx)& tex->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + o3 = ((tx + FIX_POINT_ONE) & tex->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); + + t00 = *((tVideoSample*)((u8*)tex->data + (o0 + o2))); + a00 = (t00 & MASK_A) >> SHIFT_A; + r00 = (t00 & MASK_R) >> SHIFT_R; + g00 = (t00 & MASK_G) >> SHIFT_G; + b00 = (t00 & MASK_B); + + t00 = *((tVideoSample*)((u8*)tex->data + (o0 + o3))); + a10 = (t00 & MASK_A) >> SHIFT_A; + r10 = (t00 & MASK_R) >> SHIFT_R; + g10 = (t00 & MASK_G) >> SHIFT_G; + b10 = (t00 & MASK_B); + + t00 = *((tVideoSample*)((u8*)tex->data + (o1 + o2))); + a01 = (t00 & MASK_A) >> SHIFT_A; + r01 = (t00 & MASK_R) >> SHIFT_R; + g01 = (t00 & MASK_G) >> SHIFT_G; + b01 = (t00 & MASK_B); + + t00 = *((tVideoSample*)((u8*)tex->data + (o1 + o3))); + a11 = (t00 & MASK_A) >> SHIFT_A; + r11 = (t00 & MASK_R) >> SHIFT_R; + g11 = (t00 & MASK_G) >> SHIFT_G; + b11 = (t00 & MASK_B); + + const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK; + const tFixPointu txFractInv = FIX_POINT_ONE - txFract; + + const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK; + const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract; + + const tFixPointu w00 = imulFixu(txFractInv, tyFractInv); + const tFixPointu w10 = imulFixu(txFract, tyFractInv); + const tFixPointu w01 = imulFixu(txFractInv, tyFract); + const tFixPointu w11 = imulFixu(txFract, tyFract); + + a = (a00 * w00) + + (a01 * w01) + + (a10 * w10) + + (a11 * w11); + + fix_alpha_color_max(a); + + r = (r00 * w00) + + (r01 * w01) + + (r10 * w10) + + (r11 * w11); + + g = (g00 * w00) + + (g01 * w01) + + (g10 * w10) + + (g11 * w11); + + b = (b00 * w00) + + (b01 * w01) + + (b10 * w10) + + (b11 * w11); + +} + +#else // SOFTWARE_DRIVER_2_BILINEAR // get Sample linear == getSample_fixpoint -inline void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty - ) +static REALINLINE void getSample_texture(tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sInternalTexture* burning_restrict t, const tFixPointu tx, const tFixPointu ty +) { - u32 ofs; - - ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + register size_t ofs; + ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); // texel - const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs )); + const tVideoSample t00 = *((tVideoSample*)((u8*)t->data + ofs)); - (tFixPointu &) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); - (tFixPointu &) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); - (tFixPointu &) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); + (tFixPointu &)r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE); + (tFixPointu &)g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G); + (tFixPointu &)b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B); } -inline void getSample_texture ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty - ) +static REALINLINE void getSample_texture(tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sInternalTexture* burning_restrict t, const tFixPointu tx, const tFixPointu ty +) { - u32 ofs; - - ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); + register size_t ofs; + ofs = (((ty + FIX_POINT_ZERO_DOT_FIVE) & t->textureYMask) >> FIX_POINT_PRE) << t->pitchlog2; + ofs += ((tx + FIX_POINT_ZERO_DOT_FIVE) & t->textureXMask) >> (FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY); // texel - const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs )); + const tVideoSample t00 = *((tVideoSample*)((u8*)t->data + ofs)); - (tFixPointu &)a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE); - (tFixPointu &)r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); - (tFixPointu &)g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); - (tFixPointu &)b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); + (tFixPointu &)a = (t00 & MASK_A) >> (SHIFT_A - FIX_POINT_PRE); + fix_alpha_color_max(a); + (tFixPointu &)r = (t00 & MASK_R) >> (SHIFT_R - FIX_POINT_PRE); + (tFixPointu &)g = (t00 & MASK_G) << (FIX_POINT_PRE - SHIFT_G); + (tFixPointu &)b = (t00 & MASK_B) << (FIX_POINT_PRE - SHIFT_B); } -#else +#endif // SOFTWARE_DRIVER_2_BILINEAR -// get sample linear -REALINLINE void getSample_linear ( tFixPointu &r, tFixPointu &g, tFixPointu &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty - ) -{ - u32 ofs; - - ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); - - // texel - tVideoSample t00; - t00 = *((tVideoSample*)( (u8*) t->data + ofs )); - - r = (t00 & MASK_R) >> SHIFT_R; - g = (t00 & MASK_G) >> SHIFT_G; - b = (t00 & MASK_B); -} - -// get Sample bilinear -REALINLINE void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty - ) -{ - - tFixPointu r00,g00,b00; - tFixPointu r01,g01,b01; - tFixPointu r10,g10,b10; - tFixPointu r11,g11,b11; - -#if 0 - getSample_linear ( r00, g00, b00, t, tx,ty ); - getSample_linear ( r10, g10, b10, t, tx + FIX_POINT_ONE,ty ); - getSample_linear ( r01, g01, b01, t, tx,ty + FIX_POINT_ONE ); - getSample_linear ( r11, g11, b11, t, tx + FIX_POINT_ONE,ty + FIX_POINT_ONE ); -#else - u32 o0, o1,o2,o3; - tVideoSample t00; - - o0 = ( ( (ty) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - o1 = ( ( (ty+FIX_POINT_ONE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - o2 = ( (tx) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); - o3 = ( (tx+FIX_POINT_ONE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); - - t00 = *((tVideoSample*)( (u8*) t->data + (o0 | o2 ) )); - r00 = (t00 & MASK_R) >> SHIFT_R; - g00 = (t00 & MASK_G) >> SHIFT_G; - b00 = (t00 & MASK_B); - - t00 = *((tVideoSample*)( (u8*) t->data + (o0 | o3 ) )); - r10 = (t00 & MASK_R) >> SHIFT_R; - g10 = (t00 & MASK_G) >> SHIFT_G; - b10 = (t00 & MASK_B); - - t00 = *((tVideoSample*)( (u8*) t->data + (o1 | o2 ) )); - r01 = (t00 & MASK_R) >> SHIFT_R; - g01 = (t00 & MASK_G) >> SHIFT_G; - b01 = (t00 & MASK_B); - - t00 = *((tVideoSample*)( (u8*) t->data + (o1 | o3 ) )); - r11 = (t00 & MASK_R) >> SHIFT_R; - g11 = (t00 & MASK_G) >> SHIFT_G; - b11 = (t00 & MASK_B); - -#endif - - const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK; - const tFixPointu txFractInv = FIX_POINT_ONE - txFract; - - const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK; - const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract; - - const tFixPointu w00 = imulFixu ( txFractInv, tyFractInv ); - const tFixPointu w10 = imulFixu ( txFract , tyFractInv ); - const tFixPointu w01 = imulFixu ( txFractInv, tyFract ); - const tFixPointu w11 = imulFixu ( txFract , tyFract ); - - r = (r00 * w00 ) + - (r01 * w01 ) + - (r10 * w10 ) + - (r11 * w11 ); - - g = (g00 * w00 ) + - (g01 * w01 ) + - (g10 * w10 ) + - (g11 * w11 ); - - b = (b00 * w00 ) + - (b01 * w01 ) + - (b10 * w10 ) + - (b11 * w11 ); - -} - - -// get sample linear -REALINLINE void getSample_linear ( tFixPointu &a, tFixPointu &r, tFixPointu &g, tFixPointu &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty - ) -{ - u32 ofs; - - ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; - ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); - - // texel - tVideoSample t00; - t00 = *((tVideoSample*)( (u8*) t->data + ofs )); - - a = (t00 & MASK_A) >> SHIFT_A; - r = (t00 & MASK_R) >> SHIFT_R; - g = (t00 & MASK_G) >> SHIFT_G; - b = (t00 & MASK_B); -} - -// get Sample bilinear -REALINLINE void getSample_texture ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty - ) -{ - - tFixPointu a00, r00,g00,b00; - tFixPointu a01, r01,g01,b01; - tFixPointu a10, r10,g10,b10; - tFixPointu a11, r11,g11,b11; - - getSample_linear ( a00, r00, g00, b00, t, tx,ty ); - getSample_linear ( a10, r10, g10, b10, t, tx + FIX_POINT_ONE,ty ); - getSample_linear ( a01, r01, g01, b01, t, tx,ty + FIX_POINT_ONE ); - getSample_linear ( a11, r11, g11, b11, t, tx + FIX_POINT_ONE,ty + FIX_POINT_ONE ); - - const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK; - const tFixPointu txFractInv = FIX_POINT_ONE - txFract; - - const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK; - const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract; - - const tFixPointu w00 = imulFixu ( txFractInv, tyFractInv ); - const tFixPointu w10 = imulFixu ( txFract , tyFractInv ); - const tFixPointu w01 = imulFixu ( txFractInv, tyFract ); - const tFixPointu w11 = imulFixu ( txFract , tyFract ); - - a = (a00 * w00 ) + - (a01 * w01 ) + - (a10 * w10 ) + - (a11 * w11 ); - - r = (r00 * w00 ) + - (r01 * w01 ) + - (r10 * w10 ) + - (r11 * w11 ); - - g = (g00 * w00 ) + - (g01 * w01 ) + - (g10 * w10 ) + - (g11 * w11 ); - - b = (b00 * w00 ) + - (b01 * w01 ) + - (b10 * w10 ) + - (b11 * w11 ); - -} - - -#endif - -// some 2D Defines +// 2D Region closed [x0;x1] struct AbsRectangle { s32 x0; @@ -1075,6 +1193,7 @@ inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRect return dest.x0 < dest.x1 && dest.y0 < dest.y1; } +#if 0 // some 1D defines struct sIntervall { @@ -1088,6 +1207,33 @@ inline s32 intervall_intersect_test( const sIntervall& a, const sIntervall& b) return core::s32_min( a.end, b.end ) - core::s32_max( a.start, b.start ); } +#endif + +// strings +static inline void tiny_strncpy(char* to, const char* from, const size_t count) +{ + for (size_t r = 0; r < count && (*to = *from) != '\0'; ++from, ++to, ++r); + *to = '\0'; +} + +#define tiny_strcpy(a, b) tiny_strncpy(a,b,sizeof(a)-1) + + +// tiny_isequal = !strncmp(a,b,sizeof(a)-1) +static inline int tiny_isequal(const char *s1, const char *s2, size_t n) +{ + do { + if (*s1 != *s2++) return 0; + if (*s1++ == 0) + break; + } while (--n != 0); + return 1; +} + +#define tiny_istoken(a, b) tiny_isequal(a,b,sizeof(a)-1) != 0 +//! Size of a static C-style array. +#define array_size(_arr) ((sizeof(_arr)/sizeof(*_arr))) + } // end namespace irr diff --git a/source/Irrlicht/burning_shader_color.cpp b/source/Irrlicht/burning_shader_color.cpp new file mode 100644 index 00000000..3af52abc --- /dev/null +++ b/source/Irrlicht/burning_shader_color.cpp @@ -0,0 +1,95 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" +#include "IBurningShader.h" + +#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + +namespace irr +{ + +namespace video +{ + +#define burning_shader_class burning_shader_color +#define burning_shader_frag "burning_shader_color_fraq.h" +#include "burning_shader_compile_fragment_default.h" + + +/*! +*/ +void burning_shader_class::OnSetMaterial(const SBurningShaderMaterial& material) +{ + switch (material.org.MaterialType) + { + case EMT_TRANSPARENT_ADD_COLOR: + case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR: + case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR: + //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + + case EMT_TRANSPARENT_ALPHA_CHANNEL: + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: + //? glBlendFunc(GL_ONE,GL_ZERO) or glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + case EMT_TRANSPARENT_REFLECTION_2_LAYER: + + case EMT_TRANSPARENT_VERTEX_ALPHA: + case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: + case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: + RenderPass_ShaderIsTransparent = 1; + AlphaRef = tofix(material.org.MaterialTypeParam, FIXPOINT_COLOR_MAX); + break; + default: + RenderPass_ShaderIsTransparent = 0; + AlphaRef = 0; + break; + } + + if (0 == RenderPass_ShaderIsTransparent) + { + if (material.org.ZBuffer == ECFN_LESSEQUAL) + { + if (material.depth_write) fragmentShader = &burning_shader_class::fragment_depth_less_equal_depth_write_blend_one_zero; + else fragmentShader = &burning_shader_class::fragment_depth_less_equal_no_depth_write_blend_one_zero; + } + else /*if (material.org.ZBuffer == ECFN_DISABLED)*/ + { + //check triangle on w = 1.f instead.. +#ifdef SOFTWARE_DRIVER_2_BILINEAR + if (material.org.TextureLayer[0].BilinearFilter) fragmentShader = &burning_shader_class::fragment_nodepth_perspective_blend_one_zero; + else +#endif + fragmentShader = &burning_shader_class::fragment_nodepth_noperspective_blend_one_zero; + } + } + else + { + if (material.org.ZBuffer == ECFN_LESSEQUAL) + { + if (material.depth_write) fragmentShader = &burning_shader_class::fragment_depth_less_equal_depth_write_blend_src_alpha_one_minus_src_alpha; + else fragmentShader = &burning_shader_class::fragment_depth_less_equal_no_depth_write_blend_src_alpha_one_minus_src_alpha; + } + else /*if (material.org.ZBuffer == ECFN_DISABLED)*/ + { + //check triangle on w = 1.f instead.. +#ifdef SOFTWARE_DRIVER_2_BILINEAR + if (material.org.TextureLayer[0].BilinearFilter) fragmentShader = &burning_shader_class::fragment_nodepth_perspective_blend_src_alpha_one_minus_src_alpha; + else +#endif + fragmentShader = &burning_shader_class::fragment_nodepth_noperspective_blend_src_alpha_one_minus_src_alpha; + } + } + +} + + + +} // end namespace video +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ + diff --git a/source/Irrlicht/burning_shader_color_fraq.h b/source/Irrlicht/burning_shader_color_fraq.h new file mode 100644 index 00000000..f9efae2d --- /dev/null +++ b/source/Irrlicht/burning_shader_color_fraq.h @@ -0,0 +1,24 @@ +// pixelshader +#ifdef IPOL_C0 + +#ifdef IPOL_A0 +vec4_to_fix(a0, r0, g0, b0, line.c[0][0], inversew); +if (a0 > AlphaRef) +{ + color_to_fix(r1, g1, b1, dst[i]); + + fix_color_norm(a0); + r0 = r1 + imulFix(a0, r0 - r1); + g0 = g1 + imulFix(a0, g0 - g1); + b0 = b1 + imulFix(a0, b0 - b1); + dst[i] = fix_to_sample(r0, g0, b0); +} +#else +vec4_to_fix(r0, g0, b0, line.c[0][0], inversew); +dst[i] = fix_to_sample(r0, g0, b0); +#endif + +#else +dst[i] = PrimitiveColor; +#endif + diff --git a/source/Irrlicht/burning_shader_compile_fragment_default.h b/source/Irrlicht/burning_shader_compile_fragment_default.h new file mode 100644 index 00000000..f28ab70d --- /dev/null +++ b/source/Irrlicht/burning_shader_compile_fragment_default.h @@ -0,0 +1,164 @@ + + +class burning_shader_class : public IBurningShader +{ +public: + + //! constructor + burning_shader_class(CBurningVideoDriver* driver); + + //! draws an indexed triangle list + virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_; + virtual bool canWireFrame() { return true; } + + virtual void OnSetMaterial(const SBurningShaderMaterial& material) _IRR_OVERRIDE_; + +private: + + // fragment shader + typedef void (burning_shader_class::*tFragmentShader) (); + void fragment_depth_less_equal_depth_write_blend_one_zero(); + void fragment_depth_less_equal_no_depth_write_blend_one_zero(); + void fragment_nodepth_perspective_blend_one_zero(); + void fragment_nodepth_noperspective_blend_one_zero(); // 2D Gradient + + void fragment_depth_less_equal_depth_write_blend_src_alpha_one_minus_src_alpha(); + void fragment_depth_less_equal_no_depth_write_blend_src_alpha_one_minus_src_alpha(); + void fragment_nodepth_perspective_blend_src_alpha_one_minus_src_alpha(); + void fragment_nodepth_noperspective_blend_src_alpha_one_minus_src_alpha(); + + + tFragmentShader fragmentShader; + +}; + + +//! constructor +burning_shader_class::burning_shader_color(CBurningVideoDriver* driver) + : IBurningShader(driver) +{ +#ifdef _DEBUG + setDebugName(burning_stringify(burning_shader_class) ); +#endif + + fragmentShader = &burning_shader_class::fragment_depth_less_equal_depth_write_blend_one_zero; + +} + + +IBurningShader* burning_create(burning_shader_class)(CBurningVideoDriver* driver) +{ + return new burning_shader_class(driver); +} + + + +// compile flag for this triangle +#include "burning_shader_compile_start.h" +#define SUBTEXEL +#define IPOL_W +#define IPOL_C0 +#define USE_ZBUFFER +#define CMP_W +#include "burning_shader_compile_triangle.h" + +// compile flag for this scanline fragment +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_nodepth_noperspective_blend_one_zero +#define SUBTEXEL +#define IPOL_C0 +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_nodepth_perspective_blend_one_zero +#define SUBTEXEL +#define INVERSE_W +#define IPOL_W +#define IPOL_C0 +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_depth_less_equal_no_depth_write_blend_one_zero +#define SUBTEXEL +#define INVERSE_W +#define IPOL_W +#define IPOL_C0 +#define USE_ZBUFFER +#define CMP_W +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_depth_less_equal_depth_write_blend_one_zero +#define SUBTEXEL +#define INVERSE_W +#define IPOL_W +#define IPOL_C0 +#define USE_ZBUFFER +#define CMP_W +#define WRITE_W +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + + +// compile flag for this scanline fragment +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_nodepth_noperspective_blend_src_alpha_one_minus_src_alpha +#define SUBTEXEL +#define IPOL_C0 +#define IPOL_A0 +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_nodepth_perspective_blend_src_alpha_one_minus_src_alpha +#define SUBTEXEL +#define INVERSE_W +#define IPOL_W +#define IPOL_C0 +#define IPOL_A0 +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_depth_less_equal_no_depth_write_blend_src_alpha_one_minus_src_alpha +#define SUBTEXEL +#define INVERSE_W +#define IPOL_W +#define IPOL_C0 +#define IPOL_A0 +#define USE_ZBUFFER +#define CMP_W +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" + +#include "burning_shader_compile_start.h" +#define burning_shader_fragment fragment_depth_less_equal_depth_write_blend_src_alpha_one_minus_src_alpha +#define SUBTEXEL +#define INVERSE_W +#define IPOL_W +#define IPOL_C0 +#define IPOL_A0 +#define USE_ZBUFFER +#define CMP_W +#define WRITE_W +#define INVERSE_W_RANGE FIX_POINT_F32_MUL*COLOR_MAX +#include "burning_shader_compile_fragment_start.h" +#include burning_shader_frag +#include "burning_shader_compile_fragment_end.h" diff --git a/source/Irrlicht/burning_shader_compile_fragment_end.h b/source/Irrlicht/burning_shader_compile_fragment_end.h new file mode 100644 index 00000000..8e4719e7 --- /dev/null +++ b/source/Irrlicht/burning_shader_compile_fragment_end.h @@ -0,0 +1,20 @@ + } + +#ifdef IPOL_Z + line.z[0] += slopeZ; +#endif +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1]; +#endif + } + +} diff --git a/source/Irrlicht/burning_shader_compile_fragment_start.h b/source/Irrlicht/burning_shader_compile_fragment_start.h new file mode 100644 index 00000000..64a84633 --- /dev/null +++ b/source/Irrlicht/burning_shader_compile_fragment_start.h @@ -0,0 +1,119 @@ +#include "burning_shader_compile_verify.h" + +/*! +*/ +void burning_shader_class::burning_shader_fragment() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = fill_convention_left(line.x[0]); + xEnd = fill_convention_right(line.x[1]); + + dx = xEnd - xStart; + if (dx < 0) + return; + + // slopes + const f32 invDeltaX = reciprocal_zero2(line.x[1] - line.x[0]); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ((f32)xStart) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + SOFTWARE_DRIVER_2_CLIPCHECK; + dst = (tVideoSample*)RenderTarget->getData() + (line.y * RenderTarget->getDimension().Width) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*)DepthBuffer->lock() + (line.y * RenderTarget->getDimension().Width) + xStart; +#endif + + + f32 inversew = INVERSE_W_RANGE; + +#ifdef IPOL_C0 + tFixPoint r0, g0, b0; +#endif + +#ifdef IPOL_A0 + tFixPoint a0; + tFixPoint r1, g1, b1; +#endif + + for (s32 i = 0; i <= dx; ++i) + { + if ((0 == EdgeTestPass) & i) break; + +#ifdef CMP_Z + if (line.z[0] < z[i]) +#endif +#ifdef CMP_W + if (line.w[0] >= z[i]) +#endif + { +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + /* Pixel Shader here */ +#ifdef INVERSE_W + inversew = (INVERSE_W_RANGE) / line.w[0]; /* fix_inverse32(line.w[0]);*/ +#endif diff --git a/source/Irrlicht/burning_shader_compile_start.h b/source/Irrlicht/burning_shader_compile_start.h new file mode 100644 index 00000000..0d8a5f77 --- /dev/null +++ b/source/Irrlicht/burning_shader_compile_start.h @@ -0,0 +1,24 @@ +// undef compile flag for this file +#undef USE_ZBUFFER +#undef IPOL_Z +#undef CMP_Z +#undef WRITE_Z + +#undef IPOL_W +#undef CMP_W +#undef WRITE_W + +#undef SUBTEXEL +#undef INVERSE_W + +#undef IPOL_C0 +#undef IPOL_A0 +#undef IPOL_T0 +#undef IPOL_T1 +#undef IPOL_T2 +#undef IPOL_L0 + +#undef burning_shader_fragment +#undef ipol_test + +#undef INVERSE_W_RANGE diff --git a/source/Irrlicht/burning_shader_compile_triangle.h b/source/Irrlicht/burning_shader_compile_triangle.h new file mode 100644 index 00000000..aa588581 --- /dev/null +++ b/source/Irrlicht/burning_shader_compile_triangle.h @@ -0,0 +1,368 @@ +#include "burning_shader_compile_verify.h" + + +void burning_shader_class::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) +{ + // sort on height, y + if (a->Pos.y > b->Pos.y) swapVertexPointer(&a, &b); + if (a->Pos.y > c->Pos.y) swapVertexPointer(&a, &c); + if (b->Pos.y > c->Pos.y) swapVertexPointer(&b, &c); + + const f32 ca = c->Pos.y - a->Pos.y; + const f32 ba = b->Pos.y - a->Pos.y; + const f32 cb = c->Pos.y - b->Pos.y; + + // calculate delta y of the edges + scan.invDeltaY[0] = reciprocal_edge(ca); + scan.invDeltaY[1] = reciprocal_edge(ba); + scan.invDeltaY[2] = reciprocal_edge(cb); + + if (F32_LOWER_EQUAL_0(scan.invDeltaY[0])) + return; + + // find if the major edge is left or right aligned + f32 temp[4]; + + temp[0] = a->Pos.x - c->Pos.x; + temp[1] = -ca; + temp[2] = b->Pos.x - a->Pos.x; + temp[3] = ba; + + scan.left = (temp[0] * temp[3] - temp[1] * temp[2]) > 0.f ? 0 : 1; + scan.right = 1 - scan.left; + + // calculate slopes for the major edge + scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; + scan.x[0] = a->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; + scan.z[0] = a->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; + scan.w[0] = a->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; + scan.t[0][0] = a->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; + scan.t[1][0] = a->Tex[1]; +#endif + + // top left fill convention y run + s32 yStart; + s32 yEnd; + +#ifdef SUBTEXEL + f32 subPixel; +#endif + + + // rasterize upper sub-triangle + if (F32_GREATER_0(scan.invDeltaY[1])) + { + // calculate slopes for top edge + scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; + scan.x[1] = a->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; + scan.z[1] = a->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; + scan.w[1] = a->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; + scan.t[0][1] = a->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; + scan.t[1][1] = a->Tex[1]; +#endif + + // apply top-left fill convention, top part + yStart = fill_convention_left(a->Pos.y); + yEnd = fill_convention_right(b->Pos.y); + +#ifdef SUBTEXEL + subPixel = ((f32)yStart) - a->Pos.y; + + // correct to pixel center + scan.x[0] += scan.slopeX[0] * subPixel; + scan.x[1] += scan.slopeX[1] * subPixel; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0] * subPixel; + scan.z[1] += scan.slopeZ[1] * subPixel; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0] * subPixel; + scan.w[1] += scan.slopeW[1] * subPixel; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0] * subPixel; + scan.t[0][1] += scan.slopeT[0][1] * subPixel; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0] * subPixel; + scan.t[1][1] += scan.slopeT[1][1] * subPixel; +#endif + +#endif + + // rasterize the edge scanlines + for (line.y = yStart; line.y <= yEnd; ++line.y) + { + line.x[scan.left] = scan.x[0]; + line.x[scan.right] = scan.x[1]; + +#ifdef IPOL_Z + line.z[scan.left] = scan.z[0]; + line.z[scan.right] = scan.z[1]; +#endif + +#ifdef IPOL_W + line.w[scan.left] = scan.w[0]; + line.w[scan.right] = scan.w[1]; +#endif + +#ifdef IPOL_C0 + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; +#endif + +#ifdef IPOL_T0 + line.t[0][scan.left] = scan.t[0][0]; + line.t[0][scan.right] = scan.t[0][1]; +#endif + +#ifdef IPOL_T1 + line.t[1][scan.left] = scan.t[1][0]; + line.t[1][scan.right] = scan.t[1][1]; +#endif + + // render a scanline + (this->*fragmentShader) (); + if (EdgeTestPass & edge_test_first_line) break; + + scan.x[0] += scan.slopeX[0]; + scan.x[1] += scan.slopeX[1]; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0]; + scan.z[1] += scan.slopeZ[1]; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0]; + scan.w[1] += scan.slopeW[1]; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0]; + scan.t[0][1] += scan.slopeT[0][1]; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0]; + scan.t[1][1] += scan.slopeT[1][1]; +#endif + } + } + + // rasterize lower sub-triangle + if (F32_GREATER_0(scan.invDeltaY[2])) + { + // advance to middle point + if (F32_GREATER_0(scan.invDeltaY[1])) + { + temp[0] = b->Pos.y - a->Pos.y; // dy + + scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; +#ifdef IPOL_Z + scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; +#endif +#ifdef IPOL_W + scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; +#endif +#ifdef IPOL_C0 + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; +#endif +#ifdef IPOL_T0 + scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; +#endif +#ifdef IPOL_T1 + scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; +#endif + + } + + // calculate slopes for bottom edge + scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; + scan.x[1] = b->Pos.x; + +#ifdef IPOL_Z + scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; + scan.z[1] = b->Pos.z; +#endif + +#ifdef IPOL_W + scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; + scan.w[1] = b->Pos.w; +#endif + +#ifdef IPOL_C0 + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; +#endif + +#ifdef IPOL_T0 + scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; + scan.t[0][1] = b->Tex[0]; +#endif + +#ifdef IPOL_T1 + scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; + scan.t[1][1] = b->Tex[1]; +#endif + + // apply top-left fill convention, top part + yStart = fill_convention_left(b->Pos.y); + yEnd = fill_convention_right(c->Pos.y); + +#ifdef SUBTEXEL + + subPixel = ((f32)yStart) - b->Pos.y; + + // correct to pixel center + scan.x[0] += scan.slopeX[0] * subPixel; + scan.x[1] += scan.slopeX[1] * subPixel; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0] * subPixel; + scan.z[1] += scan.slopeZ[1] * subPixel; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0] * subPixel; + scan.w[1] += scan.slopeW[1] * subPixel; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0] * subPixel; + scan.t[0][1] += scan.slopeT[0][1] * subPixel; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0] * subPixel; + scan.t[1][1] += scan.slopeT[1][1] * subPixel; +#endif + +#endif + + // rasterize the edge scanlines + for (line.y = yStart; line.y <= yEnd; ++line.y) + { + line.x[scan.left] = scan.x[0]; + line.x[scan.right] = scan.x[1]; + +#ifdef IPOL_Z + line.z[scan.left] = scan.z[0]; + line.z[scan.right] = scan.z[1]; +#endif + +#ifdef IPOL_W + line.w[scan.left] = scan.w[0]; + line.w[scan.right] = scan.w[1]; +#endif + +#ifdef IPOL_C0 + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; +#endif + +#ifdef IPOL_T0 + line.t[0][scan.left] = scan.t[0][0]; + line.t[0][scan.right] = scan.t[0][1]; +#endif + +#ifdef IPOL_T1 + line.t[1][scan.left] = scan.t[1][0]; + line.t[1][scan.right] = scan.t[1][1]; +#endif + + // render a scanline + (this->*fragmentShader) (); + if (EdgeTestPass & edge_test_first_line) break; + + scan.x[0] += scan.slopeX[0]; + scan.x[1] += scan.slopeX[1]; + +#ifdef IPOL_Z + scan.z[0] += scan.slopeZ[0]; + scan.z[1] += scan.slopeZ[1]; +#endif + +#ifdef IPOL_W + scan.w[0] += scan.slopeW[0]; + scan.w[1] += scan.slopeW[1]; +#endif + +#ifdef IPOL_C0 + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; +#endif + +#ifdef IPOL_T0 + scan.t[0][0] += scan.slopeT[0][0]; + scan.t[0][1] += scan.slopeT[0][1]; +#endif + +#ifdef IPOL_T1 + scan.t[1][0] += scan.slopeT[1][0]; + scan.t[1][1] += scan.slopeT[1][1]; +#endif + + } + } + +} diff --git a/source/Irrlicht/burning_shader_compile_verify.h b/source/Irrlicht/burning_shader_compile_verify.h new file mode 100644 index 00000000..c31c5754 --- /dev/null +++ b/source/Irrlicht/burning_shader_compile_verify.h @@ -0,0 +1,43 @@ +// apply global override +#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT +#undef INVERSE_W +#endif + +#ifndef SOFTWARE_DRIVER_2_SUBTEXEL +#undef SUBTEXEL +#endif + +#if BURNING_MATERIAL_MAX_COLORS < 1 +#undef IPOL_C0 +#undef IPOL_A0 +#endif + +#if BURNING_MATERIAL_MAX_LIGHT_TANGENT < 1 +#undef IPOL_L0 +#endif + + +// 1/x * FIX_POINT +#if !defined(INVERSE_W_RANGE) + #define INVERSE_W_RANGE FIX_POINT_F32_MUL +#endif + +#if defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) || defined ( SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT ) +#else + +#ifdef IPOL_W + #undef IPOL_W + #define IPOL_Z +#endif + +#ifdef CMP_W + #undef CMP_W + #define CMP_Z +#endif + +#ifdef WRITE_W + #undef WRITE_W + #define WRITE_Z +#endif + +#endif diff --git a/tests/media/Burning's Video-2dmatFilter.png b/tests/media/Burning's Video-2dmatFilter.png index af1a9e0b..bdd17cd1 100644 Binary files a/tests/media/Burning's Video-2dmatFilter.png and b/tests/media/Burning's Video-2dmatFilter.png differ diff --git a/tests/media/Burning's Video-b3dAnimation.png b/tests/media/Burning's Video-b3dAnimation.png index 52feb695..d16e689a 100644 Binary files a/tests/media/Burning's Video-b3dAnimation.png and b/tests/media/Burning's Video-b3dAnimation.png differ diff --git a/tests/media/Burning's Video-b3dJointPosition.png b/tests/media/Burning's Video-b3dJointPosition.png index fc33f23c..b669f8f8 100644 Binary files a/tests/media/Burning's Video-b3dJointPosition.png and b/tests/media/Burning's Video-b3dJointPosition.png differ diff --git a/tests/media/Burning's Video-billboard.png b/tests/media/Burning's Video-billboard.png index 9892076a..59f36c1d 100644 Binary files a/tests/media/Burning's Video-billboard.png and b/tests/media/Burning's Video-billboard.png differ diff --git a/tests/media/Burning's Video-billboardOrientation.png b/tests/media/Burning's Video-billboardOrientation.png index fb99360f..2805aed8 100644 Binary files a/tests/media/Burning's Video-billboardOrientation.png and b/tests/media/Burning's Video-billboardOrientation.png differ diff --git a/tests/media/Burning's Video-draw2DImage4cFilter.png b/tests/media/Burning's Video-draw2DImage4cFilter.png index a245525b..0a98b70e 100644 Binary files a/tests/media/Burning's Video-draw2DImage4cFilter.png and b/tests/media/Burning's Video-draw2DImage4cFilter.png differ diff --git a/tests/media/Burning's Video-drawPixel.png b/tests/media/Burning's Video-drawPixel.png index b7539cf8..08288a85 100644 Binary files a/tests/media/Burning's Video-drawPixel.png and b/tests/media/Burning's Video-drawPixel.png differ diff --git a/tests/media/Burning's Video-drawVPL_e.png b/tests/media/Burning's Video-drawVPL_e.png index a3f51623..bc839920 100644 Binary files a/tests/media/Burning's Video-drawVPL_e.png and b/tests/media/Burning's Video-drawVPL_e.png differ diff --git a/tests/media/Burning's Video-drawVPL_g.png b/tests/media/Burning's Video-drawVPL_g.png index 113dc35c..438941d1 100644 Binary files a/tests/media/Burning's Video-drawVPL_g.png and b/tests/media/Burning's Video-drawVPL_g.png differ diff --git a/tests/media/Burning's Video-drawVPL_h.png b/tests/media/Burning's Video-drawVPL_h.png index d1b1f8dc..8ed44557 100644 Binary files a/tests/media/Burning's Video-drawVPL_h.png and b/tests/media/Burning's Video-drawVPL_h.png differ diff --git a/tests/media/Burning's Video-drawVPL_i.png b/tests/media/Burning's Video-drawVPL_i.png index be45d0f1..e344631b 100644 Binary files a/tests/media/Burning's Video-drawVPL_i.png and b/tests/media/Burning's Video-drawVPL_i.png differ diff --git a/tests/media/Burning's Video-flyCircleAnimator.png b/tests/media/Burning's Video-flyCircleAnimator.png index fbc2ecad..218af2a7 100644 Binary files a/tests/media/Burning's Video-flyCircleAnimator.png and b/tests/media/Burning's Video-flyCircleAnimator.png differ diff --git a/tests/media/Burning's Video-lightType.png b/tests/media/Burning's Video-lightType.png index a472e92d..446cc6dd 100644 Binary files a/tests/media/Burning's Video-lightType.png and b/tests/media/Burning's Video-lightType.png differ diff --git a/tests/media/Burning's Video-loadScene.png b/tests/media/Burning's Video-loadScene.png index b68c9144..00e08b11 100644 Binary files a/tests/media/Burning's Video-loadScene.png and b/tests/media/Burning's Video-loadScene.png differ diff --git a/tests/media/Burning's Video-md2Normals.png b/tests/media/Burning's Video-md2Normals.png index 709b97e9..302b9b3d 100644 Binary files a/tests/media/Burning's Video-md2Normals.png and b/tests/media/Burning's Video-md2Normals.png differ diff --git a/tests/media/Burning's Video-multiTexture.png b/tests/media/Burning's Video-multiTexture.png index a5666b7c..338f257e 100644 Binary files a/tests/media/Burning's Video-multiTexture.png and b/tests/media/Burning's Video-multiTexture.png differ diff --git a/tests/media/Burning's Video-orthoCam.png b/tests/media/Burning's Video-orthoCam.png index 5e35ddde..41a96b8b 100644 Binary files a/tests/media/Burning's Video-orthoCam.png and b/tests/media/Burning's Video-orthoCam.png differ diff --git a/tests/media/Burning's Video-planeMatrix-scaledClip.png b/tests/media/Burning's Video-planeMatrix-scaledClip.png index 14f6dc35..7c93216e 100644 Binary files a/tests/media/Burning's Video-planeMatrix-scaledClip.png and b/tests/media/Burning's Video-planeMatrix-scaledClip.png differ diff --git a/tests/media/Burning's Video-renderMipmap.png b/tests/media/Burning's Video-renderMipmap.png index 06fc37f0..d2d53210 100644 Binary files a/tests/media/Burning's Video-renderMipmap.png and b/tests/media/Burning's Video-renderMipmap.png differ diff --git a/tests/media/Burning's Video-stencilSelfShadow.png b/tests/media/Burning's Video-stencilSelfShadow.png index dcdb6087..2bd6eecf 100644 Binary files a/tests/media/Burning's Video-stencilSelfShadow.png and b/tests/media/Burning's Video-stencilSelfShadow.png differ diff --git a/tests/media/Burning's Video-stencilShadow.png b/tests/media/Burning's Video-stencilShadow.png index 60f31cdc..77c53fd6 100644 Binary files a/tests/media/Burning's Video-stencilShadow.png and b/tests/media/Burning's Video-stencilShadow.png differ diff --git a/tests/media/Burning's Video-terrainGap.png b/tests/media/Burning's Video-terrainGap.png index 835a946c..db125626 100644 Binary files a/tests/media/Burning's Video-terrainGap.png and b/tests/media/Burning's Video-terrainGap.png differ diff --git a/tests/media/Burning's Video-terrainSceneNode-1.png b/tests/media/Burning's Video-terrainSceneNode-1.png index ba53a288..e7a89935 100644 Binary files a/tests/media/Burning's Video-terrainSceneNode-1.png and b/tests/media/Burning's Video-terrainSceneNode-1.png differ diff --git a/tests/media/Burning's Video-terrainSceneNode-2.png b/tests/media/Burning's Video-terrainSceneNode-2.png index 4c92f024..1c7538ab 100644 Binary files a/tests/media/Burning's Video-terrainSceneNode-2.png and b/tests/media/Burning's Video-terrainSceneNode-2.png differ diff --git a/tests/media/Burning's Video-testGeometryCreator.png b/tests/media/Burning's Video-testGeometryCreator.png index 5ea41667..6904bde5 100644 Binary files a/tests/media/Burning's Video-testGeometryCreator.png and b/tests/media/Burning's Video-testGeometryCreator.png differ diff --git a/tests/media/Burning's Video-testTerrainMesh.png b/tests/media/Burning's Video-testTerrainMesh.png index 53d0aa56..ffbc74c6 100644 Binary files a/tests/media/Burning's Video-testTerrainMesh.png and b/tests/media/Burning's Video-testTerrainMesh.png differ diff --git a/tests/media/Burning's Video-textureMatrix.png b/tests/media/Burning's Video-textureMatrix.png new file mode 100644 index 00000000..26afc9e7 Binary files /dev/null and b/tests/media/Burning's Video-textureMatrix.png differ diff --git a/tests/media/Burning's Video-textureMatrix2.png b/tests/media/Burning's Video-textureMatrix2.png new file mode 100644 index 00000000..26afc9e7 Binary files /dev/null and b/tests/media/Burning's Video-textureMatrix2.png differ diff --git a/tests/media/Burning's Video-textureMatrixInMixedScenes.png b/tests/media/Burning's Video-textureMatrixInMixedScenes.png new file mode 100644 index 00000000..e5cdeb2c Binary files /dev/null and b/tests/media/Burning's Video-textureMatrixInMixedScenes.png differ diff --git a/tests/media/Burning's Video-textureRenderStates.png b/tests/media/Burning's Video-textureRenderStates.png index 98282fa1..92c29fc7 100644 Binary files a/tests/media/Burning's Video-textureRenderStates.png and b/tests/media/Burning's Video-textureRenderStates.png differ diff --git a/tests/media/Burning's Video-transparentAddColor.png b/tests/media/Burning's Video-transparentAddColor.png index 87261e59..59374484 100644 Binary files a/tests/media/Burning's Video-transparentAddColor.png and b/tests/media/Burning's Video-transparentAddColor.png differ diff --git a/tests/media/Burning's Video-transparentAlphaChannel.png b/tests/media/Burning's Video-transparentAlphaChannel.png index 0986ed44..358455d3 100644 Binary files a/tests/media/Burning's Video-transparentAlphaChannel.png and b/tests/media/Burning's Video-transparentAlphaChannel.png differ diff --git a/tests/media/Burning's Video-transparentAlphaChannelRef.png b/tests/media/Burning's Video-transparentAlphaChannelRef.png index 09ff338b..21844ab2 100644 Binary files a/tests/media/Burning's Video-transparentAlphaChannelRef.png and b/tests/media/Burning's Video-transparentAlphaChannelRef.png differ diff --git a/tests/media/Burning's Video-transparentReflection2Layer.png b/tests/media/Burning's Video-transparentReflection2Layer.png index 7acfba64..926d189a 100644 Binary files a/tests/media/Burning's Video-transparentReflection2Layer.png and b/tests/media/Burning's Video-transparentReflection2Layer.png differ diff --git a/tests/media/Burning's Video-transparentVertexAlpha.png b/tests/media/Burning's Video-transparentVertexAlpha.png index b8f268c6..aef6dbd7 100644 Binary files a/tests/media/Burning's Video-transparentVertexAlpha.png and b/tests/media/Burning's Video-transparentVertexAlpha.png differ diff --git a/tests/media/Burning's Video-transparentVertexAlphaChannelMore.png b/tests/media/Burning's Video-transparentVertexAlphaChannelMore.png index 4dfaff0c..666b8145 100644 Binary files a/tests/media/Burning's Video-transparentVertexAlphaChannelMore.png and b/tests/media/Burning's Video-transparentVertexAlphaChannelMore.png differ diff --git a/tests/media/Burning's Video-viewPortText.png b/tests/media/Burning's Video-viewPortText.png index 7c9f7813..56e30650 100644 Binary files a/tests/media/Burning's Video-viewPortText.png and b/tests/media/Burning's Video-viewPortText.png differ diff --git a/tests/media/Burning's Video-writeImageToFile.png b/tests/media/Burning's Video-writeImageToFile.png new file mode 100644 index 00000000..08288a85 Binary files /dev/null and b/tests/media/Burning's Video-writeImageToFile.png differ diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 673e1c4d..9158849d 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 72 tests of 72 passed. -Compiled as DEBUG -Test suite pass at GMT Mon Feb 10 14:59:56 2020 +Compiled as RELEASE +Test suite pass at GMT Sun Feb 23 02:59:02 2020