1
1
"""
2
2
3
3
Class CommonFilters implements certain common image
4
- postprocessing filters.
4
+ postprocessing filters. See the :ref:`common-image-filters` page for
5
+ more information about how to use these filters.
5
6
6
7
It is not ideal that these filters are all included in a single
7
8
monolithic module. Unfortunately, when you want to apply two filters
27
28
from panda3d .core import Filename
28
29
from panda3d .core import AuxBitplaneAttrib
29
30
from panda3d .core import Texture , Shader , ATSNone
31
+ from panda3d .core import FrameBufferProperties
30
32
import os
31
33
32
34
CARTOON_BODY = """
@@ -177,7 +179,15 @@ def reconfigure(self, fullrebuild, changed):
177
179
self .textures [tex ].setWrapU (Texture .WMClamp )
178
180
self .textures [tex ].setWrapV (Texture .WMClamp )
179
181
180
- self .finalQuad = self .manager .renderSceneInto (textures = self .textures , auxbits = auxbits )
182
+ fbprops = None
183
+ clamping = None
184
+ if "HighDynamicRange" in configuration :
185
+ fbprops = FrameBufferProperties ()
186
+ fbprops .setFloatColor (True )
187
+ fbprops .setSrgbColor (False )
188
+ clamping = False
189
+
190
+ self .finalQuad = self .manager .renderSceneInto (textures = self .textures , auxbits = auxbits , fbprops = fbprops , clamping = clamping )
181
191
if (self .finalQuad == None ):
182
192
self .cleanup ()
183
193
return False
@@ -255,6 +265,17 @@ def reconfigure(self, fullrebuild, changed):
255
265
texcoordSets = list (enumerate (texcoordPadding .keys ()))
256
266
257
267
text = "//Cg\n "
268
+ if "HighDynamicRange" in configuration :
269
+ text += "static const float3x3 aces_input_mat = {\n "
270
+ text += " {0.59719, 0.35458, 0.04823},\n "
271
+ text += " {0.07600, 0.90834, 0.01566},\n "
272
+ text += " {0.02840, 0.13383, 0.83777},\n "
273
+ text += "};\n "
274
+ text += "static const float3x3 aces_output_mat = {\n "
275
+ text += " { 1.60475, -0.53108, -0.07367},\n "
276
+ text += " {-0.10208, 1.10813, -0.00605},\n "
277
+ text += " {-0.00327, -0.07276, 1.07602},\n "
278
+ text += "};\n "
258
279
text += "void vshader(float4 vtx_position : POSITION,\n "
259
280
text += " out float4 l_position : POSITION,\n "
260
281
@@ -301,6 +322,10 @@ def reconfigure(self, fullrebuild, changed):
301
322
if ("VolumetricLighting" in configuration ):
302
323
text += " uniform float4 k_casterpos,\n "
303
324
text += " uniform float4 k_vlparams,\n "
325
+
326
+ if ("ExposureAdjust" in configuration ):
327
+ text += " uniform float k_exposure,\n "
328
+
304
329
text += " out float4 o_color : COLOR)\n "
305
330
text += "{\n "
306
331
text += " o_color = tex2D(k_txcolor, %s);\n " % (texcoords ["color" ])
@@ -332,6 +357,14 @@ def reconfigure(self, fullrebuild, changed):
332
357
text += " }\n "
333
358
text += " o_color += float4(vlcolor * k_vlparams.z, 1);\n "
334
359
360
+ if ("ExposureAdjust" in configuration ):
361
+ text += " o_color.rgb *= k_exposure;\n "
362
+
363
+ # With thanks to Stephen Hill!
364
+ if ("HighDynamicRange" in configuration ):
365
+ text += " float3 aces_color = mul(aces_input_mat, o_color.rgb);\n "
366
+ text += " o_color.rgb = saturate(mul(aces_output_mat, (aces_color * (aces_color + 0.0245786f) - 0.000090537f) / (aces_color * (0.983729f * aces_color + 0.4329510f) + 0.238081f)));\n "
367
+
335
368
if ("GammaAdjust" in configuration ):
336
369
gamma = configuration ["GammaAdjust" ]
337
370
if gamma == 0.5 :
@@ -341,6 +374,11 @@ def reconfigure(self, fullrebuild, changed):
341
374
elif gamma != 1.0 :
342
375
text += " o_color.rgb = pow(o_color.rgb, %ff);\n " % (gamma )
343
376
377
+ if ("SrgbEncode" in configuration ):
378
+ text += " o_color.r = (o_color.r < 0.0031308) ? (o_color.r * 12.92) : (1.055 * pow(o_color.r, 0.41666) - 0.055);\n "
379
+ text += " o_color.g = (o_color.g < 0.0031308) ? (o_color.g * 12.92) : (1.055 * pow(o_color.g, 0.41666) - 0.055);\n "
380
+ text += " o_color.b = (o_color.b < 0.0031308) ? (o_color.b * 12.92) : (1.055 * pow(o_color.b, 0.41666) - 0.055);\n "
381
+
344
382
if ("Inverted" in configuration ):
345
383
text += " o_color = float4(1, 1, 1, 1) - o_color;\n "
346
384
text += "}\n "
@@ -386,6 +424,11 @@ def reconfigure(self, fullrebuild, changed):
386
424
self .ssao [0 ].setShaderInput ("params1" , config .numsamples , - float (config .amount ) / config .numsamples , config .radius , 0 )
387
425
self .ssao [0 ].setShaderInput ("params2" , config .strength , config .falloff , 0 , 0 )
388
426
427
+ if (changed == "ExposureAdjust" ) or fullrebuild :
428
+ if ("ExposureAdjust" in configuration ):
429
+ stops = configuration ["ExposureAdjust" ]
430
+ self .finalQuad .setShaderInput ("exposure" , 2 ** stops )
431
+
389
432
self .update ()
390
433
return True
391
434
@@ -547,6 +590,73 @@ def delGammaAdjust(self):
547
590
return self .reconfigure ((old_gamma != 1.0 ), "GammaAdjust" )
548
591
return True
549
592
593
+ def setSrgbEncode (self , force = False ):
594
+ """ Applies the inverse sRGB EOTF to the output, unless the window
595
+ already has an sRGB framebuffer, in which case this filter refuses to
596
+ apply, to prevent accidental double-application.
597
+
598
+ Set the force argument to True to force it to be applied in all cases.
599
+
600
+ .. versionadded:: 1.10.7
601
+ """
602
+ new_enable = force or not self .manager .win .getFbProperties ().getSrgbColor ()
603
+ old_enable = self .configuration .get ("SrgbEncode" , False )
604
+ if new_enable and not old_enable :
605
+ self .configuration ["SrgbEncode" ] = True
606
+ return self .reconfigure (True , "SrgbEncode" )
607
+ elif not new_enable and old_enable :
608
+ del self .configuration ["SrgbEncode" ]
609
+ return new_enable
610
+
611
+ def delSrgbEncode (self ):
612
+ """ Reverses the effects of setSrgbEncode. """
613
+ if ("SrgbEncode" in self .configuration ):
614
+ old_enable = self .configuration ["SrgbEncode" ]
615
+ del self .configuration ["SrgbEncode" ]
616
+ return self .reconfigure (old_enable , "SrgbEncode" )
617
+ return True
618
+
619
+ def setHighDynamicRange (self ):
620
+ """ Enables HDR rendering by using a floating-point framebuffer,
621
+ disabling color clamping on the main scene, and applying a tone map
622
+ operator (ACES).
623
+
624
+ It may also be necessary to use setExposureAdjust to perform exposure
625
+ compensation on the scene, depending on the lighting intensity.
626
+
627
+ .. versionadded:: 1.10.7
628
+ """
629
+
630
+ fullrebuild = (("HighDynamicRange" in self .configuration ) is False )
631
+ self .configuration ["HighDynamicRange" ] = 1
632
+ return self .reconfigure (fullrebuild , "HighDynamicRange" )
633
+
634
+ def delHighDynamicRange (self ):
635
+ if ("HighDynamicRange" in self .configuration ):
636
+ del self .configuration ["HighDynamicRange" ]
637
+ return self .reconfigure (True , "HighDynamicRange" )
638
+ return True
639
+
640
+ def setExposureAdjust (self , stops ):
641
+ """ Sets a relative exposure adjustment to multiply with the result of
642
+ rendering the scene, in stops. A value of 0 means no adjustment, a
643
+ positive value will result in a brighter image. Useful in conjunction
644
+ with HDR, see setHighDynamicRange.
645
+
646
+ .. versionadded:: 1.10.7
647
+ """
648
+ old_stops = self .configuration .get ("ExposureAdjust" )
649
+ if old_stops != stops :
650
+ self .configuration ["ExposureAdjust" ] = stops
651
+ return self .reconfigure (old_stops is None , "ExposureAdjust" )
652
+ return True
653
+
654
+ def delExposureAdjust (self ):
655
+ if ("ExposureAdjust" in self .configuration ):
656
+ del self .configuration ["ExposureAdjust" ]
657
+ return self .reconfigure (True , "ExposureAdjust" )
658
+ return True
659
+
550
660
#snake_case alias:
551
661
del_cartoon_ink = delCartoonInk
552
662
set_half_pixel_shift = setHalfPixelShift
@@ -555,7 +665,6 @@ def delGammaAdjust(self):
555
665
del_inverted = delInverted
556
666
del_view_glow = delViewGlow
557
667
set_volumetric_lighting = setVolumetricLighting
558
- del_gamma_adjust = delGammaAdjust
559
668
set_bloom = setBloom
560
669
set_view_glow = setViewGlow
561
670
set_ambient_occlusion = setAmbientOcclusion
@@ -566,3 +675,10 @@ def delGammaAdjust(self):
566
675
del_blur_sharpen = delBlurSharpen
567
676
del_volumetric_lighting = delVolumetricLighting
568
677
set_gamma_adjust = setGammaAdjust
678
+ del_gamma_adjust = delGammaAdjust
679
+ set_srgb_encode = setSrgbEncode
680
+ del_srgb_encode = delSrgbEncode
681
+ set_exposure_adjust = setExposureAdjust
682
+ del_exposure_adjust = delExposureAdjust
683
+ set_high_dynamic_range = setHighDynamicRange
684
+ del_high_dynamic_range = delHighDynamicRange
0 commit comments