Created
October 21, 2020 16:31
-
-
Save Eideren/d85cd767917beffbc9031eba20aaf9f2 to your computer and use it in GitHub Desktop.
Stride, charly's tessellation issues
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef InputControlPointCount | |
# define InputControlPointCount 3 | |
#endif | |
#ifndef OutputControlPointCount | |
# define OutputControlPointCount 3 | |
#endif | |
shader TessCustom : ShaderBase, TransformationBase, MaterialDomainStream, Camera, Transformation, NormalBase | |
{ | |
cbuffer PerMaterial | |
{ | |
[Link("Tessellation.DesiredTriangleSize")] | |
stage float DesiredTriangleSize = 12.0f; | |
} | |
patchstream float tessFactor[3] : SV_TessFactor; | |
patchstream float insideTessFactor : SV_InsideTessFactor; | |
[maxvertexcount(18)] | |
stage void GSMain(triangle Input input [3], inout TriangleStream<Output> triangleStream) | |
{ | |
for (int i = 0; i < 6; ++i) | |
{ | |
for (int j = 0; j < 3; ++j) | |
{ | |
streams = input[j]; | |
streams.ShadingPosition = streams.Position; // Replace this garbage | |
triangleStream.Append(streams); | |
} | |
triangleStream.RestartStrip(); | |
} | |
} | |
[domain("tri")] | |
[partitioning("fractional_odd")] | |
[outputtopology("triangle_cw")] | |
[outputcontrolpoints(3)] | |
[patchconstantfunc("HSConstantMain")] | |
void HSMain(InputPatch<Input, InputControlPointCount> input, out Output output, uint uCPID : SV_OutputControlPointID) | |
{ | |
const uint NextCPID = uCPID < 2 ? uCPID + 1 : 0; | |
streams = input[uCPID]; | |
TessellateHull(input, uCPID, NextCPID); | |
// Compute screen space position of current control point and next one | |
// TODO: Reuse ShadingPosition? | |
// However, not sure if we can do tessellation directly through ShadingPosition interpolation (in which case we wouldn't need to do it in domain shader either) | |
float2 screenPosition0 = GetScreenSpacePosition(input[uCPID].PositionWS, ViewSize.x, ViewSize.y); | |
float2 screenPosition1 = GetScreenSpacePosition(input[NextCPID].PositionWS, ViewSize.x, ViewSize.y); | |
// Screen space tessellation based on desired triangle size | |
streams.oppositeEdgeLOD = distance(screenPosition0, screenPosition1) / DesiredTriangleSize; | |
output = streams; | |
} | |
void HSConstantMain(InputPatch<Input, InputControlPointCount> input, const OutputPatch<Input2, 3> output, out Constants constants) | |
{ | |
constants.tessFactor[0] = output[1].oppositeEdgeLOD; | |
constants.tessFactor[1] = output[2].oppositeEdgeLOD; | |
constants.tessFactor[2] = output[0].oppositeEdgeLOD; | |
constants.insideTessFactor = 0.33f * (constants.tessFactor[0] + constants.tessFactor[1] + constants.tessFactor[2]); | |
TessellateHullConstant(input, output, constants); | |
if (ComputeClipping(input, output, constants)) | |
{ | |
constants.tessFactor[0] = 0.0f; | |
constants.tessFactor[1] = 0.0f; | |
constants.tessFactor[2] = 0.0f; | |
constants.insideTessFactor = 0.0f; | |
} | |
} | |
[domain("tri")] | |
void DSMain(const OutputPatch<Input, OutputControlPointCount> input, out Output output, in Constants constants, float3 f3BarycentricCoords : SV_DomainLocation) | |
{ | |
InterpolateBarycentric(input, constants, f3BarycentricCoords); | |
this.BaseTransformDS(); | |
output = streams; | |
} | |
stage override void BaseTransformVS() | |
{ | |
this.PreTransformPosition(); | |
} | |
stage void BaseTransformDS() | |
{ | |
this.TransformPosition(); | |
this.PostTransformPosition(); | |
} | |
stage override void TransformPosition() | |
{ | |
base.TransformPosition(); | |
// Apply tessellation map, etc... | |
TessellateDomain(); | |
} | |
float2 GetScreenSpacePosition( | |
float4 f3Position, // View space position of patch control point | |
float fScreenWidth, // Screen width | |
float fScreenHeight // Screen height | |
) | |
{ | |
float4 f4ProjectedPosition = this.ComputeShadingPosition(f3Position); | |
float2 f2ScreenPosition = f4ProjectedPosition.xy / f4ProjectedPosition.w; | |
f2ScreenPosition = ( f2ScreenPosition + 1.0f ) * 0.5f * float2( fScreenWidth, -fScreenHeight ); | |
return f2ScreenPosition; | |
} | |
stage void TessellateHull(InputPatch<Input, InputControlPointCount> input, uint uCPID, uint NextCPID) {} | |
stage void TessellateHullConstant(InputPatch<Input, InputControlPointCount> input, const OutputPatch<Input2, 3> output, inout Constants constants) {} | |
stage void TessellateDomain() {} | |
override stage void GenerateNormal_VS() | |
{ | |
base.GenerateNormal_VS(); | |
// Ensure that normal is normalized at every steps of the tessellation. | |
streams.normalWS = normalize(streams.normalWS); | |
} | |
float ComputeClipping(InputPatch<Input, InputControlPointCount> input, const OutputPatch<Input2, 3> output, inout Constants constants) | |
{ | |
return ComputeClippingGroup3(input[0].PositionWS, input[1].PositionWS, input[2].PositionWS); | |
} | |
float ComputeClippingGroup3(float4 f3Position1, float4 f3Position2, float4 f3Position3) | |
{ | |
float4 clipPos1 = this.ComputeShadingPosition(float4(f3Position1.xyz, 1.0f)); | |
float4 clipPos2 = this.ComputeShadingPosition(float4(f3Position2.xyz, 1.0f)); | |
float4 clipPos3 = this.ComputeShadingPosition(float4(f3Position3.xyz, 1.0f)); | |
float3 clipPos1P = sign(clipPos1.xyz + clipPos1.www); | |
float3 clipPos1M = sign(clipPos1.xyz - clipPos1.www); | |
float3 clipPos2P = sign(clipPos2.xyz + clipPos2.www); | |
float3 clipPos2M = sign(clipPos2.xyz - clipPos2.www); | |
float3 clipPos3P = sign(clipPos3.xyz + clipPos3.www); | |
float3 clipPos3M = sign(clipPos3.xyz - clipPos3.www); | |
float3 planeTests = abs(clipPos1P + clipPos1M + clipPos2P + clipPos2M + clipPos3P + clipPos3M); | |
return all(planeTests != 6.0f) ? 0.0 : 1.0; | |
} | |
void InterpolateBarycentric(const OutputPatch<Input, 3> input, in Constants constants, float3 f3BarycentricCoords) | |
{ | |
//streams = input[0] * fU + input[1] * fV + input[2] * fW; | |
float fU = f3BarycentricCoords.x; | |
float fV = f3BarycentricCoords.y; | |
float fW = f3BarycentricCoords.z; | |
streams = input[0] * fU + input[1] * fV + input[2] * fW; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace %YOUR_PROJECT_NAMESPACE_GOES_HERE.RENDERING_MAYBE? | |
{ | |
using Stride.Core; | |
using Stride.Rendering; | |
using Stride.Rendering.Materials; | |
using Stride.Shaders; | |
[DataContract("TessCustomFeature")] | |
[Display("Custom Tessellation")] | |
public class TessCustomFeature : MaterialTessellationBaseFeature | |
{ | |
public override void GenerateShader(MaterialGeneratorContext context) | |
{ | |
base.GenerateShader(context); | |
if (hasAlreadyTessellationFeature) | |
return; | |
// set the tessellation method used enumeration | |
context.MaterialPass.TessellationMethod |= StrideTessellationMethod.Flat; | |
// create and affect the shader source | |
var tessellationShader = new ShaderMixinSource(); | |
tessellationShader.Mixins.Add(new ShaderClassSource("TessCustom")); | |
context.Parameters.Set(MaterialKeys.TessellationShader, tessellationShader); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment