Saturday, October 28, 2017

Barycentric Coordinates in Pixel Shader

I needed a way to perform smooth blending between per vertex materials.
Basically I needed barycentric coordinates + access to each vertices material in the pixel shader.

Geometry Shader method:  Assign the coordinates: (1,0,0), (0,1,0), (0,0,1) to the vertices of the triangle.  Also write the three materials to each vertex.
This method is easy to implement but has terrible performance on many cards, since it requires a geometry shader.  When enabled on my AMD card, FPS drops to half or less.

AMD AGS Driver extension:  AMD has a library called AGS_SDK which exposes driver extensions, one of these is direct access to barycentric coordinates in the pixel shader.  It also allows for direct access to any of the attributes from the 3 vertices that make up the triangle.
This method is very fast and works well if you have an AMD card that supports it.

float2 bary2d = AmdDxExtShaderIntrinsics_IjBarycentricCoords(AmdDxExtShaderIntrinsicsBarycentric_PerspCenter);
 //reconstruct the 3rd coordinate
float3 bary = float3(1.0 - bary2d.x - bary2d.y, bary2d.y, bary2d.x);

//extract materials
float m0 = AmdDxExtShaderIntrinsics_VertexParameterComponent(0, 1, 0);
float m1 = AmdDxExtShaderIntrinsics_VertexParameterComponent(1, 1, 0);
float m2 = AmdDxExtShaderIntrinsics_VertexParameterComponent(2, 1, 0);

Nvidia FastGeometryShader: Nvidia also have driver extensions(NVAPI), and one of these is the the "fast geometry shader" for when you only need a subset of the features geometry shaders offer.
 It should be possible to use this to pass down barycentric coordinates & materials , but I do not have an Nvidia card to test this on.

Domain Shader?: I haven't tried this method, but I think it might be possible to pass down barycentric coordinates from a domain shader?

Embed Into Vertex Data: Another option is to enlarge the vertex, and embed the barycentric coordinates and the 3 materials directly into it.
 This is probably a better fallback than the GS, although it does have the downside of reducing vertex reuse, since many vertices that were previously identical would now differ.

No comments:

Post a Comment