diff --git a/project/include/Graphics.h b/project/include/Graphics.h index b87c3ff64..ff38a54ed 100644 --- a/project/include/Graphics.h +++ b/project/include/Graphics.h @@ -638,6 +638,7 @@ struct GraphicsJob int mDataCount; bool mIsTileJob; bool mIsPointJob; + bool mPolyAA; unsigned char mTileMode; unsigned char mBlendMode; }; @@ -691,6 +692,7 @@ class Graphics : public Object void endFill(); void beginBitmapFill(Surface *bitmapData, const Matrix &inMatrix = Matrix(), bool inRepeat = true, bool inSmooth = false); + void lineStyleSoftEdge(); void lineStyle(double thickness, unsigned int color = 0, double alpha = 1.0, bool pixelHinting = false, StrokeScaleMode scaleMode = ssmNormal, StrokeCaps caps = scRound, diff --git a/project/include/Hardware.h b/project/include/Hardware.h index 225fa514d..a7fdeab72 100644 --- a/project/include/Hardware.h +++ b/project/include/Hardware.h @@ -30,27 +30,28 @@ enum PrimType { ptTriangleFan, ptTriangleStrip, ptTriangles, ptLineStrip, ptPoin enum { - DRAW_HAS_COLOUR = 0x00000001, - DRAW_HAS_NORMAL = 0x00000002, - DRAW_HAS_PERSPECTIVE = 0x00000004, - DRAW_RADIAL = 0x00000008, - - DRAW_HAS_TEX = 0x00000010, - DRAW_BMP_REPEAT = 0x00000020, - DRAW_BMP_SMOOTH = 0x00000040, + DRAW_HAS_COLOUR = 0x0001, + DRAW_HAS_NORMAL = 0x0002, + DRAW_HAS_PERSPECTIVE = 0x0004, + DRAW_RADIAL = 0x0008, + + DRAW_HAS_TEX = 0x0010, + DRAW_BMP_REPEAT = 0x0020, + DRAW_BMP_SMOOTH = 0x0040, - DRAW_TILE_MOUSE = 0x00000080, + DRAW_TILE_MOUSE = 0x0080, + DRAW_EDGE_DIST = 0x0100, }; struct DrawElement { - uint8 mFlags; + unsigned short mFlags; + short mRadialPos; uint8 mPrimType; uint8 mBlendMode; uint8 mScaleMode; - short mRadialPos; uint8 mStride; int mCount; diff --git a/project/include/HardwareImpl.h b/project/include/HardwareImpl.h index edad85997..b996294c3 100644 --- a/project/include/HardwareImpl.h +++ b/project/include/HardwareImpl.h @@ -21,8 +21,9 @@ enum PROG_4D_INPUT = 0x0100, PROG_PREM_ALPHA = 0x0200, PROG_COMP_ALPHA = 0x0400, + PROG_EDGE_DIST = 0x0800, - PROG_COUNT = 0x0800, + PROG_COUNT = 0x1000, }; inline unsigned int getProgId( const DrawElement &element, const ColorTransform *ctrans) @@ -46,6 +47,9 @@ inline unsigned int getProgId( const DrawElement &element, const ColorTransform if (element.mFlags & DRAW_HAS_NORMAL) progId |= PROG_NORMAL_DATA; + if (element.mFlags & DRAW_EDGE_DIST) + progId |= PROG_EDGE_DIST; + if (element.mFlags & DRAW_RADIAL) { progId |= PROG_RADIAL; diff --git a/project/src/common/ExternalInterface.cpp b/project/src/common/ExternalInterface.cpp index f7cafb82c..fc718d6d7 100644 --- a/project/src/common/ExternalInterface.cpp +++ b/project/src/common/ExternalInterface.cpp @@ -2956,6 +2956,16 @@ void nme_gfx_end_fill(value inGfx) } DEFINE_PRIME1v(nme_gfx_end_fill); +void nme_gfx_line_style_soft_edge(value argGfx) +{ + Graphics *gfx; + if (AbstractToObject(argGfx,gfx)) + { + CHECK_ACCESS("nme_gfx_line_style_soft_edge"); + gfx->lineStyleSoftEdge(); + } +} +DEFINE_PRIME1v(nme_gfx_line_style_soft_edge); void nme_gfx_line_style(value argGfx, value argThickness, int argColour, double argAlpha, bool argPixelHinting, int argScaleMode, diff --git a/project/src/common/Graphics.cpp b/project/src/common/Graphics.cpp index a4e9c9909..930cb104e 100644 --- a/project/src/common/Graphics.cpp +++ b/project/src/common/Graphics.cpp @@ -384,6 +384,13 @@ void Graphics::beginTiles(Surface *bitmapData,bool inSmooth,int inBlendMode, int OnChanged(); } +void Graphics::lineStyleSoftEdge() +{ + lineStyle(-1); + Flush(); + mFillJob.mPolyAA = true; +} + void Graphics::lineStyle(double thickness, unsigned int color, double alpha, bool pixelHinting, StrokeScaleMode scaleMode, StrokeCaps caps, @@ -391,6 +398,7 @@ void Graphics::lineStyle(double thickness, unsigned int color, double alpha, { Flush(true,false,true); endTiles(); + mFillJob.mPolyAA = false; if (mLineJob.mStroke) { mLineJob.mStroke->DecRef(); diff --git a/project/src/common/Hardware.cpp b/project/src/common/Hardware.cpp index 81763b154..1852895f3 100644 --- a/project/src/common/Hardware.cpp +++ b/project/src/common/Hardware.cpp @@ -1,7 +1,7 @@ #include #include #include - +#include #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -73,7 +73,7 @@ class HardwareBuilder int align = 2*sizeof(float); mSolidMode = false; - mAlphaAA = false; + mPolyAA = inJob.mPolyAA; mPerpLen = 0.5; mStateScale = data.scaleOf(inState); mScale = mStateScale; @@ -104,6 +104,15 @@ class HardwareBuilder mElement.mScaleMode = ssmNormal; if (!SetFill(inJob.mFill,inHardware)) return; + + if (mPolyAA) + { + //printf("Reserve solid AA..\n"); + mElement.mFlags |= DRAW_HAS_NORMAL; + mElement.mNormalOffset = mElement.mVertexOffset + mElement.mStride; + mElement.mStride += sizeof(float)*2; + mPolyAA = true; + } } else if (tessellate_lines && inJob.mStroke->scaleMode==ssmNormal) { @@ -139,7 +148,6 @@ class HardwareBuilder mElement.mFlags |= DRAW_HAS_NORMAL; mElement.mNormalOffset = mElement.mVertexOffset + mElement.mStride; mElement.mStride += sizeof(float)*2; - mAlphaAA = true; } } else @@ -363,6 +371,94 @@ class HardwareBuilder mElement.mSurface->DecRef(); } + void calcEdgeDist(UserPoint &p0, UserPoint &p1, UserPoint &p2, + float &d0, float &d1, float &d2 ) + { + + UserPoint perp = UserPoint( p1.y-p0.y, p0.x-p1.x ).Normalized(); + float dist = fabs((p2-p0).Dot(perp)); + + d0 = 0; + d1 = 0; + d2 = dist; + } + + + void calcEdgePointDist(const UserPoint &p0, const UserPoint &p1, const UserPoint &p2, + float &d0, float &d1, float &d2 ) + { + UserPoint perp = UserPoint( p1.y-p0.y, p0.x-p1.x ).Normalized(); + float dist = fabs( (p2-p0).Dot(perp) ); + + d0 = d1 = dist; + d2 = 0; + } + + void CalcNormalCoords(const std::vector &isOuter) + { + UserPoint *vertices = (UserPoint *)&data.mArray[ mElement.mVertexOffset ]; + UserPoint *norm = (UserPoint *)&data.mArray[ mElement.mNormalOffset ]; + + int n = mElement.mCount/3; + for(int i=0;i &isOuter) { ReserveArrays(inV.size()); @@ -1038,6 +1134,12 @@ class HardwareBuilder if (mElement.mSurface) CalcTexCoords(); + if (mPolyAA) + { + mElement.mFlags |= DRAW_EDGE_DIST; + CalcNormalCoords(isOuter); + } + PushElement(); } @@ -1062,21 +1164,73 @@ class HardwareBuilder } - void PushTriangleWireframe(const Vertices &inV) + void expandFan(Vertices &ioV, std::vector &outEdge) { - ReserveArrays(inV.size()*2); + UserPoint p0 = ioV[0]; + UserPoint p1 = ioV[1]; + + int n = (int)ioV.size(); + Vertices tris; + tris.reserve( 3*(n-2) ); + outEdge.reserve( 3*(n-2) ); + for(int i=2;i &outOuter) + { + size_t n = ioOutline.size(); + outOuter.resize(n); + + std::map pidMap; + std::vector pids(n); + int ids = 0; + for(int i=0; isecond; + else + { + int id = ids++; + pids[i] = id; + pidMap[key] = id; + } + } + + std::map eidCount; + union + { + int p[2]; + int64 key; + }; + + for(int tri=0; tri &inSubPolys) + void AddPolygon(Vertices &ioOutline,const QuickVec &inSubPolys) { bool showTriangles = false; - if (mSolidMode && inOutline.size()<3) + if (mSolidMode && ioOutline.size()<3) return; bool isConvex = inSubPolys.size()==1; @@ -1102,14 +1307,14 @@ class HardwareBuilder { if (isConvex) { - UserPoint base = inOutline[0]; - int last = inOutline.size()-2; + UserPoint base = ioOutline[0]; + int last = ioOutline.size()-2; int i = 0; bool positive = true; for( ;iFLAT) { @@ -1120,8 +1325,8 @@ class HardwareBuilder for(++i;iFLAT && (diff>0)!=positive) { @@ -1132,11 +1337,11 @@ class HardwareBuilder } if (!isConvex) { - ConvertOutlineToTriangles(inOutline,inSubPolys,mWinding); + ConvertOutlineToTriangles(ioOutline,inSubPolys,mWinding); //showTriangles = true; } } - if (mSolidMode && inOutline.size()<3) + if (mSolidMode && ioOutline.size()<3) return; @@ -1144,17 +1349,28 @@ class HardwareBuilder if (mElement.mSurface) mElement.mTexOffset = mElement.mVertexOffset + 2*sizeof(float); + bool fan = isConvex; if (showTriangles) { - PushTriangleWireframe(inOutline); - //PushOutline(inOutline); + PushTriangleWireframe(ioOutline, fan); + //PushOutline(ioOutline); } else { - PushVertices(inOutline); + std::vector isOuter; + if (!fan) + { + mElement.mPrimType = ptTriangles; + if (mPolyAA) + calcEdgeIsOuter(ioOutline, isOuter); + } + else if (mPolyAA) + { + expandFan(ioOutline,isOuter); + mElement.mPrimType = ptTriangles; + } - if (!isConvex) - data.mElements.last().mPrimType = ptTriangles; + PushVertices(ioOutline,isOuter); } } @@ -2392,7 +2608,7 @@ class HardwareBuilder bool mGradReflect; unsigned int mGradFlags; bool mSolidMode; - bool mAlphaAA; + bool mPolyAA; double mMiterLimit; double mPerpLen; double mScale; diff --git a/project/src/opengl/OGL.h b/project/src/opengl/OGL.h index 9030fcb64..301022a6a 100644 --- a/project/src/opengl/OGL.h +++ b/project/src/opengl/OGL.h @@ -197,7 +197,6 @@ namespace nme Texture *OGLCreateTexture(Surface *inSurface,unsigned int inFlags); - class GPUProg { public: @@ -214,11 +213,13 @@ class GPUProg virtual void setColourTransform(const ColorTransform *inTransform, unsigned int inColour, bool inPremultiplyAlpha) = 0; virtual void setGradientFocus(float inFocus) = 0; + virtual void setNormScale(float inScale) = 0; int vertexSlot; int textureSlot; int normalSlot; int colourSlot; + int normScaleSlot; }; diff --git a/project/src/opengl/OGLShaders.cpp b/project/src/opengl/OGLShaders.cpp index c0f9aade4..9bbb3448c 100644 --- a/project/src/opengl/OGLShaders.cpp +++ b/project/src/opengl/OGLShaders.cpp @@ -26,6 +26,7 @@ OGLProg::OGLProg(const std::string &inVertProg, const std::string &inFragProg,in textureSlot = -1; normalSlot = -1; colourSlot = -1; + normScaleSlot = -1; //printf("%s", inVertProg.c_str()); //printf("%s", inFragProg.c_str()); @@ -146,8 +147,8 @@ void OGLProg::recreate() mFXSlot = glGetUniformLocation(mProgramId, "mFX"); mASlot = glGetUniformLocation(mProgramId, "mA"); mOn2ASlot = glGetUniformLocation(mProgramId, "mOn2A"); + normScaleSlot = glGetUniformLocation(mProgramId, "uNormScale"); - glUseProgram(mProgramId); if (mImageSlot>=0) glUniform1i(mImageSlot,0); @@ -252,6 +253,13 @@ void OGLProg::setTransform(const Trans4x4 &inTrans) glUniformMatrix4fv(mTransformSlot, 1, 0, inTrans[0]); } + +void OGLProg::setNormScale(float inScale) +{ + glUniform1f(normScaleSlot, inScale>0 ? 1.0f/inScale : 1.0f); +} + + void OGLProg::setGradientFocus(float inFocus) { if (mASlot>=0) @@ -407,11 +415,19 @@ GPUProg *GPUProg::create(unsigned int inID) VIN + " vec2 aNormal;\n" + VOUT +" vec2 vNormal;\n"; - vertexProg = - " vNormal = aNormal;\n" + vertexProg; + if (inID & PROG_EDGE_DIST) + { + vertexVars += "uniform float uNormScale;\n"; + vertexProg = + " vNormal = aNormal*uNormScale;\n" + vertexProg; + } + else + vertexProg = + " vNormal = aNormal;\n" + vertexProg; pixelVars += VOUT + " vec2 vNormal;\n"; + } std::string vertexShader = @@ -430,7 +446,13 @@ GPUProg *GPUProg::create(unsigned int inID) if ( inID & PROG_NORMAL_DATA ) { - fragColour = "(" + fragColour + ") * vec4(1,1,1, min(vNormal.x-abs(vNormal.y),1.0) )"; + std::string edgeAlpha = (inID & PROG_EDGE_DIST) ? + "min(vNormal.x,vNormal.y)" : + "vNormal.x-abs(vNormal.y)"; + if ( inID & PROG_PREM_ALPHA ) + fragColour = "(" + fragColour + ") * min(" + edgeAlpha + ",1.0)"; + else + fragColour = "(" + fragColour + ") * vec4(1,1,1, min(" + edgeAlpha + ",1.0) )"; } diff --git a/project/src/opengl/OGLShaders.h b/project/src/opengl/OGLShaders.h index 76cd4713e..9ea8a6e7a 100644 --- a/project/src/opengl/OGLShaders.h +++ b/project/src/opengl/OGLShaders.h @@ -24,6 +24,7 @@ class OGLProg : public GPUProg int getTextureSlot(); void setTransform(const Trans4x4 &inTrans); virtual void setGradientFocus(float inFocus); + void setNormScale(float inScale); std::string mVertProg; std::string mFragProg; @@ -34,11 +35,6 @@ class OGLProg : public GPUProg const ColorTransform *mColourTransform; - // int vertexSlot; - // int textureSlot; - // int normalSlot; - // int colourSlot; - GLint mImageSlot; GLint mColourArraySlot; GLint mColourScaleSlot; diff --git a/project/src/opengl/OpenGLContext.cpp b/project/src/opengl/OpenGLContext.cpp index 0a1b7a249..9a899f669 100644 --- a/project/src/opengl/OpenGLContext.cpp +++ b/project/src/opengl/OpenGLContext.cpp @@ -622,6 +622,10 @@ class OGLContext : public HardwareRenderer glVertexAttribPointer(prog->normalSlot, 2, GL_FLOAT, GL_FALSE, stride, data + element.mNormalOffset); glEnableVertexAttribArray(prog->normalSlot); + if (prog->normScaleSlot>=0) + prog->setNormScale( + sqrt( 0.5*( mModelView.m00*mModelView.m00 + mModelView.m01*mModelView.m01 + + mModelView.m10*mModelView.m10 + mModelView.m11*mModelView.m11 ) ) ); } diff --git a/src/nme/display/Graphics.hx b/src/nme/display/Graphics.hx index 45fdba3fe..7ed188864 100644 --- a/src/nme/display/Graphics.hx +++ b/src/nme/display/Graphics.hx @@ -173,6 +173,11 @@ class Graphics nme_gfx_begin_set_gradient_fill(nmeHandle, Type.enumIndex(type), colors, alphas, ratios, matrix, spreadMethod == null ? 0 : Type.enumIndex(spreadMethod), interpolationMethod == null ? 0 : Type.enumIndex(interpolationMethod), focalPointRatio, false); } + public function lineStyleSoftEdge():Void + { + nme_gfx_line_style_soft_edge(nmeHandle); + } + public function lineStyle(?thickness:Null, color:Int = 0, alpha:Float = 1.0, pixelHinting:Bool = false, ?scaleMode:LineScaleMode, ?caps:CapsStyle, ?joints:JointStyle, miterLimit:Float = 3):Void { nme_gfx_line_style(nmeHandle, thickness, color, alpha, pixelHinting, scaleMode == null ? 0 : Type.enumIndex(scaleMode), caps == null ? 0 : Type.enumIndex(caps), joints == null ? 0 : Type.enumIndex(joints), miterLimit); @@ -205,6 +210,7 @@ class Graphics private static var nme_gfx_begin_set_gradient_fill = nme.PrimeLoader.load("nme_gfx_begin_set_gradient_fill", "oiooooiidbv"); private static var nme_gfx_end_fill = PrimeLoader.load("nme_gfx_end_fill", "ov"); private static var nme_gfx_line_style = nme.PrimeLoader.load("nme_gfx_line_style", "ooidbiiidv" ); + private static var nme_gfx_line_style_soft_edge = nme.PrimeLoader.load("nme_gfx_line_style_soft_edge", "ov" ); private static var nme_gfx_move_to = PrimeLoader.load("nme_gfx_move_to", "oddv"); private static var nme_gfx_line_to = PrimeLoader.load("nme_gfx_line_to", "oddv"); private static var nme_gfx_curve_to = PrimeLoader.load("nme_gfx_curve_to", "oddddv");