// 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 burning_namespace_start class CTRTextureWire2 : public IBurningShader { public: //! constructor CTRTextureWire2(CBurningVideoDriver* driver); virtual void OnSetMaterial(const SBurningShaderMaterial& material) 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 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: void renderLine(const s4DVertex* a, const s4DVertex* b) const; int renderZero; int depth_pass; int depth_write; }; //! constructor CTRTextureWire2::CTRTextureWire2(CBurningVideoDriver* driver) : IBurningShader(driver, EMT_SOLID) { #ifdef _DEBUG setDebugName("CTRTextureWire2"); #endif renderZero = 0; depth_pass = 1; depth_write = 0; } void CTRTextureWire2::OnSetMaterial(const SBurningShaderMaterial& material) { depth_pass = material.depth_test == 0; depth_write = material.depth_write; } /*! 2d line */ void CTRTextureWire2::renderLine(const s4DVertex* a, const s4DVertex* b) const { const int pitch0 = RenderTarget->getDimension().Width << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY; #ifdef USE_ZBUFFER const int pitch1 = RenderTarget->getDimension().Width * sizeof(fp24); #endif //todo: fill_convention_none! 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; int c; int m; int d = 0; int run; tVideoSample* dst; #ifdef USE_ZBUFFER fp24* z; #endif int xInc0 = 1 << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY; int yInc0 = pitch0; #ifdef USE_ZBUFFER int xInc1 = sizeof(fp24); int yInc1 = pitch1; #endif if (dx < 0) { xInc0 = -xInc0; #ifdef USE_ZBUFFER xInc1 = -4; #endif dx = -dx; } if (dy > dx) { //swap 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) { if (!renderZero) return; dx = 1; } SOFTWARE_DRIVER_2_CLIPCHECK_WIRE; dst = (tVideoSample*)((u8*)RenderTarget->getData() + (aposy * pitch0) + (aposx << SOFTWARE_DRIVER_2_RENDERTARGET_GRANULARITY)); #ifdef USE_ZBUFFER z = (fp24*)((u8*)DepthBuffer->lock() + (aposy * pitch1) + (aposx << 2)); #endif c = dx << 1; m = dy << 1; // slopes const f32 invDeltaX = fill_step_x((f32)dx); #ifdef IPOL_Z 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) * 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) { #ifdef CMP_Z if (*z >= dataZ) #endif #ifdef CMP_W if (depth_pass || dataW >= *z) #endif { #ifdef WRITE_Z *z = dataZ; #endif #ifdef WRITE_W if (depth_write) *z = dataW; #endif #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 CMP_Z z = (fp24*)((u8*)z + xInc1); #endif #ifdef CMP_W z = (fp24*)((u8*)z + xInc1); #endif d += m; if (d > dx) { dst = (tVideoSample*)((u8*)dst + yInc0); // y += yInc #ifdef CMP_Z z = (fp24*)((u8*)z + yInc1); #endif #ifdef CMP_W z = (fp24*)((u8*)z + yInc1); #endif d -= c; } run -= 1; #ifdef IPOL_Z dataZ += slopeZ; #endif #ifdef IPOL_W dataW += slopeW; #endif #ifdef IPOL_C0 C += slopeC; #endif } } 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); if (F32_A_GREATER_B(a->Pos.y, b->Pos.y)) swapVertexPointer(&a, &b); renderLine(a, b); renderLine(b, c); renderLine(a, c); } void CTRTextureWire2::drawLine(const s4DVertex* a, const s4DVertex* b) { // query access to TexMaps // sort on height, y 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) { renderZero = 1; renderLine(a, a); renderZero = 0; } } burning_namespace_end #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ burning_namespace_start //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureGouraudWire2(CBurningVideoDriver* driver) { //ETR_TEXTURE_GOURAUD_WIRE #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureWire2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } burning_namespace_end