SPIRV-Cross/shaders-msl/tese/water_tess.tese
Chip Davis e75add42c9 MSL: Add support for tessellation evaluation shaders.
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.
2019-02-14 10:00:08 -06:00

66 lines
1.8 KiB
GLSL

#version 310 es
#extension GL_EXT_tessellation_shader : require
precision highp int;
layout(cw, quads, fractional_even_spacing) in;
layout(location = 0) patch in vec2 vOutPatchPosBase;
layout(location = 1) patch in vec4 vPatchLods;
layout(binding = 1, std140) uniform UBO
{
mat4 uMVP;
vec4 uScale;
vec2 uInvScale;
vec3 uCamPos;
vec2 uPatchSize;
vec2 uInvHeightmapSize;
};
layout(binding = 0) uniform mediump sampler2D uHeightmapDisplacement;
layout(location = 0) highp out vec3 vWorld;
layout(location = 1) highp out vec4 vGradNormalTex;
vec2 lerp_vertex(vec2 tess_coord)
{
return vOutPatchPosBase + tess_coord * uPatchSize;
}
mediump vec2 lod_factor(vec2 tess_coord)
{
mediump vec2 x = mix(vPatchLods.yx, vPatchLods.zw, tess_coord.x);
mediump float level = mix(x.x, x.y, tess_coord.y);
mediump float floor_level = floor(level);
mediump float fract_level = level - floor_level;
return vec2(floor_level, fract_level);
}
mediump vec3 sample_height_displacement(vec2 uv, vec2 off, mediump vec2 lod)
{
return mix(
textureLod(uHeightmapDisplacement, uv + 0.5 * off, lod.x).xyz,
textureLod(uHeightmapDisplacement, uv + 1.0 * off, lod.x + 1.0).xyz,
lod.y);
}
void main()
{
vec2 tess_coord = gl_TessCoord.xy;
vec2 pos = lerp_vertex(tess_coord);
mediump vec2 lod = lod_factor(tess_coord);
vec2 tex = pos * uInvHeightmapSize.xy;
pos *= uScale.xy;
mediump float delta_mod = exp2(lod.x);
vec2 off = uInvHeightmapSize.xy * delta_mod;
vGradNormalTex = vec4(tex + 0.5 * uInvHeightmapSize.xy, tex * uScale.zw);
vec3 height_displacement = sample_height_displacement(tex, off, lod);
pos += height_displacement.yz;
vWorld = vec3(pos.x, height_displacement.x, pos.y);
gl_Position = uMVP * vec4(vWorld, 1.0);
}