void GetCorner_Cut(VertexInputData vertexInputData, ref VertexOutputData output) { Vector3 normal1 = cross(normalize(vertexInputData.position1 - vertexInputData.position2), new Vector3(0, 0, 1)); Vector3 normal2 = cross(normalize(vertexInputData.position3 - vertexInputData.position2), new Vector3(0, 0, 1)); Vector3 leftPoint = vertexInputData.position2 + normal1 * vertexInputData.strokeWidth2 * HALF; Vector3 rightPoint = vertexInputData.position2 - normal1 * vertexInputData.strokeWidth2 * HALF; Vector3 leftPoint2 = vertexInputData.position2 - normal2 * vertexInputData.strokeWidth2 * HALF; Vector3 rightPoint2 = vertexInputData.position2 + normal2 * vertexInputData.strokeWidth2 * HALF; if (vertexInputData.vertexId == 0) { output.position = leftPoint2; } else if (vertexInputData.vertexId == 1) { output.position = rightPoint2; } else if (vertexInputData.vertexId == 2) { output.position = rightPoint; } else if (vertexInputData.vertexId == 3) { output.position = leftPoint; } else { output.position = vertexInputData.position2; } }
public VertexOutputData VertexProgram(VertexInputData vertexData) { Profiler.BeginSample("Vertex Program"); VertexOutputData output = GetCornerVertexOutput(vertexData); Profiler.EndSample(); return(output); }
VertexOutputData GetCornerVertexOutputLocalSpace(VertexInputData vertexInputData) { Profiler.BeginSample("GetCornerVertexOutputLocalSpace"); VertexOutputData output = new VertexOutputData(); output.uv = vertexInputData.uv; output.position = new Vector3(0, 0, 0); output.color = GetColor(vertexInputData); float cornerAngle = GetCornerAngle(vertexInputData.position1, vertexInputData.position2, vertexInputData.position3); bool isLeftTurn = cornerAngle > PI; if (cornerType == StrokeCornerType.Bevel) { GetCorner_Bevel(vertexInputData, ref output, cornerAngle, isLeftTurn); } else if (cornerType == StrokeCornerType.ExtendOrCut || cornerType == StrokeCornerType.ExtendOrMiter) { Vector3 cornerNormal = GetCornerNormal(vertexInputData.position1, vertexInputData.position2, vertexInputData.position3); float cornerNormalLength; if (abs(cornerAngle) > MIN_ANGLE_THRESHOLD) { cornerNormalLength = 1 / sin(cornerAngle * HALF); } else { cornerNormalLength = MAX_VALUE; } bool miterLimitReached = cornerNormalLength > _StrokeMiterLimit; // do extend if (miterLimitReached) { if (cornerType == StrokeCornerType.ExtendOrMiter) { GetCorner_Miter(vertexInputData, ref output, cornerNormal, cornerNormalLength, isLeftTurn); } else if (cornerType == StrokeCornerType.ExtendOrCut) { GetCorner_Cut(vertexInputData, ref output); } } else { GetCorner_Extend(vertexInputData, ref output, cornerNormal, cornerNormalLength); } } Profiler.EndSample(); return(output); }
void GetCorner_Bevel(VertexInputData vertexInputData, ref VertexOutputData output, float cornerAngle, bool isLeftTurn) { Vector3 normal1 = cross(normalize(vertexInputData.position1 - vertexInputData.position2), new Vector3(0, 0, 1)); Vector3 normal2 = cross(normalize(vertexInputData.position3 - vertexInputData.position2), new Vector3(0, 0, 1)); Vector3 leftPoint = vertexInputData.position2 + normal1 * vertexInputData.strokeWidth2 * HALF; Vector3 rightPoint = vertexInputData.position2 - normal1 * vertexInputData.strokeWidth2 * HALF; Vector3 leftPoint2 = vertexInputData.position2 - normal2 * vertexInputData.strokeWidth2 * HALF; Vector3 rightPoint2 = vertexInputData.position2 + normal2 * vertexInputData.strokeWidth2 * HALF; if (vertexInputData.vertexId == 0 || vertexInputData.vertexId == 7) { output.position = leftPoint2; } else if (vertexInputData.vertexId == 1 || vertexInputData.vertexId == 6) { output.position = rightPoint2; } else if (vertexInputData.vertexId == 2 || vertexInputData.vertexId == 5) { output.position = rightPoint; } else if (vertexInputData.vertexId == 3 || vertexInputData.vertexId == 4) { output.position = leftPoint; } if (!isLeftTurn) { if (vertexInputData.vertexId == 5 || vertexInputData.vertexId == 6) { output.uv = new Vector2(vertexInputData.uv.x, 0.5f); output.position = vertexInputData.position2; } } else { if (vertexInputData.vertexId == 4 || vertexInputData.vertexId == 7) { output.uv = new Vector2(vertexInputData.uv.x, 0.5f); output.position = vertexInputData.position2; } } }
void GetCorner_Extend(VertexInputData vertexInputData, ref VertexOutputData output, Vector3 cornerNormal, float normalLength) { Vector3 leftPoint = vertexInputData.position2 - cornerNormal * normalLength * vertexInputData.strokeWidth2 * HALF; Vector3 rightPoint = vertexInputData.position2 + cornerNormal * normalLength * vertexInputData.strokeWidth2 * HALF; Vector3 leftPoint2 = leftPoint; Vector3 rightPoint2 = rightPoint; if (vertexInputData.vertexId == 0 || vertexInputData.vertexId == 7) { output.position = leftPoint2; } else if (vertexInputData.vertexId == 1 || vertexInputData.vertexId == 6) { output.position = rightPoint2; } else if (vertexInputData.vertexId == 2 || vertexInputData.vertexId == 5) { output.position = rightPoint; } else if (vertexInputData.vertexId == 3 || vertexInputData.vertexId == 4) { output.position = leftPoint; } }
VertexOutputData GetCornerVertexOutput(VertexInputData vertexInputData) { Profiler.BeginSample("GetCornerVertexOutput"); VertexOutputData output; if (renderType == StrokeRenderType.ShapeSpace) { output = GetCornerVertexOutputLocalSpace(vertexInputData); } else if ( renderType == StrokeRenderType.ScreenSpacePixels || renderType == StrokeRenderType.ScreenSpaceRelativeToScreenHeight || renderType == StrokeRenderType.ShapeSpaceFacingCamera) { if (renderType == StrokeRenderType.ScreenSpacePixels) { float strokeWidthMulti = 1f / camera.pixelHeight; vertexInputData.strokeWidth1 *= strokeWidthMulti; vertexInputData.strokeWidth2 *= strokeWidthMulti; vertexInputData.strokeWidth3 *= strokeWidthMulti; } // clip space -1 to 1 vertexInputData.strokeWidth1 *= 2; vertexInputData.strokeWidth2 *= 2; vertexInputData.strokeWidth3 *= 2; if (renderType == StrokeRenderType.ShapeSpaceFacingCamera) { vertexInputData.position1 = MV.MultiplyPoint(vertexInputData.position1); vertexInputData.position2 = MV.MultiplyPoint(vertexInputData.position2); vertexInputData.position3 = MV.MultiplyPoint(vertexInputData.position3); vertexInputData.strokeWidth1 /= -(vertexInputData.position1.z) + 1; vertexInputData.strokeWidth2 /= -(vertexInputData.position2.z) + 1; vertexInputData.strokeWidth3 /= -(vertexInputData.position3.z) + 1; vertexInputData.position1 = P.MultiplyPoint(vertexInputData.position1); vertexInputData.position2 = P.MultiplyPoint(vertexInputData.position2); vertexInputData.position3 = P.MultiplyPoint(vertexInputData.position3); } else { vertexInputData.position1 = MVP.MultiplyPoint(vertexInputData.position1); vertexInputData.position2 = MVP.MultiplyPoint(vertexInputData.position2); vertexInputData.position3 = MVP.MultiplyPoint(vertexInputData.position3); } float z = vertexInputData.position2.z; vertexInputData.position1.x *= camera.aspect; vertexInputData.position2.x *= camera.aspect; vertexInputData.position3.x *= camera.aspect; //vertexInputData.position1.z = 0; //vertexInputData.position2.z = 0; //vertexInputData.position3.z = 0; output = GetCornerVertexOutputLocalSpace(vertexInputData); output.position.z = z; output.position.x /= camera.aspect; output.position = MVP.inverse.MultiplyPoint(output.position); } else { output = new VertexOutputData(); } Profiler.EndSample(); return(output); }
void GetCorner_Miter(VertexInputData vertexInputData, ref VertexOutputData output, Vector3 cornerNormal, float cornerNormalLength, bool isLeftTurn) { Vector3 strokeNormal = cross(normalize(vertexInputData.position2 - vertexInputData.position1), new Vector3(0, 0, 1)); float cornerNormalToStrokeNormalAngle = !isLeftTurn?GetCornerAngle(cornerNormal, new Vector3(0, 0, 0), strokeNormal) : GetCornerAngle(strokeNormal, new Vector3(0, 0, 0), cornerNormal); // outside float outsideNormalLength = _StrokeMiterLimit; Vector3 outsideNormal = cornerNormal * outsideNormalLength; // inside float insideAngle = (PI * HALF) - cornerNormalToStrokeNormalAngle; float insideNormalLength; if (abs(insideAngle) > MIN_ANGLE_THRESHOLD) { insideNormalLength = 1 / sin(abs(insideAngle)); } else { insideNormalLength = 0; } Vector3 insideNormal = -cornerNormal * insideNormalLength * vertexInputData.strokeWidth2 * HALF; /* * Vector3 projectedMax32 = Vector3.Project(vertexInputData.position3 - vertexInputData.position2, insideNormal); * insideNormal = Vector3.ClampMagnitude(insideNormal, projectedMax32.magnitude); * Vector3 projectedMax12 = Vector3.Project(vertexInputData.position1 - vertexInputData.position2, insideNormal); * insideNormal = Vector3.ClampMagnitude(insideNormal, projectedMax12.magnitude); * * float proj23Sqr = (vertexInputData.position3 - vertexInputData.position2).sqrMagnitude + vertexInputData.strokeWidth2 * vertexInputData.strokeWidth2; * float proj21Sqr = (vertexInputData.position1 - vertexInputData.position2).sqrMagnitude + vertexInputData.strokeWidth2 * vertexInputData.strokeWidth2; * float insideNormalLengthSqr = insideNormalLength * insideNormalLength; * * if (insideNormalLengthSqr > proj23Sqr || insideNormalLengthSqr > proj21Sqr) * { * // special case, normal is longer than line to next or prev point * if (proj21Sqr < proj23Sqr) { * insideNormal = (vertexInputData.position1 - vertexInputData.position2); * } else { * insideNormal = (vertexInputData.position3 - vertexInputData.position2); * } * }*/ // miter fill float miterFillLength = (1 - _StrokeMiterLimit * cos(cornerNormalToStrokeNormalAngle)) / sin(cornerNormalToStrokeNormalAngle); Vector3 miterFillVector = cross(cornerNormal, new Vector3(0, 0, 1)) * -miterFillLength; Vector3 leftPoint = vertexInputData.position2; Vector3 leftPoint2 = vertexInputData.position2; Vector3 rightPoint = vertexInputData.position2; Vector3 rightPoint2 = vertexInputData.position2; Vector3 outsideNormalMinusFillVector = (outsideNormal - miterFillVector) * vertexInputData.strokeWidth2 * HALF; Vector3 outsideNormalPlusFillVector = (outsideNormal + miterFillVector) * vertexInputData.strokeWidth2 * HALF; if (isLeftTurn) { leftPoint += insideNormal; rightPoint += outsideNormalMinusFillVector; leftPoint2 += insideNormal; rightPoint2 += outsideNormalPlusFillVector; } else { leftPoint -= outsideNormalPlusFillVector; rightPoint -= insideNormal; leftPoint2 -= outsideNormalMinusFillVector; rightPoint2 -= insideNormal; } if (vertexInputData.vertexId == 0 || vertexInputData.vertexId == 7) { output.position = leftPoint2; } else if (vertexInputData.vertexId == 1 || vertexInputData.vertexId == 6) { output.position = rightPoint2; } else if (vertexInputData.vertexId == 2 || vertexInputData.vertexId == 5) { output.position = rightPoint; } else if (vertexInputData.vertexId == 3 || vertexInputData.vertexId == 4) { output.position = leftPoint; } }