| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- /******************************************************************************/
- #define MLAAThreshold 0.1f
- #define MLAAThreshold2 (2.5f/255)
- inline Flt ColDiff(Vec a, Vec b)
- {
- return Dist2(a,b)>(MLAAThreshold*MLAAThreshold);
- }
- Vec4 EdgeSoftenEdgeDetect_PS(IF_IS_PIXEL
- Vec2 inTex:TEXCOORD):COLOR
- {
- Vec col =Tex(Col,inTex ).rgb,
- col_x=Tex(Col,inTex+PixSize*Vec2(1,0)).rgb,
- col_y=Tex(Col,inTex+PixSize*Vec2(0,1)).rgb;
- Vec2 edge =Vec2(ColDiff(col,col_x),ColDiff(col,col_y));
- //clip(edge.x+edge.y-1); // if both are zero then don't output stencil value
- return Vec4(edge,0,0);
- }
- Vec4 EdgeSoftenCalcDist_PS(IF_IS_PIXEL
- Vec2 inTex:TEXCOORD):COLOR
- {
- Vec4 dist=Vec4(0,0,0,0);
- Vec2 edge=Tex(Col,inTex).xy;
- //if(edge.x==0 && edge.y==0)clip(-1);
- #if MODEL!=SM_2
- BRANCH if(edge.y)
- #endif
- {
- // scan left
- {
- Vec2 tex=inTex; tex.y+=0.5f*PixSize.y; // use bilinear filtering to scan both top and bottom
- Flt inc=1.0f/255;
- UNROLL for(Int i=0; i<4; i++)
- {
- tex.x-=PixSize.x; Vec2 edge=TexLod(Col,tex).xy;
- if( edge.r)inc=0; // top or bottom edge found
- if(!edge.g)inc=0;
- dist.x+=inc;
- }
- }
- // scan right
- {
- Vec2 tex =inTex; tex.y+=0.5f*PixSize.y; // use bilinear filtering to scan both top and bottom
- Flt inc =1.0f/255;
- Vec2 edge=TexLod(Col,tex).xy;
- UNROLL for(Int i=0; i<3; i++)
- {
- if( edge.r)inc=0; // top or bottom edge found
- tex.x+=PixSize.x; edge=TexLod(Col,tex).xy;
- if(!edge.g)inc=0;
- dist.y+=inc;
- }
- }
- }
- #if MODEL!=SM_2
- BRANCH if(edge.x)
- #endif
- {
- // scan top
- {
- Vec2 tex=inTex; tex.x+=0.5f*PixSize.x; // use bilinear filtering to scan both left and right
- Flt inc=1.0f/255;
- UNROLL for(Int i=0; i<4; i++)
- {
- tex.y-=PixSize.y; Vec2 edge=TexLod(Col,tex).xy;
- if( edge.g)inc=0; // horizontal edge on right or left
- if(!edge.r)inc=0;
- dist.z+=inc;
- }
- }
- // scan bottom
- {
- Vec2 tex =inTex; tex.x+=0.5f*PixSize.x; // use bilinear filtering to scan both left and right
- Flt inc =1.0f/255;
- Vec2 edge=TexLod(Col,tex).xy;
- UNROLL for(Int i=0; i<3; i++)
- {
- if( edge.g)inc=0; // horizontal edge on right or left
- tex.y+=PixSize.y; edge=TexLod(Col,tex).xy;
- if(!edge.r)inc=0;
- dist.w+=inc;
- }
- }
- }
- return dist;
- }
- /*Vec4 EdgeSoftenUpdateDist1_PS(IF_IS_PIXEL
- Vec2 inTex:TEXCOORD):COLOR
- {
- Vec4 dist =Tex(Col,inTex), offset=dist*(PixSize*255).xxyy;
- dist.x+=Tex(Col,inTex-Vec2(offset.x,0)).x;
- dist.y+=Tex(Col,inTex+Vec2(offset.y,0)).y;
- dist.z+=Tex(Col,inTex-Vec2(0,offset.z)).z;
- dist.w+=Tex(Col,inTex+Vec2(0,offset.w)).w;
- return dist;
- }
- Vec4 EdgeSoftenUpdateDist_PS(IF_IS_PIXEL
- Vec2 inTex:TEXCOORD):COLOR
- {
- Vec4 deltaPos =Tex(Col,inTex);
- Vec4 result =deltaPos;
- Vec2 texSize255=PixSize*255; deltaPos*=texSize255.xxyy;
- // LEFT
- BRANCH if(result.r>=MLAAThreshold2)
- {
- Vec2 currUV=inTex-Vec2(deltaPos.r,0);
- UNROLL for(Int i=0; i<3; i++)
- {
- Flt deltaU=TexLod(Col,currUV).r;
- result.r+=deltaU;
- currUV.x-=deltaU*texSize255.x;
- }
- }
- // RIGHT
- BRANCH if(result.g>=MLAAThreshold2)
- {
- Vec2 currUV=inTex+Vec2(deltaPos.g,0);
- UNROLL for(Int i=0; i<3; i++)
- {
- Flt deltaU=TexLod(Col,currUV).g;
- result.g+=deltaU;
- currUV.x+=deltaU*texSize255.x;
- }
- }
- // TOP
- BRANCH if(result.b>=MLAAThreshold2)
- {
- Vec2 currUV=inTex-Vec2(0,deltaPos.b);
- UNROLL for(Int i=0; i<3; i++)
- {
- Flt deltaV=TexLod(Col,currUV).b;
- result.b+=deltaV;
- currUV.y-=deltaV*texSize255.y;
- }
- }
- // BOTTOM
- BRANCH if(result.a>=MLAAThreshold2)
- {
- Vec2 currUV=inTex+Vec2(0,deltaPos.a);
- UNROLL for(Int i=0; i<3; i++)
- {
- Flt deltaV=TexLod(Col,currUV).a;
- result.a+=deltaV;
- currUV.y+=deltaV*texSize255.y;
- }
- }
- return result;
- }*/
- //#define SCAN_EDGES
- //Col1=EdgeDetect
- //Col2=Distance
- /*// Scan horizontal edge
- int scanHEdge(Vec2 uv, out Vec2 startUV, out Vec2 endUV, out int negLength, out int posLength)
- {
- negLength=0;
- posLength=0;
- int length=1;
- startUV=endUV=uv;
- // scan left
- for(;;)
- {
- startUV.x -= PixSize.x;
- // current texel
- Vec2 edge=tex2Dlod(Col1,Vec4(startUV,0.f,0.f)).xy;
- // bottom texel
- Vec2 edgeB=tex2Dlod(Col1,Vec4(startUV+Vec2(0.f,PixSize.y),0.f,0.f)).xy;
- if(!edge.y || edge.x || edgeB.x) // either the horizontal edge stops, or we meet a vertical bar (above or below)
- {
- // yes ? stop
- startUV.x += PixSize.x;
- break;
- }
- ++ negLength;
- ++ length;
- }
- // scan right
- // current texel
- Vec2 edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
- // bottom texel
- Vec2 edgeB=tex2Dlod(Col1,Vec4(endUV+Vec2(0.f,PixSize.y),0.f,0.f)).xy;
- for(;;)
- {
- if(edge.x || edgeB.x) break; // met a vertical bar above or below ? -> stops
- endUV.x += PixSize.x;
- // current texel
- edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
- if(!edge.y) break; // test if horizontal edge stops
- // bottom texel
- edgeB=tex2Dlod(Col1,Vec4(endUV+Vec2(0.f,PixSize.y),0.f,0.f)).xy;
- ++ posLength;
- ++ length;
- }
- return length;
- }
- // Scan vertical edge
- int scanVEdge(Vec2 uv, out Vec2 startUV, out Vec2 endUV, out int negLength, out int posLength)
- {
- negLength=0;
- posLength=0;
- int length=1;
- startUV=endUV=uv;
- // scan up
- for(;;)
- {
- startUV.y -= PixSize.y;
- // current texel
- Vec2 edge=tex2Dlod(Col1,Vec4(startUV,0.f,0.f)).xy;
- // right texel
- Vec2 edgeR=tex2Dlod(Col1,Vec4(startUV+Vec2(PixSize.x,0.f),0.f,0.f)).xy;
- if(!edge.x || edge.y || edgeR.y) // either the vertical edge stops, or we met an horizontal bar (right or left)
- {
- // yes ? stop
- startUV.y += PixSize.y;
- break;
- }
- ++ negLength;
- ++ length;
- }
- // scan bottom
- // current texel
- Vec2 edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
- // right texel
- Vec2 edgeR=tex2Dlod(Col1,Vec4(endUV+Vec2(PixSize.x,0.f),0.f,0.f)).xy;
- for(;;)
- {
- if(edge.y || edgeR.y) break; // met a horizontal on the right or the left ? -> stops
- endUV.y += PixSize.y;
- // current texel
- edge=tex2Dlod(Col1,Vec4(endUV,0.f,0.f)).xy;
- if(!edge.x) break; // test if vertical edge stops
- // right texel
- edgeR=tex2Dlod(Col1,Vec4(endUV+Vec2(PixSize.x,0.f),0.f,0.f)).xy;
- ++ posLength;
- ++ length;
- }
- return length;
- }*/
- inline Flt BlendFactor(Flt start, Flt end, Flt pos, Flt h0, Flt h1, Flt step)
- {
- Flt slope=(h1 -h0)/(end+step-start),
- hb0 = h0 +slope*(pos-start),
- hb1 = hb0+step*slope,
- area =(hb0+hb1)*0.5f;
- return area;
- }
- Vec4 EdgeSoftenApply_PS(IF_IS_PIXEL
- Vec2 inTex:TEXCOORD):COLOR
- {
- Vec2 edges =Tex(Col1,inTex ).xy,
- edgesT=Tex(Col1,inTex+PixSize*Vec2( 0,-1)).xy,
- edgesL=Tex(Col1,inTex+PixSize*Vec2(-1, 0)).xy;
- Vec4 finalCol=0;
- Flt weight =0;
- BRANCH if(edges.g+edges.r+edgesT.g+edgesL.r>0) // no edge found -> no need for anti-aliasing
- {
- #ifndef SCAN_EDGES
- Vec4 dist =TexLod(Col2,inTex ),
- distT=TexLod(Col2,inTex+PixSize*Vec2( 0,-1)),
- distL=TexLod(Col2,inTex+PixSize*Vec2(-1, 0));
- #endif
- // BOTTOM HORIZONTAL EDGE
- if(edges.g)
- {
- Flt negLength, posLength, length;
- Vec2 startUV, endUV;
- #ifdef SCAN_EDGES
- length=scanHEdge(inTex, startUV, endUV, negLength, posLength);
- #else
- // Use distance from the distance texture
- negLength=dist.r*255;
- posLength=dist.g*255;
- length =negLength+posLength+1;
- startUV =inTex+Vec2(-PixSize.x*negLength,0);
- endUV =inTex+Vec2( PixSize.x*posLength,0);
- #endif
- // test |_____ case
- if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(-1,0));
- if(c.r)
- {
- Flt h0= 0.5f,
- h1=-0.5f,
- b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
- finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }else
- // test _____| case
- if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,endUV);
- if(c.r)
- {
- Flt h0=-0.5f,
- h1= 0.5f,
- b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
- finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }
- }else
- // TOP HORIZONTAL EDGE
- if(edgesT.g)
- {
- Flt negLength, posLength, length;
- Vec2 startUV, endUV;
- #ifdef SCAN_EDGES
- length=scanHEdge(inTex+PixSize*Vec2(0,-1), startUV, endUV, negLength, posLength);
- #else
- // use distance from the distance texture
- negLength=distT.r*255;
- posLength=distT.g*255;
- length =negLength+posLength+1;
- startUV =inTex+Vec2(-PixSize.x*negLength,-PixSize.y);
- endUV =inTex+Vec2( PixSize.x*posLength,-PixSize.y);
- #endif
- // ______
- // test | case
- if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(-1,1));
- if(c.r)
- {
- Flt h0=-0.5f,
- h1= 0.5f,
- b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
- finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }else
- // ______
- // test | case
- if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,endUV+PixSize*Vec2(0,1));
- if(c.r)
- {
- Flt h0= 0.5f,
- h1=-0.5f,
- b = BlendFactor(startUV.x, endUV.x, inTex.x, h0, h1, PixSize.x);
- finalCol+=TexLod(Col,inTex+Vec2(0,b*PixSize.y)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }
- }
- // VERTICAL EDGE ON THE RIGHT
- if(edges.r)
- {
- Flt negLength, posLength, length;
- Vec2 startUV, endUV;
- #ifdef SCAN_EDGES
- length=scanVEdge(inTex, startUV, endUV, negLength, posLength);
- #else
- // use distance from the distance texture
- negLength=dist.b*255;
- posLength=dist.a*255;
- length =negLength+posLength+1;
- startUV =inTex+Vec2(0,-PixSize.y*negLength);
- endUV =inTex+Vec2(0, PixSize.y*posLength);
- #endif
- // test _ case
- // |
- // |
- if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(0,-1));
- if(c.g)
- {
- Flt h0= 0.5f,
- h1=-0.5f,
- b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
- finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }else
- // test | case
- // |
- // --
- if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,endUV);
- if(c.g)
- {
- Flt h0=-0.5f,
- h1= 0.5f,
- b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
- finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }
- }else
- // VERTICAL EDGE ON THE LEFT
- if(edgesL.r)
- {
- Flt negLength, posLength, length;
- Vec2 startUV, endUV;
- #ifdef SCAN_EDGES
- length=scanVEdge(inTex+PixSize*Vec2(-1,0), startUV, endUV, negLength, posLength);
- #else
- // use distance from the distance texture
- negLength=distL.b*255;
- posLength=distL.a*255;
- length =negLength+posLength+1;
- startUV =inTex+Vec2(-PixSize.x,-PixSize.y*negLength);
- endUV =inTex+Vec2(-PixSize.x, PixSize.y*posLength);
- #endif
- // test _ case
- // |
- // |
- if(negLength<posLength) // if(length>1 && negLength<=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,startUV+PixSize*Vec2(1,-1));
- if(c.g)
- {
- Flt h0=-0.5f,
- h1= 0.5f,
- b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
- finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }else
- // test | case
- // |
- // --
- if(negLength>posLength) // if(length>1 && negLength>=posLength) // passed the middle, the contribution is NULL
- {
- Vec4 c=TexLod(Col1,endUV+PixSize*Vec2(1,0));
- if(c.g)
- {
- Flt h0= 0.5f,
- h1=-0.5f,
- b = BlendFactor(startUV.y, endUV.y, inTex.y, h0, h1, PixSize.y);
- finalCol+=TexLod(Col,inTex+Vec2(b*PixSize.x,0)); // lerp, using bilinear filtering for transition
- weight +=1;
- }
- }
- }
- }
- finalCol+=(1.0f/256)*Tex(Col,inTex);
- weight +=(1.0f/256);
- return finalCol/weight;
- }
- /******************************************************************************/
- #if MODEL!=SM_2
- TECHNIQUE(EdgeSoftenEdgeDetect , Draw_VS(), EdgeSoftenEdgeDetect_PS ());
- TECHNIQUE(EdgeSoftenCalcDist , Draw_VS(), EdgeSoftenCalcDist_PS ());
- //TECHNIQUE(EdgeSoftenUpdateDist1, Draw_VS(), EdgeSoftenUpdateDist1_PS());
- //TECHNIQUE(EdgeSoftenUpdateDist , Draw_VS(), EdgeSoftenUpdateDist_PS ());
- TECHNIQUE(EdgeSoftenApply , Draw_VS(), EdgeSoftenApply_PS ());
- #endif
- /******************************************************************************/
|