I have the following pixel shader for drawing a 2D polygon:
#if OPENGL
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0
#define PS_SHADERMODEL ps_4_0
#endif
Texture2D SpriteTexture;
float2 Points[20];
int numPoints;
float LineRadius;
sampler2D SpriteTextureSampler = sampler_state
{
Texture = <SpriteTexture>;
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};
// isLeft(): tests if a point is Left|On|Right of an infinite line.
// Input: three points linePointA, linePointB, and p
// Return: >0 for p left of the line through linePointA and linePointB
// =0 for p on the line
// <0 for p right of the line
float IsLeft(float2 linePointA, float2 linePointB, float2 p)
{
return ((linePointB.x - linePointA.x) * (p.y - linePointA.y) - (p.x - linePointA.x) * (linePointB.y - linePointA.y));
}
float SegmentDistanceSquared(float2 p, float2 a, float2 b)
{
// https://www.youtube.com/watch?v=PMltMdi1Wzg
float h = clamp(dot(p - a, b - a) / dot(b - a, b - a), 0, 1);
float2 distanceVector = p - lerp(a, b, h);
return distanceVector.x * distanceVector.x + distanceVector.y * distanceVector.y;
}
float4 PolygonPS(VertexShaderOutput input) : COLOR
{
float sdf = 2000000;
int j = numPoints - 1;
int wn = 0; // winding number
for (int i = 0; i < numPoints; i++)
{
float dist = SegmentDistanceSquared(input.Position.xy, Points[i], Points[j]);
sdf = min(sdf, dist);
// winding number stuff
// https://www.shadertoy.com/view/WdSGRd
// http://geomalgorithms.com/a03-_inclusion.html
bool cond1 = input.Position.y >= Points[i].y;
bool cond2 = input.Position.y < Points[j].y;
float leftVal = IsLeft(Points[j], Points[i], input.Position.xy);
wn += cond1 && cond2 && leftVal > 0 ? 1 : 0; // up intersect
wn -= !cond1 && !cond2 && leftVal < 0 ? 1 : 0; // down intersect
j = i;
}
sdf = sqrt(sdf);
if (wn != 0)
{
sdf = -sdf;
}
sdf -= LineRadius;
float alpha = clamp(-sdf, 0, 1);
float4 retval = tex2D(SpriteTextureSampler, input.TextureCoordinates) * input.Color;
retval.a *= alpha;
return retval;
}
technique Polygon
{
pass P0
{
PixelShader = compile PS_SHADERMODEL PolygonPS();
}
};
As I understand it, arrays in shaders must have a size set, which will be the maximum size for the input. The game I am making involves modifying polygons and I would like to be able to draw polygons with a lot of vertices. With DirectX I was able to set the size of Points
to 1024 with no problems, but with OpenGL increasing the size of Points
significantly increases the compile time of the shader and causes compilation to fail completely if it is too big.
Is there any way for me to use a large array in OpenGL?
For now I will continue to use DirectX, but I would like the option of putting my game on non-Windows platforms in the future.