forked from LukasBanana/LLGL
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExample.metal
More file actions
170 lines (137 loc) · 4.41 KB
/
Example.metal
File metadata and controls
170 lines (137 loc) · 4.41 KB
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Metal shader
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
// SCENE SHADERS
struct SceneSettings
{
float4x4 wvpMatrix;
float4x4 wMatrix;
float4 diffuse;
float4 glossiness;
float intensity;
};
struct InputVScene
{
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
};
struct OutputVScene
{
float4 position [[position]];
float3 normal;
};
vertex OutputVScene VScene(
InputVScene inp [[stage_in]],
constant SceneSettings& settings [[buffer(1)]])
{
OutputVScene outp;
outp.position = settings.wvpMatrix * float4(inp.position, 1);
outp.normal = (settings.wMatrix * float4(inp.normal, 0)).xyz;
return outp;
}
struct OutputPScene
{
float4 color [[color(0)]];
float4 gloss [[color(1)]];
};
fragment OutputPScene PScene(
OutputVScene inp [[stage_in]],
constant SceneSettings& settings [[buffer(1)]])
{
OutputPScene outp;
// Write simple lighting into 1st render target
float3 lightDir = float3(0, 0, -1);
float3 normal = normalize(inp.normal);
float NdotL = max(0.4, dot(lightDir, normal));
outp.color = settings.diffuse * float4((float3)NdotL, 1);
// Write glossiness into 2nd render target
outp.gloss = settings.glossiness;
return outp;
}
// POST-PROCESSING SHADERS
/*
This function generates the coordinates for a fullscreen triangle with its vertex IDs:
(-1,+3)
*
| \
| \
| \
| \
(-1,+1) (+1,+1)
*----------*\
| | \
| screen | \
| | \
*----------*--------*
(-1,-1) (+1,-1) (+3,-1)
*/
float4 GetFullscreenTriangleVertex(uint id)
{
return float4(
(id == 2 ? 3.0 : -1.0),
(id == 0 ? 3.0 : -1.0),
1.0,
1.0
);
}
struct BlurSettings
{
float2 blurShift;
};
struct OutputVPP
{
float4 position [[position]];
float2 texCoord;
};
vertex OutputVPP VPP(uint id [[vertex_id]])
{
OutputVPP outp;
// Generate coorindate for fullscreen triangle
outp.position = GetFullscreenTriangleVertex(id);
// Get texture-coordinate from vertex position
outp.texCoord = outp.position.xy * float2(0.5, -0.5) + 0.5;
return outp;
}
// Static values for the 1-dimensional gaussian kernel (sigma = 2.2, size = 11)
// see http://dev.theomader.com/gaussian-kernel-calculator/
#define GAUSSIAN_KERNEL_1 0.014374
#define GAUSSIAN_KERNEL_2 0.035855
#define GAUSSIAN_KERNEL_3 0.072994
#define GAUSSIAN_KERNEL_4 0.121281
#define GAUSSIAN_KERNEL_5 0.164472
#define GAUSSIAN_KERNEL_6 0.182049
fragment float4 PBlur(
OutputVPP inp [[stage_in]],
constant BlurSettings& settings [[buffer(2)]],
texture2d<float> glossMap [[texture(4)]],
sampler glossMapSampler [[sampler(6)]])
{
// Accumulate the samples with the gaussian kernel
float4 c = (float4)0;
c += glossMap.sample(glossMapSampler, inp.texCoord - settings.blurShift*5) * GAUSSIAN_KERNEL_1;
c += glossMap.sample(glossMapSampler, inp.texCoord - settings.blurShift*4) * GAUSSIAN_KERNEL_2;
c += glossMap.sample(glossMapSampler, inp.texCoord - settings.blurShift*3) * GAUSSIAN_KERNEL_3;
c += glossMap.sample(glossMapSampler, inp.texCoord - settings.blurShift*2) * GAUSSIAN_KERNEL_4;
c += glossMap.sample(glossMapSampler, inp.texCoord - settings.blurShift ) * GAUSSIAN_KERNEL_5;
c += glossMap.sample(glossMapSampler, inp.texCoord ) * GAUSSIAN_KERNEL_6;
c += glossMap.sample(glossMapSampler, inp.texCoord + settings.blurShift ) * GAUSSIAN_KERNEL_5;
c += glossMap.sample(glossMapSampler, inp.texCoord + settings.blurShift*2) * GAUSSIAN_KERNEL_4;
c += glossMap.sample(glossMapSampler, inp.texCoord + settings.blurShift*3) * GAUSSIAN_KERNEL_3;
c += glossMap.sample(glossMapSampler, inp.texCoord + settings.blurShift*4) * GAUSSIAN_KERNEL_2;
c += glossMap.sample(glossMapSampler, inp.texCoord + settings.blurShift*5) * GAUSSIAN_KERNEL_1;
return c;
}
fragment float4 PFinal(
OutputVPP inp [[stage_in]],
constant SceneSettings& settings [[buffer(1)]],
texture2d<float> colorMap [[texture(3)]],
texture2d<float> glossMap [[texture(4)]],
sampler colorMapSampler [[sampler(5)]],
sampler glossMapSampler [[sampler(6)]])
{
// Show final result with color and gloss map
return
colorMap.sample(colorMapSampler, inp.texCoord) +
glossMap.sample(glossMapSampler, inp.texCoord) * settings.intensity;
};