diff --git a/Engine/source/gfx/gfxDrawUtil.cpp b/Engine/source/gfx/gfxDrawUtil.cpp index 1dd9f5fca..a683c56f7 100644 --- a/Engine/source/gfx/gfxDrawUtil.cpp +++ b/Engine/source/gfx/gfxDrawUtil.cpp @@ -34,7 +34,7 @@ #include "gfx/gfxPrimitiveBuffer.h" #include "gfx/primBuilder.h" #include "gfx/gfxDebugEvent.h" - +#include "materials/shaderData.h" #include "math/mPolyhedron.impl.h" @@ -45,7 +45,7 @@ GFXDrawUtil::GFXDrawUtil( GFXDevice * d) mTextAnchorColor.set(0xFF, 0xFF, 0xFF, 0xFF); mFontRenderBatcher = new FontRenderBatcher(); - _setupStateBlocks(); + _setupStateBlocks(); } GFXDrawUtil::~GFXDrawUtil() @@ -90,6 +90,33 @@ void GFXDrawUtil::_setupStateBlocks() rectFill.setZReadWrite(false); rectFill.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); mRectFillSB = mDevice->createStateBlock(rectFill); + + // Find ShaderData + ShaderData* shaderData; + mRoundRectangleShader = Sim::findObject("RoundedRectangleGUI", shaderData) ? shaderData->getShader() : NULL; + if (!mRoundRectangleShader) + { + Con::errorf("GFXDrawUtil - could not find Rounded Rectangle shader"); + } + // Create ShaderConstBuffer and Handles + mRoundRectangleShaderConsts = mRoundRectangleShader->allocConstBuffer(); + + mCircleShader = Sim::findObject("CircularGUI", shaderData) ? shaderData->getShader() : NULL; + if (!mCircleShader) + { + Con::errorf("GFXDrawUtil - could not find circle shader"); + } + // Create ShaderConstBuffer and Handles + mCircleShaderConsts = mCircleShader->allocConstBuffer(); + + mThickLineShader = Sim::findObject("ThickLineGUI", shaderData) ? shaderData->getShader() : NULL; + if (!mThickLineShader) + { + Con::errorf("GFXDrawUtil - could not find Thick line shader"); + } + // Create ShaderConstBuffer and Handles + mThickLineShaderConsts = mThickLineShader->allocConstBuffer(); + } //----------------------------------------------------------------------------- @@ -118,13 +145,13 @@ void GFXDrawUtil::setTextAnchorColor( const ColorI &ancColor ) //----------------------------------------------------------------------------- // Draw Text //----------------------------------------------------------------------------- -U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, +U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, const ColorI *colorTable, const U32 maxColorIndex, F32 rot ) { return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot ); } -U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, +U32 GFXDrawUtil::drawText( GFont *font, const Point2I &ptDraw, const UTF8 *in_string, const ColorI *colorTable, const U32 maxColorIndex, F32 rot ) { return drawTextN( font, ptDraw, in_string, dStrlen(in_string), colorTable, maxColorIndex, rot ); @@ -154,7 +181,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF8 *in_s return drawTextN( font, ptDraw, ubuf, n, colorTable, maxColorIndex, rot ); } -U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, +U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_string, U32 n, const ColorI *colorTable, const U32 maxColorIndex, F32 rot ) { // return on zero length strings @@ -178,11 +205,11 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ S32 ptX = 0; - // Queue everything for render. + // Queue everything for render. mFontRenderBatcher->init(font, n); U32 i; - UTF16 c; + UTF16 c; for (i = 0, c = in_string[i]; i < n && in_string[i]; i++, c = in_string[i]) { switch(c) @@ -193,25 +220,25 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ case 14: { // Color code - if (colorTable) + if (colorTable) { - static U8 remap[15] = - { + static U8 remap[15] = + { 0x0, // 0 special null terminator 0x0, // 1 ascii start-of-heading?? - 0x1, - 0x2, - 0x3, - 0x4, - 0x5, - 0x6, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, 0x0, // 8 special backspace 0x0, // 9 special tab 0x0, // a special \n - 0x7, + 0x7, 0x8, 0x0, // a special \r - 0x9 + 0x9 }; U8 remapped = remap[c]; @@ -256,7 +283,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ } // Tab character - case dT('\t'): + case dT('\t'): { if ( tabci == NULL ) tabci = &(font->getCharInfo( dT(' ') )); @@ -272,7 +299,7 @@ U32 GFXDrawUtil::drawTextN( GFont *font, const Point2I &ptDraw, const UTF16 *in_ // Don't draw invalid characters. default: { - if( !font->isValidChar( c ) ) + if( !font->isValidChar( c ) ) continue; } } @@ -354,7 +381,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d { // Sanity if no texture is specified. if(!texture) - return; + return; GFXVertexBufferHandle verts(mDevice, 4, GFXBufferTypeVolatile ); verts.lock(); @@ -369,13 +396,13 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d F32 screenTop = dstRect.point.y; F32 screenBottom = (dstRect.point.y + dstRect.extent.y); - if( in_flip & GFXBitmapFlip_X ) + if( in_flip & GFXBitmapFlip_X ) { F32 temp = texLeft; texLeft = texRight; texRight = temp; } - if( in_flip & GFXBitmapFlip_Y ) + if( in_flip & GFXBitmapFlip_Y ) { F32 temp = texTop; texTop = texBottom; @@ -435,7 +462,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d AssertFatal(false, "No GFXDrawUtil state block defined for this filter type!"); mDevice->setStateBlock(mBitmapStretchSB); break; - } + } mDevice->setTexture( 0, texture ); mDevice->setupGenericShaders( GFXDevice::GSModColorTexture ); @@ -445,7 +472,7 @@ void GFXDrawUtil::drawBitmapStretchSR( GFXTextureObject* texture, const RectF &d //----------------------------------------------------------------------------- // Draw Rectangle //----------------------------------------------------------------------------- -void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) +void GFXDrawUtil::drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) { drawRect( Point2F((F32)upperLeft.x,(F32)upperLeft.y),Point2F((F32)lowerRight.x,(F32)lowerRight.y),color); } @@ -513,57 +540,94 @@ void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, //----------------------------------------------------------------------------- // Draw Rectangle Fill //----------------------------------------------------------------------------- -void GFXDrawUtil::drawRectFill( const RectF &rect, const ColorI &color ) +void GFXDrawUtil::drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor) { - drawRectFill(rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color ); + drawRoundedRect(0.0f, rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor); } -void GFXDrawUtil::drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) -{ - drawRectFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color); +void GFXDrawUtil::drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor) +{ + drawRoundedRect(0.0f, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor); } -void GFXDrawUtil::drawRectFill( const RectI &rect, const ColorI &color ) +void GFXDrawUtil::drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor) { - drawRectFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color ); + drawRoundedRect(0.0f, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor); } -void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color ) +void GFXDrawUtil::drawRectFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize,const ColorI& borderColor) +{ + // draw a rounded rect with 0 radiuse. + drawRoundedRect(0.0f, upperLeft, lowerRight, color, borderSize, borderColor); +} + +void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize, const ColorI& borderColor) +{ + drawRoundedRect(cornerRadius, rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, borderSize, borderColor); +} + +void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize, const ColorI& borderColor) +{ + drawRoundedRect(cornerRadius, Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, borderSize, borderColor); +} + +void GFXDrawUtil::drawRoundedRect(const F32& cornerRadius, + const Point2F& upperLeft, + const Point2F& lowerRight, + const ColorI& color, + const F32& borderSize, + const ColorI& borderColor) { - // - // Convert Box a----------x - // | | - // x----------b - // Into Quad - // v0---------v1 - // | a x | - // | | - // | x b | - // v2---------v3 - // // NorthWest and NorthEast facing offset vectors - Point2F nw(-0.5,-0.5); /* \ */ - Point2F ne(0.5,-0.5); /* / */ + Point2F nw(-0.5, -0.5); /* \ */ + Point2F ne(0.5, -0.5); /* / */ GFXVertexBufferHandle verts(mDevice, 4, GFXBufferTypeVolatile); verts.lock(); F32 ulOffset = 0.5f - mDevice->getFillConventionOffset(); - - verts[0].point.set( upperLeft.x+nw.x + ulOffset, upperLeft.y+nw.y + ulOffset, 0.0f ); - verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); - verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); - verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); + + verts[0].point.set(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f); + verts[1].point.set(lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); + verts[2].point.set(upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); + verts[3].point.set(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); for (S32 i = 0; i < 4; i++) verts[i].color = color; verts.unlock(); + mDevice->setVertexBuffer(verts); mDevice->setStateBlock(mRectFillSB); - mDevice->setVertexBuffer( verts ); - mDevice->setupGenericShaders(); - mDevice->drawPrimitive( GFXTriangleStrip, 0, 2 ); + + Point2F topLeftCorner(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset); + Point2F bottomRightCorner(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset); + + /*mDevice->setupGenericShaders();*/ + GFX->setShader(mRoundRectangleShader); + GFX->setShaderConstBuffer(mRoundRectangleShaderConsts); + + MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix(); + Point2F size((F32)(bottomRightCorner.x - topLeftCorner.x), (F32)(bottomRightCorner.y - topLeftCorner.y)); + + F32 minExtent = mMin(size.x, size.y); + + F32 radius = cornerRadius; + if ((minExtent * 0.5) < radius) + { + radius = mClampF(radius, 0.0f, (minExtent * 0.5)); + } + + mRoundRectangleShaderConsts->set(mRoundRectangleShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$radius"), radius); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$sizeUni"), size); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderSize"), borderSize); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$borderCol"), borderColor); + + Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0))); + mRoundRectangleShaderConsts->setSafe(mRoundRectangleShader->getShaderConstHandle("$rectCenter"), rectCenter); + + mDevice->drawPrimitive(GFXTriangleStrip, 0, 2); } void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle ) @@ -608,7 +672,73 @@ void GFXDrawUtil::draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinA } //----------------------------------------------------------------------------- -// Draw Line +// Draw Circle : FILL +//----------------------------------------------------------------------------- +void GFXDrawUtil::drawCircleFill(const RectI& rect, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor) +{ + drawCircleFill(rect.point, Point2I(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color, radius, borderSize, borderColor); +} + +void GFXDrawUtil::drawCircleFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor) +{ + drawCircleFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color, radius, borderSize, borderColor); +} + +void GFXDrawUtil::drawCircleFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, F32 radius, const F32& borderSize, const ColorI& borderColor) +{ + // NorthWest and NorthEast facing offset vectors + Point2F nw(-0.5, -0.5); /* \ */ + Point2F ne(0.5, -0.5); /* / */ + + GFXVertexBufferHandle verts(mDevice, 4, GFXBufferTypeVolatile); + verts.lock(); + + F32 ulOffset = 0.5f - mDevice->getFillConventionOffset(); + + verts[0].point.set(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f); + verts[1].point.set(lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f); + verts[2].point.set(upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f); + verts[3].point.set(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f); + for (S32 i = 0; i < 4; i++) + verts[i].color = color; + + verts.unlock(); + mDevice->setVertexBuffer(verts); + + mDevice->setStateBlock(mRectFillSB); + + Point2F topLeftCorner(upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset); + Point2F bottomRightCorner(lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset); + + /*mDevice->setupGenericShaders();*/ + GFX->setShader(mCircleShader); + GFX->setShaderConstBuffer(mCircleShaderConsts); + + MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix(); + Point2F size((F32)(bottomRightCorner.x - topLeftCorner.x), (F32)(bottomRightCorner.y - topLeftCorner.y)); + + Point2F rectCenter((F32)(topLeftCorner.x + (size.x / 2.0)), (F32)(topLeftCorner.y + (size.y / 2.0))); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$rectCenter"), rectCenter); + + F32 minExtent = mMin(size.x, size.y); + F32 shaderRadius = radius; + + if ((minExtent * 0.5) < shaderRadius) + { + shaderRadius = mClampF(radius, 0.0f, (minExtent * 0.5)); + } + + mCircleShaderConsts->set(mCircleShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$radius"), shaderRadius); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$sizeUni"), size); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$borderSize"), borderSize); + mCircleShaderConsts->setSafe(mCircleShader->getShaderConstHandle("$borderCol"), borderColor); + + mDevice->drawPrimitive(GFXTriangleStrip, 0, 2); +} + +//----------------------------------------------------------------------------- +// Draw Lines : Single Pixel //----------------------------------------------------------------------------- void GFXDrawUtil::drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color ) { @@ -648,6 +778,55 @@ void GFXDrawUtil::drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, cons mDevice->drawPrimitive( GFXLineList, 0, 1 ); } +//----------------------------------------------------------------------------- +// Draw Lines : Thick +//----------------------------------------------------------------------------- +void GFXDrawUtil::drawThickLine(const Point2I& startPt, const Point2I& endPt, const ColorI& color, const F32& thickness) +{ + drawThickLine(startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color, thickness); +} + +void GFXDrawUtil::drawThickLine(const Point2F& startPt, const Point2F& endPt, const ColorI& color, const F32& thickness) +{ + drawThickLine(startPt.x, startPt.y, 0.0f, endPt.x, endPt.y, 0.0f, color, thickness); +} + +void GFXDrawUtil::drawThickLine(F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI& color, const F32& thickness) +{ + // less than 2 just draw an ordinary line... why you ever here.... + if (thickness < 2.0f) + { + drawLine(x1, y1, z1, x2, y2, z2, color); + return; + } + + GFXVertexBufferHandle verts(mDevice, 2, GFXBufferTypeVolatile); + verts.lock(); + + verts[0].point.set(x1, y1, z1); + verts[1].point.set(x2, y2, z2); + verts[0].color = color; + verts[1].color = color; + + verts.unlock(); + + mDevice->setVertexBuffer(verts); + mDevice->setStateBlock(mRectFillSB); + GFX->setShader(mThickLineShader); + GFX->setShaderConstBuffer(mThickLineShaderConsts); + + MatrixF tempMatrix = GFX->getProjectionMatrix() * GFX->getViewMatrix() * GFX->getWorldMatrix(); + mThickLineShaderConsts->set(mThickLineShader->getShaderConstHandle("$modelView"), tempMatrix, GFXSCT_Float4x4); + mThickLineShaderConsts->setSafe(mThickLineShader->getShaderConstHandle("$thickness"), thickness); + + const Point2I& resolution = GFX->getActiveRenderTarget()->getSize(); + Point2F TargetSize(1.0 / (F32)resolution.x, 1.0 / (F32)resolution.y); + + mThickLineShaderConsts->setSafe(mThickLineShader->getShaderConstHandle("$oneOverViewport"), TargetSize); + + mDevice->drawPrimitive(GFXLineList, 0, 1); +} + //----------------------------------------------------------------------------- // 3D World Draw Misc //----------------------------------------------------------------------------- @@ -713,13 +892,13 @@ void GFXDrawUtil::drawSphere( const GFXStateBlockDesc &desc, F32 radius, const P //----------------------------------------------------------------------------- -static const Point3F cubePoints[8] = +static const Point3F cubePoints[8] = { Point3F(-1, -1, -1), Point3F(-1, -1, 1), Point3F(-1, 1, -1), Point3F(-1, 1, 1), Point3F( 1, -1, -1), Point3F( 1, -1, 1), Point3F( 1, 1, -1), Point3F( 1, 1, 1) }; -static const U32 cubeFaces[6][4] = +static const U32 cubeFaces[6][4] = { { 0, 4, 6, 2 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 }, { 3, 2, 6, 7 }, { 7, 6, 4, 5 }, { 3, 7, 5, 1 } @@ -812,7 +991,7 @@ void GFXDrawUtil::drawPolygon( const GFXStateBlockDesc& desc, const Point3F* poi for( U32 i = 0; i < numPoints; ++ i ) xfm->mulP( verts[ i ].point ); } - + if( isWireframe ) { verts[ numVerts - 1 ].point = verts[ 0 ].point; @@ -899,7 +1078,7 @@ void GFXDrawUtil::_drawSolidCube( const GFXStateBlockDesc &desc, const Point3F & for(S32 i = 0; i < 6; i++) { idx = cubeFaces[i][0]; - verts[vertexIndex].point = cubePoints[idx] * halfSize; + verts[vertexIndex].point = cubePoints[idx] * halfSize; verts[vertexIndex].color = color; vertexIndex++; @@ -1113,10 +1292,10 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s cubePts[i] = cubePoints[i]/2; } - // 8 corner points of the box + // 8 corner points of the box for ( U32 i = 0; i < 8; i++ ) { - //const Point3F &start = cubePoints[i]; + //const Point3F &start = cubePoints[i]; // 3 lines per corner point for ( U32 j = 0; j < 3; j++ ) @@ -1128,7 +1307,7 @@ void GFXDrawUtil::drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &s scaledObjMat.mulP(start); PrimBuild::vertex3fv(start); scaledObjMat.mulP(end); - PrimBuild::vertex3fv(end); + PrimBuild::vertex3fv(end); } } @@ -1164,10 +1343,10 @@ void GFXDrawUtil::drawCapsule( const GFXStateBlockDesc &desc, const Point3F &cen } void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3F ¢er, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm ) -{ +{ MatrixF mat; if ( xfm ) - mat = *xfm; + mat = *xfm; else mat = MatrixF::Identity; @@ -1176,7 +1355,7 @@ void GFXDrawUtil::_drawSolidCapsule( const GFXStateBlockDesc &desc, const Point3 verts.lock(); for (S32 i=0; i 0 ) vSteps = size.y / step.y + 0.5 + 1; - + if( uSteps <= 1 || vSteps <= 1 ) return; - + const U32 numVertices = uSteps * 2 + vSteps * 2; const U32 numLines = uSteps + vSteps; - + Point3F origin; switch( plane ) { @@ -1552,14 +1731,14 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p verts[vertCount].point = Point3F( start + step.x * i, origin.y + size.y, origin.z ); else verts[vertCount].point = Point3F( start + step.x * i, origin.y, origin.z + size.y ); - + verts[vertCount].color = color; ++vertCount; } } if( plane == PlaneXY || plane == PlaneYZ ) - { + { U32 num; F32 stp; if( plane == PlaneXY ) @@ -1574,7 +1753,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p } F32 start = mFloor( origin.y / stp + 0.5f ) * stp; - + for ( U32 i = 0; i < num; i++ ) { verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z ); @@ -1585,7 +1764,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p verts[vertCount].point = Point3F( origin.x + size.x, start + stp * i, origin.z ); else verts[vertCount].point = Point3F( origin.x, start + stp * i, origin.z + size.x ); - + verts[vertCount].color = color; ++vertCount; } @@ -1604,7 +1783,7 @@ void GFXDrawUtil::drawPlaneGrid( const GFXStateBlockDesc &desc, const Point3F &p verts[vertCount].point = Point3F( origin.x + size.x, origin.y, start + step.y * i ); else verts[vertCount].point = Point3F( origin.x, origin.y + size.x, start + step.y * i ); - + verts[vertCount].color = color; ++vertCount; } @@ -1629,7 +1808,7 @@ void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &m GFXVertexBufferHandle verts( mDevice, 6, GFXBufferTypeVolatile ); verts.lock(); - const static ColorI defColors[3] = + const static ColorI defColors[3] = { ColorI::RED, ColorI::GREEN, @@ -1655,7 +1834,7 @@ void GFXDrawUtil::drawTransform( const GFXStateBlockDesc &desc, const MatrixF &m { verts[1].point *= *scale; verts[3].point *= *scale; - verts[5].point *= *scale; + verts[5].point *= *scale; } verts.unlock(); diff --git a/Engine/source/gfx/gfxDrawUtil.h b/Engine/source/gfx/gfxDrawUtil.h index 7c74e1d9d..8cb3adb77 100644 --- a/Engine/source/gfx/gfxDrawUtil.h +++ b/Engine/source/gfx/gfxDrawUtil.h @@ -46,22 +46,36 @@ public: ~GFXDrawUtil(); //----------------------------------------------------------------------------- - // Draw Rectangles + // Draw Rectangles : OUTLINE //----------------------------------------------------------------------------- - void drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color ); - void drawRect( const RectF &rect, const ColorI &color ); - void drawRect( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ); - void drawRect( const RectI &rect, const ColorI &color ); - - void drawRectFill( const Point2F &upperL, const Point2F &lowerR, const ColorI &color ); - void drawRectFill( const RectF &rect, const ColorI &color ); - void drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ); - void drawRectFill( const RectI &rect, const ColorI &color ); - - void draw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle = 0.0f ); + void drawRect(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color); + void drawRect(const RectF& rect, const ColorI& color); + void drawRect(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color); + void drawRect(const RectI& rect, const ColorI& color); //----------------------------------------------------------------------------- - // Draw Lines + // Draw Rectangles : FILL + //----------------------------------------------------------------------------- + + void drawRectFill(const Point2F& upperL, const Point2F& lowerR, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRectFill(const RectF& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRectFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRectFill(const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRoundedRect(const F32& cornerRadius, const RectI& rect, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRoundedRect(const F32& cornerRadius, const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawRoundedRect(const F32& cornerRadius, const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + + void draw2DSquare(const Point2F& screenPoint, F32 width, F32 spinAngle = 0.0f); + + //----------------------------------------------------------------------------- + // Draw Circle : FILL + //----------------------------------------------------------------------------- + void drawCircleFill(const RectI& rect, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawCircleFill(const Point2I& upperLeft, const Point2I& lowerRight, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + void drawCircleFill(const Point2F& upperLeft, const Point2F& lowerRight, const ColorI& color, F32 radius, const F32& borderSize = 0.0f, const ColorI& borderColor = ColorI(0, 0, 0, 0)); + + //----------------------------------------------------------------------------- + // Draw Lines : Single Pixel //----------------------------------------------------------------------------- void drawLine( const Point3F &startPt, const Point3F &endPt, const ColorI &color ); void drawLine( const Point2F &startPt, const Point2F &endPt, const ColorI &color ); @@ -69,6 +83,13 @@ public: void drawLine( F32 x1, F32 y1, F32 x2, F32 y2, const ColorI &color ); void drawLine( F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI &color ); + //----------------------------------------------------------------------------- + // Draw Lines : Thick + //----------------------------------------------------------------------------- + void drawThickLine(const Point2I& startPt, const Point2I& endPt, const ColorI& color, const F32& thickness); + void drawThickLine(const Point2F& startPt, const Point2F& endPt, const ColorI& color, const F32& thickness); + void drawThickLine(F32 x1, F32 y1, F32 z1, F32 x2, F32 y2, F32 z2, const ColorI& color, const F32& thickness); + //----------------------------------------------------------------------------- // Draw Text //----------------------------------------------------------------------------- @@ -92,7 +113,7 @@ public: //----------------------------------------------------------------------------- // Draw Bitmaps - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- void drawBitmap( GFXTextureObject*texture, const Point2F &in_rAt, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f); void drawBitmapSR( GFXTextureObject*texture, const Point2F &in_rAt, const RectF &srcRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f); void drawBitmapStretch( GFXTextureObject*texture, const RectF &dstRect, const GFXBitmapFlip in_flip = GFXBitmapFlip_None, const GFXTextureFilterType filter = GFXTextureFilterPoint , bool in_wrap = true, F32 angle = 0.0f); @@ -108,15 +129,15 @@ public: //----------------------------------------------------------------------------- void drawTriangle( const GFXStateBlockDesc &desc, const Point3F &p0, const Point3F &p1, const Point3F &p2, const ColorI &color, const MatrixF *xfm = NULL ); void drawPolygon( const GFXStateBlockDesc& desc, const Point3F* points, U32 numPoints, const ColorI& color, const MatrixF* xfm = NULL ); - void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL ); - void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL ); - void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color ); - void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL ); + void drawCube( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const ColorI &color, const MatrixF *xfm = NULL ); + void drawCube( const GFXStateBlockDesc &desc, const Box3F &box, const ColorI &color, const MatrixF *xfm = NULL ); + void drawObjectBox( const GFXStateBlockDesc &desc, const Point3F &size, const Point3F &pos, const MatrixF &objMat, const ColorI &color ); + void drawSphere( const GFXStateBlockDesc &desc, F32 radius, const Point3F &pos, const ColorI &color, bool drawTop = true, bool drawBottom = true, const MatrixF *xfm = NULL ); void drawCapsule( const GFXStateBlockDesc &desc, const Point3F ¢er, F32 radius, F32 height, const ColorI &color, const MatrixF *xfm = NULL ); - void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); - void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); + void drawCone( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); + void drawCylinder( const GFXStateBlockDesc &desc, const Point3F &basePnt, const Point3F &tipPnt, F32 baseRadius, const ColorI &color ); void drawArrow( const GFXStateBlockDesc &desc, const Point3F &start, const Point3F &end, const ColorI &color, F32 baseRad = 0.0f); - void drawFrustum( const Frustum& f, const ColorI &color ); + void drawFrustum( const Frustum& f, const ColorI &color ); /// Draw a solid or wireframe (depending on fill mode of @a desc) polyhedron with the given color. /// @@ -128,7 +149,7 @@ public: /// Draws a solid XY plane centered on the point with the specified dimensions. void drawSolidPlane( const GFXStateBlockDesc &desc, const Point3F &pos, const Point2F &size, const ColorI &color ); - + enum Plane { PlaneXY, @@ -142,7 +163,7 @@ public: /// Draws axis lines representing the passed matrix. /// If scale is NULL axes will be drawn the length they exist within the MatrixF. /// If colors is NULL the default colors are RED, GREEEN, BLUE ( x, y, z ). - void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL ); + void drawTransform( const GFXStateBlockDesc &desc, const MatrixF &mat, const Point3F *scale = NULL, const ColorI colors[3] = NULL ); protected: @@ -174,8 +195,21 @@ protected: GFXStateBlockRef mBitmapStretchWrapSB; GFXStateBlockRef mBitmapStretchWrapLinearSB; GFXStateBlockRef mRectFillSB; - + FontRenderBatcher* mFontRenderBatcher; + + // Expanded shaders + // rounded rectangle. + GFXShaderRef mRoundRectangleShader; + GFXShaderConstBufferRef mRoundRectangleShaderConsts; + + // thick line. + GFXShaderRef mCircleShader; + GFXShaderConstBufferRef mCircleShaderConsts; + + // thick line. + GFXShaderRef mThickLineShader; + GFXShaderConstBufferRef mThickLineShaderConsts; }; #endif // _GFX_GFXDRAWER_H_ diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 334ffe720..549609cb0 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -134,45 +134,6 @@ void GuiShaderEditor::onPreRender() setUpdate(); } -void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2) -{ - Point2F dir = Point2F(pt2.x - pt1.x, pt2.y - pt1.y); - if (dir == Point2F::Zero) - return; - - Point2F unitDir = dir / mSqrt(dir.x * dir.x + dir.y * dir.y); - Point2F unitPerp(-unitDir.y, unitDir.x); - Point2F offset = (thickness / 2.0f) * unitPerp; - - GFX->setStateBlock(mDefaultGuiSB); - - Point2F lT = Point2F(pt1.x, pt1.y) + offset; - Point2F lB = Point2F(pt1.x, pt1.y) - offset; - Point2F rT = Point2F(pt2.x, pt2.y) + offset; - Point2F rB = Point2F(pt2.x, pt2.y) - offset; - - - PrimBuild::begin(GFXTriangleStrip, 4); - - // top left. - PrimBuild::color(col1); - PrimBuild::vertex2f(lT.x, lT.y); - - // bottom left. - PrimBuild::color(col1); - PrimBuild::vertex2f(lB.x, lB.y); - - // top right. - PrimBuild::color(col2); - PrimBuild::vertex2f(rT.x, rT.y); - - // bottom right. - PrimBuild::color(col2); - PrimBuild::vertex2f(rB.x, rB.y); - - PrimBuild::end(); -} - void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) { // Save the current clip rect @@ -224,17 +185,14 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) if (node->mSelected) border = mProfile->mBorderColorSEL; - RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); - drawer->drawRect(socketRect, border); - socketRect.inset(1, 1); - ColorI fill = mProfile->mFillColor; if (hasConnection(input)) { fill = ColorI::WHITE; } - drawer->drawRectFill(socketRect, fill); + RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); + drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 2.0f, border); } for (NodeOutput* output : node->mOutputNodes) @@ -246,9 +204,8 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) if (node->mSelected) border = mProfile->mBorderColorSEL; - RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); - drawer->drawRect(socketRect, border); - socketRect.inset(1, 1); + if(node->mSelected) + border = mProfile->mBorderColorSEL; ColorI fill = mProfile->mFillColor; if (hasConnection(output)) @@ -256,7 +213,8 @@ void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect) fill = ColorI::WHITE; } - drawer->drawRectFill(socketRect, fill); + RectI socketRect(pos, Point2I(mNodeSize, mNodeSize)); + drawer->drawCircleFill(socketRect, fill, mNodeSize / 2, 2.0f, border); } } } @@ -292,7 +250,7 @@ void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect) start += Point2I(mNodeSize / 2, mNodeSize / 2); end += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, end, mNodeSize/3); + drawer->drawThickLine(start, end,ColorI(255,255,255,255), (F32)mNodeSize/3); } // Restore the clip rect to what it was at the start @@ -328,11 +286,12 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); start += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, mLastMousePos + offset, mNodeSize/3); + + drawer->drawThickLine(start, mLastMousePos + offset, ColorI(255, 255, 255, 255), (F32)mNodeSize / 3); // draw socket overlay over the top of the line. sockActive.inset(1, 1); - drawer->drawRectFill(sockActive, ColorI(255, 255, 255)); + drawer->drawCircleFill(sockActive, ColorI(255, 255, 255), mNodeSize / 2); } } // Draw selection rectangle last so it is rendered on top. diff --git a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp index 40cfceebf..be024db68 100644 --- a/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp +++ b/Engine/source/gui/shaderEditor/nodes/shaderNode.cpp @@ -108,7 +108,13 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 RectI winRect; winRect.point = offset; winRect.extent = getExtent(); - drawer->drawRectFill(winRect, mProfile->mFillColor); + + ColorI border = mProfile->mBorderColor; + + if (mSelected) + border = mProfile->mBorderColorSEL; + + drawer->drawRoundedRect(15.0f, winRect, mProfile->mFillColor, 3.0f, border); // draw header ColorI header(50, 50, 50, 128); @@ -148,7 +154,7 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 U32 headerSize = 30; headRect.point = offset; headRect.extent = Point2I(getExtent().x, headerSize); - drawer->drawRectFill(headRect, header); + drawer->drawRoundedRect(15.0f, headRect, header); // draw header text. U32 strWidth = mProfile->mFont->getStrWidth(mTitle.c_str()); @@ -157,14 +163,6 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 drawer->drawText(mProfile->mFont, headerPos + offset, mTitle); drawer->clearBitmapModulation(); - ColorI border = mProfile->mBorderColor; - - if (mSelected) - border = mProfile->mBorderColorSEL; - - drawer->drawRect(winRect, border); - - if (mInputNodes.size() > 0 || mOutputNodes.size() > 0) { U32 textPadX = nodeSize, textPadY = mProfile->mFont->getFontSize() + (nodeSize / 2); @@ -175,7 +173,7 @@ void GuiShaderNode::renderNode(Point2I offset, const RectI& updateRect, const S3 drawer->drawText(mProfile->mFont, slotPos + offset, input->name); if (input->pos == Point2I::Zero || mPrevNodeSize != nodeSize) - input->pos = Point2I(-(nodeSize / 2), slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); + input->pos = Point2I(-(nodeSize / 2) + 1, slotPos.y + ((mProfile->mFont->getFontSize() / 2) - (nodeSize / 2))); slotPos.y += textPadY; } diff --git a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript index 6a2981fa9..0b3d1ae47 100644 --- a/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript +++ b/Templates/BaseGame/game/core/rendering/scripts/gfxData/shaders.tscript @@ -149,4 +149,32 @@ singleton ShaderData( CubemapSaveShader ) samplerNames[0] = "$cubemapTex"; pixVersion = 3.0; +}; + +//----------------------------------------------------------------------------- +// GUI shaders +//----------------------------------------------------------------------------- +singleton ShaderData( RoundedRectangleGUI ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/roundedRectangleP.hlsl"; + + pixVersion = 3.0; +}; + +singleton ShaderData( CircularGUI ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/circleP.hlsl"; + + pixVersion = 3.0; +}; + +singleton ShaderData( ThickLineGUI ) +{ + DXVertexShaderFile = $Core::CommonShaderPath @ "/fixedFunction/colorV.hlsl"; + DXGeometryShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineG.hlsl"; + DXPixelShaderFile = $Core::CommonShaderPath @ "/fixedFunction/thickLineP.hlsl"; + + pixVersion = 3.0; }; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl new file mode 100644 index 000000000..053b6e9ff --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/circleP.hlsl @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float2 sizeUni; +uniform float radius; +uniform float2 rectCenter; +uniform float borderSize; +uniform float4 borderCol; + +float circle(float2 p, float radius) +{ + float dist = length(p - float2(0.5,0.5)); + return 1.0 - smoothstep(radius - (radius*0.01), + radius + (radius*0.01), + dot(dist,dist) * 4.0); +} + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + float distance = length(IN.HPOS.xy - rectCenter); + if(distance > radius) + { + discard; + } + + if(distance < radius) + { + if(distance < (radius - borderSize)) + { + return IN.color; + } + else + { + return borderCol; + } + } + + return IN.color; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl new file mode 100644 index 000000000..e051574c1 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/roundedRectangleP.hlsl @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float2 sizeUni; +uniform float2 rectCenter; +uniform float radius; +uniform float borderSize; +uniform float4 borderCol; + +float RoundedRectSDF(float2 p, float2 size, float radius) +{ + float2 halfSize = size / 2.0; + + // Calculate distance to each side of the rectangle + float2 dist = abs(p) - halfSize + radius; + + // Compute the distance to the rounded corners + float cornerDist = length(max(abs(p) - (halfSize - float2(radius, radius)), 0.0)); + + // Return the minimum distance (negative inside, positive outside) + return min(max(dist.x, dist.y), 0.0) + cornerDist - radius; +} + +float4 main(Conn IN) : TORQUE_TARGET0 +{ + float2 p = IN.HPOS.xy; + float2 halfSize = sizeUni * 0.5; + float halfBorder = borderSize * 0.5; + + p -= rectCenter; + + // Calculate signed distance field for rounded rectangle + float4 fromColor = IN.color; + // alpha + float4 toColor = float4(0.0, 0.0, 0.0, 0.0); + + float cornerRadius = radius; + + // if ((p.y < 0.0 && p.x < 0.0) || // top left corner + // (p.y < 0.0 && p.x > 0.0) || // top right corner + // (p.y > 0.0 && p.x > 0.0) || // bottom right corner. + // (p.y > 0.0 && p.x < 0.0)) // bottom left corner + // { + // cornerRadius = radius; + // } + + if(cornerRadius > 0.0 || halfBorder > 0.0) + { + float sdf = RoundedRectSDF(p, sizeUni, cornerRadius - halfBorder); + + clip(0.01 - sdf); + + if(halfBorder > 0.0) + { + if(sdf < 0.0) + { + // if ((p.y >= -halfSize.y - radius + halfBorder && p.y <= -halfSize.y + radius - halfBorder) || // top border + // (p.y >= halfSize.y - radius + halfBorder && p.y <= halfSize.y + radius - halfBorder) || // bottom border + // (p.x >= -halfSize.x - radius + halfBorder && p.x <= -halfSize.x + radius - halfBorder) || // left border + // (p.x >= halfSize.x - radius + halfBorder && p.x <= halfSize.x + radius - halfBorder) ) { // right border + + // } + + toColor = borderCol; + } + + sdf = abs(sdf) - halfBorder; + + // Apply smoothing to create rounded effect + float blending = smoothstep(1.0, -1.0, sdf); + + return lerp(fromColor, toColor, blending); + } + + float alpha = smoothstep(1.0, 0.0, sdf); + return float4(IN.color.rgb, IN.color.a * alpha); + } + else + { + return IN.color; + } +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl new file mode 100644 index 000000000..a7cf3d67a --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineG.hlsl @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct Conn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +struct PSConn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +uniform float thickness; +uniform float2 oneOverViewport; + +[maxvertexcount(4)] +void main(line Conn lineSegment[2], inout TriangleStream outstream) +{ + // Calculate the direction of the line segment + float2 direction = normalize(lineSegment[1].HPOS.xy - lineSegment[0].HPOS.xy); + + // Calculate perpendicular direction + float2 perpendicular = normalize(float2(-direction.y, direction.x)); + + // Calculate offset for thickness + float2 offset = float2(thickness * oneOverViewport.x, thickness * oneOverViewport.y) * perpendicular; + + // Calculate vertices for the line with thickness + float2 p0 = lineSegment[0].HPOS.xy + offset; + float2 p1 = lineSegment[0].HPOS.xy - offset; + float2 p2 = lineSegment[1].HPOS.xy + offset; + float2 p3 = lineSegment[1].HPOS.xy - offset; + + PSConn output; + + output.HPOS = float4(p0, 0.0f, 1.0f); + output.color = lineSegment[0].color; + outstream.Append(output); + + output.HPOS = float4(p1, 0.0f, 1.0f); + output.color = lineSegment[0].color; + outstream.Append(output); + + output.HPOS = float4(p2, 0.0f, 1.0f); + output.color = lineSegment[1].color; + outstream.Append(output); + + output.HPOS = float4(p3, 0.0f, 1.0f); + output.color = lineSegment[1].color; + outstream.Append(output); + + outstream.RestartStrip(); +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl new file mode 100644 index 000000000..e2659f777 --- /dev/null +++ b/Templates/BaseGame/game/core/rendering/shaders/fixedFunction/thickLineP.hlsl @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "../shaderModel.hlsl" + +struct PSConn +{ + float4 HPOS : TORQUE_POSITION; + float4 color : COLOR; +}; + +float4 main(PSConn IN) : TORQUE_TARGET0 +{ + return IN.color; +} \ No newline at end of file