-
Notifications
You must be signed in to change notification settings - Fork 204
/
gfx_bloom_shader.lua
584 lines (483 loc) · 17.3 KB
/
gfx_bloom_shader.lua
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
function widget:GetInfo()
return {
name = "Bloom Shader",
desc = "Sets Spring In Bloom",
author = "Floris", -- orginal bloom shader: Kloot
date = "24-9-2016",
license = "",
layer = 9,
enabled = false,
}
end
--------------------------------------------------------------------------------
-- config
--------------------------------------------------------------------------------
local basicAlpha = 0.4
local drawHighlights = false -- apply extra bloom bright spots (note: quite costly)
local highlightsAlpha = 0.35
local dbgDraw = 0 -- debug: draw only the bloom-mask?
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local drawWorldAlpha = 0
local drawWorldPreUnitAlpha = 0
local usedBasicAlpha = basicAlpha
local camX, camY, camZ = Spring.GetCameraPosition()
local camDirX,camDirY,camDirZ = Spring.GetCameraDirection()
-- shader and texture handles
local blurShaderH71 = nil
local blurShaderV71 = nil
local brightShader = nil
local brightTexture1 = nil
local brightTexture2 = nil
local brightTexture3 = nil
local brightTexture4 = nil
local combineShader = nil
local screenTexture = nil
local screenTextureQuarter = nil
local screenTextureSixteenth = nil
-- speedups
local glCreateTexture = gl.CreateTexture
local glActiveTexture = gl.ActiveTexture
local glCopyToTexture = gl.CopyToTexture
local glRenderToTexture = gl.RenderToTexture
local glTexture = gl.Texture
local glTexRect = gl.TexRect
local glUseShader = gl.UseShader
local glUniformInt = gl.UniformInt
local glUniform = gl.Uniform
local glGetUniformLocation = gl.GetUniformLocation
local glGetActiveUniforms = gl.GetActiveUniforms
local GL_RGBA32F_ARB = 0x8814
local GL_RGB32F_ARB = 0x8815
local GL_ALPHA32F_ARB = 0x8816
local GL_INTENSITY32F_ARB = 0x8817
local GL_LUMINANCE32F_ARB = 0x8818
local GL_LUMINANCE_ALPHA32F_ARB = 0x8819
local GL_RGBA16F_ARB = 0x881A
local GL_RGB16F_ARB = 0x881B
local GL_ALPHA16F_ARB = 0x881C
local GL_INTENSITY16F_ARB = 0x881D
local GL_LUMINANCE16F_ARB = 0x881E
local GL_LUMINANCE_ALPHA16F_ARB = 0x881F
local GL_TEXTURE_RED_TYPE_ARB = 0x8C10
local GL_TEXTURE_GREEN_TYPE_ARB = 0x8C11
local GL_TEXTURE_BLUE_TYPE_ARB = 0x8C12
local GL_TEXTURE_ALPHA_TYPE_ARB = 0x8C13
local GL_TEXTURE_LUMINANCE_TYPE_ARB = 0x8C14
local GL_TEXTURE_INTENSITY_TYPE_ARB = 0x8C15
local GL_TEXTURE_DEPTH_TYPE_ARB = 0x8C16
local GL_UNSIGNED_NORMALIZED_ARB = 0x8C17
-- shader uniform locations
local brightShaderText0Loc = nil
local brightShaderInvRXLoc = nil
local brightShaderInvRYLoc = nil
local brightShaderIllumLoc = nil
local blurShaderH51Text0Loc = nil
local blurShaderH51InvRXLoc = nil
local blurShaderH51FragLoc = nil
local blurShaderV51Text0Loc = nil
local blurShaderV51InvRYLoc = nil
local blurShaderV51FragLoc = nil
local blurShaderH71Text0Loc = nil
local blurShaderH71InvRXLoc = nil
local blurShaderH71FragLoc = nil
local blurShaderV71Text0Loc = nil
local blurShaderV71InvRYLoc = nil
local blurShaderV71FragLoc = nil
local combineShaderDebgDrawLoc = nil
local combineShaderTexture0Loc = nil
local combineShaderTexture1Loc = nil
local combineShaderIllumLoc = nil
local combineShaderFragLoc = nil
local illumThreshold = 0.33
local function SetIllumThreshold()
local ra, ga, ba = gl.GetSun("ambient")
local rd, gd, bd = gl.GetSun("diffuse")
local rs, gs, bs = gl.GetSun("specular")
local ambientIntensity = ra * 0.299 + ga * 0.587 + ba * 0.114
local diffuseIntensity = rd * 0.299 + gd * 0.587 + bd * 0.114
local specularIntensity = rs * 0.299 + gs * 0.587 + bs * 0.114
--Spring.Echo(ambientIntensity..' '..diffuseIntensity..' '..specularIntensity)
illumThreshold = (0.33 * ambientIntensity) + (0.05 * diffuseIntensity) + (0.05 * specularIntensity)
end
local function RemoveMe(msg)
Spring.Echo(msg)
--widgetHandler:RemoveWidget(self)
end
function reset()
--if not initialized then return end
if drawHighlights then
usedBasicAlpha = basicAlpha
drawWorldAlpha = 0.2 - (illumThreshold*0.4) + (usedBasicAlpha/11) + (0.018 * highlightsAlpha)
drawWorldPreUnitAlpha = 0.16 - (illumThreshold*0.4) + (usedBasicAlpha/6.2) + (0.023 * highlightsAlpha)
else
usedBasicAlpha = basicAlpha
drawWorldAlpha = 0.035 + (usedBasicAlpha/11)
drawWorldPreUnitAlpha = 0.2 - (illumThreshold*0.4) + (usedBasicAlpha/6)
end
gl.DeleteTexture(brightTexture1 or "")
gl.DeleteTexture(brightTexture2 or "")
if drawHighlights then
gl.DeleteTexture(brightTexture3 or "")
gl.DeleteTexture(brightTexture4 or "")
end
gl.DeleteTexture(screenTexture or "")
local btQuality = 4.6 -- high value creates flickering, but lower is more expensive
brightTexture1 = glCreateTexture(vsx/btQuality, vsy/btQuality, {
fbo = true, min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
format = GL_RGB16F_ARB, wrap_s = GL.CLAMP, wrap_t = GL.CLAMP,
})
brightTexture2 = glCreateTexture(vsx/btQuality, vsy/btQuality, {
fbo = true, min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
format = GL_RGB16F_ARB, wrap_s = GL.CLAMP, wrap_t = GL.CLAMP,
})
if drawHighlights then
btQuality = 3.2 -- high value creates flickering, but lower is more expensive
brightTexture3 = glCreateTexture(vsx/btQuality, vsy/btQuality, {
fbo = true, min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
format = GL_RGB16F_ARB, wrap_s = GL.CLAMP, wrap_t = GL.CLAMP,
})
brightTexture4 = glCreateTexture(vsx/btQuality, vsy/btQuality, {
fbo = true, min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
format = GL_RGB16F_ARB, wrap_s = GL.CLAMP, wrap_t = GL.CLAMP,
})
end
screenTexture = glCreateTexture(vsx, vsy, {
min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
})
screenTextureQuarter = glCreateTexture(vsx/2, vsy/2, {
min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
})
screenTextureSixteenth = glCreateTexture(vsx/4, vsy/4, {
min_filter = GL.LINEAR, mag_filter = GL.LINEAR,
})
end
function widget:ViewResize(viewSizeX, viewSizeY)
vsx,vsy = gl.GetViewSizes()
ivsx = 1.0 / vsx
ivsy = 1.0 / vsy
kernelRadius = vsy / 80.0
kernelRadius2 = vsy / 30.0
reset()
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function widget:Update(dt)
if initialized == false then
return
end
camX, camY, camZ = Spring.GetCameraPosition()
camDirX,camDirY,camDirZ = Spring.GetCameraDirection()
end
function widget:DrawWorldPreUnit()
if initialized == false or drawWorldPreUnitAlpha <= 0.05 then
return
end
gl.PushMatrix()
gl.Color(0,0,0,drawWorldPreUnitAlpha)
gl.Translate(camX+(camDirX*360),camY+(camDirY*360),camZ+(camDirZ*360))
gl.Billboard()
gl.Rect(-500, -500, 500, 500)
gl.PopMatrix()
end
function widget:DrawWorld()
if initialized == false or drawWorldAlpha <= 0.05 then
return
end
gl.PushMatrix()
gl.Color(0,0,0,drawWorldAlpha)
gl.Translate(camX+(camDirX*360),camY+(camDirY*360),camZ+(camDirZ*360))
gl.Billboard()
gl.Rect(-500, -500, 500, 500)
gl.PopMatrix()
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local initialized = false
function widget:Initialize()
SetIllumThreshold()
WG['bloom'] = {}
WG['bloom'].getAdvBloom = function()
return drawHighlights
end
WG['bloom'].setAdvBloom = function(value)
drawHighlights = value
reset()
if initialized == false then
Spring.Echo('Bloom shader doesnt work (enable shaders: \'ForceShaders = 1\' in springsettings.cfg)')
end
end
WG['bloom'].getBrightness = function()
return basicAlpha
end
WG['bloom'].setBrightness = function(value)
basicAlpha = value
reset()
if initialized == false then
Spring.Echo('Bloom shader doesnt work (enable shaders: \'ForceShaders = 1\' in springsettings.cfg)')
end
end
if (gl.CreateShader == nil) then
RemoveMe("[BloomShader::Initialize] no shader support")
return
end
widget:ViewResize(widgetHandler:GetViewSizes())
combineShader = gl.CreateShader({
fragment = [[
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform float illuminationThreshold;
uniform float fragMaxBrightness;
uniform int debugDraw;
void main(void) {
vec2 C0 = vec2(gl_TexCoord[0]);
vec4 S0 = texture2D(texture0, C0);
vec4 S1 = texture2D(texture1, C0);
S1 = vec4(S1.rgb * fragMaxBrightness/max(1.0 - illuminationThreshold, 0.0001), 1.0);
gl_FragColor = bool(debugDraw) ? S1 : S0 + S1;
}
]],
uniformInt = { texture0 = 0, texture1 = 1, debugDraw = 0},
uniformFloat = {illuminationThreshold, fragMaxBrightness}
})
if (combineShader == nil) then
RemoveMe("[BloomShader::Initialize] combineShader compilation failed"); print(gl.GetShaderLog()); return
end
blurShaderH71 = gl.CreateShader({
fragment = [[
uniform sampler2D texture0;
uniform float inverseRX;
uniform float fragKernelRadius;
float bloomSigma = fragKernelRadius / 2.5;
void main(void) {
vec2 C0 = vec2(gl_TexCoord[0]);
vec4 S = texture2D(texture0, C0);
float weight = 1.0 / (2.50663 * bloomSigma);
float total_weight = weight;
S *= weight;
for (float r = 1.5; r < fragKernelRadius; r += 2)
{
weight = exp(-((r*r)/(2.0 * bloomSigma * bloomSigma)))/(2.50663 * bloomSigma);
S += texture2D(texture0, C0 - vec2(r * inverseRX, 0.0)) * weight;
S += texture2D(texture0, C0 + vec2(r * inverseRX, 0.0)) * weight;
total_weight += 2*weight;
}
gl_FragColor = vec4(S.rgb/total_weight, 1.0);
}
]],
uniformInt = {texture0 = 0},
uniformFloat = {inverseRX, fragKernelRadius}
})
if (blurShaderH71 == nil) then
RemoveMe("[BloomShader::Initialize] blurShaderH71 compilation failed"); print(gl.GetShaderLog()); return
end
blurShaderV71 = gl.CreateShader({
fragment = [[
uniform sampler2D texture0;
uniform float inverseRY;
uniform float fragKernelRadius;
float bloomSigma = fragKernelRadius / 2.5;
void main(void) {
vec2 C0 = vec2(gl_TexCoord[0]);
vec4 S = texture2D(texture0, C0);
float weight = 1.0 / (2.50663 * bloomSigma);
float total_weight = weight;
S *= weight;
for (float r = 1.5; r < fragKernelRadius; r += 2)
{
weight = exp(-((r*r)/(2.0 * bloomSigma * bloomSigma)))/(2.50663 * bloomSigma);
S += texture2D(texture0, C0 - vec2(0.0, r * inverseRY)) * weight;
S += texture2D(texture0, C0 + vec2(0.0, r * inverseRY)) * weight;
total_weight += 2*weight;
}
gl_FragColor = vec4(S.rgb/total_weight, 1.0);
}
]],
uniformInt = {texture0 = 0},
uniformFloat = {inverseRY, fragKernelRadius}
})
if (blurShaderV71 == nil) then
RemoveMe("[BloomShader::Initialize] blurShaderV71 compilation failed"); print(gl.GetShaderLog()); return
end
brightShader = gl.CreateShader({
fragment = [[
uniform sampler2D texture0;
uniform float illuminationThreshold;
uniform float inverseRX;
uniform float inverseRY;
void main(void) {
vec2 C0 = vec2(gl_TexCoord[0]);
vec3 color = vec3(texture2D(texture0, C0));
float illum = dot(color, vec3(0.2990, 0.5870, 0.1140));
if (illum > illuminationThreshold) {
gl_FragColor = vec4((color - color*(illuminationThreshold/max(illum, 0.00001))), 1.0);
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}
]],
uniformInt = {texture0 = 0},
uniformFloat = {illuminationThreshold, inverseRX, inverseRY}
})
if (brightShader == nil) then
RemoveMe("[BloomShader::Initialize] brightShader compilation failed"); print(gl.GetShaderLog()); return
end
brightShaderText0Loc = glGetUniformLocation(brightShader, "texture0")
brightShaderInvRXLoc = glGetUniformLocation(brightShader, "inverseRX")
brightShaderInvRYLoc = glGetUniformLocation(brightShader, "inverseRY")
brightShaderIllumLoc = glGetUniformLocation(brightShader, "illuminationThreshold")
blurShaderH71Text0Loc = glGetUniformLocation(blurShaderH71, "texture0")
blurShaderH71InvRXLoc = glGetUniformLocation(blurShaderH71, "inverseRX")
blurShaderH71FragLoc = glGetUniformLocation(blurShaderH71, "fragKernelRadius")
blurShaderV71Text0Loc = glGetUniformLocation(blurShaderV71, "texture0")
blurShaderV71InvRYLoc = glGetUniformLocation(blurShaderV71, "inverseRY")
blurShaderV71FragLoc = glGetUniformLocation(blurShaderV71, "fragKernelRadius")
combineShaderDebgDrawLoc = glGetUniformLocation(combineShader, "debugDraw")
combineShaderTexture0Loc = glGetUniformLocation(combineShader, "texture0")
combineShaderTexture1Loc = glGetUniformLocation(combineShader, "texture1")
combineShaderIllumLoc = glGetUniformLocation(combineShader, "illuminationThreshold")
combineShaderFragLoc = glGetUniformLocation(combineShader, "fragMaxBrightness")
initialized = true
end
function widget:Shutdown()
if initialized then
gl.DeleteTexture(brightTexture1 or "")
gl.DeleteTexture(brightTexture2 or "")
if drawHighlights then
gl.DeleteTexture(brightTexture3 or "")
gl.DeleteTexture(brightTexture4 or "")
end
gl.DeleteTexture(screenTexture or "")
if (gl.DeleteShader) then
gl.DeleteShader(brightShader or 0)
gl.DeleteShader(blurShaderH71 or 0)
gl.DeleteShader(blurShaderV71 or 0)
gl.DeleteShader(combineShader or 0)
end
end
WG['bloom'] = nil
end
local function mglDrawTexture(texUnit, tex, w, h, flipS, flipT)
glTexture(texUnit, tex)
glTexRect(0, 0, w, h, flipS, flipT)
glTexture(texUnit, false)
end
local function mglDrawFBOTexture(tex)
glTexture(tex)
glTexRect(-1, -1, 1, 1)
glTexture(false)
end
local function activeTextureFunc(texUnit, tex, w, h, flipS, flipT)
glTexture(texUnit, tex)
glTexRect(0, 0, w, h, flipS, flipT)
glTexture(texUnit, false)
end
local function mglActiveTexture(texUnit, tex, w, h, flipS, flipT)
glActiveTexture(texUnit, activeTextureFunc, texUnit, tex, w, h, flipS, flipT)
end
local function renderToTextureFunc(tex, s, t)
glTexture(tex)
glTexRect(-1 * s, -1 * t, 1 * s, 1 * t)
glTexture(false)
end
local function mglRenderToTexture(FBOTex, tex, s, t)
glRenderToTexture(FBOTex, renderToTextureFunc, tex, s, t)
end
local function Bloom()
gl.Color(1, 1, 1, 1)
glCopyToTexture(screenTexture, 0, 0, 0, 0, vsx, vsy)
-- global bloomin
glUseShader(brightShader)
glUniformInt(brightShaderText0Loc, 0)
glUniform( brightShaderInvRXLoc, ivsx)
glUniform( brightShaderInvRYLoc, ivsy)
glUniform( brightShaderIllumLoc, illumThreshold)
mglRenderToTexture(brightTexture1, screenTexture, 1, -1)
glUseShader(0)
for i = 1, 4 do
glUseShader(blurShaderH71)
glUniformInt(blurShaderH71Text0Loc, 0)
glUniform( blurShaderH71InvRXLoc, ivsx)
glUniform( blurShaderH71FragLoc, kernelRadius)
mglRenderToTexture(brightTexture2, brightTexture1, 1, -1)
glUseShader(0)
glUseShader(blurShaderV71)
glUniformInt(blurShaderV71Text0Loc, 0)
glUniform( blurShaderV71InvRYLoc, ivsy)
glUniform( blurShaderV71FragLoc, kernelRadius)
mglRenderToTexture(brightTexture1, brightTexture2, 1, -1)
glUseShader(0)
end
glUseShader(combineShader)
glUniformInt(combineShaderDebgDrawLoc, dbgDraw)
glUniformInt(combineShaderTexture0Loc, 0)
glUniformInt(combineShaderTexture1Loc, 1)
glUniform( combineShaderIllumLoc, illumThreshold)
glUniform( combineShaderFragLoc, usedBasicAlpha)
mglActiveTexture(0, screenTexture, vsx, vsy, false, true)
mglActiveTexture(1, brightTexture1, vsx, vsy, false, true)
glUseShader(0)
-- highlights
if drawHighlights then
glCopyToTexture(screenTexture, 0, 0, 0, 0, vsx, vsy)
glUseShader(brightShader)
glUniformInt(brightShaderText0Loc, 0)
glUniform( brightShaderInvRXLoc, ivsx)
glUniform( brightShaderInvRYLoc, ivsy)
glUniform( brightShaderIllumLoc, 0.5)
mglRenderToTexture(brightTexture3, screenTexture, 1, -1)
glUseShader(0)
for i = 1, 1 do
glUseShader(blurShaderH71)
glUniformInt(blurShaderH71Text0Loc, 0)
glUniform( blurShaderH71InvRXLoc, ivsx)
glUniform( blurShaderH71FragLoc, kernelRadius2)
mglRenderToTexture(brightTexture4, brightTexture3, 1, -1)
glUseShader(0)
glUseShader(blurShaderV71)
glUniformInt(blurShaderV71Text0Loc, 0)
glUniform( blurShaderV71InvRYLoc, ivsy)
glUniform( blurShaderV71FragLoc, kernelRadius2)
mglRenderToTexture(brightTexture3, brightTexture4, 1, -1)
glUseShader(0)
end
glUseShader(combineShader)
glUniformInt(combineShaderDebgDrawLoc, dbgDraw)
glUniformInt(combineShaderTexture0Loc, 0)
glUniformInt(combineShaderTexture1Loc, 1)
glUniform( combineShaderIllumLoc, illumThreshold*0.66)
glUniform( combineShaderFragLoc, highlightsAlpha)
mglActiveTexture(0, screenTexture, vsx, vsy, false, true)
mglActiveTexture(1, brightTexture3, vsx, vsy, false, true)
glUseShader(0)
end
end
function widget:DrawScreenEffects()
if initialized == false then return end
Bloom()
end
function widget:GetConfigData(data)
savedTable = {}
savedTable.basicAlpha = basicAlpha
savedTable.drawHighlights = drawHighlights
return savedTable
end
function widget:SetConfigData(data)
if data.basicAlpha ~= nil then
basicAlpha = data.basicAlpha
if data.highlightsAlpha ~= nil then
highlightsAlpha = data.highlightsAlpha
end
drawHighlights = data.drawHighlights
end
end
function widget:TextCommand(command)
if (string.find(command, "advbloom") == 1 and string.len(command) == 8) then
WG['bloom'].setAdvBloom(not drawHighlights)
if drawHighlights then
Spring.Echo('Adv bloom enabled')
else
Spring.Echo('Adv bloom disabled')
end
end
end