1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include <metal_stdlib>
using namespace metal;
struct VertexToFragment {
float2 tex;
float4 pos [[position]];
};
struct SourceRegion {
float2 UVLeftTop;
float2 UVDimensions;
uint MipLevel;
float LayerOrDepth;
};
#if COMPILE_FullscreenVert
vertex VertexToFragment FullscreenVert(uint vI [[vertex_id]]) {
float2 inTex = float2((vI << 1) & 2, vI & 2);
VertexToFragment out;
out.tex = inTex;
out.pos = float4(inTex * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
return out;
}
#endif
#if COMPILE_BlitFrom2D
fragment float4 BlitFrom2D(
VertexToFragment input [[stage_in]],
constant SourceRegion &sourceRegion [[buffer(0)]],
texture2d<float> sourceTexture [[texture(0)]],
sampler sourceSampler [[sampler(0)]])
{
float2 newCoord = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
return sourceTexture.sample(sourceSampler, newCoord, level(sourceRegion.MipLevel));
}
#endif
#if COMPILE_BlitFrom2DArray
fragment float4 BlitFrom2DArray(
VertexToFragment input [[stage_in]],
constant SourceRegion &sourceRegion [[buffer(0)]],
texture2d_array<float> sourceTexture [[texture(0)]],
sampler sourceSampler [[sampler(0)]])
{
float2 newCoord = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
return sourceTexture.sample(sourceSampler, newCoord, (uint)sourceRegion.LayerOrDepth, level(sourceRegion.MipLevel));
}
#endif
#if COMPILE_BlitFrom3D
fragment float4 BlitFrom3D(
VertexToFragment input [[stage_in]],
constant SourceRegion &sourceRegion [[buffer(0)]],
texture3d<float> sourceTexture [[texture(0)]],
sampler sourceSampler [[sampler(0)]])
{
float2 newCoord = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
return sourceTexture.sample(sourceSampler, float3(newCoord, sourceRegion.LayerOrDepth), level(sourceRegion.MipLevel));
}
#endif
#if COMPILE_BlitFromCube
fragment float4 BlitFromCube(
VertexToFragment input [[stage_in]],
constant SourceRegion &sourceRegion [[buffer(0)]],
texturecube<float> sourceTexture [[texture(0)]],
sampler sourceSampler [[sampler(0)]])
{
// Thanks, Wikipedia! https://en.wikipedia.org/wiki/Cube_mapping
float2 scaledUV = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
float u = 2.0 * scaledUV.x - 1.0;
float v = 2.0 * scaledUV.y - 1.0;
float3 newCoord;
switch ((uint)sourceRegion.LayerOrDepth) {
case 0: newCoord = float3(1.0, -v, -u); break; // POSITIVE X
case 1: newCoord = float3(-1.0, -v, u); break; // NEGATIVE X
case 2: newCoord = float3(u, 1.0, -v); break; // POSITIVE Y
case 3: newCoord = float3(u, -1.0, v); break; // NEGATIVE Y
case 4: newCoord = float3(u, -v, 1.0); break; // POSITIVE Z
case 5: newCoord = float3(-u, -v, -1.0); break; // NEGATIVE Z
default: newCoord = float3(0, 0, 0); break; // silences warning
}
return sourceTexture.sample(sourceSampler, newCoord, level(sourceRegion.MipLevel));
}
#endif
#if COMPILE_BlitFromCubeArray
fragment float4 BlitFromCubeArray(
VertexToFragment input [[stage_in]],
constant SourceRegion &sourceRegion [[buffer(0)]],
texturecube_array<float> sourceTexture [[texture(0)]],
sampler sourceSampler [[sampler(0)]])
{
// Thanks, Wikipedia! https://en.wikipedia.org/wiki/Cube_mapping
float2 scaledUV = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
float u = 2.0 * scaledUV.x - 1.0;
float v = 2.0 * scaledUV.y - 1.0;
float3 newCoord;
switch (((uint)sourceRegion.LayerOrDepth) % 6) {
case 0: newCoord = float3(1.0, -v, -u); break; // POSITIVE X
case 1: newCoord = float3(-1.0, -v, u); break; // NEGATIVE X
case 2: newCoord = float3(u, 1.0, -v); break; // POSITIVE Y
case 3: newCoord = float3(u, -1.0, v); break; // NEGATIVE Y
case 4: newCoord = float3(u, -v, 1.0); break; // POSITIVE Z
case 5: newCoord = float3(-u, -v, -1.0); break; // NEGATIVE Z
default: newCoord = float3(0, 0, 0); break; // silences warning
}
return sourceTexture.sample(sourceSampler, newCoord, (uint)sourceRegion.LayerOrDepth / 6, level(sourceRegion.MipLevel));
}
#endif
|