Skip to content

Commit 3b060ea

Browse files
committed
Fix bezier cage generation
1 parent afb1386 commit 3b060ea

File tree

2 files changed

+25
-29
lines changed

2 files changed

+25
-29
lines changed

62_CAD/common.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ enum class MajorAxis : uint32_t
2525
struct MainObject
2626
{
2727
uint32_t styleIdx;
28-
uint32_t pad; // do I even need this?
28+
uint32_t pad; // do I even need this? it's stored in structured buffer not bda
2929
uint64_t clipProjectionAddress;
3030
};
3131

62_CAD/vertex_shader.hlsl

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,16 @@ PSInput main(uint vertexID : SV_VertexID)
8484
if (objType == ObjectType::LINE || objType == ObjectType::QUAD_BEZIER || objType == ObjectType::POLYLINE_CONNECTOR)
8585
{
8686
LineStyle lineStyle = lineStyles[mainObj.styleIdx];
87+
88+
// Width is on both sides, thickness is one one side of the curve (div by 2.0f)
8789
const float screenSpaceLineWidth = lineStyle.screenSpaceLineWidth + float(lineStyle.worldSpaceLineWidth * globals.screenToWorldRatio);
88-
const float antiAliasedLineWidth = screenSpaceLineWidth + globals.antiAliasingFactor * 2.0f;
90+
const float antiAliasedLineThickness = screenSpaceLineWidth * 0.5f + globals.antiAliasingFactor;
91+
const float sdfLineThickness = screenSpaceLineWidth / 2.0f;
92+
outV.setLineThickness(sdfLineThickness);
93+
outV.setCurrentWorldToScreenRatio((float)(2.0 / (clipProjectionData.projectionToNDC[0][0] * globals.resolution.x)));
8994

9095
if (objType == ObjectType::LINE)
9196
{
92-
outV.setLineThickness(screenSpaceLineWidth / 2.0f);
93-
outV.setCurrentWorldToScreenRatio((float)(2.0 / (clipProjectionData.projectionToNDC[0][0] * globals.resolution.x)));
94-
9597
double2 points[2u];
9698
points[0u] = vk::RawBufferLoad<double2>(drawObj.geometryAddress, 8u);
9799
points[1u] = vk::RawBufferLoad<double2>(drawObj.geometryAddress + sizeof(LinePointInfo), 8u);
@@ -114,15 +116,15 @@ PSInput main(uint vertexID : SV_VertexID)
114116
{
115117
// work in screen space coordinates because of fixed pixel size
116118
outV.position.xy = transformedPoints[0u]
117-
+ normalToLine * (((float)vertexIdx - 0.5f) * antiAliasedLineWidth)
118-
- lineVector * antiAliasedLineWidth * 0.5f;
119+
+ normalToLine * (((float)vertexIdx - 0.5f) * 2.0f * antiAliasedLineThickness)
120+
- lineVector * antiAliasedLineThickness;
119121
}
120122
else // if (vertexIdx == 2u || vertexIdx == 3u)
121123
{
122124
// work in screen space coordinates because of fixed pixel size
123125
outV.position.xy = transformedPoints[1u]
124-
+ normalToLine * (((float)vertexIdx - 2.5f) * antiAliasedLineWidth)
125-
+ lineVector * antiAliasedLineWidth * 0.5f;
126+
+ normalToLine * (((float)vertexIdx - 2.5f) * 2.0f * antiAliasedLineThickness)
127+
+ lineVector * antiAliasedLineThickness;
126128
}
127129

128130
outV.setLineStart(transformedPoints[0u]);
@@ -132,8 +134,6 @@ PSInput main(uint vertexID : SV_VertexID)
132134
}
133135
else if (objType == ObjectType::QUAD_BEZIER)
134136
{
135-
outV.setLineThickness(screenSpaceLineWidth / 2.0f);
136-
137137
double2 points[3u];
138138
points[0u] = vk::RawBufferLoad<double2>(drawObj.geometryAddress, 8u);
139139
points[1u] = vk::RawBufferLoad<double2>(drawObj.geometryAddress + sizeof(double2), 8u);
@@ -143,7 +143,6 @@ PSInput main(uint vertexID : SV_VertexID)
143143
const float patternStretch = vk::RawBufferLoad<float>(drawObj.geometryAddress + sizeof(double2) * 3u + sizeof(float), 8u);
144144
outV.setCurrentPhaseShift(phaseShift);
145145
outV.setPatternStretch(patternStretch);
146-
outV.setCurrentWorldToScreenRatio((float)(2.0 / (clipProjectionData.projectionToNDC[0][0] * globals.resolution.x)));
147146

148147
// transform these points into screen space and pass to fragment
149148
float2 transformedPoints[3u];
@@ -174,7 +173,7 @@ PSInput main(uint vertexID : SV_VertexID)
174173

175174
// We only do this adaptive thing when "MinRadiusOfOsculatingCircle = RadiusOfMaxCurvature < screenSpaceLineWidth/4" OR "MaxCurvature > 4/screenSpaceLineWidth";
176175
// which means there is a self intersection because of large lineWidth relative to the curvature (in screenspace)
177-
// the reason for division by 4.0f is 1. screenSpaceLineWidth is expanded on both sides and the fact that diameter/2=radius,
176+
// the reason for division by 4.0f is 1. screenSpaceLineWidth is expanded on both sides and 2. the fact that diameter/2=radius,
178177
const bool noCurvature = abs(dot(normalize(vectorAB), normalize(vectorAC)) - 1.0f) < exp2(-10.0f);
179178
if (MaxCurvature * screenSpaceLineWidth > 4.0f || noCurvature)
180179
{
@@ -183,7 +182,7 @@ PSInput main(uint vertexID : SV_VertexID)
183182
float2 obbV1;
184183
float2 obbV2;
185184
float2 obbV3;
186-
quadraticBezier.computeOBB(screenSpaceLineWidth / 2.0f, obbV0, obbV1, obbV2, obbV3);
185+
quadraticBezier.computeOBB(antiAliasedLineThickness, obbV0, obbV1, obbV2, obbV3);
187186
if (subsectionIdx == 0)
188187
{
189188
if (vertexIdx == 0u)
@@ -233,41 +232,41 @@ PSInput main(uint vertexID : SV_VertexID)
233232
float2 interior0;
234233
float2 interior1;
235234

236-
float2 middleExteriorPoint = midPos - midNormal * screenSpaceLineWidth / 2.0f;
235+
float2 middleExteriorPoint = midPos - midNormal * antiAliasedLineThickness;
237236

238237

239238
float2 leftTangent = normalize(BezierTangent(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], optimalT));
240239
float2 leftNormal = normalize(float2(-leftTangent.y, leftTangent.x)) * flip;
241-
float2 leftExteriorPoint = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], optimalT) - leftNormal * screenSpaceLineWidth / 2.0f;
240+
float2 leftExteriorPoint = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], optimalT) - leftNormal * antiAliasedLineThickness;
242241
float2 exterior0 = nbl::hlsl::shapes::util::LineLineIntersection<float>(middleExteriorPoint, midTangent, leftExteriorPoint, leftTangent);
243242

