Index: ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.vs (revision 23483)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.vs (nonexistent)
@@ -1,13 +0,0 @@
-#version 110
-
-varying vec2 v_tex;
-
-attribute vec3 a_vertex;
-attribute vec2 a_uv0;
-
-void main()
-{
- gl_Position = vec4(a_vertex, 1.0);
-
- v_tex = a_uv0;
-}
Property changes on: ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.vs
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Index: ps/trunk/LICENSE.txt
===================================================================
--- ps/trunk/LICENSE.txt (revision 23483)
+++ ps/trunk/LICENSE.txt (revision 23484)
@@ -1,91 +1,94 @@
0 A.D. Licensing Details
==========================
0 A.D. is released as open source: you can freely use, copy, modify and
distribute the game's source code and data files, as long as you include
attribution to Wildfire Games and let anyone freely modify and distribute any
of your own modifications to the game's files.
The distribution includes several different types of files, and a number of
third-party components. The details are described here, based on the directory
structure. For any file, see the longest path name below which is a prefix of
the file's path.
Some files don't yet have licensing details specified - if you care about any
in particular, let us know and we can try to clarify it.
/binaries/data
GPL version 2 (or later) - see license_gpl-2.0.txt
/binaries/data/mods/*/art
/binaries/data/mods/*/audio
Creative Commons Attribution-Share Alike 3.0 - see
http://creativecommons.org/licenses/by-sa/3.0/
and also see LICENSE.txt within those directories
/binaries/data/mods/*/maps/
see LICENSE.txt within those directories
+ /binaries/data/mods/public/shaders/glsl/fxaa.fs
+ BSD
+
/binaries/system
Various (unspecified)
/binaries/system/dbghelp.dll
Proprietary - see license_dbghelp.txt for restrictions you must agree to
before distributing this particular file
/build
Various (unspecified)
/build/premake/premake5
BSD
/build/premake/*.lua
MIT - see license_mit.txt
/docs
Various (unspecified)
/libraries
Various - see LICENSE.txt within that directory
/source
GPL version 2 (or later) - see license_gpl-2.0.txt
/source/lib
MIT - see license_mit.txt
/source/scriptinterface/third_party
MPL 2.0
/source/third_party/cppformat
BSD
/source/third_party/encryption
GPL version 2 (or later)
ISC (pkcs5_pbkdf2.cpp)
MIT (pkcs5_pbkdf2.h) - see license_mit.txt
/source/third-party/jsonspirit
MIT - see license_mit.txt
/source/third_party/mikktspace
zlib
/source/third_party/mongoose
MIT - see license_mit.txt
/source/third_party/tinygettext
zlib
/source/tools
Various - see LICENSE.txt within that directory
/source/tools/atlas
GPL version 2 (or later) - see license_gpl-2.0.txt
/binaries/data/mods/public/gui/prelobby/common/terms
/binaries/data/mods/public/gui/userreport/Terms_and_Conditions.txt
/binaries/data/mods/mod/gui/modio/Disclaimer.txt
Redistributing modified Terms and Conditions of online services may be within the licensing,
but may not change the legality or enforceability of the terms of the service provider.
It may be against the terms of the service provider to use online services with modified terms.
Index: ps/trunk/binaries/data/config/default.cfg
===================================================================
--- ps/trunk/binaries/data/config/default.cfg (revision 23483)
+++ ps/trunk/binaries/data/config/default.cfg (revision 23484)
@@ -1,526 +1,529 @@
; Global Configuration Settings
;
; **************************************************************
; * DO NOT EDIT THIS FILE if you want personal customisations: *
; * create a text file called "local.cfg" instead, and copy *
; * the lines from this file that you want to change. *
; * *
; * If a setting is part of a section (for instance [hotkey]) *
; * you need to append the section name at the beginning of *
; * your custom line (for instance you need to write *
; * "hotkey.pause = Space" if you want to change the pausing *
; * hotkey to the spacebar). *
; * *
; * On Linux, create: *
; * $XDG_CONFIG_HOME/0ad/config/local.cfg *
; * (Note: $XDG_CONFIG_HOME defaults to ~/.config) *
; * *
; * On OS X, create: *
; * ~/Library/Application\ Support/0ad/config/local.cfg *
; * *
; * On Windows, create: *
; * %appdata%\0ad\config\local.cfg *
; * *
; **************************************************************
; Enable/disable windowed mode by default. (Use Alt+Enter to toggle in the game.)
windowed = false
; Show detailed tooltips (Unit stats)
showdetailedtooltips = false
; Pause the game on window focus loss (Only applicable to single player mode)
pauseonfocusloss = true
; Persist settings after leaving the game setup screen
persistmatchsettings = true
; Default player name to use in multiplayer
; playername = "anonymous"
; Default server name or IP to use in multiplayer
multiplayerserver = "127.0.0.1"
; Force a particular resolution. (If these are 0, the default is
; to keep the current desktop resolution in fullscreen mode or to
; use 1024x768 in windowed mode.)
xres = 0
yres = 0
; Force a non-standard bit depth (if 0 then use the current desktop bit depth)
bpp = 0
; Preferred display (for multidisplay setups, only works with SDL 2.0)
display = 0
; Emulate right-click with Ctrl+Click on Mac mice
macmouse = false
; System settings:
; if false, actors won't be rendered but anything entity will be.
renderactors = true
watereffects=true ; When disabled, force usage of the fixed pipeline water. This is faster, but really, really ugly.
waterfancyeffects = false
waterrealdepth = true
waterrefraction = true
waterreflection = true
shadowsonwater = false
shadows = true
shadowquality = 0 ; Shadow map resolution. (-2 - Very Low, -1 - Low, 0 - Medium, 1 - High, 2 - Very High)
; High values can crash the game when using a graphics card with low memory!
shadowpcf = true
shadowsfixed = false ; When enabled shadows are rendered only on the
shadowsfixeddistance = 300.0 ; fixed distance and without swimming effect.
vsync = false
particles = true
fog = true
silhouettes = true
showsky = true
nos3tc = false
noautomipmap = true
novbo = false
noframebufferobject = false
; Disable hardware cursors
nohwcursor = false
; Linux only: Set the driconf force_s3tc_enable option at startup,
; for compressed texture support
force_s3tc_enable = true
; Specify the render path. This can be one of:
; default Automatically select one of the below, depending on system capabilities
; fixed Only use OpenGL fixed function pipeline
; shader Use vertex/fragment shaders for transform and lighting where possible
; Using 'fixed' instead of 'default' may work around some graphics-related problems,
; but will reduce performance and features when a modern graphics card is available.
renderpath = default
;;;;; EXPERIMENTAL ;;;;;
; Prefer GLSL shaders over ARB shaders. Allows fancier graphical effects.
preferglsl = false
; Experimental probably-non-working GPU skinning support; requires preferglsl; use at own risk
gpuskinning = false
; Use smooth LOS interpolation
smoothlos = false
; Use screen-space postprocessing filters (HDR, bloom, DOF, etc). Incompatible with fixed renderpath.
postproc = false
+; Use anti-aliasing techniques.
+antialiasing = "disabled"
+
; Quality level of shader effects (set to 10 to display all effects)
materialmgr.quality = 2.0
; Maximum distance to display parallax effect. Set to 0 to disable parallax.
materialmgr.PARALLAX_DIST.max = 150
; Maximum distance to display high quality parallax effect.
materialmgr.PARALLAX_HQ_DIST.max = 75
; Maximum distance to display very high quality parallax effect. Set to 30 to enable.
materialmgr.PARALLAX_VHQ_DIST.max = 0
;;;;;;;;;;;;;;;;;;;;;;;;
; Replace alpha-blending with alpha-testing, for performance experiments
forcealphatest = false
; Color of the sky (in "r g b" format)
skycolor = "0 0 0"
[adaptivefps]
session = 60 ; Throttle FPS in running games (prevents 100% CPU workload).
menu = 60 ; Throttle FPS in menus only.
[hotkey]
; Each one of the specified keys will trigger the action on the left
; for multiple-key combinations, separate keys with '+'.
; See keys.txt for the list of key names.
; > SYSTEM SETTINGS
exit = "Ctrl+Break", "Super+Q" ; Exit to desktop
cancel = Escape ; Close or cancel the current dialog box/popup
confirm = Return ; Confirm the current command
pause = Pause ; Pause/unpause game
screenshot = F2 ; Take PNG screenshot
bigscreenshot = "Shift+F2" ; Take large BMP screenshot
togglefullscreen = "Alt+Return" ; Toggle fullscreen/windowed mode
screenshot.watermark = "Alt+K" ; Toggle product/company watermark for official screenshots
wireframe = "Alt+Shift+W" ; Toggle wireframe mode
silhouettes = "Alt+Shift+S" ; Toggle unit silhouettes
showsky = "Alt+Z" ; Toggle sky
; > DIALOG HOTKEYS
summary = "Ctrl+Tab" ; Toggle in-game summary
lobby = "Alt+L" ; Show the multiplayer lobby in a dialog window.
structree = "Alt+Shift+T" ; Show structure tree
civinfo = "Alt+Shift+H" ; Show civilization info
; > CLIPBOARD CONTROLS
copy = "Ctrl+C" ; Copy to clipboard
paste = "Ctrl+V" ; Paste from clipboard
cut = "Ctrl+X" ; Cut selected text and copy to the clipboard
; > CONSOLE SETTINGS
console.toggle = BackQuote, F9 ; Open/close console
; > OVERLAY KEYS
fps.toggle = "Alt+F" ; Toggle frame counter
realtime.toggle = "Alt+T" ; Toggle current display of computer time
session.devcommands.toggle = "Alt+D" ; Toggle developer commands panel
timeelapsedcounter.toggle = "F12" ; Toggle time elapsed counter
ceasefirecounter.toggle = unused ; Toggle ceasefire counter
session.showstatusbars = Tab ; Toggle display of status bars
session.highlightguarding = PgDn ; Toggle highlight of guarding units
session.highlightguarded = PgUp ; Toggle highlight of guarded units
session.toggleattackrange = "Alt+C" ; Toggle display of attack range overlays of selected defensive structures
session.toggleaurasrange = "Alt+V" ; Toggle display of aura range overlays of selected units and structures
session.togglehealrange = "Alt+B" ; Toggle display of heal range overlays of selected units
session.diplomacycolors = "Alt+X" ; Toggle diplomacy colors
; > HOTKEYS ONLY
chat = Return ; Toggle chat window
teamchat = "T" ; Toggle chat window in team chat mode
privatechat = "L" ; Toggle chat window and select the previous private chat partner
; > QUICKSAVE
quicksave = "Shift+F5"
quickload = "Shift+F8"
[hotkey.camera]
reset = "R" ; Reset camera rotation to default.
follow = "F" ; Follow the first unit in the selection
rallypointfocus = unused ; Focus the camera on the rally point of the selected building
zoom.in = Plus, Equals, NumPlus ; Zoom camera in (continuous control)
zoom.out = Minus, NumMinus ; Zoom camera out (continuous control)
zoom.wheel.in = WheelUp ; Zoom camera in (stepped control)
zoom.wheel.out = WheelDown ; Zoom camera out (stepped control)
rotate.up = "Ctrl+UpArrow", "Ctrl+W" ; Rotate camera to look upwards
rotate.down = "Ctrl+DownArrow", "Ctrl+S" ; Rotate camera to look downwards
rotate.cw = "Ctrl+LeftArrow", "Ctrl+A", Q ; Rotate camera clockwise around terrain
rotate.ccw = "Ctrl+RightArrow", "Ctrl+D", E ; Rotate camera anticlockwise around terrain
rotate.wheel.cw = "Shift+WheelUp", MouseX1 ; Rotate camera clockwise around terrain (stepped control)
rotate.wheel.ccw = "Shift+WheelDown", MouseX2 ; Rotate camera anticlockwise around terrain (stepped control)
pan = MouseMiddle ; Enable scrolling by moving mouse
left = A, LeftArrow ; Scroll or rotate left
right = D, RightArrow ; Scroll or rotate right
up = W, UpArrow ; Scroll or rotate up/forwards
down = S, DownArrow ; Scroll or rotate down/backwards
scroll.speed.increase = "Ctrl+Shift+S" ; Increase scroll speed
scroll.speed.decrease = "Ctrl+Alt+S" ; Decrease scroll speed
rotate.speed.increase = "Ctrl+Shift+R" ; Increase rotation speed
rotate.speed.decrease = "Ctrl+Alt+R" ; Decrease rotation speed
zoom.speed.increase = "Ctrl+Shift+Z" ; Increase zoom speed
zoom.speed.decrease = "Ctrl+Alt+Z" ; Decrease zoom speed
[hotkey.camera.jump]
1 = F5 ; Jump to position N
2 = F6
3 = F7
4 = F8
;5 =
;6 =
;7 =
;8 =
;9 =
;10 =
[hotkey.camera.jump.set]
1 = "Ctrl+F5" ; Set jump position N
2 = "Ctrl+F6"
3 = "Ctrl+F7"
4 = "Ctrl+F8"
;5 =
;6 =
;7 =
;8 =
;9 =
;10 =
[hotkey.profile]
toggle = "F11" ; Enable/disable real-time profiler
save = "Shift+F11" ; Save current profiler data to logs/profile.txt
[hotkey.profile2]
toggle = "Ctrl+F11" ; Enable/disable HTTP/GPU modes for new profiler
[hotkey.selection]
add = Shift ; Add units to selection
militaryonly = Alt ; Add only military units to the selection
nonmilitaryonly = "Alt+Y" ; Add only non-military units to the selection
idleonly = "I" ; Select only idle units
woundedonly = "O" ; Select only wounded units
remove = Ctrl ; Remove units from selection
cancel = Esc ; Un-select all units and cancel building placement
idleworker = Period ; Select next idle worker
idlewarrior = ForwardSlash ; Select next idle warrior
idleunit = BackSlash ; Select next idle unit
offscreen = Alt ; Include offscreen units in selection
[hotkey.selection.group.add]
0 = "Shift+0"
1 = "Shift+1"
2 = "Shift+2"
3 = "Shift+3"
4 = "Shift+4"
5 = "Shift+5"
6 = "Shift+6"
7 = "Shift+7"
8 = "Shift+8"
9 = "Shift+9"
[hotkey.selection.group.save]
0 = "Ctrl+0"
1 = "Ctrl+1"
2 = "Ctrl+2"
3 = "Ctrl+3"
4 = "Ctrl+4"
5 = "Ctrl+5"
6 = "Ctrl+6"
7 = "Ctrl+7"
8 = "Ctrl+8"
9 = "Ctrl+9"
[hotkey.selection.group.select]
0 = 0
1 = 1
2 = 2
3 = 3
4 = 4
5 = 5
6 = 6
7 = 7
8 = 8
9 = 9
[hotkey.session]
kill = Delete ; Destroy selected units
stop = "H" ; Stop the current action
backtowork = "Y" ; The unit will go back to work
unload = "U" ; Unload garrisoned units when a building/mechanical unit is selected
move = unused ; Modifier to move to a point instead of another action (e.g. gather)
attack = Ctrl ; Modifier to attack instead of another action (e.g. capture)
attackmove = Ctrl ; Modifier to attackmove when clicking on a point
attackmoveUnit = "Ctrl+Q" ; Modifier to attackmove targeting only units when clicking on a point (should contain the attackmove keys)
garrison = Ctrl ; Modifier to garrison when clicking on building
autorallypoint = Ctrl ; Modifier to set the rally point on the building itself
guard = "G" ; Modifier to escort/guard when clicking on unit/building
patrol = "P" ; Modifier to patrol a unit
repair = "J" ; Modifier to repair when clicking on building/mechanical unit
queue = Shift ; Modifier to queue unit orders instead of replacing
orderone = Alt ; Modifier to order only one entity in selection.
batchtrain = Shift ; Modifier to train units in batches
massbarter = Shift ; Modifier to barter bunch of resources
masstribute = Shift ; Modifier to tribute bunch of resources
noconfirmation = Shift ; Do not ask confirmation when deleting a building/unit
fulltradeswap = Shift ; Modifier to put the desired trade resource to 100%
unloadtype = Shift ; Modifier to unload all units of type
deselectgroup = Ctrl ; Modifier to deselect units when clicking group icon, instead of selecting
rotate.cw = RightBracket ; Rotate building placement preview clockwise
rotate.ccw = LeftBracket ; Rotate building placement preview anticlockwise
snaptoedges = Ctrl ; Modifier to align new structures with nearby existing structure
[hotkey.session.gui]
toggle = "Alt+G" ; Toggle visibility of session GUI
menu.toggle = "F10" ; Toggle in-game menu
diplomacy.toggle = "Ctrl+H" ; Toggle in-game diplomacy page
barter.toggle = "Ctrl+B" ; Toggle in-game barter/trade page
objectives.toggle = "Ctrl+O" ; Toggle in-game objectives page
tutorial.toggle = "Ctrl+P" ; Toggle in-game tutorial panel
[hotkey.session.savedgames]
delete = Delete ; Delete the selected saved game asking confirmation
noconfirmation = Shift ; Do not ask confirmation when deleting a game
[hotkey.session.queueunit] ; > UNIT TRAINING
1 = "Z" ; add first unit type to queue
2 = "X" ; add second unit type to queue
3 = "C" ; add third unit type to queue
4 = "V" ; add fourth unit type to queue
5 = "B" ; add fivth unit type to queue
6 = "N" ; add sixth unit type to queue
7 = "M" ; add seventh unit type to queue
8 = Comma ; add eighth unit type to queue
[hotkey.session.timewarp]
fastforward = Space ; If timewarp mode enabled, speed up the game
rewind = Backspace ; If timewarp mode enabled, go back to earlier point in the game
[hotkey.tab]
next = "Tab", "Alt+S" ; Show the next tab
prev = "Shift+Tab", "Alt+W" ; Show the previous tab
[hotkey.text] ; > GUI TEXTBOX HOTKEYS
delete.left = "Ctrl+Backspace" ; Delete word to the left of cursor
delete.right = "Ctrl+Del" ; Delete word to the right of cursor
move.left = "Ctrl+LeftArrow" ; Move cursor to start of word to the left of cursor
move.right = "Ctrl+RightArrow" ; Move cursor to start of word to the right of cursor
[gui]
cursorblinkrate = 0.5 ; Cursor blink rate in seconds (0.0 to disable blinking)
scale = 1.0 ; GUI scaling factor, for improved compatibility with 4K displays
[gui.gamesetup]
enabletips = true ; Enable/Disable tips during gamesetup (for newcomers)
assignplayers = everyone ; Whether to assign joining clients to free playerslots. Possible values: everyone, buddies, disabled.
aidifficulty = 3 ; Difficulty level, from 0 (easiest) to 5 (hardest)
aibehavior = "random" ; Default behavior of the AI (random, balanced, aggressive or defensive)
settingsslide = true ; Enable/Disable settings panel slide
[gui.loadingscreen]
progressdescription = false ; Whether to display the progress percent or a textual description
[gui.session]
camerajump.threshold = 40 ; How close do we have to be to the actual location in order to jump back to the previous one?
timeelapsedcounter = false ; Show the game duration in the top right corner
ceasefirecounter = false ; Show the remaining ceasefire time in the top right corner
batchtrainingsize = 5 ; Number of units to be trained per batch by default (when pressing the hotkey)
scrollbatchratio = 1 ; Number of times you have to scroll to increase/decrease the batchsize by 1
woundedunithotkeythreshold = 33 ; The wounded unit hotkey considers the selected units as wounded if their health percentage falls below this number
attackrange = true ; Display attack range overlays of selected defensive structures
aurasrange = true ; Display aura range overlays of selected units and structures
healrange = true ; Display heal range overlays of selected units
rankabovestatusbar = true ; Show rank icons above status bars
experiencestatusbar = true ; Show an experience status bar above each selected unit
respoptooltipsort = 0 ; Sorting players in the resources and population tooltip by value (0 - no sort, -1 - ascending, 1 - descending)
snaptoedges = "disabled" ; Possible values: disabled, enabled.
snaptoedgesdistancethreshold = 15 ; On which distance we don't snap to edges
disjointcontrolgroups = "true" ; Whether control groups are disjoint sets or entities can be in multiple control groups at the same time.
[gui.session.minimap]
blinkduration = 1.7 ; The blink duration while pinging
pingduration = 50.0 ; The duration for which an entity will be pinged after an attack notification
[gui.session.notifications]
attack = true ; Show a chat notification if you are attacked by another player
tribute = true ; Show a chat notification if an ally tributes resources to another team member if teams are locked, and all tributes in observer mode
barter = true ; Show a chat notification to observers when a player bartered resources
phase = completed ; Show a chat notification if you or an ally have started, aborted or completed a new phase, and phases of all players in observer mode. Possible values: none, completed, all.
[gui.splashscreen]
enable = true ; Enable/disable the splashscreen
version = 0 ; Splashscreen version (date of last modification). By default, 0 to force splashscreen to appear at first launch
[gui.session.diplomacycolors]
self = "21 55 149" ; Color of your units when diplomacy colors are enabled
ally = "86 180 31" ; Color of allies when diplomacy colors are enabled
neutral = "231 200 5" ; Color of neutral players when diplomacy colors are enabled
enemy = "150 20 20" ; Color of enemies when diplomacy colors are enabled
[joystick] ; EXPERIMENTAL: joystick/gamepad settings
enable = false
deadzone = 8192
[joystick.camera]
pan.x = 0
pan.y = 1
rotate.x = 3
rotate.y = 2
zoom.in = 5
zoom.out = 4
[chat]
timestamp = true ; Show at which time chat messages have been sent
[chat.session]
extended = true ; Whether to display the chat history
[lobby]
history = 0 ; Number of past messages to display on join
room = "arena24" ; Default MUC room to join
server = "lobby.wildfiregames.com" ; Address of lobby server
tls = true ; Whether to use TLS encryption when connecting to the server.
verify_certificate = false ; Whether to reject connecting to the lobby if the TLS certificate is invalid (TODO: wait for Gloox GnuTLS trust implementation to be fixed)
terms_url = "https://trac.wildfiregames.com/browser/ps/trunk/binaries/data/mods/public/gui/prelobby/common/terms/"; Allows the user to save the text and print the terms
terms_of_service = "0" ; Version (hash) of the Terms of Service that the user has accepted
terms_of_use = "0" ; Version (hash) of the Terms of Use that the user has accepted
privacy_policy = "0" ; Version (hash) of the Privacy Policy that the user has accepted
xpartamupp = "wfgbot24" ; Name of the server-side XMPP-account that manage games
echelon = "echelon24" ; Name of the server-side XMPP-account that manages ratings
buddies = "," ; Comma separated list of playernames that the current user has marked as buddies
rememberpassword = true ; Whether to store the encrypted password in the user config
[lobby.columns]
gamerating = false ; Show the average rating of the participating players in a column of the gamelist
[lobby.stun]
enabled = true ; The STUN protocol allows hosting games without configuring the firewall and router.
; If STUN is disabled, the game relies on direct connection, UPnP and port forwarding.
server = "lobby.wildfiregames.com" ; Address of the STUN server.
port = 3478 ; Port of the STUN server.
delay = 200 ; Duration in milliseconds that is waited between STUN messages.
; Smaller numbers speed up joins but also become less stable.
[mod]
enabledmods = "mod public"
[modio]
public_key = "RWTsHxQMrRq4xwHisyBa2rNQfAedcINzbTT83jeX4/ZcfVxqLfWB4y8w" ; Public key corresponding to the private key valid mods are signed with
disclaimer = "0" ; Version (hash) of the Disclaimer that the user has accepted
[modio.v1]
baseurl = "https://api.mod.io/v1"
api_key = "23df258a71711ea6e4b50893acc1ba55"
name_id = "0ad"
[network]
duplicateplayernames = false ; Rename joining player to "User (2)" if "User" is already connected, otherwise prohibit join.
lateobservers = everyone ; Allow observers to join the game after it started. Possible values: everyone, buddies, disabled.
observerlimit = 8 ; Prevent further observer joins in running games if this limit is reached
gamestarttimeout = 60000 ; Don't disconnect clients timing out in the loading screen and rejoin process before exceeding this timeout.
[overlay]
fps = "false" ; Show frames per second in top right corner
realtime = "false" ; Show current system time in top right corner
netwarnings = "true" ; Show warnings if the network connection is bad
[profiler2]
autoenable = false ; Enable HTTP server output at startup (default off for security/performance)
gpu.arb.enable = true ; Allow GL_ARB_timer_query timing mode when available
gpu.ext.enable = true ; Allow GL_EXT_timer_query timing mode when available
gpu.intel.enable = true ; Allow GL_INTEL_performance_queries timing mode when available
[sound]
mastergain = 0.9
musicgain = 0.2
ambientgain = 0.6
actiongain = 0.7
uigain = 0.7
[sound.notify]
nick = true ; Play a sound when someone mentions your name in the lobby or game
gamesetup.join = false ; Play a sound when a new client joins the game setup
[tinygettext]
debug = false ; Print error messages each time a translation for an English string is not found.
[userreport] ; Opt-in online user reporting system
url_upload = "https://feedback.wildfiregames.com/report/upload/v1/" ; URL where UserReports are uploaded to
url_publication = "https://feedback.wildfiregames.com/" ; URL where UserReports were analyzed and published
url_terms = "https://trac.wildfiregames.com/browser/ps/trunk/binaries/data/mods/public/gui/userreport/Terms_and_Conditions.txt"; Allows the user to save the text and print the terms
terms = "0" ; Version (hash) of the UserReporter Terms that the user has accepted
[view] ; Camera control settings
scroll.speed = 120.0
scroll.speed.modifier = 1.05 ; Multiplier for changing scroll speed
rotate.x.speed = 1.2
rotate.x.min = 28.0
rotate.x.max = 60.0
rotate.x.default = 35.0
rotate.y.speed = 2.0
rotate.y.speed.wheel = 0.45
rotate.y.default = 0.0
rotate.speed.modifier = 1.05 ; Multiplier for changing rotation speed
drag.speed = 0.5
zoom.speed = 256.0
zoom.speed.wheel = 32.0
zoom.min = 50.0
zoom.max = 200.0
zoom.default = 120.0
zoom.speed.modifier = 1.05 ; Multiplier for changing zoom speed
pos.smoothness = 0.1
zoom.smoothness = 0.4
rotate.x.smoothness = 0.5
rotate.y.smoothness = 0.3
near = 2.0 ; Near plane distance
far = 4096.0 ; Far plane distance
fov = 45.0 ; Field of view (degrees), lower is narrow, higher is wide
height.smoothness = 0.5
height.min = 16
Index: ps/trunk/binaries/data/mods/public/gui/options/options.json
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/options/options.json (revision 23483)
+++ ps/trunk/binaries/data/mods/public/gui/options/options.json (revision 23484)
@@ -1,586 +1,598 @@
[
{
"label": "General",
"options":
[
{
"type": "string",
"label": "Player name (single-player)",
"tooltip": "How you want to be addressed in single-player matches.",
"config": "playername.singleplayer"
},
{
"type": "string",
"label": "Player name (multiplayer)",
"tooltip": "How you want to be addressed in multiplayer matches (except lobby).",
"config": "playername.multiplayer"
},
{
"type": "boolean",
"label": "Background pause",
"tooltip": "Pause single-player games when window loses focus.",
"config": "pauseonfocusloss"
},
{
"type": "boolean",
"label": "Enable welcome screen",
"tooltip": "If you disable it, the welcome screen will still appear once, each time a new version is available. You can always launch it from the main menu.",
"config": "gui.splashscreen.enable"
},
{
"type": "boolean",
"label": "Network warnings",
"tooltip": "Show which player has a bad connection in multiplayer games.",
"config": "overlay.netwarnings"
},
{
"type": "boolean",
"label": "FPS overlay",
"tooltip": "Show frames per second in top right corner.",
"config": "overlay.fps"
},
{
"type": "boolean",
"label": "Real time overlay",
"tooltip": "Show current system time in top right corner.",
"config": "overlay.realtime"
},
{
"type": "boolean",
"label": "Game time overlay",
"tooltip": "Show current simulation time in top right corner.",
"config": "gui.session.timeelapsedcounter"
},
{
"type": "boolean",
"label": "Ceasefire time overlay",
"tooltip": "Always show the remaining ceasefire time.",
"config": "gui.session.ceasefirecounter"
},
{
"type": "dropdown",
"label": "Late observer joins",
"tooltip": "Allow everybody or buddies only to join the game as observer after it started.",
"config": "network.lateobservers",
"list": [
{ "value": "everyone", "label": "Everyone" },
{ "value": "buddies", "label": "Buddies" },
{ "value": "disabled", "label": "Disabled" }
]
},
{
"type": "number",
"label": "Observer limit",
"tooltip": "Prevent further observers from joining if the limit is reached.",
"config": "network.observerlimit",
"min": 0,
"max": 32
},
{
"type": "boolean",
"label": "Chat timestamp",
"tooltip": "Show time that messages are posted in the lobby, gamesetup and ingame chat.",
"config": "chat.timestamp"
}
]
},
{
"label": "Graphics",
"tooltip": "Set the balance between performance and visual appearance.",
"options":
[
{
"type": "boolean",
"label": "Windowed mode",
"tooltip": "Start 0 A.D. in a window.",
"config": "windowed"
},
{
"type": "boolean",
"label": "Prefer GLSL",
"tooltip": "Use OpenGL 2.0 shaders (recommended).",
"config": "preferglsl",
"function": "Renderer_SetPreferGLSLEnabled"
},
{
"type": "boolean",
"label": "Fog",
"tooltip": "Enable Fog.",
"dependencies": ["preferglsl"],
"config": "fog",
"function": "Renderer_SetFogEnabled"
},
{
"type": "boolean",
"label": "Post-processing",
"tooltip": "Use screen-space post-processing filters (HDR, Bloom, DOF, etc).",
"config": "postproc",
"function": "Renderer_SetPostProcEnabled"
},
{
+ "type": "dropdown",
+ "label": "Anti-Aliasing",
+ "tooltip": "Reduce aliasing effect on edges.",
+ "dependencies": ["postproc"],
+ "config": "antialiasing",
+ "list": [
+ { "value": "disabled", "label": "Disabled", "tooltip": "Do not use anti-aliasing." },
+ { "value": "fxaa", "label": "FXAA", "tooltip": "Fast, but simple anti-aliasing." }
+ ],
+ "function": "Renderer_UpdateAntiAliasingTechnique"
+ },
+ {
"type": "slider",
"label": "Shader effects",
"tooltip": "Number of shader effects. REQUIRES GAME RESTART",
"config": "materialmgr.quality",
"min": 0,
"max": 10
},
{
"type": "boolean",
"label": "Shadows",
"tooltip": "Enable shadows.",
"config": "shadows",
"function": "Renderer_SetShadowsEnabled"
},
{
"type": "dropdown",
"label": "Shadow quality",
"tooltip": "Shadow map resolution. High values can crash the game when using a graphics card with low memory!",
"dependencies": ["shadows"],
"config": "shadowquality",
"function": "Renderer_RecreateShadowMap",
"list": [
{ "value": -2, "label": "Very Low" },
{ "value": -1, "label": "Low" },
{ "value": 0, "label": "Medium" },
{ "value": 1, "label": "High" },
{ "value": 2, "label": "Very High" }
]
},
{
"type": "boolean",
"label": "Shadow filtering",
"tooltip": "Smooth shadows.",
"dependencies": ["shadows"],
"config": "shadowpcf",
"function": "Renderer_SetShadowPCFEnabled"
},
{
"type": "boolean",
"label": "Unit silhouettes",
"tooltip": "Show outlines of units behind structures.",
"config": "silhouettes",
"function": "Renderer_SetSilhouettesEnabled"
},
{
"type": "boolean",
"label": "Particles",
"tooltip": "Enable particles.",
"config": "particles",
"function": "Renderer_SetParticlesEnabled"
},
{
"type": "boolean",
"label": "Water effects",
"tooltip": "When OFF, use the lowest settings possible to render water. This makes other settings irrelevant.",
"config": "watereffects",
"function": "Renderer_SetWaterEffectsEnabled"
},
{
"type": "boolean",
"label": "High-quality water effects",
"tooltip": "Use higher-quality effects for water, rendering coastal waves, shore foam, and ships trails.",
"dependencies": ["watereffects"],
"config": "waterfancyeffects",
"function": "Renderer_SetWaterFancyEffectsEnabled"
},
{
"type": "boolean",
"label": "Real water depth",
"tooltip": "Use actual water depth in rendering calculations.",
"dependencies": ["watereffects"],
"config": "waterrealdepth",
"function": "Renderer_SetWaterRealDepthEnabled"
},
{
"type": "boolean",
"label": "Water reflections",
"tooltip": "Allow water to reflect a mirror image.",
"dependencies": ["watereffects"],
"config": "waterreflection",
"function": "Renderer_SetWaterReflectionEnabled"
},
{
"type": "boolean",
"label": "Water refraction",
"tooltip": "Use a real water refraction map and not transparency.",
"dependencies": ["watereffects"],
"config": "waterrefraction",
"function": "Renderer_SetWaterRefractionEnabled"
},
{
"type": "boolean",
"label": "Shadows on water",
"tooltip": "Cast shadows on water.",
"dependencies": ["watereffects"],
"config": "shadowsonwater",
"function": "Renderer_SetWaterShadowsEnabled"
},
{
"type": "boolean",
"label": "Smooth vision",
"tooltip": "Lift darkness and fog-of-war smoothly.",
"config": "smoothlos",
"function": "Renderer_SetSmoothLOSEnabled"
},
{
"type": "boolean",
"label": "Show sky",
"tooltip": "Render Sky.",
"config": "showsky",
"function": "Renderer_SetShowSkyEnabled"
},
{
"type": "boolean",
"label": "VSync",
"tooltip": "Run vertical sync to fix screen tearing. REQUIRES GAME RESTART",
"config": "vsync"
},
{
"type": "slider",
"label": "FPS throttling in menus",
"tooltip": "To save CPU workload, throttle render frequency in all menus. Set to maximum to disable throttling.",
"config": "adaptivefps.menu",
"min": 20,
"max": 100
},
{
"type": "slider",
"label": "FPS throttling in games",
"tooltip": "To save CPU workload, throttle render frequency in running games. Set to maximum to disable throttling.",
"config": "adaptivefps.session",
"min": 20,
"max": 100
}
]
},
{
"label": "Sound",
"options":
[
{
"type": "slider",
"label": "Master volume",
"tooltip": "Master audio gain.",
"config": "sound.mastergain",
"function": "SetMasterGain",
"min": 0,
"max": 2
},
{
"type": "slider",
"label": "Music volume",
"tooltip": "In game music gain.",
"config": "sound.musicgain",
"function": "SetMusicGain",
"min": 0,
"max": 2
},
{
"type": "slider",
"label": "Ambient volume",
"tooltip": "In game ambient sound gain.",
"config": "sound.ambientgain",
"function": "SetAmbientGain",
"min": 0,
"max": 2
},
{
"type": "slider",
"label": "Action volume",
"tooltip": "In game unit action sound gain.",
"config": "sound.actiongain",
"function": "SetActionGain",
"min": 0,
"max": 2
},
{
"type": "slider",
"label": "UI volume",
"tooltip": "UI sound gain.",
"config": "sound.uigain",
"function": "SetUIGain",
"min": 0,
"max": 2
},
{
"type": "boolean",
"label": "Nick notification",
"tooltip": "Receive audio notification when someone types your nick.",
"config": "sound.notify.nick"
},
{
"type": "boolean",
"label": "Game setup - new player notification",
"tooltip": "Receive audio notification when a new client joins the game setup.",
"config": "sound.notify.gamesetup.join"
}
]
},
{
"label": "Game Setup",
"options":
[
{
"type": "boolean",
"label": "Enable game setting tips",
"tooltip": "Show tips when setting up a game.",
"config": "gui.gamesetup.enabletips"
},
{
"type": "boolean",
"label": "Enable settings panel slide",
"tooltip": "Slide the settings panel when opening, closing or resizing.",
"config": "gui.gamesetup.settingsslide"
},
{
"type": "boolean",
"label": "Persist match settings",
"tooltip": "Save and restore match settings for quick reuse when hosting another game.",
"config": "persistmatchsettings"
},
{
"type": "dropdown",
"label": "Default AI difficulty",
"tooltip": "Default difficulty of the AI.",
"config": "gui.gamesetup.aidifficulty",
"list": [
{ "value": 0, "label": "Sandbox" },
{ "value": 1, "label": "Very Easy" },
{ "value": 2, "label": "Easy" },
{ "value": 3, "label": "Medium" },
{ "value": 4, "label": "Hard" },
{ "value": 5, "label": "Very Hard" }
]
},
{
"type": "dropdown",
"label": "Default AI behavior",
"tooltip": "Default behavior of the AI.",
"config": "gui.gamesetup.aibehavior",
"list": [
{ "value": "random", "label": "Random" },
{ "value": "balanced", "label": "Balanced" },
{ "value": "aggressive", "label": "Aggressive" },
{ "value": "defensive", "label": "Defensive" }
]
},
{
"type": "dropdown",
"label": "Assign players",
"tooltip": "Automatically assign joining clients to free player slots during the match setup.",
"config": "gui.gamesetup.assignplayers",
"list": [
{
"value": "everyone",
"label": "Everyone",
"tooltip": "Players joining the match will be assigned if there is a free slot."
},
{
"value": "buddies",
"label": "Buddies",
"tooltip": "Players joining the match will only be assigned if they are a buddy of the host and if there is a free slot."
},
{
"value": "disabled",
"label": "Disabled",
"tooltip": "Players only receive a slot when the host assigns them explicitly."
}
]
}
]
},
{
"label": "Lobby",
"tooltip": "These settings only affect the multiplayer.",
"options":
[
{
"type": "boolean",
"label": "TLS encryption",
"tooltip": "Protect login and data exchanged with the lobby server using TLS encryption.",
"config": "lobby.tls"
},
{
"type": "number",
"label": "Chat backlog",
"tooltip": "Number of backlogged messages to load when joining the lobby.",
"config": "lobby.history",
"min": "0"
},
{
"type": "boolean",
"label": "Game rating column",
"tooltip": "Show the average rating of the participating players in a column of the gamelist.",
"config": "lobby.columns.gamerating"
}
]
},
{
"label": "In-Game",
"tooltip": "Change options regarding the in-game settings.",
"options":
[
{
"type": "slider",
"label": "Wounded unit health",
"tooltip": "The wounded unit hotkey considers the selected units as wounded if their health percentage falls below this number.",
"config": "gui.session.woundedunithotkeythreshold",
"min": 0,
"max": 100
},
{
"type": "number",
"label": "Batch training size",
"tooltip": "Number of units trained per batch by default.",
"config": "gui.session.batchtrainingsize",
"min": 1,
"max": 20
},
{
"type": "slider",
"label": "Scroll batch increment ratio",
"tooltip": "Number of times you have to scroll to increase/decrease the batchsize by 1.",
"config": "gui.session.scrollbatchratio",
"min": 0.1,
"max": 30
},
{
"type": "boolean",
"label": "Chat notification attack",
"tooltip": "Show a chat notification if you are attacked by another player.",
"config": "gui.session.notifications.attack"
},
{
"type": "boolean",
"label": "Chat notification tribute",
"tooltip": "Show a chat notification if an ally tributes resources to another team member if teams are locked, and all tributes in observer mode.",
"config": "gui.session.notifications.tribute"
},
{
"type": "boolean",
"label": "Chat notification barter",
"tooltip": "Show a chat notification to observers when a player bartered resources.",
"config": "gui.session.notifications.barter"
},
{
"type": "dropdown",
"label": "Chat notification phase",
"tooltip": "Show a chat notification if you or an ally have started, aborted or completed a new phase, and phases of all players in observer mode.",
"config": "gui.session.notifications.phase",
"list": [
{ "value": "none", "label": "Disable" },
{ "value": "completed", "label": "Completed" },
{ "value": "all", "label": "All displayed" }
]
},
{
"type": "boolean",
"label": "Attack range visualization",
"tooltip": "Display the attack range of selected defensive structures (can also be toggled in-game with the hotkey).",
"config": "gui.session.attackrange"
},
{
"type": "boolean",
"label": "Aura range visualization",
"tooltip": "Display the range of auras of selected units and structures (can also be toggled in-game with the hotkey).",
"config": "gui.session.aurasrange"
},
{
"type": "boolean",
"label": "Heal range visualization",
"tooltip": "Display the healing range of selected units (can also be toggled in-game with the hotkey).",
"config": "gui.session.healrange"
},
{
"type": "boolean",
"label": "Rank icon above status bar",
"tooltip": "Show rank icons above status bars.",
"config": "gui.session.rankabovestatusbar"
},
{
"type": "boolean",
"label": "Experience status bar",
"tooltip": "Show an experience status bar above each selected unit.",
"config": "gui.session.experiencestatusbar"
},
{
"type": "boolean",
"label": "Detailed tooltips",
"tooltip": "Show detailed tooltips for trainable units in unit-producing structures.",
"config": "showdetailedtooltips"
},
{
"type": "dropdown",
"label": "Sort resources and population tooltip",
"tooltip": "Dynamically sort players in the resources and population tooltip by value.",
"config": "gui.session.respoptooltipsort",
"list": [
{ "value": 0, "label": "Unordered" },
{ "value": -1, "label": "Ascending" },
{ "value": 1, "label": "Descending" }
]
},
{
"type": "color",
"label": "Diplomacy colors: self",
"tooltip": "Color of your units when diplomacy colors are enabled.",
"config": "gui.session.diplomacycolors.self"
},
{
"type": "color",
"label": "Diplomacy colors: ally",
"tooltip": "Color of allies when diplomacy colors are enabled.",
"config": "gui.session.diplomacycolors.ally"
},
{
"type": "color",
"label": "Diplomacy colors: neutral",
"tooltip": "Color of neutral players when diplomacy colors are enabled.",
"config": "gui.session.diplomacycolors.neutral"
},
{
"type": "color",
"label": "Diplomacy colors: enemy",
"tooltip": "Color of enemies when diplomacy colors are enabled.",
"config": "gui.session.diplomacycolors.enemy"
},
{
"type": "dropdown",
"label": "Snap to edges",
"tooltip": "This option allows to align new structures with nearby structures.",
"config": "gui.session.snaptoedges",
"list": [
{
"value": "disabled",
"label": "Hotkey to enable snapping",
"tooltip": "New structures are aligned with nearby structures while pressing the hotkey."
},
{
"value": "enabled",
"label": "Hotkey to disable snapping",
"tooltip": "New structures are aligned with nearby structures unless the hotkey is pressed."
}
]
},
{
"type": "dropdown",
"label": "Control Group Membership",
"tooltip": "Decide whether units can be part of multiple control groups.",
"config": "gui.session.disjointcontrolgroups",
"list": [
{
"value": "true",
"label": "Single",
"tooltip": "When adding a Unit or Structure to a control group, they are removed from other control groups. Use this choice if you want control groups to refer to distinct armies."
},
{
"value": "false",
"label": "Multiple",
"tooltip": "Units and Structures can be part of multiple control groups. This is useful to keep control groups for distinct armies and a control group for the entire army simultaneously."
}
]
}
]
}
]
Index: ps/trunk/binaries/data/mods/public/gui/options/options.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/options/options.xml (revision 23483)
+++ ps/trunk/binaries/data/mods/public/gui/options/options.xml (revision 23484)
@@ -1,66 +1,66 @@
-
Index: ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml (nonexistent)
+++ ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml (revision 23484)
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
Property changes on: ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/bloom.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/bloom.xml (revision 23483)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/bloom.xml (revision 23484)
@@ -1,13 +1,13 @@
-
+
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/dof.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/dof.xml (revision 23483)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/dof.xml (revision 23484)
@@ -1,13 +1,13 @@
-
+
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.fs (nonexistent)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.fs (revision 23484)
@@ -0,0 +1,623 @@
+#version 120
+
+// Our GLSL adoptation of:
+//
+// * Removed all unrelated code (such as HLSL or console implementations).
+// * Removed unused macro (such as FXAA_DISCARD, FXAA_GATHER4_ALPHA, ...).
+// * Luma calculated by 3 components instead of the only green one.
+
+#define FXAA_QUALITY__PRESET 10
+
+//
+// NVIDIA FXAA 3.11 by TIMOTHY LOTTES
+//
+// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of NVIDIA CORPORATION nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+/*============================================================================
+ FXAA QUALITY - PRESETS
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 10)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 3.0
+ #define FXAA_QUALITY__P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 11)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 3.0
+ #define FXAA_QUALITY__P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 12)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 4.0
+ #define FXAA_QUALITY__P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 13)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 4.0
+ #define FXAA_QUALITY__P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 14)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 4.0
+ #define FXAA_QUALITY__P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 15)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 20)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 2.0
+ #define FXAA_QUALITY__P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 21)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 22)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 23)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 24)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 3.0
+ #define FXAA_QUALITY__P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 25)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 26)
+ #define FXAA_QUALITY__PS 9
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 4.0
+ #define FXAA_QUALITY__P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 27)
+ #define FXAA_QUALITY__PS 10
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 4.0
+ #define FXAA_QUALITY__P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 28)
+ #define FXAA_QUALITY__PS 11
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 4.0
+ #define FXAA_QUALITY__P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 29)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 39)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.0
+ #define FXAA_QUALITY__P2 1.0
+ #define FXAA_QUALITY__P3 1.0
+ #define FXAA_QUALITY__P4 1.0
+ #define FXAA_QUALITY__P5 1.5
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+#define FxaaTexTop(t, p) texture2DLod((t), (p), 0.0)
+#define FxaaTexOff(t, p, o, r) texture2DLod((t), (p) + (o) * (r), 0.0)
+#define FxaaLuma(rgba) dot((rgba).rgb, vec3(0.299, 0.587, 0.114))
+
+vec4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ vec2 pos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ sampler2D tex,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ vec2 fxaaQualityRcpFrame,
+ //
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ float fxaaQualitySubpix,
+ //
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ float fxaaQualityEdgeThreshold,
+ //
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ float fxaaQualityEdgeThresholdMin)
+{
+/*--------------------------------------------------------------------------*/
+ vec2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ vec4 rgbyM = FxaaTexTop(tex, posM);
+ float lumaM = FxaaLuma(rgbyM);
+ float lumaS = FxaaLuma(FxaaTexOff(tex, posM, vec2(0, 1), fxaaQualityRcpFrame.xy));
+ float lumaE = FxaaLuma(FxaaTexOff(tex, posM, vec2(1, 0), fxaaQualityRcpFrame.xy));
+ float lumaN = FxaaLuma(FxaaTexOff(tex, posM, vec2(0, -1), fxaaQualityRcpFrame.xy));
+ float lumaW = FxaaLuma(FxaaTexOff(tex, posM, vec2(-1, 0), fxaaQualityRcpFrame.xy));
+/*--------------------------------------------------------------------------*/
+ float maxSM = max(lumaS, lumaM);
+ float minSM = min(lumaS, lumaM);
+ float maxESM = max(lumaE, maxSM);
+ float minESM = min(lumaE, minSM);
+ float maxWN = max(lumaN, lumaW);
+ float minWN = min(lumaN, lumaW);
+ float rangeMax = max(maxWN, maxESM);
+ float rangeMin = min(minWN, minESM);
+ float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ float range = rangeMax - rangeMin;
+ float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ bool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit)
+ return rgbyM;
+/*--------------------------------------------------------------------------*/
+ float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, vec2(-1,-1), fxaaQualityRcpFrame.xy));
+ float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, vec2( 1, 1), fxaaQualityRcpFrame.xy));
+ float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, vec2( 1,-1), fxaaQualityRcpFrame.xy));
+ float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, vec2(-1, 1), fxaaQualityRcpFrame.xy));
+/*--------------------------------------------------------------------------*/
+ float lumaNS = lumaN + lumaS;
+ float lumaWE = lumaW + lumaE;
+ float subpixRcpRange = 1.0/range;
+ float subpixNSWE = lumaNS + lumaWE;
+ float edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ float edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ float lumaNESE = lumaNE + lumaSE;
+ float lumaNWNE = lumaNW + lumaNE;
+ float edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ float edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ float lumaNWSW = lumaNW + lumaSW;
+ float lumaSWSE = lumaSW + lumaSE;
+ float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ float edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ float edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ float edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ float subpixNWSWNESE = lumaNWSW + lumaNESE;
+ float lengthSign = fxaaQualityRcpFrame.x;
+ bool horzSpan = edgeHorz >= edgeVert;
+ float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ float subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ float gradientN = lumaN - lumaM;
+ float gradientS = lumaS - lumaM;
+ float lumaNN = lumaN + lumaM;
+ float lumaSS = lumaS + lumaM;
+ bool pairN = abs(gradientN) >= abs(gradientS);
+ float gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ float subpixC = clamp(abs(subpixB) * subpixRcpRange, 0.0, 1.0);
+/*--------------------------------------------------------------------------*/
+ vec2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ vec2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ vec2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
+ vec2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
+ float subpixD = ((-2.0)*subpixC) + 3.0;
+ float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ float subpixE = subpixC * subpixC;
+ float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ float gradientScaled = gradient * 1.0/4.0;
+ float lumaMM = lumaM - lumaNN * 0.5;
+ float subpixF = subpixD * subpixE;
+ bool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ bool doneN = abs(lumaEndN) >= gradientScaled;
+ bool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
+ bool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ float dstN = posM.x - posN.x;
+ float dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ float spanLength = (dstP + dstN);
+ bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ float spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ bool directionN = dstN < dstP;
+ float dst = min(dstN, dstP);
+ bool goodSpan = directionN ? goodSpanN : goodSpanP;
+ float subpixG = subpixF * subpixF;
+ float pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ float subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ float pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ return vec4(FxaaTexTop(tex, posM).xyz, lumaM);
+}
+
+uniform sampler2D renderedTex;
+uniform float width;
+uniform float height;
+
+varying vec2 v_tex;
+
+void main()
+{
+ // See comment for the FxaaPixelShader function.
+ const float fxaaQualitySubpix = 0.75;
+ const float fxaaQualityEdgeThreshold = 0.125;
+ const float fxaaQualityEdgeThresholdMin = 0.0312;
+ gl_FragColor = FxaaPixelShader(
+ v_tex, renderedTex,
+ vec2(1.0, 1.0) / vec2(width, height),
+ fxaaQualitySubpix,
+ fxaaQualityEdgeThreshold,
+ fxaaQualityEdgeThresholdMin);
+}
Property changes on: ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.fs
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.xml (nonexistent)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.xml (revision 23484)
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Property changes on: ps/trunk/binaries/data/mods/public/shaders/glsl/fxaa.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.xml (revision 23483)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/hdr.xml (revision 23484)
@@ -1,13 +1,13 @@
-
+
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/simple.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/simple.vs (nonexistent)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/simple.vs (revision 23484)
@@ -0,0 +1,13 @@
+#version 110
+
+varying vec2 v_tex;
+
+attribute vec3 a_vertex;
+attribute vec2 a_uv0;
+
+void main()
+{
+ gl_Position = vec4(a_vertex, 1.0);
+
+ v_tex = a_uv0;
+}
Property changes on: ps/trunk/binaries/data/mods/public/shaders/glsl/simple.vs
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/source/renderer/PostprocManager.cpp
===================================================================
--- ps/trunk/source/renderer/PostprocManager.cpp (revision 23483)
+++ ps/trunk/source/renderer/PostprocManager.cpp (revision 23484)
@@ -1,614 +1,648 @@
/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "renderer/PostprocManager.h"
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/ShaderManager.h"
#include "lib/bits.h"
#include "lib/ogl.h"
#include "maths/MathUtil.h"
+#include "ps/ConfigDB.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
#include "ps/Game.h"
#include "ps/World.h"
#include "renderer/Renderer.h"
+#include "renderer/RenderingOptions.h"
#if !CONFIG2_GLES
CPostprocManager::CPostprocManager()
: m_IsInitialized(false), m_PingFbo(0), m_PongFbo(0), m_PostProcEffect(L"default"), m_ColorTex1(0), m_ColorTex2(0),
m_DepthTex(0), m_BloomFbo(0), m_BlurTex2a(0), m_BlurTex2b(0), m_BlurTex4a(0), m_BlurTex4b(0),
m_BlurTex8a(0), m_BlurTex8b(0), m_WhichBuffer(true)
{
}
CPostprocManager::~CPostprocManager()
{
Cleanup();
}
void CPostprocManager::Cleanup()
{
if (!m_IsInitialized) // Only cleanup if previously used
return;
if (m_PingFbo) pglDeleteFramebuffersEXT(1, &m_PingFbo);
if (m_PongFbo) pglDeleteFramebuffersEXT(1, &m_PongFbo);
if (m_BloomFbo) pglDeleteFramebuffersEXT(1, &m_BloomFbo);
m_PingFbo = m_PongFbo = m_BloomFbo = 0;
if (m_ColorTex1) glDeleteTextures(1, &m_ColorTex1);
if (m_ColorTex2) glDeleteTextures(1, &m_ColorTex2);
if (m_DepthTex) glDeleteTextures(1, &m_DepthTex);
m_ColorTex1 = m_ColorTex2 = m_DepthTex = 0;
if (m_BlurTex2a) glDeleteTextures(1, &m_BlurTex2a);
if (m_BlurTex2b) glDeleteTextures(1, &m_BlurTex2b);
if (m_BlurTex4a) glDeleteTextures(1, &m_BlurTex4a);
if (m_BlurTex4b) glDeleteTextures(1, &m_BlurTex4b);
if (m_BlurTex8a) glDeleteTextures(1, &m_BlurTex8a);
if (m_BlurTex8b) glDeleteTextures(1, &m_BlurTex8b);
m_BlurTex2a = m_BlurTex2b = m_BlurTex4a = m_BlurTex4b = m_BlurTex8a = m_BlurTex8b = 0;
}
void CPostprocManager::Initialize()
{
if (m_IsInitialized)
return;
// The screen size starts out correct and then must be updated with Resize()
m_Width = g_Renderer.GetWidth();
m_Height = g_Renderer.GetHeight();
+ UpdateAntiAliasingTechnique();
RecreateBuffers();
m_IsInitialized = true;
// This might happen after the map is loaded and the effect chosen
SetPostEffect(m_PostProcEffect);
}
void CPostprocManager::Resize()
{
m_Width = g_Renderer.GetWidth();
m_Height = g_Renderer.GetHeight();
// If the buffers were intialized, recreate them to the new size.
if (m_IsInitialized)
RecreateBuffers();
}
void CPostprocManager::RecreateBuffers()
{
Cleanup();
#define GEN_BUFFER_RGBA(name, w, h) \
glGenTextures(1, (GLuint*)&name); \
glBindTexture(GL_TEXTURE_2D, name); \
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); \
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); \
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); \
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); \
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Two fullscreen ping-pong textures.
GEN_BUFFER_RGBA(m_ColorTex1, m_Width, m_Height);
GEN_BUFFER_RGBA(m_ColorTex2, m_Width, m_Height);
// Textures for several blur sizes. It would be possible to reuse
// m_BlurTex2b, thus avoiding the need for m_BlurTex4b and m_BlurTex8b, though given
// that these are fairly small it's probably not worth complicating the coordinates passed
// to the blur helper functions.
GEN_BUFFER_RGBA(m_BlurTex2a, m_Width / 2, m_Height / 2);
GEN_BUFFER_RGBA(m_BlurTex2b, m_Width / 2, m_Height / 2);
GEN_BUFFER_RGBA(m_BlurTex4a, m_Width / 4, m_Height / 4);
GEN_BUFFER_RGBA(m_BlurTex4b, m_Width / 4, m_Height / 4);
GEN_BUFFER_RGBA(m_BlurTex8a, m_Width / 8, m_Height / 8);
GEN_BUFFER_RGBA(m_BlurTex8b, m_Width / 8, m_Height / 8);
#undef GEN_BUFFER_RGBA
// Allocate the Depth/Stencil texture.
glGenTextures(1, (GLuint*)&m_DepthTex);
glBindTexture(GL_TEXTURE_2D, m_DepthTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height,
0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
// Set up the framebuffers with some initial textures.
pglGenFramebuffersEXT(1, &m_PingFbo);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_ColorTex1, 0);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, m_DepthTex, 0);
GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
LOGWARNING("Framebuffer object incomplete (A): 0x%04X", status);
}
pglGenFramebuffersEXT(1, &m_PongFbo);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_ColorTex2, 0);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, m_DepthTex, 0);
status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
LOGWARNING("Framebuffer object incomplete (B): 0x%04X", status);
}
pglGenFramebuffersEXT(1, &m_BloomFbo);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
/*
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_BloomTex1, 0);
status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
LOGWARNING("Framebuffer object incomplete (B): 0x%04X", status);
}
*/
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void CPostprocManager::ApplyBlurDownscale2x(GLuint inTex, GLuint outTex, int inWidth, int inHeight)
{
// Bind inTex to framebuffer for rendering.
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, outTex, 0);
// Get bloom shader with instructions to simply copy texels.
CShaderDefines defines;
defines.Add(str_BLOOM_NOP, str_1);
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom,
g_Renderer.GetSystemShaderDefines(), defines);
tech->BeginPass();
CShaderProgramPtr shader = tech->GetShader();
GLuint renderedTex = inTex;
// Cheat by creating high quality mipmaps for inTex, so the copying operation actually
// produces good scaling due to hardware filtering.
glBindTexture(GL_TEXTURE_2D, renderedTex);
pglGenerateMipmapEXT(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
shader->BindTexture(str_renderedTex, renderedTex);
const SViewPort oldVp = g_Renderer.GetViewport();
const SViewPort vp = { 0, 0, inWidth / 2, inHeight / 2 };
g_Renderer.SetViewport(vp);
float quadVerts[] = {
1.0f, 1.0f,
-1.0f, 1.0f,
-1.0f, -1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
1.0f, 1.0f
};
float quadTex[] = {
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
g_Renderer.SetViewport(oldVp);
tech->EndPass();
}
void CPostprocManager::ApplyBlurGauss(GLuint inOutTex, GLuint tempTex, int inWidth, int inHeight)
{
// Set tempTex as our rendering target.
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tempTex, 0);
// Get bloom shader, for a horizontal Gaussian blur pass.
CShaderDefines defines2;
defines2.Add(str_BLOOM_PASS_H, str_1);
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom,
g_Renderer.GetSystemShaderDefines(), defines2);
tech->BeginPass();
CShaderProgramPtr shader = tech->GetShader();
shader->BindTexture(str_renderedTex, inOutTex);
shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
const SViewPort oldVp = g_Renderer.GetViewport();
const SViewPort vp = { 0, 0, inWidth, inHeight };
g_Renderer.SetViewport(vp);
float quadVerts[] = {
1.0f, 1.0f,
-1.0f, 1.0f,
-1.0f, -1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
1.0f, 1.0f
};
float quadTex[] = {
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
g_Renderer.SetViewport(oldVp);
tech->EndPass();
// Set result texture as our render target.
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, inOutTex, 0);
// Get bloom shader, for a vertical Gaussian blur pass.
CShaderDefines defines3;
defines3.Add(str_BLOOM_PASS_V, str_1);
tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom,
g_Renderer.GetSystemShaderDefines(), defines3);
tech->BeginPass();
shader = tech->GetShader();
// Our input texture to the shader is the output of the horizontal pass.
shader->BindTexture(str_renderedTex, tempTex);
shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
g_Renderer.SetViewport(vp);
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
g_Renderer.SetViewport(oldVp);
tech->EndPass();
}
void CPostprocManager::ApplyBlur()
{
glDisable(GL_BLEND);
int width = m_Width, height = m_Height;
#define SCALE_AND_BLUR(tex1, tex2, temptex) \
ApplyBlurDownscale2x(tex1, tex2, width, height); \
width /= 2; \
height /= 2; \
ApplyBlurGauss(tex2, temptex, width, height);
// We do the same thing for each scale, incrementally adding more and more blur.
SCALE_AND_BLUR(m_WhichBuffer ? m_ColorTex1 : m_ColorTex2, m_BlurTex2a, m_BlurTex2b);
SCALE_AND_BLUR(m_BlurTex2a, m_BlurTex4a, m_BlurTex4b);
SCALE_AND_BLUR(m_BlurTex4a, m_BlurTex8a, m_BlurTex8b);
#undef SCALE_AND_BLUR
}
void CPostprocManager::CaptureRenderOutput()
{
ENSURE(m_IsInitialized);
// clear both FBOs and leave m_PingFbo selected for rendering;
// m_WhichBuffer stays true at this point
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
pglDrawBuffers(1, buffers);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
pglDrawBuffers(1, buffers);
m_WhichBuffer = true;
}
void CPostprocManager::ReleaseRenderOutput()
{
ENSURE(m_IsInitialized);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// we blit to screen from the previous active buffer
if (m_WhichBuffer)
pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_PingFbo);
else
pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_PongFbo);
pglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
pglBlitFramebufferEXT(0, 0, m_Width, m_Height, 0, 0, m_Width, m_Height,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
{
// select the other FBO for rendering
if (!m_WhichBuffer)
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
else
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
shaderTech1->BeginPass(pass);
CShaderProgramPtr shader = shaderTech1->GetShader(pass);
shader->Bind();
// Use the textures from the current FBO as input to the shader.
// We also bind a bunch of other textures and parameters, but since
// this only happens once per frame the overhead is negligible.
if (m_WhichBuffer)
shader->BindTexture(str_renderedTex, m_ColorTex1);
else
shader->BindTexture(str_renderedTex, m_ColorTex2);
shader->BindTexture(str_depthTex, m_DepthTex);
shader->BindTexture(str_blurTex2, m_BlurTex2a);
shader->BindTexture(str_blurTex4, m_BlurTex4a);
shader->BindTexture(str_blurTex8, m_BlurTex8a);
shader->Uniform(str_width, m_Width);
shader->Uniform(str_height, m_Height);
shader->Uniform(str_zNear, m_NearPlane);
shader->Uniform(str_zFar, m_FarPlane);
shader->Uniform(str_brightness, g_LightEnv.m_Brightness);
shader->Uniform(str_hdr, g_LightEnv.m_Contrast);
shader->Uniform(str_saturation, g_LightEnv.m_Saturation);
shader->Uniform(str_bloom, g_LightEnv.m_Bloom);
float quadVerts[] = {
1.0f, 1.0f,
-1.0f, 1.0f,
-1.0f, -1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
1.0f, 1.0f
};
float quadTex[] = {
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, quadTex);
shader->VertexPointer(2, GL_FLOAT, 0, quadVerts);
shader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
shader->Unbind();
shaderTech1->EndPass(pass);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
m_WhichBuffer = !m_WhichBuffer;
}
void CPostprocManager::ApplyPostproc()
{
ENSURE(m_IsInitialized);
// Don't do anything if we are using the default effect.
if (m_PostProcEffect == L"default")
return;
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT };
pglDrawBuffers(1, buffers);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
pglDrawBuffers(1, buffers);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
// First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied!
// (This may need to change depending on future usage, however that will have a fps hit)
ApplyBlur();
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
for (int pass = 0; pass < m_PostProcTech->GetNumPasses(); ++pass)
ApplyEffect(m_PostProcTech, pass);
+ if (m_AATech)
+ {
+ for (int pass = 0; pass < m_AATech->GetNumPasses(); ++pass)
+ ApplyEffect(m_AATech, pass);
+ }
+
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
}
// Generate list of available effect-sets
std::vector CPostprocManager::GetPostEffects()
{
std::vector effects;
const VfsPath path(L"shaders/effects/postproc/");
VfsPaths pathnames;
if (vfs::GetPathnames(g_VFS, path, 0, pathnames) < 0)
LOGERROR("Error finding Post effects in '%s'", path.string8());
for (const VfsPath& path : pathnames)
if (path.Extension() == L".xml")
effects.push_back(path.Basename().string());
// Add the default "null" effect to the list.
effects.push_back(L"default");
sort(effects.begin(), effects.end());
return effects;
}
void CPostprocManager::SetPostEffect(const CStrW& name)
{
if (m_IsInitialized)
{
if (name != L"default")
{
CStrW n = L"postproc/" + name;
m_PostProcTech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern(n.ToUTF8()));
}
}
m_PostProcEffect = name;
}
+void CPostprocManager::UpdateAntiAliasingTechnique()
+{
+ if (!g_RenderingOptions.GetPreferGLSL())
+ return;
+
+ CStr newAAName;
+ CFG_GET_VAL("antialiasing", newAAName);
+ if (m_AAName == newAAName)
+ return;
+ m_AAName = newAAName;
+ m_AATech.reset();
+
+ // We have to hardcode names in the engine, because anti-aliasing
+ // techinques strongly depend on the graphics pipeline.
+ // We might use enums in future though.
+ if (m_AAName == "fxaa")
+ {
+ m_AATech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("fxaa"));
+ }
+}
+
void CPostprocManager::SetDepthBufferClipPlanes(float nearPlane, float farPlane)
{
m_NearPlane = nearPlane;
m_FarPlane = farPlane;
}
#else
#warning TODO: implement PostprocManager for GLES
void ApplyBlurDownscale2x(GLuint UNUSED(inTex), GLuint UNUSED(outTex), int UNUSED(inWidth), int UNUSED(inHeight))
{
}
void CPostprocManager::ApplyBlurGauss(GLuint UNUSED(inOutTex), GLuint UNUSED(tempTex), int UNUSED(inWidth), int UNUSED(inHeight))
{
}
void CPostprocManager::ApplyEffect(CShaderTechniquePtr &UNUSED(shaderTech1), int UNUSED(pass))
{
}
CPostprocManager::CPostprocManager()
{
}
CPostprocManager::~CPostprocManager()
{
}
void CPostprocManager::Initialize()
{
}
void CPostprocManager::Resize()
{
}
void CPostprocManager::Cleanup()
{
}
void CPostprocManager::RecreateBuffers()
{
}
std::vector CPostprocManager::GetPostEffects()
{
return std::vector();
}
void CPostprocManager::SetPostEffect(const CStrW& UNUSED(name))
{
}
void CPostprocManager::SetDepthBufferClipPlanes(float UNUSED(nearPlane), float UNUSED(farPlane))
{
}
+void CPostprocManager::UpdateAntiAliasingTechnique()
+{
+}
+
void CPostprocManager::CaptureRenderOutput()
{
}
void CPostprocManager::ApplyPostproc()
{
}
void CPostprocManager::ReleaseRenderOutput()
{
}
#endif
Index: ps/trunk/source/renderer/PostprocManager.h
===================================================================
--- ps/trunk/source/renderer/PostprocManager.h (revision 23483)
+++ ps/trunk/source/renderer/PostprocManager.h (revision 23484)
@@ -1,123 +1,129 @@
-/* Copyright (C) 2019 Wildfire Games.
+/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_POSTPROCMANAGER
#define INCLUDED_POSTPROCMANAGER
#include "graphics/ShaderTechnique.h"
#include "ps/CStr.h"
#include
class CPostprocManager
{
public:
CPostprocManager();
~CPostprocManager();
// Create all buffers/textures in GPU memory and set default effect.
// @note Must be called before using in the renderer. May be called multiple times.
void Initialize();
// Update the size of the screen
void Resize();
// Returns a list of xml files found in shaders/effects/postproc.
static std::vector GetPostEffects();
// Returns the name of the current effect.
const CStrW& GetPostEffect() const
{
return m_PostProcEffect;
}
// Sets the current effect.
void SetPostEffect(const CStrW& name);
+ // Triggers update of shaders and FBO if needed.
+ void UpdateAntiAliasingTechnique();
+
void SetDepthBufferClipPlanes(float nearPlane, float farPlane);
// Clears the two color buffers and depth buffer, and redirects all rendering
// to our textures instead of directly to the system framebuffer.
// @note CPostprocManager must be initialized first
void CaptureRenderOutput();
// First renders blur textures, then calls ApplyEffect for each effect pass,
// ping-ponging the buffers at each step.
// @note CPostprocManager must be initialized first
void ApplyPostproc();
// Blits the final postprocessed texture to the system framebuffer. The system framebuffer
// is selected as the output buffer. Should be called before silhouette rendering.
// @note CPostprocManager must be initialized first
void ReleaseRenderOutput();
private:
// Two framebuffers, that we flip between at each shader pass.
GLuint m_PingFbo, m_PongFbo;
// Unique color textures for the framebuffers.
GLuint m_ColorTex1, m_ColorTex2;
// The framebuffers share a depth/stencil texture.
GLuint m_DepthTex;
float m_NearPlane, m_FarPlane;
// A framebuffer and textures x2 for each blur level we render.
GLuint m_BloomFbo, m_BlurTex2a, m_BlurTex2b, m_BlurTex4a, m_BlurTex4b, m_BlurTex8a, m_BlurTex8b;
// Indicates which of the ping-pong buffers is used for reading and which for drawing.
bool m_WhichBuffer;
// The name and shader technique we are using. "default" name means no technique is used
// (i.e. while we do allocate the buffers, no effects are rendered).
CStrW m_PostProcEffect;
CShaderTechniquePtr m_PostProcTech;
+ CStr m_AAName;
+ CShaderTechniquePtr m_AATech;
+
// The current screen dimensions in pixels.
int m_Width, m_Height;
// Is the postproc manager initialized? Buffers created? Default effect loaded?
bool m_IsInitialized;
// Creates blur textures at various scales, for bloom, DOF, etc.
void ApplyBlur();
// High quality GPU image scaling to half size. outTex must have exactly half the size
// of inTex. inWidth and inHeight are the dimensions of inTex in texels.
void ApplyBlurDownscale2x(GLuint inTex, GLuint outTex, int inWidth, int inHeight);
// GPU-based Gaussian blur in two passes. inOutTex contains the input image and will be filled
// with the blurred image. tempTex must have the same size as inOutTex.
// inWidth and inHeight are the dimensions of the images in texels.
void ApplyBlurGauss(GLuint inOutTex, GLuint tempTex, int inWidth, int inHeight);
// Applies a pass of a given effect to the entire current framebuffer. The shader is
// provided with a number of general-purpose variables, including the rendered screen so far,
// the depth buffer, a number of blur textures, the screen size, the zNear/zFar planes and
// some other parameters used by the optional bloom/HDR pass.
void ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass);
// Delete all allocated buffers/textures from GPU memory.
void Cleanup();
// Delete existing buffers/textures and create them again, using a new screen size if needed.
// (the textures are also attached to the framebuffers)
void RecreateBuffers();
};
#endif // INCLUDED_POSTPROCMANAGER
Index: ps/trunk/source/renderer/scripting/JSInterface_Renderer.cpp
===================================================================
--- ps/trunk/source/renderer/scripting/JSInterface_Renderer.cpp (revision 23483)
+++ ps/trunk/source/renderer/scripting/JSInterface_Renderer.cpp (revision 23484)
@@ -1,108 +1,115 @@
/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "JSInterface_Renderer.h"
#include "graphics/TextureManager.h"
+#include "renderer/PostprocManager.h"
#include "renderer/RenderingOptions.h"
#include "renderer/Renderer.h"
#include "renderer/ShadowMap.h"
#include "scriptinterface/ScriptInterface.h"
#define IMPLEMENT_BOOLEAN_SCRIPT_SETTING(NAME) \
bool JSI_Renderer::Get##NAME##Enabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) \
{ \
return g_RenderingOptions.Get##NAME(); \
} \
\
void JSI_Renderer::Set##NAME##Enabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool enabled) \
{ \
g_RenderingOptions.Set##NAME(enabled); \
}
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Shadows);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(ShadowPCF);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Particles);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(PreferGLSL);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterEffects);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterRealDepth);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterReflection);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterRefraction);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterShadows);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Fog);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Silhouettes);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(ShowSky);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SmoothLOS);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(PostProc);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(DisplayFrustum);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(DisplayShadowsFrustum);
#undef IMPLEMENT_BOOLEAN_SCRIPT_SETTING
std::string JSI_Renderer::GetRenderPath(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
{
return RenderPathEnum::ToString(g_RenderingOptions.GetRenderPath());
}
void JSI_Renderer::SetRenderPath(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& name)
{
g_RenderingOptions.SetRenderPath(RenderPathEnum::FromString(name));
}
+void JSI_Renderer::UpdateAntiAliasingTechnique(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
+{
+ g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique();
+}
+
void JSI_Renderer::RecreateShadowMap(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
{
g_Renderer.GetShadowMap().RecreateTexture();
}
bool JSI_Renderer::TextureExists(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& filename)
{
return g_Renderer.GetTextureManager().TextureExists(filename);
}
#define REGISTER_BOOLEAN_SCRIPT_SETTING(NAME) \
scriptInterface.RegisterFunction("Renderer_Get" #NAME "Enabled"); \
scriptInterface.RegisterFunction("Renderer_Set" #NAME "Enabled");
void JSI_Renderer::RegisterScriptFunctions(const ScriptInterface& scriptInterface)
{
scriptInterface.RegisterFunction("Renderer_GetRenderPath");
scriptInterface.RegisterFunction("Renderer_SetRenderPath");
scriptInterface.RegisterFunction("Renderer_RecreateShadowMap");
+ scriptInterface.RegisterFunction("Renderer_UpdateAntiAliasingTechnique");
scriptInterface.RegisterFunction("TextureExists");
REGISTER_BOOLEAN_SCRIPT_SETTING(Shadows);
REGISTER_BOOLEAN_SCRIPT_SETTING(ShadowPCF);
REGISTER_BOOLEAN_SCRIPT_SETTING(Particles);
REGISTER_BOOLEAN_SCRIPT_SETTING(PreferGLSL);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterEffects);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterRealDepth);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterReflection);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterRefraction);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterShadows);
REGISTER_BOOLEAN_SCRIPT_SETTING(Fog);
REGISTER_BOOLEAN_SCRIPT_SETTING(Silhouettes);
REGISTER_BOOLEAN_SCRIPT_SETTING(ShowSky);
REGISTER_BOOLEAN_SCRIPT_SETTING(SmoothLOS);
REGISTER_BOOLEAN_SCRIPT_SETTING(PostProc);
REGISTER_BOOLEAN_SCRIPT_SETTING(DisplayFrustum);
REGISTER_BOOLEAN_SCRIPT_SETTING(DisplayShadowsFrustum);
}
#undef REGISTER_BOOLEAN_SCRIPT_SETTING
Index: ps/trunk/source/renderer/scripting/JSInterface_Renderer.h
===================================================================
--- ps/trunk/source/renderer/scripting/JSInterface_Renderer.h (revision 23483)
+++ ps/trunk/source/renderer/scripting/JSInterface_Renderer.h (revision 23484)
@@ -1,57 +1,58 @@
/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_JSINTERFACE_RENDERER
#define INCLUDED_JSINTERFACE_RENDERER
#include "scriptinterface/ScriptInterface.h"
#define DECLARE_BOOLEAN_SCRIPT_SETTING(NAME) \
bool Get##NAME##Enabled(ScriptInterface::CxPrivate* pCxPrivate); \
void Set##NAME##Enabled(ScriptInterface::CxPrivate* pCxPrivate, bool Enabled);
namespace JSI_Renderer
{
std::string GetRenderPath(ScriptInterface::CxPrivate* pCxPrivate);
void SetRenderPath(ScriptInterface::CxPrivate* pCxPrivate, const std::string& name);
+ void UpdateAntiAliasingTechnique(ScriptInterface::CxPrivate* pCxPrivate);
void RecreateShadowMap(ScriptInterface::CxPrivate* pCxPrivate);
bool TextureExists(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filename);
DECLARE_BOOLEAN_SCRIPT_SETTING(Shadows);
DECLARE_BOOLEAN_SCRIPT_SETTING(ShadowPCF);
DECLARE_BOOLEAN_SCRIPT_SETTING(Particles);
DECLARE_BOOLEAN_SCRIPT_SETTING(PreferGLSL);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterEffects);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterRealDepth);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterReflection);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterRefraction);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterShadows);
DECLARE_BOOLEAN_SCRIPT_SETTING(Fog);
DECLARE_BOOLEAN_SCRIPT_SETTING(Silhouettes);
DECLARE_BOOLEAN_SCRIPT_SETTING(ShowSky);
DECLARE_BOOLEAN_SCRIPT_SETTING(SmoothLOS);
DECLARE_BOOLEAN_SCRIPT_SETTING(PostProc);
DECLARE_BOOLEAN_SCRIPT_SETTING(DisplayFrustum);
DECLARE_BOOLEAN_SCRIPT_SETTING(DisplayShadowsFrustum);
void RegisterScriptFunctions(const ScriptInterface& scriptInterface);
}
#undef DECLARE_BOOLEAN_SCRIPT_SETTING
#endif // INCLUDED_JSINTERFACE_RENDERER