// A point on line might be far away, causing clipping ratio (clipLineSegmentEnd) to become extremely close to 1.0
// even if the another point is not on the plane. Prevent clipping ratio from saturating by using points on line
// that are (nearly) on this and (nearly) on the opposite plane.
- const ClipVec4 clippedV0 = tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
- const ClipVec4 clippedV1 = tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
- // Find intersection point of line from v0 to v1 and the current plane.
- return tcu::mix(clippedV0, clippedV1, clipLineSegmentEnd(clippedV0, clippedV1));
+ const ClipVec4 clippedV0 = tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
+ const ClipVec4 clippedV1 = tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
+ const ClipFloat clipRatio = clipLineSegmentEnd(clippedV0, clippedV1);
+
+ // Find intersection point of line from v0 to v1 and the current plane. Avoid ratios near 1.0
+ if (clipRatio <= (ClipFloat)0.5)
+ return tcu::mix(clippedV0, clippedV1, clipRatio);
+ else
+ {
+ const ClipFloat complementClipRatio = clipLineSegmentEnd(clippedV1, clippedV0);
+ return tcu::mix(clippedV1, clippedV0, complementClipRatio);
+ }
}
struct TriangleVertex
bool outputDegenerate = false;
{
- const TriangleVertex& inside = v1;
- const TriangleVertex& outside = clipped;
- TriangleVertex& middle = mid1;
+ const TriangleVertex& inside = v1;
+ const TriangleVertex& outside = clipped;
+ TriangleVertex& middle = mid1;
- const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
- DE_ASSERT(hitDist >= (ClipFloat)0.0);
+ const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
if (hitDist >= degenerateLimit)
{
}
{
- const TriangleVertex& inside = v2;
- const TriangleVertex& outside = clipped;
- TriangleVertex& middle = mid2;
+ const TriangleVertex& inside = v2;
+ const TriangleVertex& outside = clipped;
+ TriangleVertex& middle = mid2;
- const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
- DE_ASSERT(hitDist >= (ClipFloat)0.0);
+ const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
if (hitDist >= degenerateLimit)
{
void clipTriangleTwoVertices (std::vector<TriangleVertex>& clippedEdges, const ClipVolumePlane& plane, const TriangleVertex& v0, const TriangleVertex& clipped1, const TriangleVertex& clipped2)
{
- const ClipFloat degenerateLimit = (ClipFloat)1.0;
+ const ClipFloat unclippableLimit = (ClipFloat)1.0;
// calc clip pos
TriangleVertex mid1;
TriangleVertex mid2;
- bool outputDegenerate = false;
+ bool unclippableVertex1 = false;
+ bool unclippableVertex2 = false;
{
- const TriangleVertex& inside = v0;
- const TriangleVertex& outside = clipped1;
- TriangleVertex& middle = mid1;
+ const TriangleVertex& inside = v0;
+ const TriangleVertex& outside = clipped1;
+ TriangleVertex& middle = mid1;
- const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
- DE_ASSERT(hitDist >= (ClipFloat)0.0);
+ const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
- if (hitDist >= degenerateLimit)
+ if (hitDist >= unclippableLimit)
{
- // do not generate degenerate triangles
- outputDegenerate = true;
+ // this edge cannot be clipped because the edge is really close to the volume boundary
+ unclippableVertex1 = true;
}
else
{
}
{
- const TriangleVertex& inside = v0;
- const TriangleVertex& outside = clipped2;
- TriangleVertex& middle = mid2;
+ const TriangleVertex& inside = v0;
+ const TriangleVertex& outside = clipped2;
+ TriangleVertex& middle = mid2;
- const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
- DE_ASSERT(hitDist >= (ClipFloat)0.0);
+ const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
- if (hitDist >= degenerateLimit)
+ if (hitDist >= unclippableLimit)
{
- // do not generate degenerate triangles
- outputDegenerate = true;
+ // this edge cannot be clipped because the edge is really close to the volume boundary
+ unclippableVertex2 = true;
}
else
{
}
}
- if (!outputDegenerate)
+ if (!unclippableVertex1 && !unclippableVertex2)
{
// gen triangle (v0) -> mid1 -> mid2
clippedEdges.push_back(v0);
clippedEdges.push_back(mid1);
clippedEdges.push_back(mid2);
}
+ else if (!unclippableVertex1 && unclippableVertex2)
+ {
+ // clip just vertex 1
+ clippedEdges.push_back(v0);
+ clippedEdges.push_back(mid1);
+ clippedEdges.push_back(clipped2);
+ }
+ else if (unclippableVertex1 && !unclippableVertex2)
+ {
+ // clip just vertex 2
+ clippedEdges.push_back(v0);
+ clippedEdges.push_back(clipped1);
+ clippedEdges.push_back(mid2);
+ }
else
{
// don't modify
{
std::vector<TriangleVertex> convexPrimitive;
- // Clip triangle and form a convex n-gon ( n c {2, 3} )
+ // Clip triangle and form a convex n-gon ( n c {3, 4} )
clipTriangleToPlane(convexPrimitive, subTriangles[subTriangleNdx].vertices, *planes[planeNdx]);
// Subtriangle completely discarded
}
}
-static tcu::TextureLevel getPixels (const glu::RenderContext& renderCtx, const IVec2& size, const tcu::TextureFormat& colorBufferFormat)
-{
- tcu::TextureLevel result(colorBufferFormat, size.x(), size.y());
- glu::readPixels(renderCtx, 0, 0, result.getAccess());
- return result;
-}
-
static inline bool isDepthFormat (const tcu::TextureFormat& fmt)
{
return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
type == tcu::TextureFormat::UNSIGNED_INT32;
}
+static tcu::TextureLevel getPixels (const glu::RenderContext& renderCtx, const IVec2& size, const tcu::TextureFormat& colorBufferFormat)
+{
+ tcu::TextureLevel result(colorBufferFormat, size.x(), size.y());
+
+ // only a few pixel formats are guaranteed to be valid targets for readPixels, convert the rest
+ if (colorBufferFormat.order == tcu::TextureFormat::RGBA &&
+ (colorBufferFormat.type == tcu::TextureFormat::UNORM_INT8 ||
+ colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT32 ||
+ colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT32))
+ {
+ // valid as is
+ glu::readPixels(renderCtx, 0, 0, result.getAccess());
+ }
+ else if (colorBufferFormat.order == tcu::TextureFormat::RGBA &&
+ (isSIntFormatType(colorBufferFormat.type) ||
+ isUIntFormatType(colorBufferFormat.type)))
+ {
+ // signed and unsigned integers must be read using 32-bit values
+ const bool isSigned = isSIntFormatType(colorBufferFormat.type);
+ tcu::TextureLevel readResult (tcu::TextureFormat(tcu::TextureFormat::RGBA,
+ (isSigned) ? (tcu::TextureFormat::SIGNED_INT32) : (tcu::TextureFormat::UNSIGNED_INT32)),
+ size.x(),
+ size.y());
+
+ glu::readPixels(renderCtx, 0, 0, readResult.getAccess());
+ tcu::copy(result.getAccess(), readResult.getAccess());
+ }
+ else
+ {
+ // unreadable format
+ DE_ASSERT(false);
+ }
+
+ return result;
+}
+
enum TextureSwizzleComponent
{
TEXTURESWIZZLECOMPONENT_R = 0,