244243
float2 rightTangent = normalize(BezierTangent(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 1.0f - optimalT));
245244
float2 rightNormal = normalize(float2(-rightTangent.y, rightTangent.x)) * flip;
246-
float2 rightExteriorPoint = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 1.0f - optimalT) - rightNormal * screenSpaceLineWidth / 2.0f;
245+
float2 rightExteriorPoint = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 1.0f - optimalT) - rightNormal * antiAliasedLineThickness;
247246
float2 exterior1 = nbl::hlsl::shapes::util::LineLineIntersection<float>(middleExteriorPoint, midTangent, rightExteriorPoint, rightTangent);
248247

249248
// Interiors
250249
{
251250
float2 tangent = normalize(BezierTangent(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 0.286f));
252251
float2 normal = normalize(float2(-tangent.y, tangent.x)) * flip;
253-
interior0 = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 0.286) + normal * screenSpaceLineWidth / 2.0f;
252+
interior0 = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 0.286) + normal * antiAliasedLineThickness;
254253
}
255254
{
256255
float2 tangent = normalize(BezierTangent(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 0.714f));
257256
float2 normal = normalize(float2(-tangent.y, tangent.x)) * flip;
258-
interior1 = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 0.714f) + normal * screenSpaceLineWidth / 2.0f;
257+
interior1 = QuadraticBezier(transformedPoints[0u], transformedPoints[1u], transformedPoints[2u], 0.714f) + normal * antiAliasedLineThickness;
259258
}
260259

