e75add42c9
These are mapped to Metal's post-tessellation vertex functions. The semantic difference is much less here, so this change should be simpler than the previous one. There are still some hairy parts, though. In MSL, the array of control point data is represented by a special type, `patch_control_point<T>`, where `T` is a valid stage-input type. This object must be embedded inside the patch-level stage input. For this reason, I've added a new type to the type system to represent this. On Mac, the number of input control points to the function must be specified in the `patch()` attribute. This is optional on iOS. SPIRV-Cross takes this from the `OutputVertices` execution mode; the intent is that if it's not set in the shader itself, MoltenVK will set it from the tessellation control shader. If you're translating these offline, you'll have to update the control point count manually, since this number must match the number that is passed to the `drawPatches:...` family of methods. Fixes #120.
73 lines
2.6 KiB
GLSL
73 lines
2.6 KiB
GLSL
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
|
|
#include <metal_stdlib>
|
|
#include <simd/simd.h>
|
|
|
|
using namespace metal;
|
|
|
|
struct UBO
|
|
{
|
|
float4x4 uMVP;
|
|
float4 uScale;
|
|
float2 uInvScale;
|
|
float3 uCamPos;
|
|
float2 uPatchSize;
|
|
float2 uInvHeightmapSize;
|
|
};
|
|
|
|
struct main0_out
|
|
{
|
|
float3 vWorld [[user(locn0)]];
|
|
float4 vGradNormalTex [[user(locn1)]];
|
|
float4 gl_Position [[position]];
|
|
};
|
|
|
|
struct main0_patchIn
|
|
{
|
|
float2 vOutPatchPosBase [[attribute(0)]];
|
|
float4 vPatchLods [[attribute(1)]];
|
|
};
|
|
|
|
float2 lerp_vertex(thread const float2& tess_coord, thread float2& vOutPatchPosBase, constant UBO& v_31)
|
|
{
|
|
return vOutPatchPosBase + (tess_coord * v_31.uPatchSize);
|
|
}
|
|
|
|
float2 lod_factor(thread const float2& tess_coord, thread float4& vPatchLods)
|
|
{
|
|
float2 x = mix(vPatchLods.yx, vPatchLods.zw, float2(tess_coord.x));
|
|
float level = mix(x.x, x.y, tess_coord.y);
|
|
float floor_level = floor(level);
|
|
float fract_level = level - floor_level;
|
|
return float2(floor_level, fract_level);
|
|
}
|
|
|
|
float3 sample_height_displacement(thread const float2& uv, thread const float2& off, thread const float2& lod, thread texture2d<float> uHeightmapDisplacement, thread const sampler uHeightmapDisplacementSmplr)
|
|
{
|
|
return mix(uHeightmapDisplacement.sample(uHeightmapDisplacementSmplr, (uv + (off * 0.5)), level(lod.x)).xyz, uHeightmapDisplacement.sample(uHeightmapDisplacementSmplr, (uv + (off * 1.0)), level(lod.x + 1.0)).xyz, float3(lod.y));
|
|
}
|
|
|
|
[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], constant UBO& v_31 [[buffer(1)]], texture2d<float> uHeightmapDisplacement [[texture(0)]], sampler uHeightmapDisplacementSmplr [[sampler(0)]], float2 gl_TessCoord [[position_in_patch]])
|
|
{
|
|
main0_out out = {};
|
|
float2 tess_coord = gl_TessCoord.xy;
|
|
float2 param = tess_coord;
|
|
float2 pos = lerp_vertex(param, patchIn.vOutPatchPosBase, v_31);
|
|
float2 param_1 = tess_coord;
|
|
float2 lod = lod_factor(param_1, patchIn.vPatchLods);
|
|
float2 tex = pos * v_31.uInvHeightmapSize;
|
|
pos *= v_31.uScale.xy;
|
|
float delta_mod = exp2(lod.x);
|
|
float2 off = v_31.uInvHeightmapSize * delta_mod;
|
|
out.vGradNormalTex = float4(tex + (v_31.uInvHeightmapSize * 0.5), tex * v_31.uScale.zw);
|
|
float2 param_2 = tex;
|
|
float2 param_3 = off;
|
|
float2 param_4 = lod;
|
|
float3 height_displacement = sample_height_displacement(param_2, param_3, param_4, uHeightmapDisplacement, uHeightmapDisplacementSmplr);
|
|
pos += height_displacement.yz;
|
|
out.vWorld = float3(pos.x, height_displacement.x, pos.y);
|
|
out.gl_Position = v_31.uMVP * float4(out.vWorld, 1.0);
|
|
return out;
|
|
}
|
|
|