261260
if (subsectionIdx == 0u)
262261
{
263262
float2 endPointTangent = normalize(transformedPoints[1u] - transformedPoints[0u]);
264263
float2 endPointNormal = float2(-endPointTangent.y, endPointTangent.x) * flip;
265-
float2 endPointExterior = transformedPoints[0u] - endPointTangent * screenSpaceLineWidth / 2.0f;
264+
float2 endPointExterior = transformedPoints[0u] - endPointTangent * antiAliasedLineThickness;
266265

267266
if (vertexIdx == 0u)
268267
outV.position = float4(nbl::hlsl::shapes::util::LineLineIntersection<float>(leftExteriorPoint, leftTangent, endPointExterior, endPointNormal), 0.0, 1.0f);
269268
else if (vertexIdx == 1u)
270-
outV.position = float4(transformedPoints[0u] + endPointNormal * screenSpaceLineWidth / 2.0f - endPointTangent * screenSpaceLineWidth / 2.0f, 0.0, 1.0f);
269+
outV.position = float4(transformedPoints[0u] + endPointNormal * antiAliasedLineThickness - endPointTangent * antiAliasedLineThickness, 0.0, 1.0f);
271270
else if (vertexIdx == 2u)
272271
outV.position = float4(exterior0, 0.0, 1.0f);
273272
else if (vertexIdx == 3u)
@@ -288,12 +287,12 @@ PSInput main(uint vertexID : SV_VertexID)
288287
{
289288
float2 endPointTangent = normalize(transformedPoints[2u] - transformedPoints[1u]);
290289
float2 endPointNormal = float2(-endPointTangent.y, endPointTangent.x) * flip;
291-
float2 endPointExterior = transformedPoints[2u] + endPointTangent * screenSpaceLineWidth / 2.0f;
290+
float2 endPointExterior = transformedPoints[2u] + endPointTangent * antiAliasedLineThickness;
292291

293292
if (vertexIdx == 0u)
294293
outV.position = float4(nbl::hlsl::shapes::util::LineLineIntersection<float>(rightExteriorPoint, rightTangent, endPointExterior, endPointNormal), 0.0, 1.0f);
295294
else if (vertexIdx == 1u)
296-
outV.position = float4(transformedPoints[2u] + endPointNormal * screenSpaceLineWidth / 2.0f + endPointTangent * screenSpaceLineWidth / 2.0f, 0.0, 1.0f);
295+
outV.position = float4(transformedPoints[2u] + endPointNormal * antiAliasedLineThickness + endPointTangent * antiAliasedLineThickness, 0.0, 1.0f);
297296
else if (vertexIdx == 2u)
298297
outV.position = float4(exterior1, 0.0, 1.0f);
299298
else if (vertexIdx == 3u)
@@ -310,9 +309,6 @@ PSInput main(uint vertexID : SV_VertexID)
310309

311310
if (lineStyle.isRoadStyleFlag)
312311
{
313-
const float sdfLineThickness = screenSpaceLineWidth / 2.0f;
314-
outV.setLineThickness(sdfLineThickness);
315-
316312
const double2 circleCenter = vk::RawBufferLoad<double2>(drawObj.geometryAddress, 8u);
317313
const float2 v = vk::RawBufferLoad<float2>(drawObj.geometryAddress + sizeof(double2), 8u);
318314
const float cosHalfAngleBetweenNormals = vk::RawBufferLoad<float>(drawObj.geometryAddress + sizeof(double2) + sizeof(float2), 8u);
@@ -342,7 +338,7 @@ PSInput main(uint vertexID : SV_VertexID)
342338

343339
if (vertexIdx == 0u)
344340
{
345-
const float2 V1 = normalize(mul(v, rotationMatrix)) * antiAliasedLineWidth;
341+
const float2 V1 = normalize(mul(v, rotationMatrix)) * antiAliasedLineThickness * 2.0f;
346342
const float2 screenSpaceV1 = circleCenterScreenSpace + V1;
347343
outV.position = float4(screenSpaceV1, 0.0f, 1.0f);
348344
}
@@ -353,13 +349,13 @@ PSInput main(uint vertexID : SV_VertexID)
353349
else if (vertexIdx == 2u)
354350
{
355351
// find intersection point vertex
356-
float2 intersectionPoint = v * antiAliasedLineWidth;
352+
float2 intersectionPoint = v * antiAliasedLineThickness * 2.0f;
357353
intersectionPoint += circleCenterScreenSpace;
358354
outV.position = float4(intersectionPoint, 0.0f, 1.0f);
359355
}
360356
else if (vertexIdx == 3u)
361357
{
362-
const float2 V2 = normalize(mul(rotationMatrix, v)) * antiAliasedLineWidth;
358+
const float2 V2 = normalize(mul(rotationMatrix, v)) * antiAliasedLineThickness * 2.0f;
363359
const float2 screenSpaceV2 = circleCenterScreenSpace + V2;
364360
outV.position = float4(screenSpaceV2, 0.0f, 1.0f);
365361
}

0 commit comments

Comments
 (0)