renderpipiline 更新

This commit is contained in:
ayuan9957 2026-02-25 14:56:09 +08:00
parent a00b276233
commit 35a75bba29
647 changed files with 154245 additions and 153932 deletions

View File

@ -1,4 +1,4 @@
[flake8]
max-line-length=100
exclude=rplibs/*,data/*,hosek_wilkie_scattering,bake_gi,_DEV,*_generated.py,resources_rc.py
[flake8]
max-line-length=100
exclude=rplibs/*,data/*,hosek_wilkie_scattering,bake_gi,_DEV,*_generated.py,resources_rc.py

View File

@ -1,60 +1,60 @@
# --- Ignored extensions ---
*.pyd
*.pyc
*.ignore
*.old
*.egg
*.psd
*.blend1
*.blend2
*.pdb
*.stackdump
*.exr
*.trace
*.autogen*
*.mip
mitsuba.*.log
*.exr
*.txo.pz
# --- Ignored folders and patterns ---
temp/
models/
data/film_grain/*.png
data/default_cubemap/filtered/
_DEV
toolkit/pathtracing_reference/mitsuba/
toolkit/pathtracing_reference/scene*.png
toolkit/pathtracing_reference/Scene*.blend
toolkit/pathtracing_reference/envmap.png
rpplugins/clouds/resources/slices/*
toolkit/rp_distributor/built/
# --- Ignored files ---
TODO.txt
*.flag
desktop.ini
scattering_lut.png
old/
data/gui/loading_screen
data/environment_brdf/scene.png
data/environment_brdf/res/scene.png
toolkit/pathtracing_reference/batch_compare/
toolkit/pathtracing_reference/difference.png
toolkit/pathtracing_reference/res/Scene.blend
toolkit/pathtracing_reference/res/scene.png
toolkit/pathtracing_reference/scene*.png
toolkit/pathtracing_reference/res/tex/envmap.png
_tmp_material.py
*/poisson_disk_generator/source/config_module*
_bake_params*
raw-bake.png
toolkit/bake_gi/resources/*.bam
toolkit/bake_gi/resources/*.blend
toolkit/bake_gi/scene
.vscode
# --- Ignored extensions ---
*.pyd
*.pyc
*.ignore
*.old
*.egg
*.psd
*.blend1
*.blend2
*.pdb
*.stackdump
*.exr
*.trace
*.autogen*
*.mip
mitsuba.*.log
*.exr
*.txo.pz
# --- Ignored folders and patterns ---
temp/
models/
data/film_grain/*.png
data/default_cubemap/filtered/
_DEV
toolkit/pathtracing_reference/mitsuba/
toolkit/pathtracing_reference/scene*.png
toolkit/pathtracing_reference/Scene*.blend
toolkit/pathtracing_reference/envmap.png
rpplugins/clouds/resources/slices/*
toolkit/rp_distributor/built/
# --- Ignored files ---
TODO.txt
*.flag
desktop.ini
scattering_lut.png
old/
data/gui/loading_screen
data/environment_brdf/scene.png
data/environment_brdf/res/scene.png
toolkit/pathtracing_reference/batch_compare/
toolkit/pathtracing_reference/difference.png
toolkit/pathtracing_reference/res/Scene.blend
toolkit/pathtracing_reference/res/scene.png
toolkit/pathtracing_reference/scene*.png
toolkit/pathtracing_reference/res/tex/envmap.png
_tmp_material.py
*/poisson_disk_generator/source/config_module*
_bake_params*
raw-bake.png
toolkit/bake_gi/resources/*.bam
toolkit/bake_gi/resources/*.blend
toolkit/bake_gi/scene
.vscode

View File

@ -1,379 +1,379 @@
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
init-hook=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS,rplibs,.git,scripts,build.py
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Use multiple processes to speed up Pylint.
jobs=1
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=
# Allow optimization of some AST trees. This will activate a peephole AST
# optimizer, which will apply various small optimizations. For instance, it can
# be used to obtain the result of joining multiple strings with the addition
# operator. Joining a lot of strings can lead to a maximum recursion error in
# Pylint and this flag can prevent that. It has one side effect, the resulting
# AST will be different than the one from reality.
optimize-ast=yes
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time. See also the "--disable" option for examples.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,E0611,W0622,W0201,C0111,R0201,R0913,R0902,R0904,R0914
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
[BASIC]
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,input,xrange,iteritems,raw_input
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,x,y,r,g,b,a,uv,w,h,np
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata,tmp,temp
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Regular expression matching correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for function names
function-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for variable names
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for attribute names
attr-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for argument names
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Naming hint for class names
class-name-hint=[A-Z_][a-zA-Z0-9]+$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for method names
method-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
[ELIF]
# Maximum number of nested blocks for function / method body
max-nested-blocks=4
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=100
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=8
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set). This supports can work
# with qualified names.
ignored-classes=
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_$|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setup,init,load,create
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
init-hook=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS,rplibs,.git,scripts,build.py
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Use multiple processes to speed up Pylint.
jobs=1
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=
# Allow optimization of some AST trees. This will activate a peephole AST
# optimizer, which will apply various small optimizations. For instance, it can
# be used to obtain the result of joining multiple strings with the addition
# operator. Joining a lot of strings can lead to a maximum recursion error in
# Pylint and this flag can prevent that. It has one side effect, the resulting
# AST will be different than the one from reality.
optimize-ast=yes
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time. See also the "--disable" option for examples.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,E0611,W0622,W0201,C0111,R0201,R0913,R0902,R0904,R0914
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
[BASIC]
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,input,xrange,iteritems,raw_input
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,x,y,r,g,b,a,uv,w,h,np
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata,tmp,temp
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Regular expression matching correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for function names
function-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for variable names
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for attribute names
attr-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for argument names
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Naming hint for class names
class-name-hint=[A-Z_][a-zA-Z0-9]+$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for method names
method-name-hint=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
[ELIF]
# Maximum number of nested blocks for function / method body
max-nested-blocks=4
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=100
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=8
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set). This supports can work
# with qualified names.
ignored-classes=
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_$|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setup,init,load,create
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

View File

@ -1,18 +1,18 @@
language: cpp
sudo: required
dist: trusty
compiler: gcc
addons:
apt:
sources:
- sourceline: "deb http://archive.panda3d.org/ubuntu/ trusty-dev main"
packages:
- cmake
- libeigen3-dev
- libfreetype6-dev
- panda3d1.10
script:
- export PYTHONPATH=${PYTHONPATH}:/usr/lib/python2.7/dist-packages
- export PYTHONPATH=${PYTHONPATH}:/usr/share/panda3d
- python2.7 setup.py --ci-build
language: cpp
sudo: required
dist: trusty
compiler: gcc
addons:
apt:
sources:
- sourceline: "deb http://archive.panda3d.org/ubuntu/ trusty-dev main"
packages:
- cmake
- libeigen3-dev
- libfreetype6-dev
- panda3d1.10
script:
- export PYTHONPATH=${PYTHONPATH}:/usr/lib/python2.7/dist-packages
- export PYTHONPATH=${PYTHONPATH}:/usr/share/panda3d
- python2.7 setup.py --ci-build

View File

@ -1,22 +1,22 @@
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,70 +1,70 @@
[![Join the chat at https://gitter.im/tobspr/RenderPipeline](https://badges.gitter.im/tobspr/RenderPipeline.svg)](https://gitter.im/tobspr/RenderPipeline?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/tobspr/RenderPipeline.svg?branch=master)](https://travis-ci.org/tobspr/RenderPipeline)
<!-- # Render Pipeline -->
<img src="http://i.imgur.com/PO4OK4a.png" alt="Deferred Rendering Pipeline with Physically Based Shading" />
Deferred Realtime Rendering Pipeline with Physically Based Shading for the <a href="http://github.com/panda3d/panda3d">Panda3D Game Engine</a>.
### Core Features
- Physically Based Shading
- Deferred Rendering
- Advanced Post-Processing Effects and Framework
- Time of Day System
- Plugin System
## Screenshots
You can click on the images to enlarge them. Besides of that, you can find many more screenshots in my <a href="https://www.dropbox.com/sh/dq4wu3g9jwjqnht/AAABSOPnglDHZYsG5HXR-mhWa" target="_blank">dropbox folder</a>.
**Forest**
<img src="http://i.imgur.com/fD88ZMU.png" />
**Material demo**
<img src="http://i.imgur.com/M5YtvYR.png" />
**Screen space reflections**
<img src="http://i.imgur.com/oOwLXAK.png" />
**Car rendering**
<img src="http://i.imgur.com/hFD4qjV.png" alt="Car rendering" />
**Plugin and Time of Day editor:**
<img src="http://i.imgur.com/a8VpiHS.png" />
**Terrain and volumetric clouds**
<img src="http://i.imgur.com/zE0ywPl.png" />
See the <a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki/Features">Feature List</a>
for a list of features, and list of techniques I intend to implement.
You can find my todo list for the render pipeline here: <a href="https://trello.com/b/Li2JQi0q/render-pipeline" target="_blank">Render Pipeline Roadmap</a>.
### Getting Started / Wiki
You should checkout the wiki if you want to find out more about the pipeline:
<a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki">Render Pipeline WIKI</a>
There is also a page about getting started there: <a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki/Getting%20Started">Getting Started</a>
### Requirements
- OpenGL 4.3 capable GPU (and drivers)
- <a target="_blank" href="https://github.com/panda3d/panda3d">Panda3D</a> Development Build
- 1 GB Graphics Memory recommended *(Can run with less, depends on enabled plugins and resolution)*
**Notice**: It seems that the drivers for Intel HD Graphics on Linux are not
capable of all 4.3 features, so the pipeline is not able to run there!
If you want to use the C++ Modules, checkout <a href="https://github.com/tobspr/RenderPipeline/wiki/Building%20the%20CPP%20Modules" target="_blank">
Building the C++ Modules</a> to get a list of requirements for them.
### Reporting Bugs / Contributing
If you find bugs, or find information missing in the wiki, or want to contribute,
you can find me most of the time in the `#panda3d` channel on freenode.
If I shouldn't be there, feel free to contact me per E-Mail: `tobias.springer1@googlemail.com`
[![Join the chat at https://gitter.im/tobspr/RenderPipeline](https://badges.gitter.im/tobspr/RenderPipeline.svg)](https://gitter.im/tobspr/RenderPipeline?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/tobspr/RenderPipeline.svg?branch=master)](https://travis-ci.org/tobspr/RenderPipeline)
<!-- # Render Pipeline -->
<img src="http://i.imgur.com/PO4OK4a.png" alt="Deferred Rendering Pipeline with Physically Based Shading" />
Deferred Realtime Rendering Pipeline with Physically Based Shading for the <a href="http://github.com/panda3d/panda3d">Panda3D Game Engine</a>.
### Core Features
- Physically Based Shading
- Deferred Rendering
- Advanced Post-Processing Effects and Framework
- Time of Day System
- Plugin System
## Screenshots
You can click on the images to enlarge them. Besides of that, you can find many more screenshots in my <a href="https://www.dropbox.com/sh/dq4wu3g9jwjqnht/AAABSOPnglDHZYsG5HXR-mhWa" target="_blank">dropbox folder</a>.
**Forest**
<img src="http://i.imgur.com/fD88ZMU.png" />
**Material demo**
<img src="http://i.imgur.com/M5YtvYR.png" />
**Screen space reflections**
<img src="http://i.imgur.com/oOwLXAK.png" />
**Car rendering**
<img src="http://i.imgur.com/hFD4qjV.png" alt="Car rendering" />
**Plugin and Time of Day editor:**
<img src="http://i.imgur.com/a8VpiHS.png" />
**Terrain and volumetric clouds**
<img src="http://i.imgur.com/zE0ywPl.png" />
See the <a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki/Features">Feature List</a>
for a list of features, and list of techniques I intend to implement.
You can find my todo list for the render pipeline here: <a href="https://trello.com/b/Li2JQi0q/render-pipeline" target="_blank">Render Pipeline Roadmap</a>.
### Getting Started / Wiki
You should checkout the wiki if you want to find out more about the pipeline:
<a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki">Render Pipeline WIKI</a>
There is also a page about getting started there: <a target="_blank" href="https://github.com/tobspr/RenderPipeline/wiki/Getting%20Started">Getting Started</a>
### Requirements
- OpenGL 4.3 capable GPU (and drivers)
- <a target="_blank" href="https://github.com/panda3d/panda3d">Panda3D</a> Development Build
- 1 GB Graphics Memory recommended *(Can run with less, depends on enabled plugins and resolution)*
**Notice**: It seems that the drivers for Intel HD Graphics on Linux are not
capable of all 4.3 features, so the pipeline is not able to run there!
If you want to use the C++ Modules, checkout <a href="https://github.com/tobspr/RenderPipeline/wiki/Building%20the%20CPP%20Modules" target="_blank">
Building the C++ Modules</a> to get a list of requirements for them.
### Reporting Bugs / Contributing
If you find bugs, or find information missing in the wiki, or want to contribute,
you can find me most of the time in the `#panda3d` channel on freenode.
If I shouldn't be there, feel free to contact me per E-Mail: `tobias.springer1@googlemail.com`

File diff suppressed because one or more lines are too long

View File

@ -1,30 +1,30 @@
# This file contains all available debug modes.
# You can add or remove debug modes here, aswell as
# disable or enable them, whatever fits to you.
# NOTICE: This file only has effect if debugging is enabled
# in the pipeline.yaml (settings.pipeline.display_debuger == True)
# Usually you don't have to touch this file, except when developing
# new plugins or adding new features.
render_modes:
- { name: "Shading Model", key: "SHADING_MODEL" }
- { name: "Diffuse", key: "DIFFUSE" }
- { name: "Roughness", key: "ROUGHNESS" }
- { name: "Specular", key: "SPECULAR" }
- { name: "Normal", key: "NORMAL" }
- { name: "Metallic", key: "METALLIC" }
- { name: "Translucency", key: "TRANSLUCENCY" }
- { name: "PSSM Splits", key: "PSSM_SPLITS", requires: "pssm", cxx_only: true }
- { name: "Ambient Occlusion", key: "OCCLUSION", requires: "ao" }
- { name: "Sky AO", key: "SKY_AO", requires: "sky_ao" }
- { name: "Scattering", key: "SCATTERING", requires: "scattering" }
- { name: "Velocity", key: "VELOCITY" }
- { name: "Diffuse Ambient", key: "DIFFUSE_AMBIENT" }
- { name: "Specular Ambient", key: "SPECULAR_AMBIENT" }
- { name: "Luminance", key: "LUMINANCE", special: true }
- { name: "Probe Count", key: "ENVPROBE_COUNT", requires: "env_probes" }
- { name: "Light Count", key: "LIGHT_COUNT" }
- { name: "Light Tiles", key: "LIGHT_TILES", special: true }
# This file contains all available debug modes.
# You can add or remove debug modes here, aswell as
# disable or enable them, whatever fits to you.
# NOTICE: This file only has effect if debugging is enabled
# in the pipeline.yaml (settings.pipeline.display_debuger == True)
# Usually you don't have to touch this file, except when developing
# new plugins or adding new features.
render_modes:
- { name: "Shading Model", key: "SHADING_MODEL" }
- { name: "Diffuse", key: "DIFFUSE" }
- { name: "Roughness", key: "ROUGHNESS" }
- { name: "Specular", key: "SPECULAR" }
- { name: "Normal", key: "NORMAL" }
- { name: "Metallic", key: "METALLIC" }
- { name: "Translucency", key: "TRANSLUCENCY" }
- { name: "PSSM Splits", key: "PSSM_SPLITS", requires: "pssm", cxx_only: true }
- { name: "Ambient Occlusion", key: "OCCLUSION", requires: "ao" }
- { name: "Sky AO", key: "SKY_AO", requires: "sky_ao" }
- { name: "Scattering", key: "SCATTERING", requires: "scattering" }
- { name: "Velocity", key: "VELOCITY" }
- { name: "Diffuse Ambient", key: "DIFFUSE_AMBIENT" }
- { name: "Specular Ambient", key: "SPECULAR_AMBIENT" }
- { name: "Luminance", key: "LUMINANCE", special: true }
- { name: "Probe Count", key: "ENVPROBE_COUNT", requires: "env_probes" }
- { name: "Light Count", key: "LIGHT_COUNT" }
- { name: "Light Tiles", key: "LIGHT_TILES", special: true }

View File

@ -0,0 +1,174 @@
# This is the config file used to configure basic settings for Panda3D.
# The pipeline loads it at startup to ensure the environment is setup properly.
# -------------- Development options --------------
pstats-gpu-timing #t
gl-debug #t
gl-debug-object-labels #t
# -------------- Production options ---------------
# pstats-gpu-timing #f
# gl-debug #f
# gl-debug-object-labels #f
# ----------------- Misc Settings -----------------
# Disable V-Sync
sync-video #f
# Limit the pstats-rate. This causes huge lag on windows 10.
pstats-max-rate 200
# No stack trace on assertion, set this to true to make panda crash on assertions
# (which will allow to debug it)
# assert-abort #t
# show-dll-error-dialog #f
# File system should be case sensitive
# NOTICE: Set this to #f if you are using tempfile, since it returns
# wrong cased directory paths
vfs-case-sensitive #t
# Enable state cache, this seems to actually help the performance by a lot
state-cache #t
transform-cache #t
# Hide frame rate meter (we have our own)
show-frame-rate-meter #f
# Set text settings
text-minfilter linear
text-magfilter linear
text-page-size 512 512
text-rwap-mode WM_border_clor
# Better text performance since rdb's patch
text-flatten 0
text-dynamic-merge 1
# For smoother animations
# even-animation #t
# Threading, really buggy!
#threading-model App/Cull/Draw
# Disable stencil, not supported/required
support-stencil #f
framebuffer-stencil #f
# Don't use srgb correction, we do that in the final shader
framebuffer-srgb #f
# Don't use multisamples
framebuffer-multisample #f
multisamples 0
# Don't rescale textures which are no power-of-2
textures-power-2 none
# Set default texture filters
texture-anisotropic-degree 16
texture-magfilter linear
texture-minfilter linear
texture-quality-level fastest
# Enable seamless cubemap filtering, important for environment filtering
gl-cube-map-seamless #t
# Disable caching of textures
model-cache-textures #f
# Disable the annoying SRGB warning from pnmimage
notify-level-pnmimage error
# Disable the buffer viewer, we have our own
show-buffers #f
# Use the default coordinate system, this makes our matrix transformations
# faster because we don't have have to transform them to a different coordinate
# system before
gl-coordinate-system default
# This makes animations smoother, especially if they were exported at 30 FPS
# and are played at 60 FPS
interpolate-frames #t
# Disable workarround in panda which causes our shadow atlas to take twice
# the amount of vram it should, due to an intel driver bug.
gl-force-fbo-color #f
# ----------- OpenGL / Performance Settings ------------
# Require OpenGL 4.3 at least, necessary for Intel drivers on Linux
gl-version 4 3
# Animations on the gpu. The default shader has to get adjusted to support this
# feature before this option can be turned on.
# hardware-animated-vertices #t
# Try this options for performance
# uniquify-matrix #t
# uniquify-transforms #t
# uniquify-states #t
# uniquify-attribs #f
# Enable garbarge collection
garbage-collect-states #t
# garbage-collect-states-rate 0.2
# Compress textures on the drivers?
# driver-compress-textures #t
# Faster animations? (Have to test)
# matrix-palette #t
# display-list-animation #t
# Better GL performance by not using gl-finish and so on
gl-finish #f
gl-force-no-error #t
gl-check-errors #f
gl-force-no-flush #t
gl-force-no-scissor #t
# Eventually disable memory barriers, have to check if this is faster
gl-enable-memory-barriers #f
# Disable threading
lock-to-one-cpu #t
support-threads #f
# Let the driver generate the mipmaps
driver-generate-mipmaps #t
# Use immutable texture storage, it is *supposed* to be faster, but might not be
# XXX: Seems to produce an GL_INVALID_VALUE when disabled
gl-immutable-texture-storage #t
# Default window settings
# depth-bits 0
color-bits 0
framebuffer-depth #f
# Small performance gain by specifying fixed vertex attribute locations.
# Might cause issues with some (incorrectly converted/loaded) meshes though
gl-fixed-vertex-attrib-locations #f
# Disable the fragment shader performance warning
gl-validate-shaders #f
gl-skip-shader-recompilation-warnings #t
alpha-scale-via-texture #f
pstats-name Render Pipeline Stats
rescale-normals #f
screenshot-extension png
# Required for correct velocity
always-store-prev-transform #t
allow-incomplete-render #t
no-singular-invert #f

View File

@ -1,82 +1,84 @@
# This file stores internal settings of the pipeline. It does not contain the
# plugin settings, but just the basic settings of the internal pipeline components.
pipeline:
# This controls whether to show or hide the onscreen debugger. Not showing
# it will also disable the hotkeys, and give a small performance boost.
# Most likely you also don't want to show it in your own game, so set
# it to false in that case.
display_debugger: False
# Affects which debugging information is displayed. If this is set to false,
# only frame time is displayed, otherwise much more information is visible.
# Has no effect when display_debugger is set to false.
advanced_debugging_info: False
# Whether to use the GL_R11F_G11F_B10F texture format to save memory
# and bandwidth. Usually you want to enable this, however it can
# cause banding sometimes, in which case you can disable this setting.
use_r11_g11_b10: false
# Enables to render at a higher or lower resolution than the window size.
# A value of 2.0 for example renders at twice the resolution (supoersampling)
# whereas a value of 0.5 would render at half resolution.
resolution_scale: 1.0
# Whether to render in a special reference mode, which displays the
# environment map as a background, and disable special effects like color
# grading and so on. This is used by the pathtracing reference.
reference_mode: false
# This are the settings affecting the lighting part of the pipeline,
# including builtin shadows and lights.
lighting:
# The pipeline uses clustered deferred shading, this means that the
# screen gets divided into tiles, and for each tile, the lights affecting
# that tile are accumulated. You can adjust the tile size here (in pixels),
# optimal is a tile size which is not too big (to avoid unecessary shading),
# but also not too small (to avoid excessive culling).
culling_grid_size_x: 24
culling_grid_size_y: 16
# The view frustum is additionally divived into slices, to be able to do
# better culling. If you use a higher amount of slices, the culling will
# get more exact, but also more expensive. You have to find the optimal
# size depending on your scene.
culling_grid_slices: 32
# This controls the maximum culling distance in world space. After this
# distance, no lights are rendered anymore. If you choose a lower
# distance, this *can* positively impact performance, but you should not
# set it too low, to avoid getting artifacts.
culling_max_distance: 500.0
# Controls the size of a slice in culling. Lower values might produce
# better performance for less amount of lights, but higher values should
# be used when using many lights, e.g. > 1024, to get better coherency.
culling_slice_width: 2048
# Controls the maximum amount of lights for each cell. If this value
# is set too low, you might get artifacts when having many lights.
# In general, try to set this value as low as possible without getting
# artifacts
max_lights_per_cell: 64
shadows:
# The size of the global shadow atlas, used for point and spot light
# shadows. This should be a power of 2.
atlas_size: 4096
# Maximum of shadow updates which may occur at one time. All updates
# which are beyond that count will get delayed to the next frame.
# If you set this too low, artifacts may occur because of shadows not
# getting updated fast enough. However, this also affects the performance
# quite a bit, since for every shadow map a part of the scene has
# to get re-rendered.
max_updates: 16
# Sets the maximum distance until which shadows are updated. If a shadow
# source is further away, it will no longer recieve updates
max_update_distance: 300.0
# This file stores internal settings of the pipeline. It does not contain the
# plugin settings, but just the basic settings of the internal pipeline components.
pipeline:
# This controls whether to show or hide the onscreen debugger. Not showing
# it will also disable the hotkeys, and give a small performance boost.
# Most likely you also don't want to show it in your own game, so set
# it to false in that case.
display_debugger: true
# Affects which debugging information is displayed. If this is set to false,
# only frame time is displayed, otherwise much more information is visible.
# Has no effect when display_debugger is set to false.
advanced_debugging_info: true
# Whether to use the GL_R11F_G11F_B10F texture format to save memory
# and bandwidth. Usually you want to enable this, however it can
# cause banding sometimes, in which case you can disable this setting.
use_r11_g11_b10: false
# Enables to render at a higher or lower resolution than the window size.
# A value of 2.0 for example renders at twice the resolution (supoersampling)
# whereas a value of 0.5 would render at half resolution.
resolution_scale: 1.0
# Whether to render in a special reference mode, which displays the
# environment map as a background, and disable special effects like color
# grading and so on. This is used by the pathtracing reference.
reference_mode: false
# This are the settings affecting the lighting part of the pipeline,
# including builtin shadows and lights.
lighting:
# The pipeline uses clustered deferred shading, this means that the
# screen gets divided into tiles, and for each tile, the lights affecting
# that tile are accumulated. You can adjust the tile size here (in pixels),
# optimal is a tile size which is not too big (to avoid unecessary shading),
# but also not too small (to avoid excessive culling).
culling_grid_size_x: 24
culling_grid_size_y: 16
# The view frustum is additionally divived into slices, to be able to do
# better culling. If you use a higher amount of slices, the culling will
# get more exact, but also more expensive. You have to find the optimal
# size depending on your scene.
culling_grid_slices: 32
# This controls the maximum culling distance in world space. After this
# distance, no lights are rendered anymore. If you choose a lower
# distance, this *can* positively impact performance, but you should not
# set it too low, to avoid getting artifacts.
culling_max_distance: 500.0
# Controls the size of a slice in culling. Lower values might produce
# better performance for less amount of lights, but higher values should
# be used when using many lights, e.g. > 1024, to get better coherency.
culling_slice_width: 2048
# Controls the maximum amount of lights for each cell. If this value
# is set too low, you might get artifacts when having many lights.
# In general, try to set this value as low as possible without getting
# artifacts
max_lights_per_cell: 64
shadows:
# The size of the global shadow atlas, used for point and spot light
# shadows. This should be a power of 2.
atlas_size: 4096
# Maximum of shadow updates which may occur at one time. All updates
# which are beyond that count will get delayed to the next frame.
# If you set this too low, artifacts may occur because of shadows not
# getting updated fast enough. However, this also affects the performance
# quite a bit, since for every shadow map a part of the scene has
# to get re-rendered.
max_updates: 8
# Sets the maximum distance until which shadows are updated. If a shadow
# source is further away, it will no longer recieve updates
max_update_distance: 150.0

View File

@ -1,199 +1,199 @@
# Render Pipeline Plugin Configuration
# Instead of editing this file, prefer to use the Plugin Configurator
# Any formatting and comments will be lost
enabled:
- ao
- bloom
- color_correction
- env_probes
- forward_shading
# - motion_blur # disabled for editor performance
- pssm
- scattering
- skin_shading
- sky_ao
- smaa
# - ssr # disabled for editor performance
#- clouds
#- dof
#- fxaa
#- volumetrics
#- vxgi
overrides:
ao:
blur_quality: LOW
blur_normal_factor: 2.97
blur_depth_factor: 0.88158
occlusion_strength: 2.19
clip_length: 4
technique: SSAO
ssao_sample_radius: 95.29
ssao_sequence: halton_3D_8
ssao_bias: 0.0143
ssao_max_distance: 7.5
hbao_sample_radius: 255.0
hbao_ray_count: 4
hbao_ray_steps: 3
hbao_tangent_bias: 0.64997
hbao_max_distance: 11.5
ssvo_sequence: halton_2D_8
ssvo_sphere_radius: 18.0
ssvo_max_distance: 3.19
alchemy_sample_radius: 38.86
alchemy_sequence: halton_2D_8
alchemy_max_distance: 5.86
ue4ao_sample_radius: 50.14286
ue4ao_sample_sequence: halton_2D_8
ue4ao_max_distance: 1.47
bloom:
num_mipmaps: 6
bloom_strength: 0.8003
remove_fireflies: False
lens_dirt_factor: 0.0
clouds:
raymarch_steps: 160
color_correction:
tonemap_operator: optimized
reinhard_version: rgb
exponential_factor: 1.23
uc2t_shoulder_strength: 0.3352
uc2t_linear_strength: 0.5339
uc2t_linear_angle: 0.1797
uc2t_toe_strength: 0.3919
uc2t_toe_numerator: 0.0029
uc2t_toe_denumerator: 0.2787
uc2t_reference_white: 10.05
vignette_strength: 0.1286
film_grain_strength: 0.1286
color_lut: film_luts/default_lut.png
use_chromatic_aberration: True
chromatic_aberration_strength: 0.019
chromatic_aberration_samples: 2
manual_camera_parameters: False
min_exposure_value: 0.01
max_exposure_value: 1.0
exposure_scale: 1.0
brightness_adaption_rate: 3.6
darkness_adaption_rate: 0.7
use_sharpen: True
sharpen_strength: 0.5
sharpen_twice: False
dof:
focal_point: 5
focal_size: 1
blur_strength: 1
near_blur_strength: 1
env_probes:
probe_resolution: 128
diffuse_probe_resolution: 2
max_probes: 16
max_probes_per_cell: 3
forward_shading:
fxaa:
quality: ultra
subpixel_quality: 0.5
edge_threshold: 0.166
min_threshold: 0.833
motion_blur:
num_camera_samples: 6
camera_blur_factor: 0.4
enable_object_blur: False
blur_factor: 0.5
tile_size: 32
max_blur_radius: 10.0
num_samples: 12
pssm:
max_distance: 50.0
logarithmic_factor: 3.0
sun_distance: 100.0
split_count: 4
resolution: 512
border_bias: 0.058
use_pcf: True
filter_sequence: halton_2D_32
filter_radius: 0.7
fixed_bias: 0.11429
slope_bias: 0.0
normal_bias: 0.67
use_pcss: False
pcss_sequence: halton_2D_16
pcss_penumbra_size: 2.38
pcss_min_penumbra_size: 7.0
use_distant_shadows: True
dist_shadow_resolution: 1024
dist_shadow_clipsize: 400.0
dist_shadow_sundist: 300.0
scene_shadow_resolution: 512
scene_shadow_sundist: 300.0
scattering:
scattering_method: eric_bruneton
ground_reflectance: 0.1231
rayleigh_factor: 0.5
rayleigh_height_scale: 8.0
mie_height_scale: 1.3
mie_phase_factor: 0.3
beta_mie_scattering: 4.0
enable_godrays: False
atmosphere_start: 549.61
skin_shading:
quality: medium
blur_scale: 0.43
sky_ao:
sample_radius: 17.17
max_radius: 500.0
resolution: 512
sample_sequence: poisson_2D_32
ao_multiplier: 0.83
ao_bias: 0.0
blend_factor: 0.01
capture_height: 568.75
smaa:
use_reprojection: True
smaa_quality: ultra
jitter_pattern: halton8
history_length: 8
jitter_amount: 0.16143
ssr:
effect_scale: 1.0
trace_steps: 64
history_length: 16
abort_on_object_infront: True
intial_bias: 0.1
hit_tolerance: 0.1
roughness_fade: 0.72
skip_invalid_samples: False
border_fade: 0.005
volumetrics:
enable_volumetric_shadows: True
volumetric_shadow_intensity: 8.31
volumetric_shadow_brightness: 1.66
volumetric_shadow_pow: 1.15999
volumetric_max_distance: 79.41429
volumetric_shadow_fadein_distance: 9.49
volumetric_num_steps: 128
vxgi:
grid_resolution: 256
grid_ws_size: 100.0
diffuse_cone_steps: 32
specular_cone_steps: 150
# Render Pipeline Plugin Configuration
# Instead of editing this file, prefer to use the Plugin Configurator
# Any formatting and comments will be lost
enabled:
- ao
- bloom
- color_correction
- forward_shading
- motion_blur
- pssm
- scattering
- skin_shading
- sky_ao
- smaa
- ssr
# - clouds
# - dof
- env_probes
# - fxaa
# - volumetrics
# - vxgi
overrides:
ao:
blur_quality: MEDIUM
blur_normal_factor: 2.97
blur_depth_factor: 0.88158
occlusion_strength: 2.19
clip_length: 4
technique: SSAO
ssao_sample_radius: 95.29
ssao_sequence: halton_3D_8
ssao_bias: 0.0143
ssao_max_distance: 7.5
hbao_sample_radius: 255.0
hbao_ray_count: 4
hbao_ray_steps: 3
hbao_tangent_bias: 0.64997
hbao_max_distance: 11.5
ssvo_sequence: halton_2D_8
ssvo_sphere_radius: 18.0
ssvo_max_distance: 3.19
alchemy_sample_radius: 38.86
alchemy_sequence: halton_2D_8
alchemy_max_distance: 5.86
ue4ao_sample_radius: 50.14286
ue4ao_sample_sequence: halton_2D_8
ue4ao_max_distance: 1.47
bloom:
num_mipmaps: 6
bloom_strength: 0.8003
remove_fireflies: False
lens_dirt_factor: 0.0
clouds:
raymarch_steps: 160
color_correction:
tonemap_operator: optimized
reinhard_version: rgb
exponential_factor: 1.23
uc2t_shoulder_strength: 0.3352
uc2t_linear_strength: 0.5339
uc2t_linear_angle: 0.1797
uc2t_toe_strength: 0.3919
uc2t_toe_numerator: 0.0029
uc2t_toe_denumerator: 0.2787
uc2t_reference_white: 10.05
vignette_strength: 0.1286
film_grain_strength: 0.1286
color_lut: film_luts/default_lut.png
use_chromatic_aberration: True
chromatic_aberration_strength: 0.019
chromatic_aberration_samples: 2
manual_camera_parameters: False
min_exposure_value: 0.01
max_exposure_value: 1.0
exposure_scale: 1.0
brightness_adaption_rate: 3.6
darkness_adaption_rate: 0.7
use_sharpen: True
sharpen_strength: 0.5
sharpen_twice: False
dof:
focal_point: 1000.0
focal_size: 994.0
blur_strength: 0.0
near_blur_strength: 0.4286
env_probes:
probe_resolution: 128
diffuse_probe_resolution: 2
max_probes: 16
max_probes_per_cell: 3
forward_shading:
fxaa:
quality: ultra
subpixel_quality: 0.5
edge_threshold: 0.166
min_threshold: 0.833
motion_blur:
num_camera_samples: 6
camera_blur_factor: 0.4
enable_object_blur: False
blur_factor: 0.5
tile_size: 32
max_blur_radius: 10.0
num_samples: 12
pssm:
max_distance: 50.0
logarithmic_factor: 3.0
sun_distance: 100.0
split_count: 4
resolution: 1024
border_bias: 0.058
use_pcf: True
filter_sequence: halton_2D_32
filter_radius: 0.7
fixed_bias: 0.11429
slope_bias: 0.0
normal_bias: 0.67
use_pcss: False
pcss_sequence: halton_2D_16
pcss_penumbra_size: 2.38
pcss_min_penumbra_size: 7.0
use_distant_shadows: True
dist_shadow_resolution: 4096
dist_shadow_clipsize: 400.0
dist_shadow_sundist: 300.0
scene_shadow_resolution: 512
scene_shadow_sundist: 300.0
scattering:
scattering_method: eric_bruneton
ground_reflectance: 0.1231
rayleigh_factor: 0.5
rayleigh_height_scale: 8.0
mie_height_scale: 1.3
mie_phase_factor: 0.3
beta_mie_scattering: 4.0
enable_godrays: False
atmosphere_start: 549.61
skin_shading:
quality: medium
blur_scale: 0.43
sky_ao:
sample_radius: 17.17
max_radius: 500.0
resolution: 1024
sample_sequence: poisson_2D_32
ao_multiplier: 0.83
ao_bias: 0.0
blend_factor: 0.01
capture_height: 568.75
smaa:
use_reprojection: True
smaa_quality: ultra
jitter_pattern: halton8
history_length: 8
jitter_amount: 0.16143
ssr:
effect_scale: 1.0
trace_steps: 64
history_length: 16
abort_on_object_infront: True
intial_bias: 0.1
hit_tolerance: 0.1
roughness_fade: 0.72
skip_invalid_samples: False
border_fade: 0.005
volumetrics:
enable_volumetric_shadows: True
volumetric_shadow_intensity: 8.31
volumetric_shadow_brightness: 1.66
volumetric_shadow_pow: 1.15999
volumetric_max_distance: 79.41429
volumetric_shadow_fadein_distance: 9.49
volumetric_num_steps: 128
vxgi:
grid_resolution: 256
grid_ws_size: 100.0
diffuse_cone_steps: 32
specular_cone_steps: 150

View File

@ -1,67 +1,67 @@
# This file controls the order of all render stages.
# Usually you do not have to modify this, except if you are adding new plugins.
# If you move stages, you should know what you do.
# Commenting out a stage won't disable it, but instead produce an error when
# it is created.
global_stage_order:
# Shadows, Environment and Voxelization
- PSSMShadowStage
- PSSMDistShadowStage
- PSSMSceneShadowStage
- ScatteringEnvmapStage
- SkyAOCaptureStage
- EnvironmentCaptureStage
- VoxelizationStage
# Main scene
- GBufferStage
- ShadowStage
- DownscaleZStage
- CombineVelocityStage
# Light(-culling)
- FlagUsedCellsStage
- CollectUsedCellsStage
- CullLightsStage
- CullProbesStage
# Plugins
- CloudVoxelStage
- AOStage
- SkyAOStage
- ApplyLightsStage
- PSSMStage
- ScatteringStage
- ApplyEnvprobesStage
- VXGIStage
- SSRStage
- AmbientStage
- ForwardStage
- ApplyCloudsStage
- GodrayStage
- VolumetricsStage
- AutoExposureStage
- ManualExposureStage
# Post AA & Effects
- BloomStage
- TonemappingStage
- SMAAStage
- FXAAStage
- DoFStage
- MotionBlurStage
- SkinShadingStage
- SharpenStage
- ColorCorrectionStage
# Finishing stages, do not insert anything below
- UpscaleStage
- FinalStage
- UpdatePreviousPipesStage
# This file controls the order of all render stages.
# Usually you do not have to modify this, except if you are adding new plugins.
# If you move stages, you should know what you do.
# Commenting out a stage won't disable it, but instead produce an error when
# it is created.
global_stage_order:
# Shadows, Environment and Voxelization
- PSSMShadowStage
- PSSMDistShadowStage
- PSSMSceneShadowStage
- ScatteringEnvmapStage
- SkyAOCaptureStage
- EnvironmentCaptureStage
- VoxelizationStage
# Main scene
- GBufferStage
- ShadowStage
- DownscaleZStage
- CombineVelocityStage
# Light(-culling)
- FlagUsedCellsStage
- CollectUsedCellsStage
- CullLightsStage
- CullProbesStage
# Plugins
- CloudVoxelStage
- AOStage
- SkyAOStage
- ApplyLightsStage
- PSSMStage
- ScatteringStage
- ApplyEnvprobesStage
- VXGIStage
- SSRStage
- AmbientStage
- ForwardStage
- ApplyCloudsStage
- GodrayStage
- VolumetricsStage
- AutoExposureStage
- ManualExposureStage
# Post AA & Effects
- BloomStage
- TonemappingStage
- SMAAStage
- FXAAStage
- DoFStage
- MotionBlurStage
- SkinShadingStage
- SharpenStage
- ColorCorrectionStage
# Finishing stages, do not insert anything below
- UpscaleStage
- FinalStage
- UpdatePreviousPipesStage

View File

@ -1,33 +1,33 @@
# This file controls which tasks are allowed to run each frame.
# Usually you do not have to edit this file, except when developing plugins.
frame_cycles: !!omap
- frame1:
- envprobes_select_and_cull
- pssm_scene_shadows
- frame2:
- envprobes_capture_envmap_face0
- pssm_distant_shadows
- frame3:
- envprobes_capture_envmap_face1
- pssm_convert_distant_to_esm
- frame4:
- envprobes_capture_envmap_face2
- pssm_blur_distant_vert
- frame5:
- pssm_blur_distant_horiz
- envprobes_capture_envmap_face3
- envprobes_capture_envmap_face4
- frame6:
- envprobes_capture_envmap_face5
- scattering_update_envmap
- frame7:
- envprobes_filter_and_store_envmap
# This file controls which tasks are allowed to run each frame.
# Usually you do not have to edit this file, except when developing plugins.
frame_cycles: !!omap
- frame1:
- envprobes_select_and_cull
- pssm_scene_shadows
- frame2:
- envprobes_capture_envmap_face0
- pssm_distant_shadows
- frame3:
- envprobes_capture_envmap_face1
- pssm_convert_distant_to_esm
- frame4:
- envprobes_capture_envmap_face2
- pssm_blur_distant_vert
- frame5:
- pssm_blur_distant_horiz
- envprobes_capture_envmap_face3
- envprobes_capture_envmap_face4
- frame6:
- envprobes_capture_envmap_face5
- scattering_update_envmap
- frame7:
- envprobes_filter_and_store_envmap

View File

@ -1,16 +1,16 @@
The skydomes for the skybox were taken from:
Skybox.jpg:
http://www.gravis.com.ua/gal/content/photoprint/sky/sk_21.jpg
Skybox2.jpg:
http://www.artist-reference.com/wp-content/gallery/marlin-studios-gallery/sky-dome-panorma.jpg
I couldn't find a direct license for those photos. If there is one, please contact me.
The skydomes for the skybox were taken from:
Skybox.jpg:
http://www.gravis.com.ua/gal/content/photoprint/sky/sk_21.jpg
Skybox2.jpg:
http://www.artist-reference.com/wp-content/gallery/marlin-studios-gallery/sky-dome-panorma.jpg
I couldn't find a direct license for those photos. If there is one, please contact me.

View File

@ -1,116 +1,116 @@
#version 430
// Shader to pre-filter the cubemap using importance sampling
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#define M_PI 3.1415926535897932384626433
vec3 get_transformed_coord(vec2 coord, uint face) {
float f = 1.0;
switch (face) {
case 1: return vec3(-f, coord);
case 2: return vec3(coord, -f);
case 0: return vec3(f, -coord.x, coord.y);
case 3: return vec3(coord.xy * vec2(1, -1), f);
case 4: return vec3(coord.x, f, coord.y);
case 5: return vec3(-coord.x, -f, coord.y);
}
return vec3(0);
}
// From:
// http://www.trentreed.net/blog/physically-based-shading-and-image-based-lighting/
vec2 hammersley(uint i, uint N)
{
return vec2(float(i) / float(N), float(bitfieldReverse(i)) * 2.3283064365386963e-10);
}
// From:
// http://www.gamedev.net/topic/655431-ibl-problem-with-consistency-using-ggx-anisotropy/
vec3 importance_sample_ggx(vec2 xi, float roughness)
{
float r_square = roughness * roughness;
float phi = 2 * M_PI * xi.x;
float cos_theta = sqrt((1 - xi.y) / (1 + (r_square * r_square - 1) * xi.y));
float sin_theta = sqrt(1 - cos_theta * cos_theta);
return vec3(sin_theta * cos(phi), sin_theta * sin(phi), cos_theta);
}
// Converts a normalized spherical coordinate (r = 1) to cartesian coordinates
vec3 spherical_to_vector(float theta, float phi) {
float sin_theta = sin(theta);
return normalize(vec3(
sin_theta * cos(phi),
sin_theta * sin(phi),
cos(theta)
));
}
float brdf_distribution_ggx(float NxH, float roughness) {
float nxh_sq = NxH * NxH;
float tan_sq = (1 - nxh_sq) / nxh_sq;
float f = roughness / max(1e-10, nxh_sq * (roughness * roughness + tan_sq));
return f * f / M_PI;
}
// Finds a tangent and bitangent vector based on a given normal
void find_arbitrary_tangent(vec3 normal, out vec3 tangent, out vec3 bitangent) {
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0);
tangent = normalize(cross(v0, normal));
bitangent = normalize(cross(tangent, normal));
}
vec3 transform_cubemap_coordinates(vec3 coord) {
return normalize(coord.xyz * vec3(1, -1, 1));
}
uniform samplerCube SourceTex;
uniform int currentSize;
uniform int currentMip;
uniform int currentFace;
layout(rgba16f) uniform imageCube DestTex;
void main() {
ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
vec2 texcoord = vec2(coord + 0.5) / float(currentSize);
texcoord = texcoord * 2.0 - 1.0;
vec3 n = get_transformed_coord(texcoord, currentFace);
n = normalize(n);
n = transform_cubemap_coordinates(n);
float roughness = clamp(float(currentMip) / 7.0, 0.001, 1.0);
// roughness *= roughness;
vec3 tangent, binormal;
find_arbitrary_tangent(n, tangent, binormal);
vec4 accum = vec4(0);
const uint num_samples = 512;
// Ultra high quality, might cause TDR on low-end systems
// const uint num_samples = 4096;
for (uint i = 0; i < num_samples; ++i) {
vec2 xi = hammersley(i, num_samples);
vec3 r = importance_sample_ggx(xi, roughness);
vec3 h = normalize(r.x * tangent + r.y * binormal + r.z * n);
vec3 l = 2.0 * dot(n, h) * h - n;
float NxL = clamp(dot(n, l), 0.0, 1.0);
float NxH = clamp(dot(n, h), 0.0, 1.0);
vec3 sampled = textureLod(SourceTex, l, 0).rgb;
float weight = 1;
weight = clamp(weight, 0.0, 1.0);
accum += vec4(sampled, 1) * weight;
}
accum /= max(0.1, accum.w);
accum.xyz = pow(accum.xyz, vec3(2.2));
imageStore(DestTex, ivec3(coord, currentFace), vec4(accum.xyz, 1.0));
}
#version 430
// Shader to pre-filter the cubemap using importance sampling
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#define M_PI 3.1415926535897932384626433
vec3 get_transformed_coord(vec2 coord, uint face) {
float f = 1.0;
switch (face) {
case 1: return vec3(-f, coord);
case 2: return vec3(coord, -f);
case 0: return vec3(f, -coord.x, coord.y);
case 3: return vec3(coord.xy * vec2(1, -1), f);
case 4: return vec3(coord.x, f, coord.y);
case 5: return vec3(-coord.x, -f, coord.y);
}
return vec3(0);
}
// From:
// http://www.trentreed.net/blog/physically-based-shading-and-image-based-lighting/
vec2 hammersley(uint i, uint N)
{
return vec2(float(i) / float(N), float(bitfieldReverse(i)) * 2.3283064365386963e-10);
}
// From:
// http://www.gamedev.net/topic/655431-ibl-problem-with-consistency-using-ggx-anisotropy/
vec3 importance_sample_ggx(vec2 xi, float roughness)
{
float r_square = roughness * roughness;
float phi = 2 * M_PI * xi.x;
float cos_theta = sqrt((1 - xi.y) / (1 + (r_square * r_square - 1) * xi.y));
float sin_theta = sqrt(1 - cos_theta * cos_theta);
return vec3(sin_theta * cos(phi), sin_theta * sin(phi), cos_theta);
}
// Converts a normalized spherical coordinate (r = 1) to cartesian coordinates
vec3 spherical_to_vector(float theta, float phi) {
float sin_theta = sin(theta);
return normalize(vec3(
sin_theta * cos(phi),
sin_theta * sin(phi),
cos(theta)
));
}
float brdf_distribution_ggx(float NxH, float roughness) {
float nxh_sq = NxH * NxH;
float tan_sq = (1 - nxh_sq) / nxh_sq;
float f = roughness / max(1e-10, nxh_sq * (roughness * roughness + tan_sq));
return f * f / M_PI;
}
// Finds a tangent and bitangent vector based on a given normal
void find_arbitrary_tangent(vec3 normal, out vec3 tangent, out vec3 bitangent) {
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0);
tangent = normalize(cross(v0, normal));
bitangent = normalize(cross(tangent, normal));
}
vec3 transform_cubemap_coordinates(vec3 coord) {
return normalize(coord.xyz * vec3(1, -1, 1));
}
uniform samplerCube SourceTex;
uniform int currentSize;
uniform int currentMip;
uniform int currentFace;
layout(rgba16f) uniform imageCube DestTex;
void main() {
ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
vec2 texcoord = vec2(coord + 0.5) / float(currentSize);
texcoord = texcoord * 2.0 - 1.0;
vec3 n = get_transformed_coord(texcoord, currentFace);
n = normalize(n);
n = transform_cubemap_coordinates(n);
float roughness = clamp(float(currentMip) / 7.0, 0.001, 1.0);
// roughness *= roughness;
vec3 tangent, binormal;
find_arbitrary_tangent(n, tangent, binormal);
vec4 accum = vec4(0);
const uint num_samples = 512;
// Ultra high quality, might cause TDR on low-end systems
// const uint num_samples = 4096;
for (uint i = 0; i < num_samples; ++i) {
vec2 xi = hammersley(i, num_samples);
vec3 r = importance_sample_ggx(xi, roughness);
vec3 h = normalize(r.x * tangent + r.y * binormal + r.z * n);
vec3 l = 2.0 * dot(n, h) * h - n;
float NxL = clamp(dot(n, l), 0.0, 1.0);
float NxH = clamp(dot(n, h), 0.0, 1.0);
vec3 sampled = textureLod(SourceTex, l, 0).rgb;
float weight = 1;
weight = clamp(weight, 0.0, 1.0);
accum += vec4(sampled, 1) * weight;
}
accum /= max(0.1, accum.w);
accum.xyz = pow(accum.xyz, vec3(2.2));
imageStore(DestTex, ivec3(coord, currentFace), vec4(accum.xyz, 1.0));
}

View File

@ -1,106 +1,106 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function, division
import os
import shutil
from os.path import dirname, realpath
from panda3d.core import *
from direct.stdpy.file import isdir, isfile, join
from direct.showbase.ShowBase import ShowBase
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
textures-power-2 none
window-type offscreen
win-size 100 100
gl-coordinate-system default
notify-level-display error
print-pipe-types #f
gl-version 4 3
""")
ShowBase.__init__(self)
base_path = realpath(dirname(__file__))
os.chdir(base_path)
filter_dir = join(base_path, "tmp/")
if isdir(filter_dir):
shutil.rmtree(filter_dir)
os.makedirs(filter_dir)
source_path = join(base_path, "source")
extension = ".jpg"
if isfile(join(source_path, "1.png")):
extension = ".png"
cubemap = self.loader.loadCubeMap(
Filename.from_os_specific(join(source_path, "#" + extension)))
mipmap, size = -1, 1024
cshader = Shader.load_compute(Shader.SL_GLSL, "filter.compute.glsl")
while size > 1:
size = size // 2
mipmap += 1
print("Filtering mipmap", mipmap)
dest_cubemap = Texture("Dest")
dest_cubemap.setup_cube_map(size, Texture.T_float, Texture.F_rgba16)
node = NodePath("")
for i in range(6):
node.set_shader(cshader)
node.set_shader_inputs(
SourceTex=cubemap,
DestTex=dest_cubemap,
currentSize=size,
currentMip=mipmap,
currentFace=i)
attr = node.get_attrib(ShaderAttrib)
self.graphicsEngine.dispatch_compute(
( (size + 15) // 16, (size+15) // 16, 1), attr, self.win.gsg)
print(" Extracting data ..")
self.graphicsEngine.extract_texture_data(dest_cubemap, self.win.gsg)
print(" Writing data ..")
dest_cubemap.write(join(filter_dir, "{}-#.png".format(mipmap)), 0, 0, True, False)
print("Reading in data back in ..")
tex = self.loader.loadCubeMap(Filename.from_os_specific(join(base_path, "tmp/#-#.png")), readMipmaps="True")
print("Writing txo ..")
tex.write("cubemap.txo.pz")
shutil.rmtree(join(base_path, "tmp"))
Application()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function, division
import os
import shutil
from os.path import dirname, realpath
from panda3d.core import *
from direct.stdpy.file import isdir, isfile, join
from direct.showbase.ShowBase import ShowBase
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
textures-power-2 none
window-type offscreen
win-size 100 100
gl-coordinate-system default
notify-level-display error
print-pipe-types #f
gl-version 4 3
""")
ShowBase.__init__(self)
base_path = realpath(dirname(__file__))
os.chdir(base_path)
filter_dir = join(base_path, "tmp/")
if isdir(filter_dir):
shutil.rmtree(filter_dir)
os.makedirs(filter_dir)
source_path = join(base_path, "source")
extension = ".jpg"
if isfile(join(source_path, "1.png")):
extension = ".png"
cubemap = self.loader.loadCubeMap(
Filename.from_os_specific(join(source_path, "#" + extension)))
mipmap, size = -1, 1024
cshader = Shader.load_compute(Shader.SL_GLSL, "filter.compute.glsl")
while size > 1:
size = size // 2
mipmap += 1
print("Filtering mipmap", mipmap)
dest_cubemap = Texture("Dest")
dest_cubemap.setup_cube_map(size, Texture.T_float, Texture.F_rgba16)
node = NodePath("")
for i in range(6):
node.set_shader(cshader)
node.set_shader_inputs(
SourceTex=cubemap,
DestTex=dest_cubemap,
currentSize=size,
currentMip=mipmap,
currentFace=i)
attr = node.get_attrib(ShaderAttrib)
self.graphicsEngine.dispatch_compute(
( (size + 15) // 16, (size+15) // 16, 1), attr, self.win.gsg)
print(" Extracting data ..")
self.graphicsEngine.extract_texture_data(dest_cubemap, self.win.gsg)
print(" Writing data ..")
dest_cubemap.write(join(filter_dir, "{}-#.png".format(mipmap)), 0, 0, True, False)
print("Reading in data back in ..")
tex = self.loader.loadCubeMap(Filename.from_os_specific(join(base_path, "tmp/#-#.png")), readMipmaps="True")
print("Writing txo ..")
tex.write("cubemap.txo.pz")
shutil.rmtree(join(base_path, "tmp"))
Application()

View File

@ -1,7 +1,7 @@
### Empty textures
This are the empty textures you can use in your models in case you don't have
a detailmap for example.
See the wiki for further information.
### Empty textures
This are the empty textures you can use in your models in case you don't have
a detailmap for example.
See the wiki for further information.

View File

@ -1,120 +1,120 @@
"""
Uses mitsuba to generate the environment brdf
"""
from __future__ import print_function
import os
import sys
import math
from panda3d.core import PNMImage, load_prc_file_data, Vec3
load_prc_file_data("", "notify-level error")
load_prc_file_data("", "notify-level-pnmimage error")
configs = {
"normal": {
"out_dir": "slices",
"out_name": "env_brdf_{}.png",
"template_suffix": "",
"sequence": xrange(7),
"samples": 32,
},
"metallic": {
"out_dir": "slices_metal",
"out_name": "env_brdf.png",
"template_suffix": "-metal",
"sequence": [1],
"samples": 32,
},
"clearcoat": {
"out_dir": "slices_coat",
"out_name": "env_brdf.png",
"template_suffix": "-coat",
"sequence": [1],
"samples": 2048,
}
}
# configs_to_run = ["normal", "metallic", "clearcoat"]
configs_to_run = ["clearcoat"]
for config_name in configs_to_run:
config = configs[config_name]
if not os.path.isdir(config["out_dir"]):
os.makedirs(config["out_dir"])
for pass_index in config["sequence"]:
ior = 1.01 + 0.2 * pass_index
dest_size = 512
dest_h = 32
dest = PNMImage(dest_size, dest_h)
# run mitsuba
print("Running mitsuba for ior =", ior, "( index =", pass_index,")")
with open("res/scene" + config["template_suffix"] + ".templ.xml", "r") as handle:
content = handle.read()
content = content.replace("%IOR%", str(ior))
content = content.replace("%SAMPLES%", str(config["samples"]))
with open("res/scene.xml", "w") as handle:
handle.write(content)
os.system("run_mitsuba.bat")
img = PNMImage("scene.png")
source_w = img.get_x_size()
print("Converting ..")
indices = []
nxv_values = []
# Generate nonlinear NxV sequence
for i in xrange(source_w):
v = 1 - i / float(source_w)
NxV = math.sqrt(1 - v*v)
nxv_values.append(NxV)
# Generate lerp indices and weights
for x in xrange(dest_size):
NxV = (x) / float(dest_size)
index = 0
for i, s_nxv in enumerate(reversed(nxv_values)):
if NxV >= s_nxv:
index = i
break
index = len(nxv_values) - index - 1
next_index = index + 1 if index < dest_size - 1 else index
curr_nxv = nxv_values[index]
next_nxv = nxv_values[next_index]
lerp_factor = (NxV - curr_nxv) / max(1e-10, abs(next_nxv - curr_nxv))
lerp_factor = max(0.0, min(1.0, lerp_factor))
indices.append((index, next_index, lerp_factor))
# Generate the final linear lut using the lerp weights
for y in xrange(dest_h):
for x in xrange(dest_size):
curr_i, next_i, lerp = indices[x]
curr_v = img.get_xel(curr_i, y)
next_v = img.get_xel(next_i, y)
dest.set_xel(x, y, curr_v * (1 - lerp) + next_v * lerp)
out_name = config["out_name"].replace("{}", str(pass_index))
dest.write(config["out_dir"] + "/" + out_name)
try:
os.remove("scene.png")
except:
pass
"""
Uses mitsuba to generate the environment brdf
"""
from __future__ import print_function
import os
import sys
import math
from panda3d.core import PNMImage, load_prc_file_data, Vec3
load_prc_file_data("", "notify-level error")
load_prc_file_data("", "notify-level-pnmimage error")
configs = {
"normal": {
"out_dir": "slices",
"out_name": "env_brdf_{}.png",
"template_suffix": "",
"sequence": xrange(7),
"samples": 32,
},
"metallic": {
"out_dir": "slices_metal",
"out_name": "env_brdf.png",
"template_suffix": "-metal",
"sequence": [1],
"samples": 32,
},
"clearcoat": {
"out_dir": "slices_coat",
"out_name": "env_brdf.png",
"template_suffix": "-coat",
"sequence": [1],
"samples": 2048,
}
}
# configs_to_run = ["normal", "metallic", "clearcoat"]
configs_to_run = ["clearcoat"]
for config_name in configs_to_run:
config = configs[config_name]
if not os.path.isdir(config["out_dir"]):
os.makedirs(config["out_dir"])
for pass_index in config["sequence"]:
ior = 1.01 + 0.2 * pass_index
dest_size = 512
dest_h = 32
dest = PNMImage(dest_size, dest_h)
# run mitsuba
print("Running mitsuba for ior =", ior, "( index =", pass_index,")")
with open("res/scene" + config["template_suffix"] + ".templ.xml", "r") as handle:
content = handle.read()
content = content.replace("%IOR%", str(ior))
content = content.replace("%SAMPLES%", str(config["samples"]))
with open("res/scene.xml", "w") as handle:
handle.write(content)
os.system("run_mitsuba.bat")
img = PNMImage("scene.png")
source_w = img.get_x_size()
print("Converting ..")
indices = []
nxv_values = []
# Generate nonlinear NxV sequence
for i in xrange(source_w):
v = 1 - i / float(source_w)
NxV = math.sqrt(1 - v*v)
nxv_values.append(NxV)
# Generate lerp indices and weights
for x in xrange(dest_size):
NxV = (x) / float(dest_size)
index = 0
for i, s_nxv in enumerate(reversed(nxv_values)):
if NxV >= s_nxv:
index = i
break
index = len(nxv_values) - index - 1
next_index = index + 1 if index < dest_size - 1 else index
curr_nxv = nxv_values[index]
next_nxv = nxv_values[next_index]
lerp_factor = (NxV - curr_nxv) / max(1e-10, abs(next_nxv - curr_nxv))
lerp_factor = max(0.0, min(1.0, lerp_factor))
indices.append((index, next_index, lerp_factor))
# Generate the final linear lut using the lerp weights
for y in xrange(dest_h):
for x in xrange(dest_size):
curr_i, next_i, lerp = indices[x]
curr_v = img.get_xel(curr_i, y)
next_v = img.get_xel(next_i, y)
dest.set_xel(x, y, curr_v * (1 - lerp) + next_v * lerp)
out_name = config["out_name"].replace("{}", str(pass_index))
dest.write(config["out_dir"] + "/" + out_name)
try:
os.remove("scene.png")
except:
pass

View File

@ -1,68 +1,68 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughcoating">
<string name="distribution" value="ggx" />
<rgb name="specularReflectance" value="0, 1, 0" />
<float name="alpha" value="0.0001" />
<float name="thickness" value="5.0" />
<float name="intIOR" value="1.51" />
<bsdf type="roughconductor">
<rgb name="specularReflectance" value="1, 0, 0" />
<string name="material" value="none"/>
<!-- <string name="distribution" value="ggx"/> -->
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
<!-- <float name="alpha" value="0.5" /> -->
</bsdf>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughcoating">
<string name="distribution" value="ggx" />
<rgb name="specularReflectance" value="0, 1, 0" />
<float name="alpha" value="0.0001" />
<float name="thickness" value="5.0" />
<float name="intIOR" value="1.51" />
<bsdf type="roughconductor">
<rgb name="specularReflectance" value="1, 0, 0" />
<string name="material" value="none"/>
<!-- <string name="distribution" value="ggx"/> -->
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
<!-- <float name="alpha" value="0.5" /> -->
</bsdf>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -1,56 +1,56 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughconductor">
<string name="material" value="Ag"/>
<string name="distribution" value="ggx"/>
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughconductor">
<string name="material" value="Ag"/>
<string name="distribution" value="ggx"/>
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -1,62 +1,62 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughplastic">
<!-- <string name="material" value="Cu"/> -->
<string name="distribution" value="ggx"/>
<rgb name="diffuseReflectance" value="0,1,0" />
<rgb name="specularReflectance" value="1,0,0" />
<float name="intIOR" value="%IOR%"/>
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughplastic">
<!-- <string name="material" value="Cu"/> -->
<string name="distribution" value="ggx"/>
<rgb name="diffuseReflectance" value="0,1,0" />
<rgb name="specularReflectance" value="1,0,0" />
<float name="intIOR" value="%IOR%"/>
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="%SAMPLES%" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -1,68 +1,68 @@
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughcoating">
<string name="distribution" value="ggx" />
<rgb name="specularReflectance" value="0, 1, 0" />
<float name="alpha" value="0.0001" />
<float name="thickness" value="5.0" />
<float name="intIOR" value="1.51" />
<bsdf type="roughconductor">
<rgb name="specularReflectance" value="1, 0, 0" />
<string name="material" value="none"/>
<!-- <string name="distribution" value="ggx"/> -->
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
<!-- <float name="alpha" value="0.5" /> -->
</bsdf>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="2048" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>
<?xml version='1.0' encoding='utf-8'?>
<scene version="0.5.0">
<integrator type="path">
<integer name="maxDepth" value="2"/>
</integrator>
<shape type="cylinder">
<float name="radius" value="1" />
<point name="p0" x="0" y="0.5" z="0" />
<point name="p1" x="0" y="-0.5" z="0" />
<bsdf type="roughcoating">
<string name="distribution" value="ggx" />
<rgb name="specularReflectance" value="0, 1, 0" />
<float name="alpha" value="0.0001" />
<float name="thickness" value="5.0" />
<float name="intIOR" value="1.51" />
<bsdf type="roughconductor">
<rgb name="specularReflectance" value="1, 0, 0" />
<string name="material" value="none"/>
<!-- <string name="distribution" value="ggx"/> -->
<texture name="alpha" type="bitmap">
<string name="filename" value="roughness.png"/>
</texture>
<!-- <float name="alpha" value="0.5" /> -->
</bsdf>
</bsdf>
</shape>
<emitter type="envmap">
<string name="filename" value="environment.png" />
<float name="gamma" value="1.0" />
</emitter>
<sensor type="orthographic">
<float name="nearClip" value="0.05"/>
<float name="farClip" value="15"/>
<!-- <float name="fov" value="40"/> -->
<string name="fovAxis" value="x"/>
<transform name="toWorld">
<scale x="0.5" y="128" />
<lookat origin="0.5, 0.0, -3.5" target="0.5, 0.0, 0" up="0, 1, 0"/>
</transform>
<sampler type="ldsampler">
<integer name="sampleCount" value="2048" />
</sampler>
<film type="hdrfilm">
<boolean name="banner" value="false"/>
<boolean name="attachLog" value="false" />
<!-- <boolean name="highQualityEdges" value="true" /> -->
<integer name="height" value="32"/>
<integer name="width" value="8192"/>
<!-- <rfilter type="box"/> -->
</film>
</sensor>
</scene>

View File

@ -1,10 +1,10 @@
@echo off
"C:/mitsuba/mitsuba" -p 6 res/scene.xml
echo ""
echo Rendering done
echo ""
echo ""
echo ""
"C:/mitsuba/mtsutil" tonemap -g 2.0 res/scene.exr
copy res\scene.png scene.png
@echo off
"C:/mitsuba/mitsuba" -p 6 res/scene.xml
echo ""
echo Rendering done
echo ""
echo ""
echo ""
"C:/mitsuba/mtsutil" tonemap -g 2.0 res/scene.exr
copy res\scene.png scene.png

View File

@ -1,77 +1,77 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# This script precomputes the noise for the film grain to improve performance
import os
curr_dir = os.path.dirname(os.path.realpath(__file__))
os.chdir(curr_dir)
import sys
sys.path.insert(0, "../../rpcore")
sys.path.insert(0, "../../")
from panda3d.core import load_prc_file_data, NodePath, Shader, Texture, ShaderAttrib
from panda3d.core import PNMImage
from direct.showbase.ShowBase import ShowBase
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
textures-power-2 none
window-type offscreen
win-size 100 100
gl-coordinate-system default
notify-level-display error
print-pipe-types #f
gl-version 4 3
""")
ShowBase.__init__(self)
dest_tex = Texture()
dest_tex.setup_2d_texture(2048, 2048, Texture.T_unsigned_byte, Texture.F_rgba8)
cshader = Shader.load_compute(Shader.SL_GLSL, "grain.compute.glsl")
node = NodePath("")
node.set_shader(cshader)
node.set_shader_input("DestTex", dest_tex)
attr = node.get_attrib(ShaderAttrib)
self.graphicsEngine.dispatch_compute(
(2048 // 16, 2048 // 16, 1), attr, self.win.gsg)
base.graphicsEngine.extract_texture_data(dest_tex, base.win.gsg)
# Convert to single channel
img = PNMImage(2048, 2048, 1, 255)
dest_tex.store(img)
img.set_num_channels(1)
tex = Texture()
tex.load(img)
tex.write("grain.txo.pz")
Application()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# This script precomputes the noise for the film grain to improve performance
import os
curr_dir = os.path.dirname(os.path.realpath(__file__))
os.chdir(curr_dir)
import sys
sys.path.insert(0, "../../rpcore")
sys.path.insert(0, "../../")
from panda3d.core import load_prc_file_data, NodePath, Shader, Texture, ShaderAttrib
from panda3d.core import PNMImage
from direct.showbase.ShowBase import ShowBase
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
textures-power-2 none
window-type offscreen
win-size 100 100
gl-coordinate-system default
notify-level-display error
print-pipe-types #f
gl-version 4 3
""")
ShowBase.__init__(self)
dest_tex = Texture()
dest_tex.setup_2d_texture(2048, 2048, Texture.T_unsigned_byte, Texture.F_rgba8)
cshader = Shader.load_compute(Shader.SL_GLSL, "grain.compute.glsl")
node = NodePath("")
node.set_shader(cshader)
node.set_shader_input("DestTex", dest_tex)
attr = node.get_attrib(ShaderAttrib)
self.graphicsEngine.dispatch_compute(
(2048 // 16, 2048 // 16, 1), attr, self.win.gsg)
base.graphicsEngine.extract_texture_data(dest_tex, base.win.gsg)
# Convert to single channel
img = PNMImage(2048, 2048, 1, 255)
dest_tex.store(img)
img.set_num_channels(1)
tex = Texture()
tex.load(img)
tex.write("grain.txo.pz")
Application()

View File

@ -1,25 +1,25 @@
#version 430
// Precomputes the film grain
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#define ASPECT_RATIO 1
#define SCREEN_SIZE vec2(2048, 2048)
#define gl_FragCoord vec4(0)
#pragma include "../../rpcore/shader/includes/noise.inc.glsl"
layout(rgba8) uniform image2D DestTex;
float generate_grain(vec2 texCoord, vec2 resolution, float frame, float multiplier) {
vec2 mult = texCoord * resolution;
float offset = snoise3D(vec3(mult / multiplier, frame));
float n1 = pnoise3D(vec3(mult, offset), vec3(1.0 / texCoord * resolution, 1.0));
return n1 * 0.5 + 0.5;
}
void main() {
vec2 texcoord = vec2(ivec2(gl_GlobalInvocationID.xy) + 0.5) / 2048.0;
vec4 result = vec4(generate_grain(texcoord * 2048.0, vec2(4096.0), 0.0, 4.634523));
imageStore(DestTex, ivec2(gl_GlobalInvocationID.xy), result);
}
#version 430
// Precomputes the film grain
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#define ASPECT_RATIO 1
#define SCREEN_SIZE vec2(2048, 2048)
#define gl_FragCoord vec4(0)
#pragma include "../../rpcore/shader/includes/noise.inc.glsl"
layout(rgba8) uniform image2D DestTex;
float generate_grain(vec2 texCoord, vec2 resolution, float frame, float multiplier) {
vec2 mult = texCoord * resolution;
float offset = snoise3D(vec3(mult / multiplier, frame));
float n1 = pnoise3D(vec3(mult, offset), vec3(1.0 / texCoord * resolution, 1.0));
return n1 * 0.5 + 0.5;
}
void main() {
vec2 texcoord = vec2(ivec2(gl_GlobalInvocationID.xy) + 0.5) / 2048.0;
vec4 result = vec4(generate_grain(texcoord * 2048.0, vec2(4096.0), 0.0, 4.634523));
imageStore(DestTex, ivec2(gl_GlobalInvocationID.xy), result);
}

View File

@ -1,178 +1,178 @@
Font data copyright Google 2012
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
“License” shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
“Licensor” shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
“Legal Entity” shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
“control” means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity
exercising permissions granted by this License.
“Source” form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
“Object” form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
“Work” shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, “submitted”
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as “Not a Contribution.”
“Contributor” shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a “NOTICE” text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Font data copyright Google 2012
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
“License” shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
“Licensor” shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
“Legal Entity” shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
“control” means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity
exercising permissions granted by this License.
“Source” form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
“Object” form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
“Work” shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, “submitted”
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as “Not a Contribution.”
“Contributor” shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a “NOTICE” text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,37 +1,37 @@
"""
Converts pipeline resources to TXO files to speed up loading.
This is called during the setup.
"""
from __future__ import print_function
import os
from panda3d.core import Filename, Texture, load_prc_file_data
load_prc_file_data("", "window-type none")
load_prc_file_data("", "notify-level-pnmimage error")
load_prc_file_data("", "textures-power-2 none")
files_to_convert = [
"data/gui/loading_screen_bg.png",
"rpplugins/bloom/resources/lens_dirt.png",
"data/builtin_models/skybox/skybox.jpg"
]
this_dir = os.path.realpath(os.path.dirname(__file__))
os.chdir(this_dir)
pipeline_dir = "../"
import direct.directbase.DirectStart
for filename in files_to_convert:
src_path = os.path.abspath(os.path.join(pipeline_dir, filename))
fullpath = Filename.from_os_specific(src_path).get_fullpath()
dest_path = fullpath.replace(".png", ".txo.pz")
dest_path = dest_path.replace(".jpg", ".txo.pz")
print(src_path, "->", dest_path)
loader.load_texture(fullpath).write(dest_path)
"""
Converts pipeline resources to TXO files to speed up loading.
This is called during the setup.
"""
from __future__ import print_function
import os
from panda3d.core import Filename, Texture, load_prc_file_data
load_prc_file_data("", "window-type none")
load_prc_file_data("", "notify-level-pnmimage error")
load_prc_file_data("", "textures-power-2 none")
files_to_convert = [
"data/gui/loading_screen_bg.png",
"rpplugins/bloom/resources/lens_dirt.png",
"data/builtin_models/skybox/skybox.jpg"
]
this_dir = os.path.realpath(os.path.dirname(__file__))
os.chdir(this_dir)
pipeline_dir = "../"
import direct.directbase.DirectStart
for filename in files_to_convert:
src_path = os.path.abspath(os.path.join(pipeline_dir, filename))
fullpath = Filename.from_os_specific(src_path).get_fullpath()
dest_path = fullpath.replace(".png", ".txo.pz")
dest_path = dest_path.replace(".jpg", ".txo.pz")
print(src_path, "->", dest_path)
loader.load_texture(fullpath).write(dest_path)

View File

@ -1,25 +1,25 @@
# IES Profiles
### Source
This files were aqcuired from:
http://www.derekjenson.com/3d-blog/ies-light-profiles
### Finding new IES Profiles
You can download IES profile files from the vendors directly.
Here are some links to start with:
- http://www.colorkinetics.com/support/ies/
- http://www.seleconlight.com/index.php?option=com_content&view=article&id=475
- http://www.lithonia.com/photometrics.aspx
### Previewing IES Profiles
You can preview the profiles with a viewer like this:
http://www.photometricviewer.com
# IES Profiles
### Source
This files were aqcuired from:
http://www.derekjenson.com/3d-blog/ies-light-profiles
### Finding new IES Profiles
You can download IES profile files from the vendors directly.
Here are some links to start with:
- http://www.colorkinetics.com/support/ies/
- http://www.seleconlight.com/index.php?option=com_content&view=article&id=475
- http://www.lithonia.com/photometrics.aspx
### Previewing IES Profiles
You can preview the profiles with a viewer like this:
http://www.photometricviewer.com

View File

@ -1,83 +1,83 @@
IESNA:LM-63-1995
[ISSUEDATE] 07-16-2008
[TEST] S0710292-R1
[MANUFAC] QSSI
[LUMCAT] KH40A-Type III
[LUMINAIRE] KH40 with Adjustable Reflector in Type III position
[LAMP] 400W Venture Uni-Form Pulse Start Lamp, Rated at 41,000 Lumens
[SKTPOSITION] Horizontal Socket Position 5, Street Side Lamp Holder
TILT=NONE
1 41000 1.27 35 35 1 1 1.25 1.25 0
1 1 433.62
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 95 105 115 125 135 145 155 165 175 180
0 5 15 25 35 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95 105 115 125 135 145 155 165 175 180
7417.00 7382.00 7263.00 7121.00 6990.00 6758.00 6434.00 6118.00 5692.00 4547.00 3496.00 4195.00 4796.00 5633.00 5783.00 5751.00
4859.00 3975.00 2344.00 1366.00 160.00 72.00 39.00 24.00 21.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7405.00 7283.00 7135.00 7003.00 6820.00 6491.00 6141.00 5694.00 4606.00 3541.00 4075.00 4778.00 5313.00 5496.00 5075.00
4280.00 3598.00 1962.00 1151.00 141.00 67.00 40.00 23.00 21.00 19.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7383.00 7267.00 7116.00 6985.00 6824.00 6642.00 6130.00 5292.00 4304.00 3494.00 3652.00 4934.00 5076.00 4892.00 4279.00
2986.00 2173.00 1626.00 732.00 190.00 67.00 42.00 23.00 21.00 19.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7338.00 7186.00 7004.00 6792.00 6636.00 6374.00 5738.00 4946.00 4762.00 4024.00 3997.00 5536.00 5402.00 5123.00 4709.00
3693.00 2178.00 1438.00 685.00 161.00 72.00 39.00 23.00 20.00 19.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7324.00 7066.00 6717.00 6486.00 6325.00 5900.00 5379.00 5421.00 4917.00 4550.00 4575.00 5901.00 8328.00 7841.00 6686.00
5417.00 2837.00 1896.00 1123.00 177.00 71.00 41.00 24.00 21.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7284.00 6859.00 6523.00 6335.00 6048.00 5654.00 5112.00 5736.00 5706.00 5144.00 5769.00 10385.00 10952.00 10744.00 9057.00
6083.00 3307.00 2350.00 1042.00 167.00 76.00 41.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7272.00 6802.00 6505.00 6253.00 5947.00 5546.00 5083.00 5713.00 5777.00 5236.00 7030.00 10955.00 11004.00 11331.00 9180.00
5616.00 3669.00 2326.00 700.00 150.00 76.00 42.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7271.00 6780.00 6512.00 6255.00 5925.00 5422.00 5108.00 5698.00 5856.00 5267.00 7787.00 11280.00 11056.00 11588.00 8604.00
5357.00 4075.00 2388.00 624.00 150.00 77.00 44.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7283.00 6781.00 6529.00 6229.00 5824.00 5318.00 5151.00 5653.00 5917.00 5389.00 7867.00 11388.00 11116.00 10907.00 7978.00
5353.00 4324.00 2291.00 595.00 163.00 89.00 43.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7252.00 6706.00 6496.00 6161.00 5735.00 5214.00 5111.00 5586.00 5951.00 5500.00 8022.00 11522.00 11494.00 9242.00 7462.00
5174.00 4516.00 2094.00 594.00 191.00 87.00 43.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7224.00 6669.00 6459.00 6086.00 5610.00 5150.00 5099.00 5499.00 5899.00 5565.00 7933.00 11560.00 11858.00 8529.00 7029.00
4917.00 4292.00 2027.00 619.00 209.00 88.00 42.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7219.00 6654.00 6449.00 6073.00 5494.00 5090.00 5076.00 5442.00 5831.00 5637.00 7786.00 11528.00 11335.00 8436.00 6553.00
4715.00 3972.00 1899.00 626.00 241.00 94.00 42.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7225.00 6658.00 6469.00 6030.00 5441.00 5046.00 5116.00 5435.00 5771.00 5787.00 7685.00 11568.00 10502.00 8333.00 6219.00
4476.00 3582.00 1644.00 641.00 253.00 90.00 43.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7287.00 6700.00 6520.00 6031.00 5380.00 5032.00 5191.00 5403.00 5729.00 5891.00 7489.00 11227.00 9688.00 8036.00 5924.00
4353.00 3030.00 1294.00 604.00 257.00 87.00 49.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7238.00 6625.00 6449.00 5934.00 5232.00 4936.00 5183.00 5393.00 5653.00 5980.00 7355.00 10352.00 8867.00 7433.00 5389.00
4232.00 2454.00 1000.00 488.00 280.00 78.00 45.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7215.00 6607.00 6445.00 5862.00 5161.00 4900.00 5195.00 5390.00 5590.00 6054.00 7236.00 9281.00 8026.00 6696.00 5128.00
4013.00 2035.00 778.00 409.00 215.00 79.00 41.00 25.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7202.00 6596.00 6417.00 5833.00 5078.00 4804.00 5214.00 5410.00 5505.00 6057.00 7124.00 8613.00 7409.00 6003.00 5068.00
4005.00 1857.00 568.00 257.00 131.00 69.00 38.00 25.00 22.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7198.00 6559.00 6398.00 5781.00 5001.00 4741.00 5227.00 5452.00 5376.00 6037.00 6982.00 7652.00 6384.00 5441.00 4949.00
4260.00 1950.00 441.00 169.00 109.00 64.00 35.00 25.00 22.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7209.00 6581.00 6423.00 5768.00 4945.00 4717.00 5255.00 5458.00 5273.00 6009.00 6841.00 6818.00 5427.00 5345.00 5378.00
5257.00 2594.00 517.00 194.00 158.00 67.00 34.00 25.00 22.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7249.00 6627.00 6441.00 5774.00 4912.00 4687.00 5213.00 5383.00 5201.00 5955.00 6672.00 6098.00 5163.00 5212.00 5595.00
5994.00 3246.00 995.00 262.00 147.00 74.00 36.00 25.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7220.00 6574.00 6416.00 5722.00 4852.00 4628.00 5136.00 5255.00 5090.00 5723.00 6408.00 5524.00 5543.00 5326.00 5697.00
5900.00 2620.00 1258.00 332.00 134.00 72.00 33.00 24.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7204.00 6563.00 6422.00 5659.00 4808.00 4586.00 5061.00 5175.00 5011.00 5620.00 6185.00 5303.00 5609.00 5550.00 6641.00
6023.00 2144.00 1230.00 275.00 129.00 70.00 33.00 24.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7213.00 6587.00 6404.00 5652.00 4780.00 4572.00 4995.00 5118.00 4963.00 5582.00 5940.00 5607.00 5486.00 5667.00 7137.00
5903.00 2045.00 900.00 218.00 113.00 66.00 34.00 24.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7206.00 6542.00 6407.00 5637.00 4739.00 4549.00 4938.00 5067.00 4970.00 5547.00 5724.00 5658.00 5314.00 6006.00 7655.00
5363.00 1908.00 642.00 179.00 91.00 58.00 32.00 24.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7217.00 6564.00 6406.00 5634.00 4719.00 4566.00 4855.00 5050.00 5103.00 5396.00 5597.00 5391.00 5163.00 6692.00 8064.00
5238.00 1781.00 490.00 167.00 95.00 53.00 31.00 24.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7286.00 6641.00 6476.00 5639.00 4713.00 4554.00 4773.00 5052.00 5127.00 5168.00 5272.00 5191.00 5129.00 7315.00 7707.00
5151.00 1457.00 411.00 163.00 91.00 54.00 31.00 24.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7243.00 6589.00 6437.00 5748.00 4721.00 4489.00 4610.00 5047.00 4800.00 4975.00 5468.00 5017.00 5275.00 5262.00 4489.00
3129.00 839.00 279.00 151.00 101.00 90.00 30.00 23.00 22.00 22.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7268.00 6633.00 6416.00 5949.00 4866.00 4390.00 4377.00 4763.00 4275.00 4100.00 4194.00 3792.00 3797.00 3409.00 3078.00
2472.00 738.00 230.00 137.00 129.00 69.00 28.00 22.00 22.00 23.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7292.00 6733.00 6404.00 6097.00 5175.00 4364.00 4151.00 4142.00 3841.00 3661.00 3526.00 3221.00 3089.00 2900.00 2676.00
2374.00 1206.00 314.00 138.00 77.00 54.00 26.00 22.00 22.00 23.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7297.00 6902.00 6409.00 6182.00 5542.00 4511.00 4002.00 3796.00 3539.00 3411.00 3264.00 2961.00 2817.00 2632.00 2439.00
2127.00 1415.00 388.00 129.00 157.00 47.00 25.00 21.00 21.00 22.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7310.00 7105.00 6591.00 6171.00 5732.00 4813.00 4065.00 3605.00 3299.00 3404.00 3190.00 2840.00 2596.00 2425.00 2177.00
1837.00 994.00 356.00 153.00 78.00 42.00 24.00 21.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7332.00 7219.00 6927.00 6432.00 5846.00 5194.00 4422.00 3788.00 3171.00 3017.00 2873.00 2689.00 2478.00 2121.00 1807.00
1441.00 740.00 332.00 169.00 93.00 49.00 24.00 20.00 20.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7319.00 7224.00 7077.00 6815.00 6270.00 5499.00 4735.00 3994.00 3098.00 2739.00 2489.00 2235.00 1983.00 1672.00 1383.00
1057.00 553.00 272.00 168.00 89.00 44.00 23.00 20.00 19.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7337.00 7218.00 7041.00 6856.00 6402.00 5656.00 4670.00 3658.00 2889.00 2547.00 2219.00 1898.00 1632.00 1349.00 1086.00
792.00 492.00 283.00 213.00 136.00 56.00 23.00 19.00 19.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7348.00 7218.00 7033.00 6787.00 6357.00 5609.00 4578.00 3463.00 2809.00 2508.00 2217.00 1920.00 1583.00 1285.00 987.00
694.00 490.00 238.00 142.00 86.00 44.00 22.00 19.00 20.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
IESNA:LM-63-1995
[ISSUEDATE] 07-16-2008
[TEST] S0710292-R1
[MANUFAC] QSSI
[LUMCAT] KH40A-Type III
[LUMINAIRE] KH40 with Adjustable Reflector in Type III position
[LAMP] 400W Venture Uni-Form Pulse Start Lamp, Rated at 41,000 Lumens
[SKTPOSITION] Horizontal Socket Position 5, Street Side Lamp Holder
TILT=NONE
1 41000 1.27 35 35 1 1 1.25 1.25 0
1 1 433.62
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 95 105 115 125 135 145 155 165 175 180
0 5 15 25 35 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95 105 115 125 135 145 155 165 175 180
7417.00 7382.00 7263.00 7121.00 6990.00 6758.00 6434.00 6118.00 5692.00 4547.00 3496.00 4195.00 4796.00 5633.00 5783.00 5751.00
4859.00 3975.00 2344.00 1366.00 160.00 72.00 39.00 24.00 21.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7405.00 7283.00 7135.00 7003.00 6820.00 6491.00 6141.00 5694.00 4606.00 3541.00 4075.00 4778.00 5313.00 5496.00 5075.00
4280.00 3598.00 1962.00 1151.00 141.00 67.00 40.00 23.00 21.00 19.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7383.00 7267.00 7116.00 6985.00 6824.00 6642.00 6130.00 5292.00 4304.00 3494.00 3652.00 4934.00 5076.00 4892.00 4279.00
2986.00 2173.00 1626.00 732.00 190.00 67.00 42.00 23.00 21.00 19.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7338.00 7186.00 7004.00 6792.00 6636.00 6374.00 5738.00 4946.00 4762.00 4024.00 3997.00 5536.00 5402.00 5123.00 4709.00
3693.00 2178.00 1438.00 685.00 161.00 72.00 39.00 23.00 20.00 19.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7324.00 7066.00 6717.00 6486.00 6325.00 5900.00 5379.00 5421.00 4917.00 4550.00 4575.00 5901.00 8328.00 7841.00 6686.00
5417.00 2837.00 1896.00 1123.00 177.00 71.00 41.00 24.00 21.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7284.00 6859.00 6523.00 6335.00 6048.00 5654.00 5112.00 5736.00 5706.00 5144.00 5769.00 10385.00 10952.00 10744.00 9057.00
6083.00 3307.00 2350.00 1042.00 167.00 76.00 41.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7272.00 6802.00 6505.00 6253.00 5947.00 5546.00 5083.00 5713.00 5777.00 5236.00 7030.00 10955.00 11004.00 11331.00 9180.00
5616.00 3669.00 2326.00 700.00 150.00 76.00 42.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7271.00 6780.00 6512.00 6255.00 5925.00 5422.00 5108.00 5698.00 5856.00 5267.00 7787.00 11280.00 11056.00 11588.00 8604.00
5357.00 4075.00 2388.00 624.00 150.00 77.00 44.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7283.00 6781.00 6529.00 6229.00 5824.00 5318.00 5151.00 5653.00 5917.00 5389.00 7867.00 11388.00 11116.00 10907.00 7978.00
5353.00 4324.00 2291.00 595.00 163.00 89.00 43.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7252.00 6706.00 6496.00 6161.00 5735.00 5214.00 5111.00 5586.00 5951.00 5500.00 8022.00 11522.00 11494.00 9242.00 7462.00
5174.00 4516.00 2094.00 594.00 191.00 87.00 43.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7224.00 6669.00 6459.00 6086.00 5610.00 5150.00 5099.00 5499.00 5899.00 5565.00 7933.00 11560.00 11858.00 8529.00 7029.00
4917.00 4292.00 2027.00 619.00 209.00 88.00 42.00 26.00 23.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7219.00 6654.00 6449.00 6073.00 5494.00 5090.00 5076.00 5442.00 5831.00 5637.00 7786.00 11528.00 11335.00 8436.00 6553.00
4715.00 3972.00 1899.00 626.00 241.00 94.00 42.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7225.00 6658.00 6469.00 6030.00 5441.00 5046.00 5116.00 5435.00 5771.00 5787.00 7685.00 11568.00 10502.00 8333.00 6219.00
4476.00 3582.00 1644.00 641.00 253.00 90.00 43.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7287.00 6700.00 6520.00 6031.00 5380.00 5032.00 5191.00 5403.00 5729.00 5891.00 7489.00 11227.00 9688.00 8036.00 5924.00
4353.00 3030.00 1294.00 604.00 257.00 87.00 49.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7238.00 6625.00 6449.00 5934.00 5232.00 4936.00 5183.00 5393.00 5653.00 5980.00 7355.00 10352.00 8867.00 7433.00 5389.00
4232.00 2454.00 1000.00 488.00 280.00 78.00 45.00 26.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7215.00 6607.00 6445.00 5862.00 5161.00 4900.00 5195.00 5390.00 5590.00 6054.00 7236.00 9281.00 8026.00 6696.00 5128.00
4013.00 2035.00 778.00 409.00 215.00 79.00 41.00 25.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7202.00 6596.00 6417.00 5833.00 5078.00 4804.00 5214.00 5410.00 5505.00 6057.00 7124.00 8613.00 7409.00 6003.00 5068.00
4005.00 1857.00 568.00 257.00 131.00 69.00 38.00 25.00 22.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7198.00 6559.00 6398.00 5781.00 5001.00 4741.00 5227.00 5452.00 5376.00 6037.00 6982.00 7652.00 6384.00 5441.00 4949.00
4260.00 1950.00 441.00 169.00 109.00 64.00 35.00 25.00 22.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7209.00 6581.00 6423.00 5768.00 4945.00 4717.00 5255.00 5458.00 5273.00 6009.00 6841.00 6818.00 5427.00 5345.00 5378.00
5257.00 2594.00 517.00 194.00 158.00 67.00 34.00 25.00 22.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7249.00 6627.00 6441.00 5774.00 4912.00 4687.00 5213.00 5383.00 5201.00 5955.00 6672.00 6098.00 5163.00 5212.00 5595.00
5994.00 3246.00 995.00 262.00 147.00 74.00 36.00 25.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7220.00 6574.00 6416.00 5722.00 4852.00 4628.00 5136.00 5255.00 5090.00 5723.00 6408.00 5524.00 5543.00 5326.00 5697.00
5900.00 2620.00 1258.00 332.00 134.00 72.00 33.00 24.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7204.00 6563.00 6422.00 5659.00 4808.00 4586.00 5061.00 5175.00 5011.00 5620.00 6185.00 5303.00 5609.00 5550.00 6641.00
6023.00 2144.00 1230.00 275.00 129.00 70.00 33.00 24.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7213.00 6587.00 6404.00 5652.00 4780.00 4572.00 4995.00 5118.00 4963.00 5582.00 5940.00 5607.00 5486.00 5667.00 7137.00
5903.00 2045.00 900.00 218.00 113.00 66.00 34.00 24.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7206.00 6542.00 6407.00 5637.00 4739.00 4549.00 4938.00 5067.00 4970.00 5547.00 5724.00 5658.00 5314.00 6006.00 7655.00
5363.00 1908.00 642.00 179.00 91.00 58.00 32.00 24.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7217.00 6564.00 6406.00 5634.00 4719.00 4566.00 4855.00 5050.00 5103.00 5396.00 5597.00 5391.00 5163.00 6692.00 8064.00
5238.00 1781.00 490.00 167.00 95.00 53.00 31.00 24.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7286.00 6641.00 6476.00 5639.00 4713.00 4554.00 4773.00 5052.00 5127.00 5168.00 5272.00 5191.00 5129.00 7315.00 7707.00
5151.00 1457.00 411.00 163.00 91.00 54.00 31.00 24.00 22.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7243.00 6589.00 6437.00 5748.00 4721.00 4489.00 4610.00 5047.00 4800.00 4975.00 5468.00 5017.00 5275.00 5262.00 4489.00
3129.00 839.00 279.00 151.00 101.00 90.00 30.00 23.00 22.00 22.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7268.00 6633.00 6416.00 5949.00 4866.00 4390.00 4377.00 4763.00 4275.00 4100.00 4194.00 3792.00 3797.00 3409.00 3078.00
2472.00 738.00 230.00 137.00 129.00 69.00 28.00 22.00 22.00 23.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7292.00 6733.00 6404.00 6097.00 5175.00 4364.00 4151.00 4142.00 3841.00 3661.00 3526.00 3221.00 3089.00 2900.00 2676.00
2374.00 1206.00 314.00 138.00 77.00 54.00 26.00 22.00 22.00 23.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7297.00 6902.00 6409.00 6182.00 5542.00 4511.00 4002.00 3796.00 3539.00 3411.00 3264.00 2961.00 2817.00 2632.00 2439.00
2127.00 1415.00 388.00 129.00 157.00 47.00 25.00 21.00 21.00 22.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7310.00 7105.00 6591.00 6171.00 5732.00 4813.00 4065.00 3605.00 3299.00 3404.00 3190.00 2840.00 2596.00 2425.00 2177.00
1837.00 994.00 356.00 153.00 78.00 42.00 24.00 21.00 21.00 21.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7332.00 7219.00 6927.00 6432.00 5846.00 5194.00 4422.00 3788.00 3171.00 3017.00 2873.00 2689.00 2478.00 2121.00 1807.00
1441.00 740.00 332.00 169.00 93.00 49.00 24.00 20.00 20.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7319.00 7224.00 7077.00 6815.00 6270.00 5499.00 4735.00 3994.00 3098.00 2739.00 2489.00 2235.00 1983.00 1672.00 1383.00
1057.00 553.00 272.00 168.00 89.00 44.00 23.00 20.00 19.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7337.00 7218.00 7041.00 6856.00 6402.00 5656.00 4670.00 3658.00 2889.00 2547.00 2219.00 1898.00 1632.00 1349.00 1086.00
792.00 492.00 283.00 213.00 136.00 56.00 23.00 19.00 19.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
7417.00 7348.00 7218.00 7033.00 6787.00 6357.00 5609.00 4578.00 3463.00 2809.00 2508.00 2217.00 1920.00 1583.00 1285.00 987.00
694.00 490.00 238.00 142.00 86.00 44.00 22.00 19.00 20.00 20.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

View File

@ -1,16 +1,16 @@
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14397.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 03-DEC-2008
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W CLEAR ED17 LAMP 6"DIA 38.25"TALL WHITE BOLLARD
[MORE] 4.5"DIA SPECULAR CONE REFLECTOR w/5.875"TALL ACRYLIC
[MORE] CYLINDER LENS
[LUMCAT] OSA6R-100PSMH120-AC
[LAMPCAT] M90 MH100W/U/PS
TILT=NONE
1 9000 1 35 1 1 1 -0.49 -0.49 0.406
1 1 100
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 95 105 115 125 135 145 155 165 175 180
0
0.00 12.00 87.00 182.00 167.00 300.00 655.00 944.00 822.00 703.00 614.00 565.00 487.00 438.00 372.00 309.00 262.00 216.00 182.00 142.00 111.00 83.00 61.00 42.00 25.00 19.00 14.00 14.00 15.00 20.00 33.00 36.00 27.00 4.00 0.00
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14397.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 03-DEC-2008
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W CLEAR ED17 LAMP 6"DIA 38.25"TALL WHITE BOLLARD
[MORE] 4.5"DIA SPECULAR CONE REFLECTOR w/5.875"TALL ACRYLIC
[MORE] CYLINDER LENS
[LUMCAT] OSA6R-100PSMH120-AC
[LAMPCAT] M90 MH100W/U/PS
TILT=NONE
1 9000 1 35 1 1 1 -0.49 -0.49 0.406
1 1 100
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 95 105 115 125 135 145 155 165 175 180
0
0.00 12.00 87.00 182.00 167.00 300.00 655.00 944.00 822.00 703.00 614.00 565.00 487.00 438.00 372.00 309.00 262.00 216.00 182.00 142.00 111.00 83.00 61.00 42.00 25.00 19.00 14.00 14.00 15.00 20.00 33.00 36.00 27.00 4.00 0.00

View File

@ -1,13 +1,13 @@
IESNA:LM-63-1995
[TEST] INFINITY LIGHTING PHOTOMETRIC REPORT NO. W00006
[LUMINAIRE] ICEAL8-2X150-FL-CG1
TILT=NONE
2 11000 1 19 5 1 1 1.375 1.04167 0
1 1 314
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0 22.5 45 67.5 90
9085.62 9033.58 8923.24 8687.43 8145.53 7454.18 6336.9 5050.9 3180.16 2162.21 1292.02 677.24 243.87 48.44 16.1 6.48 6.25 6.99 3.31
9085.62 8902.2 8825.21 8578.38 8462.81 7787.37 6902.89 5633.64 3822.33 2423.91 1614.81 927.01 382.27 72.18 18.92 8.91 6.41 5.19 2.16
9085.62 9029.2 9168.27 8989.93 8818.57 8434.18 7791.45 6806.71 5489.39 3939.15 2518.39 1573.92 770.93 308.04 81.18 28.92 14.71 8.88 4.75
9085.62 9404.94 9244.69 9202.21 9146.45 8779.2 8121.15 7346.47 6513.38 5407.45 3976.98 2453.4 1106.06 428.6 117.57 35.96 12.34 7.19 1.55
9085.62 9315.27 9317.59 9459.68 9433.84 9128.13 8380.85 7752.85 6655.4 5439.5 3990.21 2472.54 1140.85 377.1 65.79 17.41 9 4.71 2.77
IESNA:LM-63-1995
[TEST] INFINITY LIGHTING PHOTOMETRIC REPORT NO. W00006
[LUMINAIRE] ICEAL8-2X150-FL-CG1
TILT=NONE
2 11000 1 19 5 1 1 1.375 1.04167 0
1 1 314
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0 22.5 45 67.5 90
9085.62 9033.58 8923.24 8687.43 8145.53 7454.18 6336.9 5050.9 3180.16 2162.21 1292.02 677.24 243.87 48.44 16.1 6.48 6.25 6.99 3.31
9085.62 8902.2 8825.21 8578.38 8462.81 7787.37 6902.89 5633.64 3822.33 2423.91 1614.81 927.01 382.27 72.18 18.92 8.91 6.41 5.19 2.16
9085.62 9029.2 9168.27 8989.93 8818.57 8434.18 7791.45 6806.71 5489.39 3939.15 2518.39 1573.92 770.93 308.04 81.18 28.92 14.71 8.88 4.75
9085.62 9404.94 9244.69 9202.21 9146.45 8779.2 8121.15 7346.47 6513.38 5407.45 3976.98 2453.4 1106.06 428.6 117.57 35.96 12.34 7.19 1.55
9085.62 9315.27 9317.59 9459.68 9433.84 9128.13 8380.85 7752.85 6655.4 5439.5 3990.21 2472.54 1140.85 377.1 65.79 17.41 9 4.71 2.77

View File

@ -1,16 +1,16 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 10974.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/250W HALOGEN CLEAR MINICAN 7.5"DIA RECESSED LUMINAIRE
[LUMINAIRE] FACETED HYDROFORMED SEMI-SPECULAR REFLECTOR
[LUMINAIRE] CLEAR GLASS LENS w/4"DEEPSPUN SPECULAR ALUMINUM CONE
[LUMCAT]CATALOG NO. : TH75-250-T4 NARROW w/SPACER I
[LAMPCAT]LAMP CODE : 250Q/CL/MC (EHT)
TILT=NONE
1 5000. 1.000000 19 1 1 1 .625 .625 .000
1.0000 1.0000 247.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0
8183. 6729. 4775. 3866. 2714. 1600. 992. 715. 373. 119.
46. 20. 8. 4. 0. 0. 0. 0. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 10974.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/250W HALOGEN CLEAR MINICAN 7.5"DIA RECESSED LUMINAIRE
[LUMINAIRE] FACETED HYDROFORMED SEMI-SPECULAR REFLECTOR
[LUMINAIRE] CLEAR GLASS LENS w/4"DEEPSPUN SPECULAR ALUMINUM CONE
[LUMCAT]CATALOG NO. : TH75-250-T4 NARROW w/SPACER I
[LAMPCAT]LAMP CODE : 250Q/CL/MC (EHT)
TILT=NONE
1 5000. 1.000000 19 1 1 1 .625 .625 .000
1.0000 1.0000 247.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0
8183. 6729. 4775. 3866. 2714. 1600. 992. 715. 373. 119.
46. 20. 8. 4. 0. 0. 0. 0. 0.

View File

@ -1,16 +1,16 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 10979.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/500W HALOGEN CLEAR MINICAN 7.5"DIA RECESSED LUMINAIRE
[LUMINAIRE] FACETED HYDROFORMED SEMI-SPECULAR REFLECTOR
[LUMINAIRE] CLEAR GLASS LENS w/4"DEEP SPUN SPECULAR ALUMINUM CONE
[LUMCAT]CATALOG NO. : TH75-500-T4 WIDE w/SPACER D
[LAMPCAT]LAMP CODE : 500Q/CL/MC (EVR)
TILT=NONE
1 10450. 1.000000 19 1 1 1 .625 .625 .000
1.0000 1.0000 503.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0
4612. 5322. 6414. 6917. 6708. 5675. 4019. 2703. 1870. 872.
169. 42. 9. 0. 0. 0. 0. 0. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 10979.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/500W HALOGEN CLEAR MINICAN 7.5"DIA RECESSED LUMINAIRE
[LUMINAIRE] FACETED HYDROFORMED SEMI-SPECULAR REFLECTOR
[LUMINAIRE] CLEAR GLASS LENS w/4"DEEP SPUN SPECULAR ALUMINUM CONE
[LUMCAT]CATALOG NO. : TH75-500-T4 WIDE w/SPACER D
[LAMPCAT]LAMP CODE : 500Q/CL/MC (EVR)
TILT=NONE
1 10450. 1.000000 19 1 1 1 .625 .625 .000
1.0000 1.0000 503.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0
4612. 5322. 6414. 6917. 6708. 5675. 4019. 2703. 1870. 872.
169. 42. 9. 0. 0. 0. 0. 0. 0.

View File

@ -1,16 +1,16 @@
IESNA91
[TEST] Test unknown
[MANUFAC] Manufacturing company unknown
TILT=NONE
1 13172.61 1
37 1
1
2
0 0 0
1 1 0
0.00 2.50 5.00 7.50 9.11 10.00 10.80 12.50 15.83 22.50 25.00 27.50 32.50 34.28 35.00 42.50 47.02 47.50 47.81 50.00 50.78 52.50
55.00 57.50 60.00 62.50 65.00 67.50 70.00 72.50 75.00 77.50 80.00 82.50 85.00 87.50 90.00
0.00
8379.00 8409.00 8528.00 8126.65 8500.00 8564.00 8301.00 8158.61 8411.98 8036.59 7865.61 7283.76 5209.38 6038.93 4533.49 3091.00
3665.38 2996.97 3625.45 2194.62 3170.85 1115.28 651.00 450.00 244.00 102.00 80.00 43.00 5.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00
0.00
IESNA91
[TEST] Test unknown
[MANUFAC] Manufacturing company unknown
TILT=NONE
1 13172.61 1
37 1
1
2
0 0 0
1 1 0
0.00 2.50 5.00 7.50 9.11 10.00 10.80 12.50 15.83 22.50 25.00 27.50 32.50 34.28 35.00 42.50 47.02 47.50 47.81 50.00 50.78 52.50
55.00 57.50 60.00 62.50 65.00 67.50 70.00 72.50 75.00 77.50 80.00 82.50 85.00 87.50 90.00
0.00
8379.00 8409.00 8528.00 8126.65 8500.00 8564.00 8301.00 8158.61 8411.98 8036.59 7865.61 7283.76 5209.38 6038.93 4533.49 3091.00
3665.38 2996.97 3625.45 2194.62 3170.85 1115.28 651.00 450.00 244.00 102.00 80.00 43.00 5.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00
0.00

View File

@ -1,64 +1,64 @@
ERCO Leuchten GmbH
3399_0 - IES format
ERCO 89064
ERCO Double Focus Downlight
DL40-QT12-2HA-SI-DOUBLE
1*QT-ax12 100W/12V
light output ratio: 0.5912
ident no. for symmetry: 1
D694
TILT=NONE
1
2200
2.2
19
1
1
2
0
0
0
1
1
100
0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
0
681.879276637
557.110079287
490.896871945
628.387368307
682.069349408
430.426577604
286.398935592
254.901162159
76.9183773216
18.9393939394
11.0377973281
.488758553275
.00678831323993
0
0
0
0
0
0
END
ERCO Leuchten GmbH
3399_0 - IES format
ERCO 89064
ERCO Double Focus Downlight
DL40-QT12-2HA-SI-DOUBLE
1*QT-ax12 100W/12V
light output ratio: 0.5912
ident no. for symmetry: 1
D694
TILT=NONE
1
2200
2.2
19
1
1
2
0
0
0
1
1
100
0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
0
681.879276637
557.110079287
490.896871945
628.387368307
682.069349408
430.426577604
286.398935592
254.901162159
76.9183773216
18.9393939394
11.0377973281
.488758553275
.00678831323993
0
0
0
0
0
0
END


View File

@ -1,29 +1,29 @@
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
74216023+Q50MR16/C/CG55°-FNV.IES
-
-
-
-
-
-
TILT=NONE
1 825 .825 73 2 1 2 -.2 0 0
1.00 1.00 50
0 1.25 2.5 3.75 5 6.25 7.5 8.75 10 11.25 12.5 13.75 15 16.25 17.5 18.75 20
21.25 22.5 23.75 25 26.25 27.5 28.75 30 31.25 32.5 33.75 35 36.25 37.5 38.75
40 41.25 42.5 43.75 45 46.25 47.5 48.75 50 51.25 52.5 53.75 55 56.25 57.5
58.75 60 61.25 62.5 63.75 65 66.25 67.5 68.75 70 71.25 72.5 73.75 75 76.25
77.5 78.75 80 81.25 82.5 83.75 85 86.25 87.5 88.75 90
0 90
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
74216023+Q50MR16/C/CG55°-FNV.IES
-
-
-
-
-
-
TILT=NONE
1 825 .825 73 2 1 2 -.2 0 0
1.00 1.00 50
0 1.25 2.5 3.75 5 6.25 7.5 8.75 10 11.25 12.5 13.75 15 16.25 17.5 18.75 20
21.25 22.5 23.75 25 26.25 27.5 28.75 30 31.25 32.5 33.75 35 36.25 37.5 38.75
40 41.25 42.5 43.75 45 46.25 47.5 48.75 50 51.25 52.5 53.75 55 56.25 57.5
58.75 60 61.25 62.5 63.75 65 66.25 67.5 68.75 70 71.25 72.5 73.75 75 76.25
77.5 78.75 80 81.25 82.5 83.75 85 86.25 87.5 88.75 90
0 90
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97

View File

@ -1,14 +1,14 @@
IESNA:LM-63-1995
[TEST] 100068_0 BY: ERCO / LUM650
[DATE]02.12.2004
[MANUFAC] ERCO Leuchten GmbH
[LUMCAT] 22619000_83670000
[LUMINAIRE] Lightcast Downlight
[LAMPCAT] HIPAR-L30 35W 30°
TILT=NONE
1 2200 1 19 1 1 2 -.097 0 0
1.00 1.00 35
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0
7399.9 7219.5 6097.7 3707.0 836.0 281.6 239.8 145.2 90.2 46.2 33.0 17.6 12.1
11.0 9.9 9.0 0.0 0.0 0.0
IESNA:LM-63-1995
[TEST] 100068_0 BY: ERCO / LUM650
[DATE]02.12.2004
[MANUFAC] ERCO Leuchten GmbH
[LUMCAT] 22619000_83670000
[LUMINAIRE] Lightcast Downlight
[LAMPCAT] HIPAR-L30 35W 30°
TILT=NONE
1 2200 1 19 1 1 2 -.097 0 0
1.00 1.00 35
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0
7399.9 7219.5 6097.7 3707.0 836.0 281.6 239.8 145.2 90.2 46.2 33.0 17.6 12.1
11.0 9.9 9.0 0.0 0.0 0.0

View File

@ -1,29 +1,29 @@
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
73011023+CHM70/U/PAR38/12.IES
-
-
-
-
-
-
TILT=NONE
1 4100 4.1 73 2 1 2 -.12 0 0
1.00 1.00 92
0 1.25 2.5 3.75 5 6.25 7.5 8.75 10 11.25 12.5 13.75 15 16.25 17.5 18.75 20
21.25 22.5 23.75 25 26.25 27.5 28.75 30 31.25 32.5 33.75 35 36.25 37.5 38.75
40 41.25 42.5 43.75 45 46.25 47.5 48.75 50 51.25 52.5 53.75 55 56.25 57.5
58.75 60 61.25 62.5 63.75 65 66.25 67.5 68.75 70 71.25 72.5 73.75 75 76.25
77.5 78.75 80 81.25 82.5 83.75 85 86.25 87.5 88.75 90
0 90
13800 13140 11450 9275 7132 5238 3687 2529 1731 1206 867.8 644.4 493.7 385.4
306.8 250.1 211 186.1 170.7 160.7 153.9 149.1 145.6 142.8 140 136.7 134.3
134.7 139.8 150.2 162.8 173.3 177.3 171.9 159.2 142.4 124.9 109.4 96.15 84.85
75.12 66.63 59 51.87 44.88 37.79 30.91 24.68 19.51 15.73 13.11 11.31 10 8.932
8.275 8.298 9.268 11.25 13.52 15.12 15.12 12.93 9.3 5.354 2.195 .6462 .3783
.7748 1.22 1.234 .8939 .4114 0
13800 13140 11450 9275 7132 5238 3687 2529 1731 1206 867.8 644.4 493.7 385.4
306.8 250.1 211 186.1 170.7 160.7 153.9 149.1 145.6 142.8 140 136.7 134.3
134.7 139.8 150.2 162.8 173.3 177.3 171.9 159.2 142.4 124.9 109.4 96.15 84.85
75.12 66.63 59 51.87 44.88 37.79 30.91 24.68 19.51 15.73 13.11 11.31 10 8.932
8.275 8.298 9.268 11.25 13.52 15.12 15.12 12.93 9.3 5.354 2.195 .6462 .3783
.7748 1.22 1.234 .8939 .4114 0
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
73011023+CHM70/U/PAR38/12.IES
-
-
-
-
-
-
TILT=NONE
1 4100 4.1 73 2 1 2 -.12 0 0
1.00 1.00 92
0 1.25 2.5 3.75 5 6.25 7.5 8.75 10 11.25 12.5 13.75 15 16.25 17.5 18.75 20
21.25 22.5 23.75 25 26.25 27.5 28.75 30 31.25 32.5 33.75 35 36.25 37.5 38.75
40 41.25 42.5 43.75 45 46.25 47.5 48.75 50 51.25 52.5 53.75 55 56.25 57.5
58.75 60 61.25 62.5 63.75 65 66.25 67.5 68.75 70 71.25 72.5 73.75 75 76.25
77.5 78.75 80 81.25 82.5 83.75 85 86.25 87.5 88.75 90
0 90
13800 13140 11450 9275 7132 5238 3687 2529 1731 1206 867.8 644.4 493.7 385.4
306.8 250.1 211 186.1 170.7 160.7 153.9 149.1 145.6 142.8 140 136.7 134.3
134.7 139.8 150.2 162.8 173.3 177.3 171.9 159.2 142.4 124.9 109.4 96.15 84.85
75.12 66.63 59 51.87 44.88 37.79 30.91 24.68 19.51 15.73 13.11 11.31 10 8.932
8.275 8.298 9.268 11.25 13.52 15.12 15.12 12.93 9.3 5.354 2.195 .6462 .3783
.7748 1.22 1.234 .8939 .4114 0
13800 13140 11450 9275 7132 5238 3687 2529 1731 1206 867.8 644.4 493.7 385.4
306.8 250.1 211 186.1 170.7 160.7 153.9 149.1 145.6 142.8 140 136.7 134.3
134.7 139.8 150.2 162.8 173.3 177.3 171.9 159.2 142.4 124.9 109.4 96.15 84.85
75.12 66.63 59 51.87 44.88 37.79 30.91 24.68 19.51 15.73 13.11 11.31 10 8.932
8.275 8.298 9.268 11.25 13.52 15.12 15.12 12.93 9.3 5.354 2.195 .6462 .3783
.7748 1.22 1.234 .8939 .4114 0

View File

@ -1,80 +1,80 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 12788.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W ICETRON INDUCTION 20x15"DIRECT AREALIGHT LUMINAIRE
[LUMINAIRE] MIRO4 SPEC ALUM TYPE II OPTICS & CLEAR FLAT GLASS LENS
[LUMINAIRE] BLACK PANEL STREET SIDE SYLVANIA # QT 1x150 ICE/UNV-T
[LUMCAT] ICEAL2-150S-TYPE2/CG1-277
[LAMPCAT] ICE100/QT150 2PIN
TILT=NONE
1 11000. 1.000000 25 21 1 1 .938 1.266 .000
1.0000 1.0000 140.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 62.5 65.0 67.5 70.0 72.5 75.0 77.5
80.0 82.5 85.0 87.5 90.0
.0 5.0 15.0 25.0 35.0 45.0 55.0 65.0 75.0 85.0
90.0 95.0 105.0 115.0 125.0 135.0 145.0 155.0 165.0 175.0
180.0
1789. 1841. 1911. 1979. 2023. 2025. 1994. 1867. 1718. 1551.
1374. 1208. 990. 808. 637. 469. 347. 202. 89. 18.
9. 7. 7. 6. 0.
1789. 1831. 1908. 1969. 2013. 2018. 1983. 1865. 1701. 1548.
1353. 1193. 981. 842. 661. 503. 352. 172. 68. 19.
8. 6. 6. 5. 0.
1789. 1828. 1891. 1939. 1958. 1939. 1908. 1808. 1668. 1559.
1428. 1300. 1222. 1161. 999. 778. 580. 318. 129. 39.
10. 7. 7. 4. 0.
1789. 1818. 1865. 1891. 1942. 1959. 1927. 1843. 1761. 1714.
1673. 1599. 1445. 1325. 1165. 948. 668. 400. 186. 75.
30. 9. 7. 2. 0.
1789. 1811. 1821. 1891. 1941. 1974. 1980. 1943. 1993. 2082.
1963. 1808. 1621. 1601. 1424. 1166. 829. 487. 279. 152.
65. 15. 8. 2. 0.
1789. 1794. 1804. 1893. 1935. 1995. 2020. 2145. 2342. 2221.
2063. 2135. 2157. 1694. 948. 340. 101. 8. 0. 185.
94. 32. 9. 0. 0.
1789. 1775. 1803. 1868. 1931. 1992. 2076. 2357. 2333. 2285.
2254. 2608. 2375. 2010. 1722. 1448. 981. 661. 376. 244.
122. 38. 8. 0. 0.
1789. 1763. 1798. 1839. 1918. 1961. 2151. 2291. 2310. 2263.
2575. 2700. 2380. 2075. 1792. 1483. 1102. 702. 430. 298.
192. 67. 11. 2. 0.
1789. 1746. 1801. 1827. 1871. 1923. 2176. 2119. 2124. 2062.
2553. 2596. 2201. 1907. 1678. 1368. 1015. 673. 440. 303.
178. 63. 10. 1. 0.
1789. 1738. 1788. 1808. 1830. 1895. 2081. 2024. 1953. 1883.
2313. 2285. 1854. 1661. 1400. 1139. 833. 577. 404. 267.
157. 54. 12. 1. 0.
1789. 1735. 1783. 1797. 1812. 1868. 2046. 1983. 1911. 1805.
2191. 2151. 1759. 1513. 1288. 1033. 802. 568. 386. 243.
134. 56. 10. 3. 0.
1789. 1734. 1778. 1786. 1797. 1838. 2016. 1951. 1871. 1766.
2128. 2078. 1681. 1474. 1248. 1009. 739. 523. 349. 228.
144. 52. 13. 2. 0.
1789. 1733. 1774. 1773. 1771. 1777. 1959. 1895. 1811. 1647.
2034. 1957. 1595. 1293. 1118. 925. 717. 481. 319. 208.
125. 51. 7. 1. 0.
1789. 1738. 1763. 1755. 1744. 1704. 1880. 1794. 1752. 1541.
1772. 1720. 1427. 1191. 1003. 795. 588. 427. 274. 166.
98. 39. 8. 3. 0.
1789. 1734. 1744. 1732. 1708. 1647. 1674. 1703. 1620. 1413.
1325. 1423. 1205. 983. 808. 642. 464. 312. 192. 107.
57. 18. 8. 3. 0.
1789. 1735. 1714. 1725. 1673. 1590. 1481. 1511. 1373. 1230.
982. 993. 902. 771. 626. 456. 300. 187. 112. 60.
31. 14. 8. 4. 0.
1789. 1736. 1681. 1700. 1617. 1511. 1381. 1252. 1210. 1043.
875. 657. 554. 487. 398. 294. 195. 122. 70. 40.
19. 11. 8. 3. 0.
1789. 1737. 1666. 1641. 1577. 1471. 1333. 1172. 1015. 890.
728. 574. 409. 326. 243. 181. 114. 72. 40. 24.
14. 9. 7. 4. 0.
1789. 1740. 1679. 1601. 1493. 1388. 1268. 1114. 956. 769.
624. 481. 347. 267. 201. 141. 85. 41. 25. 16.
10. 7. 6. 3. 0.
1789. 1737. 1693. 1616. 1479. 1340. 1187. 1041. 896. 724.
572. 431. 303. 233. 167. 117. 62. 29. 18. 12.
9. 6. 6. 4. 1.
1789. 1742. 1698. 1623. 1491. 1354. 1196. 1040. 894. 722.
565. 421. 302. 227. 159. 108. 57. 20. 14. 10.
8. 6. 6. 5. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 12788.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W ICETRON INDUCTION 20x15"DIRECT AREALIGHT LUMINAIRE
[LUMINAIRE] MIRO4 SPEC ALUM TYPE II OPTICS & CLEAR FLAT GLASS LENS
[LUMINAIRE] BLACK PANEL STREET SIDE SYLVANIA # QT 1x150 ICE/UNV-T
[LUMCAT] ICEAL2-150S-TYPE2/CG1-277
[LAMPCAT] ICE100/QT150 2PIN
TILT=NONE
1 11000. 1.000000 25 21 1 1 .938 1.266 .000
1.0000 1.0000 140.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 62.5 65.0 67.5 70.0 72.5 75.0 77.5
80.0 82.5 85.0 87.5 90.0
.0 5.0 15.0 25.0 35.0 45.0 55.0 65.0 75.0 85.0
90.0 95.0 105.0 115.0 125.0 135.0 145.0 155.0 165.0 175.0
180.0
1789. 1841. 1911. 1979. 2023. 2025. 1994. 1867. 1718. 1551.
1374. 1208. 990. 808. 637. 469. 347. 202. 89. 18.
9. 7. 7. 6. 0.
1789. 1831. 1908. 1969. 2013. 2018. 1983. 1865. 1701. 1548.
1353. 1193. 981. 842. 661. 503. 352. 172. 68. 19.
8. 6. 6. 5. 0.
1789. 1828. 1891. 1939. 1958. 1939. 1908. 1808. 1668. 1559.
1428. 1300. 1222. 1161. 999. 778. 580. 318. 129. 39.
10. 7. 7. 4. 0.
1789. 1818. 1865. 1891. 1942. 1959. 1927. 1843. 1761. 1714.
1673. 1599. 1445. 1325. 1165. 948. 668. 400. 186. 75.
30. 9. 7. 2. 0.
1789. 1811. 1821. 1891. 1941. 1974. 1980. 1943. 1993. 2082.
1963. 1808. 1621. 1601. 1424. 1166. 829. 487. 279. 152.
65. 15. 8. 2. 0.
1789. 1794. 1804. 1893. 1935. 1995. 2020. 2145. 2342. 2221.
2063. 2135. 2157. 1694. 948. 340. 101. 8. 0. 185.
94. 32. 9. 0. 0.
1789. 1775. 1803. 1868. 1931. 1992. 2076. 2357. 2333. 2285.
2254. 2608. 2375. 2010. 1722. 1448. 981. 661. 376. 244.
122. 38. 8. 0. 0.
1789. 1763. 1798. 1839. 1918. 1961. 2151. 2291. 2310. 2263.
2575. 2700. 2380. 2075. 1792. 1483. 1102. 702. 430. 298.
192. 67. 11. 2. 0.
1789. 1746. 1801. 1827. 1871. 1923. 2176. 2119. 2124. 2062.
2553. 2596. 2201. 1907. 1678. 1368. 1015. 673. 440. 303.
178. 63. 10. 1. 0.
1789. 1738. 1788. 1808. 1830. 1895. 2081. 2024. 1953. 1883.
2313. 2285. 1854. 1661. 1400. 1139. 833. 577. 404. 267.
157. 54. 12. 1. 0.
1789. 1735. 1783. 1797. 1812. 1868. 2046. 1983. 1911. 1805.
2191. 2151. 1759. 1513. 1288. 1033. 802. 568. 386. 243.
134. 56. 10. 3. 0.
1789. 1734. 1778. 1786. 1797. 1838. 2016. 1951. 1871. 1766.
2128. 2078. 1681. 1474. 1248. 1009. 739. 523. 349. 228.
144. 52. 13. 2. 0.
1789. 1733. 1774. 1773. 1771. 1777. 1959. 1895. 1811. 1647.
2034. 1957. 1595. 1293. 1118. 925. 717. 481. 319. 208.
125. 51. 7. 1. 0.
1789. 1738. 1763. 1755. 1744. 1704. 1880. 1794. 1752. 1541.
1772. 1720. 1427. 1191. 1003. 795. 588. 427. 274. 166.
98. 39. 8. 3. 0.
1789. 1734. 1744. 1732. 1708. 1647. 1674. 1703. 1620. 1413.
1325. 1423. 1205. 983. 808. 642. 464. 312. 192. 107.
57. 18. 8. 3. 0.
1789. 1735. 1714. 1725. 1673. 1590. 1481. 1511. 1373. 1230.
982. 993. 902. 771. 626. 456. 300. 187. 112. 60.
31. 14. 8. 4. 0.
1789. 1736. 1681. 1700. 1617. 1511. 1381. 1252. 1210. 1043.
875. 657. 554. 487. 398. 294. 195. 122. 70. 40.
19. 11. 8. 3. 0.
1789. 1737. 1666. 1641. 1577. 1471. 1333. 1172. 1015. 890.
728. 574. 409. 326. 243. 181. 114. 72. 40. 24.
14. 9. 7. 4. 0.
1789. 1740. 1679. 1601. 1493. 1388. 1268. 1114. 956. 769.
624. 481. 347. 267. 201. 141. 85. 41. 25. 16.
10. 7. 6. 3. 0.
1789. 1737. 1693. 1616. 1479. 1340. 1187. 1041. 896. 724.
572. 431. 303. 233. 167. 117. 62. 29. 18. 12.
9. 6. 6. 4. 1.
1789. 1742. 1698. 1623. 1491. 1354. 1196. 1040. 894. 722.
565. 421. 302. 227. 159. 108. 57. 20. 14. 10.
8. 6. 6. 5. 0.

View File

@ -1,385 +1,385 @@
IESNA:LM-63-2002
[TEST] 5890_0
[TESTLAB] ERCO GmbH
[ISSUEDATE] 02-12-2008
[MANUFAC] ERCO GmbH
[LUMCAT] 33519000
[LUMINAIRE] Kubus Floor washlight
[LAMP] HIT-TC-CE 20W
TILT=NONE
1 1615 1 37 73 1 2 0.103 0.059 0
1.0 1.0 24
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30
32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5
65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30
32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5
65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95
97.5 100 102.5 105 107.5 110 112.5 115 117.5 120 122.5 125 127.5
130 132.5 135 137.5 140 142.5 145 147.5 150 152.5 155 157.5 160
162.5 165 167.5 170 172.5 175 177.5 180
174.408695 186.514735 207.74714 232.0109 259.393225 290.905105 329.41801 371.299805 413.25912
451.245535 487.59757 510.86326 514.272525 504.50339 491.06659 481.24739 473.75702 470.79188
471.491175 465.94688 448.826265 421.89291 385.692685 336.53693 275.843615 220.833485 172.667725
138.452335 109.86845 87.28106 67.431095 50.761065 36.44086 23.40458 12.382205 3.77264
0
174.408695 186.24503 208.21226 231.893005 258.99432 290.456135 328.705795 370.82015 411.190305
451.636365 486.478375 509.308015 514.198235 503.661975 490.829185 481.08266 472.12264 470.44627
469.93593 463.828 448.5824 424.378395 389.798015 336.6629 278.547125 220.067975 173.953265
138.071195 110.2722 87.81078 67.763785 50.964555 36.345575 23.34321 12.27077 3.75649
0
174.408695 186.0157 207.63086 230.823875 258.333785 290.4416 328.276205 369.71872 411.584365
449.65153 484.175385 507.77215 512.935305 503.86708 488.84435 479.21249 469.905245 467.854195
466.145525 462.72011 447.43575 420.92068 387.178485 339.510145 278.682785 222.855465 176.492045
140.47916 111.16368 87.650895 68.65688 51.0017 36.442475 23.260845 12.34506 3.72096
0
174.408695 185.77345 207.59856 230.94177 258.35478 288.73293 327.291055 368.62052 409.81917
449.25424 483.86692 504.188465 511.136195 501.5544 486.959645 476.44115 467.35193 462.392265
461.99982 458.337 441.14371 417.88771 386.903935 340.17714 282.22448 226.653945 178.465575
140.67942 111.313875 88.38249 68.78285 51.319855 36.348805 23.29153 12.31599 3.74357
0
174.408695 185.81867 206.934795 230.462115 258.078615 287.920585 325.67121 366.390205 407.695445
447.705455 480.947 502.689745 508.27926 499.385455 486.3088 474.42886 464.59028 457.1419
454.82276 449.010375 435.418535 415.26818 383.87258 338.59121 284.75034 231.444035 182.480465
144.773445 114.2774 89.45808 68.965345 51.22134 36.58298 23.16556 12.336985 3.74034
0
174.408695 185.96079 206.6231 229.86618 257.293725 285.88084 323.179265 363.877265 405.780055
444.85175 477.25511 499.88772 505.199455 498.019165 484.188305 472.73311 459.288235 450.66575
446.08238 437.337155 424.565735 406.19834 378.51401 336.5983 285.727415 230.462115 184.02602
145.044765 114.05776 89.47746 68.874905 51.26979 36.290665 23.170405 12.16418 3.741955
0
174.408695 185.080615 205.778455 229.060295 256.58797 284.425725 320.876275 361.193135 402.785845
439.17018 474.37718 496.98718 502.315065 496.097315 482.618525 467.20335 455.396085 444.68379
436.20181 425.79475 415.253645 395.80743 367.84209 328.870525 279.27226 228.09291 181.41941
142.81122 111.34133 88.20161 67.660425 50.496205 35.347505 22.71013 11.8541 3.64667
0
174.408695 185.16944 205.778455 228.01862 254.89545 283.282305 317.630125 357.39304 399.119795
435.883655 468.8991 491.830485 500.61447 494.71003 479.5581 463.735945 448.241635 437.19019
426.04023 416.629625 404.18282 382.9488 355.27093 319.555205 273.821635 224.84676 178.866095
142.686865 109.811925 86.98713 66.442715 49.49329 34.44472 22.05767 11.51172 3.596605
0
174.408695 184.83352 204.96934 227.102915 252.97683 281.0746 314.581005 353.40722 394.09553
431.413335 463.55668 487.50713 496.41224 491.533325 477.0064 460.560855 444.61273 429.75796
418.42389 407.062365 392.67433 372.40285 342.278255 310.327095 271.008305 225.303805 181.03181
143.474985 111.09908 86.539775 65.80479 49.13476 34.26384 21.964 11.471345 3.561075
0
174.408695 184.61388 204.66895 225.662335 251.44581 279.35301 311.732145 348.838385 389.20854
425.237575 458.577635 478.813585 491.26685 487.78168 473.40172 459.32861 439.76773 423.69848
410.85277 395.89464 383.12968 362.301025 335.831175 306.092565 270.66108 227.96371 185.74438
147.867785 115.01707 90.105695 67.922055 50.4203 35.024505 22.307995 11.5957 3.632135
0
174.408695 184.3684 203.498075 224.45916 249.356 276.85622 307.88683 344.129045 382.67102
419.811175 451.79302 472.605525 485.17184 485.580435 472.779945 456.84797 436.20504 418.64999
402.03487 388.609375 373.25557 354.79612 330.240045 302.678455 272.830025 233.504775 195.090385
156.071985 121.898585 94.663225 71.05677 52.58117 36.04034 22.97499 11.89609 3.72419
0
174.408695 183.685255 202.709955 222.878075 247.94126 274.57907 304.72466 339.216215 376.800495
412.563055 445.169905 466.672015 479.269015 481.484795 470.04575 454.24782 433.264125 412.986185
393.296105 376.638995 363.499355 346.72112 324.616615 300.136445 272.33422 237.707005 202.08495
163.588195 129.40995 100.606425 75.519015 54.960065 37.72317 23.732425 12.249775 3.79525
0
174.408695 183.698175 202.34981 221.40681 245.207065 271.96923 300.452985 332.875725 368.97582
404.827205 436.15659 459.50949 472.34551 475.85652 467.62002 451.28914 430.344205 407.524255
386.422665 368.55915 352.41238 336.667745 315.92307 294.106035 269.95048 238.42245 206.09338
169.021055 135.04307 105.23986 79.136615 58.03664 39.594955 24.95175 12.727815 3.94706
0
174.408695 183.362255 201.279065 219.593165 242.287145 267.93496 295.45133 326.92445 361.6631
395.453745 426.23726 450.832095 464.575745 468.219185 463.316045 447.524575 426.09191 402.365945
381.08832 361.018715 341.90519 325.356285 307.681725 286.76263 266.65265 238.2125 207.50812
172.196145 141.26728 110.629115 84.08013 61.09545 42.08367 26.23729 13.39481 4.119865
0
174.408695 182.945585 200.197015 218.37707 239.758055 264.564455 290.078225 319.84106 353.27156
386.06898 417.316 440.39112 455.34279 459.488495 455.677095 442.967045 422.369335 397.143035
372.546585 352.20243 332.633475 315.611375 297.135775 279.874655 259.251105 234.095865 206.73615
174.828595 144.48113 114.372685 88.81208 64.07997 44.720965 27.60681 14.17001 4.349195
0
174.408695 182.40133 199.173105 216.615105 237.471215 259.97624 284.44995 313.453735 345.023755
376.21748 405.19381 429.769265 445.040705 449.74197 448.03653 438.248015 419.145795 394.97409
368.08757 345.46465 323.909245 306.0425 286.615665 269.506355 251.515255 229.3946 204.609195
175.930025 147.56255 118.830085 93.23718 67.569985 48.015565 29.31548 15.28113 4.665735
0
174.408695 182.451395 198.15081 214.48169 234.806465 255.9452 279.306175 306.43979 336.45941
365.60047 394.78998 418.26885 432.44209 438.041295 439.065205 430.508935 413.95034 390.747635
363.189275 340.133535 317.4444 296.87253 277.213135 258.398385 241.721895 219.583475 196.73607
172.06856 147.98568 120.060715 95.751735 70.318715 50.02301 30.76898 16.00465 4.92898
0
174.408695 182.04603 197.529035 213.217145 232.16594 252.60861 274.01382 299.32733 327.76425
354.45051 382.578965 404.51228 419.220085 425.17782 426.267945 419.220085 406.04976 384.66716
358.06488 332.93871 309.041555 288.10631 267.28573 249.26233 230.17626 210.71551 190.364895
168.20871 144.069305 119.61013 96.11188 71.200505 51.47974 31.6217 16.671645 5.033955
0
174.408695 181.676195 196.29679 211.09342 228.63555 248.30625 269.251185 291.64316 317.42825
343.00016 369.3505 390.43271 404.33786 411.280745 412.42901 407.16734 397.54517 377.446495
351.0364 325.69705 300.985935 277.3924 255.271745 236.02902 217.516275 197.474125 178.68037
159.589455 138.03082 116.139495 93.6054 70.66917 51.45713 31.87364 16.852525 5.10986
0
174.408695 181.203 194.80453 209.263625 225.701095 244.48516 263.230465 284.5953 308.511835
332.18612 356.661445 376.949075 388.55931 395.143665 397.201175 392.65172 384.181045 365.81688
343.747905 317.0568 290.56111 265.281515 241.55878 221.750805 201.70381 181.824775 166.181885
148.051895 130.196455 109.337115 89.80692 68.093245 49.762995 30.883645 16.37287 4.90314
0
174.408695 180.62483 193.659495 207.1076 223.297975 239.993845 257.35671 277.717015 299.85059
321.383385 343.19719 361.583965 373.266875 379.119635 380.686185 377.17679 368.61083 353.34908
333.124435 307.584825 281.76259 254.60152 229.619085 208.191265 186.960475 167.83403 150.002815
133.833435 116.81941 99.475925 82.00324 62.52634 45.954825 28.67594 15.095405 4.54138
0
174.408695 180.374505 192.331965 205.481295 219.609315 235.145615 251.65576 271.001845 290.536885
308.931735 328.68803 345.282155 357.617525 362.75807 362.74838 358.896605 350.485685 338.001735
321.325245 297.13739 273.072275 245.37664 218.78728 195.72508 173.753005 154.392385 136.343145
120.936045 104.64231 88.135395 71.281255 56.19877 40.44929 25.74633 13.377045 4.058495
0
174.408695 179.880315 191.446945 203.469005 216.81698 231.182405 246.211595 263.30637 280.77744
297.23752 315.824555 329.794305 340.80699 345.07382 344.1565 340.139995 332.29917 320.785835
303.54571 282.390825 260.29278 235.429855 208.775895 184.379705 161.83269 142.74985 124.689305
109.673035 93.229105 78.34365 62.783125 49.036245 35.114945 22.36452 11.571475 3.490015
0
174.408695 179.17456 190.038665 201.33236 213.33181 226.71047 240.778735 255.6222 271.670455
285.772635 302.394215 315.40627 325.062355 328.29397 326.34305 322.249025 313.67822 302.148735
286.48808 267.7347 245.39602 222.196545 197.21088 173.517215 152.102315 131.985875 113.29548
97.783405 82.02585 68.332265 54.188095 42.4422 29.99055 19.28956 9.824045 2.989365
0
174.408695 178.988835 188.701445 198.966385 210.274615 222.206235 234.903365 248.827895 262.73466
274.713115 289.40154 300.36416 308.708865 311.65624 308.628115 304.15618 295.365735 283.45188
267.303495 250.55433 230.18272 207.64055 184.24243 161.705105 141.608045 121.21867 103.57964
88.16931 72.57164 60.15875 47.1903 36.6605 25.64297 16.55052 8.299485 2.57108
0
174.408695 178.69652 187.04284 196.76837 207.15928 217.98301 229.467275 241.17764 253.42257
263.81348 275.950205 285.804935 291.993615 295.246225 291.547875 285.05719 276.234445 263.970135
248.47421 231.321295 211.831475 192.180155 170.95421 150.42756 130.877985 111.446305 94.93293
79.66795 65.967905 54.149335 42.66507 32.902395 22.72951 14.704575 7.33533 0
0
174.408695 178.239475 186.19658 194.864285 204.22321 213.691955 223.51923 233.569375 244.72418
253.19324 263.492095 271.65269 277.710555 277.952805 274.50478 266.75601 256.42324 244.98904
228.485355 213.30274 193.830685 176.185195 156.010615 137.987215 119.747405 102.363545 86.54785
72.43275 60.16521 49.04432 38.231895 29.352625 20.40714 13.041125 6.49876 0
0
174.408695 177.793735 184.86259 192.27221 200.81556 208.96162 217.803745 225.99018 235.68664
243.634055 251.5847 258.98463 262.4052 263.482405 259.29148 250.31531 239.044225 227.254725
210.89639 196.811975 177.61447 159.721885 141.88744 125.748745 109.088405 93.76367 79.11885
66.058345 54.20909 44.43834 34.35751 26.322885 18.131605 11.510105 5.75909 0
0
174.408695 177.590245 183.833835 190.342285 197.826195 204.557515 212.002665 218.966545 228.04123
234.221835 240.33784 246.4167 249.464205 248.98778 244.144395 236.51675 223.514385 211.553695
195.529665 180.51178 162.489995 146.727595 129.301745 114.02223 98.658735 85.464185 71.749605
60.57542 49.116995 40.008395 30.8465 23.545085 16.2469 10.22618 5.11309 0
0
174.408695 177.154195 182.46916 188.09905 194.67533 200.503865 206.673165 213.485235 219.71752
225.174605 229.85972 234.325195 236.8236 236.45215 231.15818 224.464005 210.445805 197.648545
182.80831 167.0556 149.79448 134.86542 118.41826 104.31608 90.525595 78.009345 66.00505
55.564075 45.39765 36.684725 28.412695 21.406825 14.77725 9.226495 4.626975 0
0
174.408695 176.256255 181.094795 186.272485 191.61006 196.479285 201.770025 207.416065 212.11733
216.90096 220.187485 223.614515 225.177835 224.51084 220.113195 212.525925 200.513555 186.007625
172.38833 157.23317 140.03019 126.4222 110.454695 97.357045 84.34499 72.57164 61.1116
51.357 42.08367 34.126565 26.351955 19.610945 13.566 8.45937 4.23776 0
0
174.408695 175.73138 179.76242 184.66233 188.632 192.645275 196.97832 201.495475 204.793305
209.286235 211.834705 213.62574 214.19422 213.265595 210.22778 203.685415 192.11071 177.603165
163.5026 151.472465 134.812125 121.074935 105.02345 92.340855 79.721245 69.084855 57.55537
48.4177 39.81298 32.178875 24.714345 18.496595 12.67775 7.94903 3.96321 0
0
174.408695 175.613485 178.6836 182.267285 185.820285 189.315145 192.125245 195.97702 199.305535
202.393415 204.48807 205.019405 205.41508 205.3634 202.38857 196.944405 185.96402 173.59958
160.138555 148.16979 132.954875 119.311355 103.600635 90.74685 77.9399 66.67689 55.974285
46.920595 37.860445 30.55903 23.590305 17.731085 12.2417 7.621185 3.806555 0
0
174.408695 175.10799 177.76305 180.836395 183.66103 186.15136 188.46081 191.488935 194.10685
197.357845 198.94539 199.118195 199.760965 199.518715 196.76514 191.34843 182.335115 171.995885
160.36627 147.55286 134.4326 120.79231 105.412665 92.05177 79.175375 67.402025 56.626745
46.99327 38.238355 30.328085 23.34321 17.3451 11.91224 7.437075 3.70804 0
0
174.408695 174.828595 176.863495 179.45557 181.78763 183.617425 185.55704 188.145885 190.55708
193.097475 195.229275 195.63141 196.17405 195.445685 192.54353 189.00022 180.035355 172.041105
161.233525 149.59099 136.47719 124.091755 109.01896 96.05374 82.159895 70.493135 59.00564
48.887665 38.78261 31.019305 23.80187 17.391935 12.139955 7.395085 3.74357 0
0
174.408695 174.440995 175.96394 178.01822 179.80118 181.82639 183.8839 185.306715 187.88587
190.261535 193.25413 193.7354 195.287415 193.26059 191.921755 188.149115 180.84447 173.081165
162.91474 152.118465 140.422635 127.951605 114.760285 101.18621 88.103095 76.126255 62.618395
51.65093 40.43314 32.382365 23.92784 17.72624 11.936465 7.340175 3.68543 0
0
174.408695 174.024325 175.10476 176.50981 178.92585 180.594145 182.984345 184.35871 187.919785
189.289305 192.222145 193.940505 195.41177 192.7018 192.68888 188.04091 183.685255 172.364105
164.502285 153.76738 145.487275 132.864435 119.589135 106.14426 95.835715 81.85143 68.9282
55.98559 43.85694 34.32844 25.424945 18.163905 12.030135 7.330485 3.606295 0
0
174.408695 173.61896 174.54274 176.065685 178.006915 179.854475 183.016645 185.05962 188.413975
189.49764 192.212455 194.786765 194.56874 191.93629 189.91431 183.37356 177.880945 166.09629
158.64468 150.2596 143.726925 132.08439 121.730625 108.846155 99.198145 83.61501 71.50251
56.894835 47.311425 35.25868 26.67657 18.37547 12.275615 7.330485 3.61114 0
0
174.408695 173.756235 174.45553 175.49882 177.14612 180.154865 183.8839 185.736305 190.18563
191.53577 191.908835 191.818395 188.56094 185.60872 178.313765 171.340195 161.23837 153.355555
145.84096 137.832175 129.3292 118.24707 110.286735 99.595435 90.012025 75.26546 66.239225
53.54371 45.03589 34.38658 26.439165 18.10738 12.74558 7.40962 3.75649 0
0
174.408695 173.585045 173.95811 174.99171 177.44005 181.33543 185.490825 187.7922 191.614905
192.083255 188.82903 186.149745 178.67391 172.028185 160.942825 150.82485 141.67103 133.22135
124.178965 116.11527 106.610995 96.239465 88.77009 81.032625 71.487975 62.754055 53.984605
45.586605 38.183445 29.691775 23.7405 17.04794 12.198095 7.2352 3.70804 0
0
174.408695 173.265275 173.491375 174.689705 177.935855 182.661345 187.66623 189.744735 192.267365
190.04674 180.955905 174.47168 164.38762 153.798065 141.520835 131.0411 121.204135 113.80259
102.489515 94.524335 86.759415 76.943445 68.85391 63.267625 54.02175 49.41577 41.85111
36.145315 29.59326 24.6126 19.604485 14.759485 10.36184 6.42124 3.254225 0
0
174.408695 173.236205 173.774 175.20812 178.942 184.40393 189.163335 190.901075 189.825485
182.373875 171.369265 160.85723 148.17302 135.180345 123.28264 112.244115 103.4892 95.092815
85.105655 77.379495 68.810305 63.206255 55.62383 50.347625 43.370825 38.852055 32.621385
28.745385 23.52086 19.62548 15.68165 12.06728 8.328555 5.35211 2.73258 0
0
174.408695 173.239435 173.891895 175.91226 179.90454 185.797675 190.46987 190.14041 185.81544
173.213595 160.513235 146.33515 132.166755 120.306195 107.38458 97.973975 89.366025 80.89858
72.179195 66.06642 57.84607 52.87833 46.54107 42.19026 36.4021 32.27416 27.53575
23.8374 19.94202 16.781465 13.02336 10.105055 7.106 4.59629 0 0
0
174.408695 173.20552 173.711015 176.71653 181.104485 187.09452 190.474715 187.0816 178.90647
164.02909 146.5774 131.882515 118.54423 107.00021 95.40774 86.281375 77.637895 70.993785
62.77828 57.305045 50.88542 45.589835 40.631785 36.048415 31.555485 27.818375 23.79218
20.70107 17.61965 14.63836 11.52787 8.880885 6.29204 4.06011 0 0
0
174.408695 173.065015 173.988795 177.33023 182.373875 187.4369 188.785425 182.138085 170.57953
152.97926 133.791445 118.523235 106.14749 95.951995 85.415735 76.97736 69.25443 62.770205
55.66259 50.52689 44.59661 39.808135 35.03258 31.59263 27.611655 24.178165 20.91748
18.173595 15.224605 12.766575 10.14543 7.844055 5.5879 3.635365 0 0
0
174.408695 172.98911 174.14545 178.15388 182.761475 187.45305 186.065765 176.462975 160.29521
141.369025 122.00033 107.53639 95.81795 86.152175 77.279365 70.12976 62.579635 56.000125
49.375395 44.746805 39.41246 35.19731 31.025765 27.695635 24.036045 21.284085 18.52082
16.057945 13.57246 11.274315 8.977785 6.984875 5.001655 3.33336 0 0
0
174.408695 172.806615 174.45876 178.895165 183.724015 187.5984 182.0751 169.398965 150.803855
130.74071 112.386235 98.88322 87.615365 78.43409 70.72731 64.033135 56.70588 50.386385
44.19609 39.87435 35.063265 31.368145 27.682715 24.426875 21.60224 19.40907 16.75401
14.69973 12.391895 10.50719 8.43676 6.535905 4.743255 3.17509 0 0
0
174.408695 172.53045 174.86897 179.73335 184.53636 185.84774 177.2947 161.223835 140.929745
120.923125 103.36 91.22166 80.073315 72.41014 64.588695 58.03018 50.86927 45.45902
39.9228 35.454095 31.28901 28.050935 24.86131 22.349985 20.00339 18.15906 15.883525
13.86962 11.888015 9.911255 8.076615 6.232285 4.55753 3.050735 0 0
0
174.408695 172.59505 175.206505 180.846085 184.73985 182.926205 171.92967 152.75962 130.564675
111.436615 95.987525 83.76682 74.78419 67.043495 58.480765 52.46489 45.98874 41.200265
35.935365 32.256395 28.645255 25.93367 23.283455 21.15973 19.152285 17.159375 15.273055
13.322135 11.371215 9.52204 7.74554 6.00457 4.429945 2.96837 0 0
0
174.408695 172.65319 175.79921 181.81347 184.10354 179.8787 166.0866 144.311555 121.771
103.31155 89.721325 78.138545 70.134605 61.927175 54.165485 48.031715 41.86403 37.450235
33.034825 29.79998 26.809 24.56092 22.301535 20.47497 18.580575 16.62158 14.68358
12.834405 10.964235 9.239415 7.521055 5.8463 4.300745 2.91669 0 0
0
174.408695 172.54983 176.288555 182.402945 183.501145 176.62932 159.27776 135.890945 113.87365
96.914535 83.396985 73.513185 65.93399 57.41325 49.785605 43.77942 38.499985 34.433415
30.7819 28.15914 25.65266 23.68236 21.48596 19.64809 17.85544 15.990115 14.139325
12.404815 10.615395 8.90834 7.24166 5.676725 4.207075 2.866625 0 0
0
174.408695 172.6112 176.75206 182.687185 182.399715 172.335035 152.725705 128.623445 106.87747
91.30887 77.97543 69.29642 61.817355 53.01722 45.56561 40.444445 35.609135 32.146575
29.349395 27.07709 24.817705 22.78119 20.77213 19.09576 17.25466 15.450705 13.606375
11.907395 10.25848 8.680625 7.12861 5.586285 4.168315 2.84563 0 0
0
174.408695 172.65319 177.25271 182.793775 180.37289 168.55432 146.091285 121.685405 100.83414
86.28945 74.537095 66.0212 57.721715 49.23812 42.501955 37.76193 33.60492 30.625245
28.325485 26.255055 24.032815 22.38713 20.347385 18.635485 16.61835 14.885455 13.263995
11.68291 10.13897 8.580495 7.085005 5.54591 4.148935 2.83917 0 0
0
174.408695 172.829225 177.63385 182.6565 177.72106 163.88374 140.047955 115.761585 95.45942
81.27972 71.46698 62.38745 53.858635 46.13732 39.93572 35.57845 32.14173 29.65463
27.70694 25.53638 23.709815 21.804115 19.872575 18.01694 16.24367 14.659355 13.131565
11.59893 10.0776 8.538505 7.04786 5.531375 4.148935 2.85855 0 0
0
174.408695 172.39802 178.06021 182.82123 175.63448 159.2067 134.075685 110.622655 91.1506
77.954435 68.312885 58.95719 50.370235 43.374055 37.750625 33.890775 31.080675 29.097455
26.881675 24.97436 23.196245 21.27924 19.355775 17.68102 16.07248 14.55438 13.054045
11.542405 10.050145 8.50459 7.03171 5.51361 4.14732 2.86178 0 0
0
174.408695 172.6758 178.2637 181.937825 173.00526 154.634635 128.86408 106.006985 87.4684
75.36236 65.722425 56.02112 47.76201 41.135665 36.129165 32.883015 30.466975 28.41431
26.435935 24.55446 22.48726 20.64939 19.05054 17.49368 15.99173 14.44456 13.02013
11.51495 10.02915 8.490055 7.03171 5.51361 4.148935 2.86178 0 0
0
174.408695 172.515915 178.862865 181.262755 170.42772 149.673355 123.88019 101.937185 84.398285
73.20472 63.22402 53.49849 45.563995 39.003865 34.850085 32.140115 29.83228 28.13007
25.880375 24.04412 21.968845 20.298935 18.78245 17.330565 15.93036 14.43487 13.0492
11.53433 10.04207 8.49813 7.039785 5.534605 4.15701 2.882775 0 0
0
174.408695 172.59182 179.02598 180.31475 167.93739 145.270865 119.443785 98.58606 82.00001
71.45083 60.47529 51.22457 43.32076 37.60043 33.96345 31.77674 29.41238 27.715015
25.70111 23.40781 21.67976 20.166505 18.69847 17.31603 15.977195 14.468785 13.070195
11.55694 10.069525 8.53689 7.065625 5.56529 4.19577 2.908615 0 0
0
174.408695 172.767855 179.47818 179.489485 165.471285 141.220445 115.71152 95.709745 79.947345
69.614575 58.067325 49.042705 41.78974 36.591055 33.50156 31.28578 29.220195 27.495375
25.211765 23.141335 21.545715 20.10675 18.75338 17.35156 16.03372 14.51562 13.118645
11.60539 10.11636 8.599875 7.130225 5.625045 4.232915 2.934455 0 0
0
174.408695 172.909975 179.447495 178.6513 163.139225 137.88547 112.179515 93.27917 78.199915
67.78155 56.080875 47.405095 40.680235 35.912755 33.0752 30.867495 28.96341 27.091625
24.859695 22.966915 21.46335 20.143895 18.813135 17.47753 16.15646 14.64805 13.24623
11.67968 10.21972 8.680625 7.18029 5.67834 4.278135 2.969985 0 0
0
174.408695 173.139305 179.970755 177.85026 160.4341 135.02692 109.924975 91.110225 77.014505
65.945295 54.485255 46.096945 39.66117 35.463785 32.82972 30.54611 28.787375 26.823535
24.42526 22.831255 21.458505 20.237565 18.890655 17.64872 16.264665 14.79986 13.338285
11.797575 10.29401 8.751685 7.23843 5.73325 4.307205 2.995825 0 0
0
174.408695 173.071475 180.19847 176.521115 158.25385 132.2362 107.44918 89.33857 75.993825
64.449805 52.99784 44.927685 38.7923 35.16824 32.744125 30.6527 28.819675 26.41817
24.320285 22.85548 21.52472 20.32316 19.0247 17.766615 16.35672 14.91291 13.409345
11.894475 10.373145 8.825975 7.307875 5.76878 4.33466 3.01682 0 0
0
174.408695 172.867985 180.46333 175.94456 156.314235 129.686115 105.2657 87.72357 75.150795
63.254705 51.894795 44.181555 38.31103 35.29098 32.602005 30.88526 28.729235 26.054795
24.36066 22.966915 21.642615 20.437825 19.152285 17.882895 16.41163 15.00012 13.4691
11.99622 10.42321 8.88573 7.34502 5.815615 4.36696 3.03297 0 0
0
174.408695 172.968115 180.125795 174.931955 154.44568 127.386355 103.58287 86.03751 74.07359
62.411675 51.384455 43.42735 38.13338 35.23607 32.63592 30.9111 28.44015 26.038645
24.47371 23.067045 21.771815 20.567025 19.29925 17.957185 16.54406 15.085715 13.56277
12.09312 10.51042 8.96971 7.391855 5.860835 4.394415 3.05235 0 0
0
174.408695 173.28627 180.15971 173.8063 152.98249 125.438665 102.208505 85.024905 73.51157
61.80282 51.17612 43.06236 38.105925 35.16501 32.92339 30.83035 28.319025 25.980505
24.517315 23.154255 21.952695 20.641315 19.400995 18.008865 16.661955 15.13901 13.658055
12.17064 10.60086 9.044 7.472605 5.902825 4.426715 3.07496 0 0
0
174.408695 173.00526 180.31475 173.14738 151.5516 123.797825 101.15068 84.252935 72.912405
61.75114 50.996855 42.608545 37.8233 34.969595 32.74897 30.73668 28.134915 25.88845
24.568995 23.21724 22.05121 20.757595 19.48659 18.08477 16.72817 15.23591 13.780795
12.22232 10.670305 9.090835 7.537205 5.93674 4.47032 3.086265 0 0
0
174.408695 173.44131 179.99821 172.276895 149.95275 122.51713 100.154225 83.836265 72.550645
61.232725 50.61087 42.136965 37.55844 34.940525 32.602005 30.79159 28.012175 25.941745
24.656205 23.286685 22.16426 20.83027 19.578645 18.13322 16.823455 15.31343 13.884155
12.285305 10.757515 9.161895 7.60665 5.9755 4.488085 3.09757 0 0
0
174.408695 173.22813 180.219465 171.378955 148.47341 121.071705 99.278895 83.151505 72.38107
61.003395 50.43645 41.927015 37.398555 34.830705 32.640765 30.69469 27.97826 25.86261
24.649745 23.341595 22.18364 20.951395 19.62548 18.26565 16.849295 15.399025 13.9213
12.36444 10.812425 9.21519 7.634105 6.01103 4.51231 3.11049 0 0
0
174.408695 173.55113 180.193625 170.946135 147.2557 119.82331 98.89614 82.822045 71.756065
60.55281 50.08115 41.755825 37.556825 34.884 32.91047 30.521885 27.805455 25.896525
24.48986 23.396505 22.188485 21.035375 19.659395 18.28503 16.87998 15.44586 13.96329
12.39351 10.81404 9.249105 7.653485 6.03364 4.51231 3.12018 0 0
0
174.408695 173.139305 180.642595 170.65382 146.259245 118.99643 98.4827 82.53619 71.355545
60.18136 50.01655 41.97385 37.679565 35.10687 33.060665 30.431445 27.847445 25.91752
24.43818 23.41427 22.236935 21.05637 19.71592 18.318945 16.942965 15.44909 13.964905
12.427425 10.835035 9.255565 7.66479 6.038485 4.522 3.121795 0 0
0
174.408695 173.50591 180.703965 170.3179 145.79574 118.22123 98.6119 82.14536 70.777375
59.55151 50.024625 42.02553 37.640805 34.969595 32.83941 30.499275 27.695635 25.873915
24.50278 23.377125 22.356445 21.09836 19.762755 18.34963 16.942965 15.470085 14.003665
12.443575 10.86249 9.27656 7.679325 6.06917 4.53815 3.12664 0 0
0
174.408695 173.89351 180.962365 169.941605 145.24018 117.70443 98.65389 81.82882 70.26865
59.369015 50.176435 42.107895 37.73609 34.80325 32.844255 30.525115 27.50668 25.780245
24.48017 23.40135 22.40651 21.103205 19.80959 18.357705 16.99626 15.50077 14.029505
12.44842 10.886715 9.30563 7.70678 6.07886 4.54138 3.131485 0 0
0
174.408695 173.807915 180.787945 170.032045 145.329005 117.612375 98.72172 81.55104 70.476985
59.446535 50.31371 41.962545 37.8233 34.859775 32.76512 30.418525 27.43239 25.70434
24.40911 23.42396 22.333835 21.112895 19.76437 18.377085 17.01887 15.518535 14.00851
12.462955 10.87541 9.310475 7.705165 6.06917 4.54784 3.131485 0 0
0
IESNA:LM-63-2002
[TEST] 5890_0
[TESTLAB] ERCO GmbH
[ISSUEDATE] 02-12-2008
[MANUFAC] ERCO GmbH
[LUMCAT] 33519000
[LUMINAIRE] Kubus Floor washlight
[LAMP] HIT-TC-CE 20W
TILT=NONE
1 1615 1 37 73 1 2 0.103 0.059 0
1.0 1.0 24
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30
32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5
65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30
32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5
65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95
97.5 100 102.5 105 107.5 110 112.5 115 117.5 120 122.5 125 127.5
130 132.5 135 137.5 140 142.5 145 147.5 150 152.5 155 157.5 160
162.5 165 167.5 170 172.5 175 177.5 180
174.408695 186.514735 207.74714 232.0109 259.393225 290.905105 329.41801 371.299805 413.25912
451.245535 487.59757 510.86326 514.272525 504.50339 491.06659 481.24739 473.75702 470.79188
471.491175 465.94688 448.826265 421.89291 385.692685 336.53693 275.843615 220.833485 172.667725
138.452335 109.86845 87.28106 67.431095 50.761065 36.44086 23.40458 12.382205 3.77264
0
174.408695 186.24503 208.21226 231.893005 258.99432 290.456135 328.705795 370.82015 411.190305
451.636365 486.478375 509.308015 514.198235 503.661975 490.829185 481.08266 472.12264 470.44627
469.93593 463.828 448.5824 424.378395 389.798015 336.6629 278.547125 220.067975 173.953265
138.071195 110.2722 87.81078 67.763785 50.964555 36.345575 23.34321 12.27077 3.75649
0
174.408695 186.0157 207.63086 230.823875 258.333785 290.4416 328.276205 369.71872 411.584365
449.65153 484.175385 507.77215 512.935305 503.86708 488.84435 479.21249 469.905245 467.854195
466.145525 462.72011 447.43575 420.92068 387.178485 339.510145 278.682785 222.855465 176.492045
140.47916 111.16368 87.650895 68.65688 51.0017 36.442475 23.260845 12.34506 3.72096
0
174.408695 185.77345 207.59856 230.94177 258.35478 288.73293 327.291055 368.62052 409.81917
449.25424 483.86692 504.188465 511.136195 501.5544 486.959645 476.44115 467.35193 462.392265
461.99982 458.337 441.14371 417.88771 386.903935 340.17714 282.22448 226.653945 178.465575
140.67942 111.313875 88.38249 68.78285 51.319855 36.348805 23.29153 12.31599 3.74357
0
174.408695 185.81867 206.934795 230.462115 258.078615 287.920585 325.67121 366.390205 407.695445
447.705455 480.947 502.689745 508.27926 499.385455 486.3088 474.42886 464.59028 457.1419
454.82276 449.010375 435.418535 415.26818 383.87258 338.59121 284.75034 231.444035 182.480465
144.773445 114.2774 89.45808 68.965345 51.22134 36.58298 23.16556 12.336985 3.74034
0
174.408695 185.96079 206.6231 229.86618 257.293725 285.88084 323.179265 363.877265 405.780055
444.85175 477.25511 499.88772 505.199455 498.019165 484.188305 472.73311 459.288235 450.66575
446.08238 437.337155 424.565735 406.19834 378.51401 336.5983 285.727415 230.462115 184.02602
145.044765 114.05776 89.47746 68.874905 51.26979 36.290665 23.170405 12.16418 3.741955
0
174.408695 185.080615 205.778455 229.060295 256.58797 284.425725 320.876275 361.193135 402.785845
439.17018 474.37718 496.98718 502.315065 496.097315 482.618525 467.20335 455.396085 444.68379
436.20181 425.79475 415.253645 395.80743 367.84209 328.870525 279.27226 228.09291 181.41941
142.81122 111.34133 88.20161 67.660425 50.496205 35.347505 22.71013 11.8541 3.64667
0
174.408695 185.16944 205.778455 228.01862 254.89545 283.282305 317.630125 357.39304 399.119795
435.883655 468.8991 491.830485 500.61447 494.71003 479.5581 463.735945 448.241635 437.19019
426.04023 416.629625 404.18282 382.9488 355.27093 319.555205 273.821635 224.84676 178.866095
142.686865 109.811925 86.98713 66.442715 49.49329 34.44472 22.05767 11.51172 3.596605
0
174.408695 184.83352 204.96934 227.102915 252.97683 281.0746 314.581005 353.40722 394.09553
431.413335 463.55668 487.50713 496.41224 491.533325 477.0064 460.560855 444.61273 429.75796
418.42389 407.062365 392.67433 372.40285 342.278255 310.327095 271.008305 225.303805 181.03181
143.474985 111.09908 86.539775 65.80479 49.13476 34.26384 21.964 11.471345 3.561075
0
174.408695 184.61388 204.66895 225.662335 251.44581 279.35301 311.732145 348.838385 389.20854
425.237575 458.577635 478.813585 491.26685 487.78168 473.40172 459.32861 439.76773 423.69848
410.85277 395.89464 383.12968 362.301025 335.831175 306.092565 270.66108 227.96371 185.74438
147.867785 115.01707 90.105695 67.922055 50.4203 35.024505 22.307995 11.5957 3.632135
0
174.408695 184.3684 203.498075 224.45916 249.356 276.85622 307.88683 344.129045 382.67102
419.811175 451.79302 472.605525 485.17184 485.580435 472.779945 456.84797 436.20504 418.64999
402.03487 388.609375 373.25557 354.79612 330.240045 302.678455 272.830025 233.504775 195.090385
156.071985 121.898585 94.663225 71.05677 52.58117 36.04034 22.97499 11.89609 3.72419
0
174.408695 183.685255 202.709955 222.878075 247.94126 274.57907 304.72466 339.216215 376.800495
412.563055 445.169905 466.672015 479.269015 481.484795 470.04575 454.24782 433.264125 412.986185
393.296105 376.638995 363.499355 346.72112 324.616615 300.136445 272.33422 237.707005 202.08495
163.588195 129.40995 100.606425 75.519015 54.960065 37.72317 23.732425 12.249775 3.79525
0
174.408695 183.698175 202.34981 221.40681 245.207065 271.96923 300.452985 332.875725 368.97582
404.827205 436.15659 459.50949 472.34551 475.85652 467.62002 451.28914 430.344205 407.524255
386.422665 368.55915 352.41238 336.667745 315.92307 294.106035 269.95048 238.42245 206.09338
169.021055 135.04307 105.23986 79.136615 58.03664 39.594955 24.95175 12.727815 3.94706
0
174.408695 183.362255 201.279065 219.593165 242.287145 267.93496 295.45133 326.92445 361.6631
395.453745 426.23726 450.832095 464.575745 468.219185 463.316045 447.524575 426.09191 402.365945
381.08832 361.018715 341.90519 325.356285 307.681725 286.76263 266.65265 238.2125 207.50812
172.196145 141.26728 110.629115 84.08013 61.09545 42.08367 26.23729 13.39481 4.119865
0
174.408695 182.945585 200.197015 218.37707 239.758055 264.564455 290.078225 319.84106 353.27156
386.06898 417.316 440.39112 455.34279 459.488495 455.677095 442.967045 422.369335 397.143035
372.546585 352.20243 332.633475 315.611375 297.135775 279.874655 259.251105 234.095865 206.73615
174.828595 144.48113 114.372685 88.81208 64.07997 44.720965 27.60681 14.17001 4.349195
0
174.408695 182.40133 199.173105 216.615105 237.471215 259.97624 284.44995 313.453735 345.023755
376.21748 405.19381 429.769265 445.040705 449.74197 448.03653 438.248015 419.145795 394.97409
368.08757 345.46465 323.909245 306.0425 286.615665 269.506355 251.515255 229.3946 204.609195
175.930025 147.56255 118.830085 93.23718 67.569985 48.015565 29.31548 15.28113 4.665735
0
174.408695 182.451395 198.15081 214.48169 234.806465 255.9452 279.306175 306.43979 336.45941
365.60047 394.78998 418.26885 432.44209 438.041295 439.065205 430.508935 413.95034 390.747635
363.189275 340.133535 317.4444 296.87253 277.213135 258.398385 241.721895 219.583475 196.73607
172.06856 147.98568 120.060715 95.751735 70.318715 50.02301 30.76898 16.00465 4.92898
0
174.408695 182.04603 197.529035 213.217145 232.16594 252.60861 274.01382 299.32733 327.76425
354.45051 382.578965 404.51228 419.220085 425.17782 426.267945 419.220085 406.04976 384.66716
358.06488 332.93871 309.041555 288.10631 267.28573 249.26233 230.17626 210.71551 190.364895
168.20871 144.069305 119.61013 96.11188 71.200505 51.47974 31.6217 16.671645 5.033955
0
174.408695 181.676195 196.29679 211.09342 228.63555 248.30625 269.251185 291.64316 317.42825
343.00016 369.3505 390.43271 404.33786 411.280745 412.42901 407.16734 397.54517 377.446495
351.0364 325.69705 300.985935 277.3924 255.271745 236.02902 217.516275 197.474125 178.68037
159.589455 138.03082 116.139495 93.6054 70.66917 51.45713 31.87364 16.852525 5.10986
0
174.408695 181.203 194.80453 209.263625 225.701095 244.48516 263.230465 284.5953 308.511835
332.18612 356.661445 376.949075 388.55931 395.143665 397.201175 392.65172 384.181045 365.81688
343.747905 317.0568 290.56111 265.281515 241.55878 221.750805 201.70381 181.824775 166.181885
148.051895 130.196455 109.337115 89.80692 68.093245 49.762995 30.883645 16.37287 4.90314
0
174.408695 180.62483 193.659495 207.1076 223.297975 239.993845 257.35671 277.717015 299.85059
321.383385 343.19719 361.583965 373.266875 379.119635 380.686185 377.17679 368.61083 353.34908
333.124435 307.584825 281.76259 254.60152 229.619085 208.191265 186.960475 167.83403 150.002815
133.833435 116.81941 99.475925 82.00324 62.52634 45.954825 28.67594 15.095405 4.54138
0
174.408695 180.374505 192.331965 205.481295 219.609315 235.145615 251.65576 271.001845 290.536885
308.931735 328.68803 345.282155 357.617525 362.75807 362.74838 358.896605 350.485685 338.001735
321.325245 297.13739 273.072275 245.37664 218.78728 195.72508 173.753005 154.392385 136.343145
120.936045 104.64231 88.135395 71.281255 56.19877 40.44929 25.74633 13.377045 4.058495
0
174.408695 179.880315 191.446945 203.469005 216.81698 231.182405 246.211595 263.30637 280.77744
297.23752 315.824555 329.794305 340.80699 345.07382 344.1565 340.139995 332.29917 320.785835
303.54571 282.390825 260.29278 235.429855 208.775895 184.379705 161.83269 142.74985 124.689305
109.673035 93.229105 78.34365 62.783125 49.036245 35.114945 22.36452 11.571475 3.490015
0
174.408695 179.17456 190.038665 201.33236 213.33181 226.71047 240.778735 255.6222 271.670455
285.772635 302.394215 315.40627 325.062355 328.29397 326.34305 322.249025 313.67822 302.148735
286.48808 267.7347 245.39602 222.196545 197.21088 173.517215 152.102315 131.985875 113.29548
97.783405 82.02585 68.332265 54.188095 42.4422 29.99055 19.28956 9.824045 2.989365
0
174.408695 178.988835 188.701445 198.966385 210.274615 222.206235 234.903365 248.827895 262.73466
274.713115 289.40154 300.36416 308.708865 311.65624 308.628115 304.15618 295.365735 283.45188
267.303495 250.55433 230.18272 207.64055 184.24243 161.705105 141.608045 121.21867 103.57964
88.16931 72.57164 60.15875 47.1903 36.6605 25.64297 16.55052 8.299485 2.57108
0
174.408695 178.69652 187.04284 196.76837 207.15928 217.98301 229.467275 241.17764 253.42257
263.81348 275.950205 285.804935 291.993615 295.246225 291.547875 285.05719 276.234445 263.970135
248.47421 231.321295 211.831475 192.180155 170.95421 150.42756 130.877985 111.446305 94.93293
79.66795 65.967905 54.149335 42.66507 32.902395 22.72951 14.704575 7.33533 0
0
174.408695 178.239475 186.19658 194.864285 204.22321 213.691955 223.51923 233.569375 244.72418
253.19324 263.492095 271.65269 277.710555 277.952805 274.50478 266.75601 256.42324 244.98904
228.485355 213.30274 193.830685 176.185195 156.010615 137.987215 119.747405 102.363545 86.54785
72.43275 60.16521 49.04432 38.231895 29.352625 20.40714 13.041125 6.49876 0
0
174.408695 177.793735 184.86259 192.27221 200.81556 208.96162 217.803745 225.99018 235.68664
243.634055 251.5847 258.98463 262.4052 263.482405 259.29148 250.31531 239.044225 227.254725
210.89639 196.811975 177.61447 159.721885 141.88744 125.748745 109.088405 93.76367 79.11885
66.058345 54.20909 44.43834 34.35751 26.322885 18.131605 11.510105 5.75909 0
0
174.408695 177.590245 183.833835 190.342285 197.826195 204.557515 212.002665 218.966545 228.04123
234.221835 240.33784 246.4167 249.464205 248.98778 244.144395 236.51675 223.514385 211.553695
195.529665 180.51178 162.489995 146.727595 129.301745 114.02223 98.658735 85.464185 71.749605
60.57542 49.116995 40.008395 30.8465 23.545085 16.2469 10.22618 5.11309 0
0
174.408695 177.154195 182.46916 188.09905 194.67533 200.503865 206.673165 213.485235 219.71752
225.174605 229.85972 234.325195 236.8236 236.45215 231.15818 224.464005 210.445805 197.648545
182.80831 167.0556 149.79448 134.86542 118.41826 104.31608 90.525595 78.009345 66.00505
55.564075 45.39765 36.684725 28.412695 21.406825 14.77725 9.226495 4.626975 0
0
174.408695 176.256255 181.094795 186.272485 191.61006 196.479285 201.770025 207.416065 212.11733
216.90096 220.187485 223.614515 225.177835 224.51084 220.113195 212.525925 200.513555 186.007625
172.38833 157.23317 140.03019 126.4222 110.454695 97.357045 84.34499 72.57164 61.1116
51.357 42.08367 34.126565 26.351955 19.610945 13.566 8.45937 4.23776 0
0
174.408695 175.73138 179.76242 184.66233 188.632 192.645275 196.97832 201.495475 204.793305
209.286235 211.834705 213.62574 214.19422 213.265595 210.22778 203.685415 192.11071 177.603165
163.5026 151.472465 134.812125 121.074935 105.02345 92.340855 79.721245 69.084855 57.55537
48.4177 39.81298 32.178875 24.714345 18.496595 12.67775 7.94903 3.96321 0
0
174.408695 175.613485 178.6836 182.267285 185.820285 189.315145 192.125245 195.97702 199.305535
202.393415 204.48807 205.019405 205.41508 205.3634 202.38857 196.944405 185.96402 173.59958
160.138555 148.16979 132.954875 119.311355 103.600635 90.74685 77.9399 66.67689 55.974285
46.920595 37.860445 30.55903 23.590305 17.731085 12.2417 7.621185 3.806555 0
0
174.408695 175.10799 177.76305 180.836395 183.66103 186.15136 188.46081 191.488935 194.10685
197.357845 198.94539 199.118195 199.760965 199.518715 196.76514 191.34843 182.335115 171.995885
160.36627 147.55286 134.4326 120.79231 105.412665 92.05177 79.175375 67.402025 56.626745
46.99327 38.238355 30.328085 23.34321 17.3451 11.91224 7.437075 3.70804 0
0
174.408695 174.828595 176.863495 179.45557 181.78763 183.617425 185.55704 188.145885 190.55708
193.097475 195.229275 195.63141 196.17405 195.445685 192.54353 189.00022 180.035355 172.041105
161.233525 149.59099 136.47719 124.091755 109.01896 96.05374 82.159895 70.493135 59.00564
48.887665 38.78261 31.019305 23.80187 17.391935 12.139955 7.395085 3.74357 0
0
174.408695 174.440995 175.96394 178.01822 179.80118 181.82639 183.8839 185.306715 187.88587
190.261535 193.25413 193.7354 195.287415 193.26059 191.921755 188.149115 180.84447 173.081165
162.91474 152.118465 140.422635 127.951605 114.760285 101.18621 88.103095 76.126255 62.618395
51.65093 40.43314 32.382365 23.92784 17.72624 11.936465 7.340175 3.68543 0
0
174.408695 174.024325 175.10476 176.50981 178.92585 180.594145 182.984345 184.35871 187.919785
189.289305 192.222145 193.940505 195.41177 192.7018 192.68888 188.04091 183.685255 172.364105
164.502285 153.76738 145.487275 132.864435 119.589135 106.14426 95.835715 81.85143 68.9282
55.98559 43.85694 34.32844 25.424945 18.163905 12.030135 7.330485 3.606295 0
0
174.408695 173.61896 174.54274 176.065685 178.006915 179.854475 183.016645 185.05962 188.413975
189.49764 192.212455 194.786765 194.56874 191.93629 189.91431 183.37356 177.880945 166.09629
158.64468 150.2596 143.726925 132.08439 121.730625 108.846155 99.198145 83.61501 71.50251
56.894835 47.311425 35.25868 26.67657 18.37547 12.275615 7.330485 3.61114 0
0
174.408695 173.756235 174.45553 175.49882 177.14612 180.154865 183.8839 185.736305 190.18563
191.53577 191.908835 191.818395 188.56094 185.60872 178.313765 171.340195 161.23837 153.355555
145.84096 137.832175 129.3292 118.24707 110.286735 99.595435 90.012025 75.26546 66.239225
53.54371 45.03589 34.38658 26.439165 18.10738 12.74558 7.40962 3.75649 0
0
174.408695 173.585045 173.95811 174.99171 177.44005 181.33543 185.490825 187.7922 191.614905
192.083255 188.82903 186.149745 178.67391 172.028185 160.942825 150.82485 141.67103 133.22135
124.178965 116.11527 106.610995 96.239465 88.77009 81.032625 71.487975 62.754055 53.984605
45.586605 38.183445 29.691775 23.7405 17.04794 12.198095 7.2352 3.70804 0
0
174.408695 173.265275 173.491375 174.689705 177.935855 182.661345 187.66623 189.744735 192.267365
190.04674 180.955905 174.47168 164.38762 153.798065 141.520835 131.0411 121.204135 113.80259
102.489515 94.524335 86.759415 76.943445 68.85391 63.267625 54.02175 49.41577 41.85111
36.145315 29.59326 24.6126 19.604485 14.759485 10.36184 6.42124 3.254225 0
0
174.408695 173.236205 173.774 175.20812 178.942 184.40393 189.163335 190.901075 189.825485
182.373875 171.369265 160.85723 148.17302 135.180345 123.28264 112.244115 103.4892 95.092815
85.105655 77.379495 68.810305 63.206255 55.62383 50.347625 43.370825 38.852055 32.621385
28.745385 23.52086 19.62548 15.68165 12.06728 8.328555 5.35211 2.73258 0
0
174.408695 173.239435 173.891895 175.91226 179.90454 185.797675 190.46987 190.14041 185.81544
173.213595 160.513235 146.33515 132.166755 120.306195 107.38458 97.973975 89.366025 80.89858
72.179195 66.06642 57.84607 52.87833 46.54107 42.19026 36.4021 32.27416 27.53575
23.8374 19.94202 16.781465 13.02336 10.105055 7.106 4.59629 0 0
0
174.408695 173.20552 173.711015 176.71653 181.104485 187.09452 190.474715 187.0816 178.90647
164.02909 146.5774 131.882515 118.54423 107.00021 95.40774 86.281375 77.637895 70.993785
62.77828 57.305045 50.88542 45.589835 40.631785 36.048415 31.555485 27.818375 23.79218
20.70107 17.61965 14.63836 11.52787 8.880885 6.29204 4.06011 0 0
0
174.408695 173.065015 173.988795 177.33023 182.373875 187.4369 188.785425 182.138085 170.57953
152.97926 133.791445 118.523235 106.14749 95.951995 85.415735 76.97736 69.25443 62.770205
55.66259 50.52689 44.59661 39.808135 35.03258 31.59263 27.611655 24.178165 20.91748
18.173595 15.224605 12.766575 10.14543 7.844055 5.5879 3.635365 0 0
0
174.408695 172.98911 174.14545 178.15388 182.761475 187.45305 186.065765 176.462975 160.29521
141.369025 122.00033 107.53639 95.81795 86.152175 77.279365 70.12976 62.579635 56.000125
49.375395 44.746805 39.41246 35.19731 31.025765 27.695635 24.036045 21.284085 18.52082
16.057945 13.57246 11.274315 8.977785 6.984875 5.001655 3.33336 0 0
0
174.408695 172.806615 174.45876 178.895165 183.724015 187.5984 182.0751 169.398965 150.803855
130.74071 112.386235 98.88322 87.615365 78.43409 70.72731 64.033135 56.70588 50.386385
44.19609 39.87435 35.063265 31.368145 27.682715 24.426875 21.60224 19.40907 16.75401
14.69973 12.391895 10.50719 8.43676 6.535905 4.743255 3.17509 0 0
0
174.408695 172.53045 174.86897 179.73335 184.53636 185.84774 177.2947 161.223835 140.929745
120.923125 103.36 91.22166 80.073315 72.41014 64.588695 58.03018 50.86927 45.45902
39.9228 35.454095 31.28901 28.050935 24.86131 22.349985 20.00339 18.15906 15.883525
13.86962 11.888015 9.911255 8.076615 6.232285 4.55753 3.050735 0 0
0
174.408695 172.59505 175.206505 180.846085 184.73985 182.926205 171.92967 152.75962 130.564675
111.436615 95.987525 83.76682 74.78419 67.043495 58.480765 52.46489 45.98874 41.200265
35.935365 32.256395 28.645255 25.93367 23.283455 21.15973 19.152285 17.159375 15.273055
13.322135 11.371215 9.52204 7.74554 6.00457 4.429945 2.96837 0 0
0
174.408695 172.65319 175.79921 181.81347 184.10354 179.8787 166.0866 144.311555 121.771
103.31155 89.721325 78.138545 70.134605 61.927175 54.165485 48.031715 41.86403 37.450235
33.034825 29.79998 26.809 24.56092 22.301535 20.47497 18.580575 16.62158 14.68358
12.834405 10.964235 9.239415 7.521055 5.8463 4.300745 2.91669 0 0
0
174.408695 172.54983 176.288555 182.402945 183.501145 176.62932 159.27776 135.890945 113.87365
96.914535 83.396985 73.513185 65.93399 57.41325 49.785605 43.77942 38.499985 34.433415
30.7819 28.15914 25.65266 23.68236 21.48596 19.64809 17.85544 15.990115 14.139325
12.404815 10.615395 8.90834 7.24166 5.676725 4.207075 2.866625 0 0
0
174.408695 172.6112 176.75206 182.687185 182.399715 172.335035 152.725705 128.623445 106.87747
91.30887 77.97543 69.29642 61.817355 53.01722 45.56561 40.444445 35.609135 32.146575
29.349395 27.07709 24.817705 22.78119 20.77213 19.09576 17.25466 15.450705 13.606375
11.907395 10.25848 8.680625 7.12861 5.586285 4.168315 2.84563 0 0
0
174.408695 172.65319 177.25271 182.793775 180.37289 168.55432 146.091285 121.685405 100.83414
86.28945 74.537095 66.0212 57.721715 49.23812 42.501955 37.76193 33.60492 30.625245
28.325485 26.255055 24.032815 22.38713 20.347385 18.635485 16.61835 14.885455 13.263995
11.68291 10.13897 8.580495 7.085005 5.54591 4.148935 2.83917 0 0
0
174.408695 172.829225 177.63385 182.6565 177.72106 163.88374 140.047955 115.761585 95.45942
81.27972 71.46698 62.38745 53.858635 46.13732 39.93572 35.57845 32.14173 29.65463
27.70694 25.53638 23.709815 21.804115 19.872575 18.01694 16.24367 14.659355 13.131565
11.59893 10.0776 8.538505 7.04786 5.531375 4.148935 2.85855 0 0
0
174.408695 172.39802 178.06021 182.82123 175.63448 159.2067 134.075685 110.622655 91.1506
77.954435 68.312885 58.95719 50.370235 43.374055 37.750625 33.890775 31.080675 29.097455
26.881675 24.97436 23.196245 21.27924 19.355775 17.68102 16.07248 14.55438 13.054045
11.542405 10.050145 8.50459 7.03171 5.51361 4.14732 2.86178 0 0
0
174.408695 172.6758 178.2637 181.937825 173.00526 154.634635 128.86408 106.006985 87.4684
75.36236 65.722425 56.02112 47.76201 41.135665 36.129165 32.883015 30.466975 28.41431
26.435935 24.55446 22.48726 20.64939 19.05054 17.49368 15.99173 14.44456 13.02013
11.51495 10.02915 8.490055 7.03171 5.51361 4.148935 2.86178 0 0
0
174.408695 172.515915 178.862865 181.262755 170.42772 149.673355 123.88019 101.937185 84.398285
73.20472 63.22402 53.49849 45.563995 39.003865 34.850085 32.140115 29.83228 28.13007
25.880375 24.04412 21.968845 20.298935 18.78245 17.330565 15.93036 14.43487 13.0492
11.53433 10.04207 8.49813 7.039785 5.534605 4.15701 2.882775 0 0
0
174.408695 172.59182 179.02598 180.31475 167.93739 145.270865 119.443785 98.58606 82.00001
71.45083 60.47529 51.22457 43.32076 37.60043 33.96345 31.77674 29.41238 27.715015
25.70111 23.40781 21.67976 20.166505 18.69847 17.31603 15.977195 14.468785 13.070195
11.55694 10.069525 8.53689 7.065625 5.56529 4.19577 2.908615 0 0
0
174.408695 172.767855 179.47818 179.489485 165.471285 141.220445 115.71152 95.709745 79.947345
69.614575 58.067325 49.042705 41.78974 36.591055 33.50156 31.28578 29.220195 27.495375
25.211765 23.141335 21.545715 20.10675 18.75338 17.35156 16.03372 14.51562 13.118645
11.60539 10.11636 8.599875 7.130225 5.625045 4.232915 2.934455 0 0
0
174.408695 172.909975 179.447495 178.6513 163.139225 137.88547 112.179515 93.27917 78.199915
67.78155 56.080875 47.405095 40.680235 35.912755 33.0752 30.867495 28.96341 27.091625
24.859695 22.966915 21.46335 20.143895 18.813135 17.47753 16.15646 14.64805 13.24623
11.67968 10.21972 8.680625 7.18029 5.67834 4.278135 2.969985 0 0
0
174.408695 173.139305 179.970755 177.85026 160.4341 135.02692 109.924975 91.110225 77.014505
65.945295 54.485255 46.096945 39.66117 35.463785 32.82972 30.54611 28.787375 26.823535
24.42526 22.831255 21.458505 20.237565 18.890655 17.64872 16.264665 14.79986 13.338285
11.797575 10.29401 8.751685 7.23843 5.73325 4.307205 2.995825 0 0
0
174.408695 173.071475 180.19847 176.521115 158.25385 132.2362 107.44918 89.33857 75.993825
64.449805 52.99784 44.927685 38.7923 35.16824 32.744125 30.6527 28.819675 26.41817
24.320285 22.85548 21.52472 20.32316 19.0247 17.766615 16.35672 14.91291 13.409345
11.894475 10.373145 8.825975 7.307875 5.76878 4.33466 3.01682 0 0
0
174.408695 172.867985 180.46333 175.94456 156.314235 129.686115 105.2657 87.72357 75.150795
63.254705 51.894795 44.181555 38.31103 35.29098 32.602005 30.88526 28.729235 26.054795
24.36066 22.966915 21.642615 20.437825 19.152285 17.882895 16.41163 15.00012 13.4691
11.99622 10.42321 8.88573 7.34502 5.815615 4.36696 3.03297 0 0
0
174.408695 172.968115 180.125795 174.931955 154.44568 127.386355 103.58287 86.03751 74.07359
62.411675 51.384455 43.42735 38.13338 35.23607 32.63592 30.9111 28.44015 26.038645
24.47371 23.067045 21.771815 20.567025 19.29925 17.957185 16.54406 15.085715 13.56277
12.09312 10.51042 8.96971 7.391855 5.860835 4.394415 3.05235 0 0
0
174.408695 173.28627 180.15971 173.8063 152.98249 125.438665 102.208505 85.024905 73.51157
61.80282 51.17612 43.06236 38.105925 35.16501 32.92339 30.83035 28.319025 25.980505
24.517315 23.154255 21.952695 20.641315 19.400995 18.008865 16.661955 15.13901 13.658055
12.17064 10.60086 9.044 7.472605 5.902825 4.426715 3.07496 0 0
0
174.408695 173.00526 180.31475 173.14738 151.5516 123.797825 101.15068 84.252935 72.912405
61.75114 50.996855 42.608545 37.8233 34.969595 32.74897 30.73668 28.134915 25.88845
24.568995 23.21724 22.05121 20.757595 19.48659 18.08477 16.72817 15.23591 13.780795
12.22232 10.670305 9.090835 7.537205 5.93674 4.47032 3.086265 0 0
0
174.408695 173.44131 179.99821 172.276895 149.95275 122.51713 100.154225 83.836265 72.550645
61.232725 50.61087 42.136965 37.55844 34.940525 32.602005 30.79159 28.012175 25.941745
24.656205 23.286685 22.16426 20.83027 19.578645 18.13322 16.823455 15.31343 13.884155
12.285305 10.757515 9.161895 7.60665 5.9755 4.488085 3.09757 0 0
0
174.408695 173.22813 180.219465 171.378955 148.47341 121.071705 99.278895 83.151505 72.38107
61.003395 50.43645 41.927015 37.398555 34.830705 32.640765 30.69469 27.97826 25.86261
24.649745 23.341595 22.18364 20.951395 19.62548 18.26565 16.849295 15.399025 13.9213
12.36444 10.812425 9.21519 7.634105 6.01103 4.51231 3.11049 0 0
0
174.408695 173.55113 180.193625 170.946135 147.2557 119.82331 98.89614 82.822045 71.756065
60.55281 50.08115 41.755825 37.556825 34.884 32.91047 30.521885 27.805455 25.896525
24.48986 23.396505 22.188485 21.035375 19.659395 18.28503 16.87998 15.44586 13.96329
12.39351 10.81404 9.249105 7.653485 6.03364 4.51231 3.12018 0 0
0
174.408695 173.139305 180.642595 170.65382 146.259245 118.99643 98.4827 82.53619 71.355545
60.18136 50.01655 41.97385 37.679565 35.10687 33.060665 30.431445 27.847445 25.91752
24.43818 23.41427 22.236935 21.05637 19.71592 18.318945 16.942965 15.44909 13.964905
12.427425 10.835035 9.255565 7.66479 6.038485 4.522 3.121795 0 0
0
174.408695 173.50591 180.703965 170.3179 145.79574 118.22123 98.6119 82.14536 70.777375
59.55151 50.024625 42.02553 37.640805 34.969595 32.83941 30.499275 27.695635 25.873915
24.50278 23.377125 22.356445 21.09836 19.762755 18.34963 16.942965 15.470085 14.003665
12.443575 10.86249 9.27656 7.679325 6.06917 4.53815 3.12664 0 0
0
174.408695 173.89351 180.962365 169.941605 145.24018 117.70443 98.65389 81.82882 70.26865
59.369015 50.176435 42.107895 37.73609 34.80325 32.844255 30.525115 27.50668 25.780245
24.48017 23.40135 22.40651 21.103205 19.80959 18.357705 16.99626 15.50077 14.029505
12.44842 10.886715 9.30563 7.70678 6.07886 4.54138 3.131485 0 0
0
174.408695 173.807915 180.787945 170.032045 145.329005 117.612375 98.72172 81.55104 70.476985
59.446535 50.31371 41.962545 37.8233 34.859775 32.76512 30.418525 27.43239 25.70434
24.40911 23.42396 22.333835 21.112895 19.76437 18.377085 17.01887 15.518535 14.00851
12.462955 10.87541 9.310475 7.705165 6.06917 4.54784 3.131485 0 0
0

View File

@ -1,24 +1,24 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 14061.0
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 8/54W T5HO LAMP 25x48"CABLE MOUNT LUMINAIRE
[MORE] MIRO4 SPECULAR REFLECTOR w/OPEN BOTTOM
[MORE] 2 UNIVERSAL BALLAST #B454PUNV-E WATTS=432
[LUMCAT] HL-4-854T5H-MD-EB4/4-BD-UNV
[LAMPCAT] FP54T5HO/835
TILT=NONE
8 5000. 1.000000 19 5 1 1 2.083 4.000 .000
1.0000 1.0000 432.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0
19229. 19192. 19185. 18789. 18134. 17000. 15662. 14433. 13163. 11892.
10500. 8916. 7319. 5817. 4110. 2580. 1269. 327. 0.
19229. 19239. 19253. 18898. 18188. 16905. 15184. 13505. 11443. 9375.
7606. 5721. 4260. 3031. 2007. 1447. 1037. 396. 0.
19229. 19140. 19267. 18557. 17041. 14788. 12139. 10050. 8097. 6603.
5311. 4123. 3523. 3004. 2621. 1925. 1106. 368. 0.
19229. 19168. 19090. 17820. 15280. 12808. 10091. 8466. 6854. 5739.
4833. 4192. 3919. 3577. 2826. 1898. 1078. 300. 0.
19229. 19182. 18980. 17451. 14652. 12139. 9613. 8042. 6513. 5624.
4861. 4328. 4096. 3686. 2812. 1884. 1065. 259. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 14061.0
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 8/54W T5HO LAMP 25x48"CABLE MOUNT LUMINAIRE
[MORE] MIRO4 SPECULAR REFLECTOR w/OPEN BOTTOM
[MORE] 2 UNIVERSAL BALLAST #B454PUNV-E WATTS=432
[LUMCAT] HL-4-854T5H-MD-EB4/4-BD-UNV
[LAMPCAT] FP54T5HO/835
TILT=NONE
8 5000. 1.000000 19 5 1 1 2.083 4.000 .000
1.0000 1.0000 432.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0
19229. 19192. 19185. 18789. 18134. 17000. 15662. 14433. 13163. 11892.
10500. 8916. 7319. 5817. 4110. 2580. 1269. 327. 0.
19229. 19239. 19253. 18898. 18188. 16905. 15184. 13505. 11443. 9375.
7606. 5721. 4260. 3031. 2007. 1447. 1037. 396. 0.
19229. 19140. 19267. 18557. 17041. 14788. 12139. 10050. 8097. 6603.
5311. 4123. 3523. 3004. 2621. 1925. 1106. 368. 0.
19229. 19168. 19090. 17820. 15280. 12808. 10091. 8466. 6854. 5739.
4833. 4192. 3919. 3577. 2826. 1898. 1078. 300. 0.
19229. 19182. 18980. 17451. 14652. 12139. 9613. 8042. 6513. 5624.
4861. 4328. 4096. 3686. 2812. 1884. 1065. 259. 0.

View File

@ -1,35 +1,35 @@
IESNA:LM-63-2002
[TEST] 3907_1
[TESTLAB] ERCO GmbH
[ISSUEDATE] 02-12-2008
[MANUFAC] ERCO GmbH
[LUMCAT] 81051000
[LUMINAIRE] Lightcast Directional luminaire
[LAMP] HIT-CE 70W
TILT=NONE
1 6600 1 19 7 1 2 -0.127 -0.127 0
1.0 1.0 79
0 5 10 15 20 25 30 35 40 45 50 55 60
65 70 75 80 85 90
0 15 30 45 60 75 90
11501.82 8886.24 4579.74 2596.836 1430.154 810.546 487.8588 266.8446 163.6338
108.933 71.247 41.349 20.0178 10.2234 0 0 0 0
0
11501.82 8992.5 4689.564 2685.144 1510.806 853.512 524.139 292.0962 171.7056
113.3682 72.9366 43.0452 20.4006 10.0782 0 0 0 0
0
11501.82 9288.84 5057.58 2943.864 1719.432 987.162 595.7424 347.8464 193.71
120.1464 74.7186 45.5994 22.1232 9.8736 0 0 0 0
0
11501.82 9724.44 5794.14 3453.186 2080.782 1230.108 722.238 427.614 235.719
138.6726 83.4702 49.1502 24.0768 9.207 0 0 0 0
0
11501.82 10198.32 7048.8 4538.688 2758.668 1656.402 938.916 532.158 289.707
157.3836 89.9844 53.1366 24.783 8.1642 0 0 0 0
0
11501.82 10580.46 8413.02 6409.458 4582.182 2761.044 1490.742 710.754 335.8674
173.3754 96.4194 55.9944 26.4858 8.4678 0 0 0 0
0
11501.82 10746.12 9057.18 7549.74 6203.736 3923.898 1914.198 784.278 360.2148
177.9558 99.2772 57.8556 27.5748 8.976 0 0 0 0
0
IESNA:LM-63-2002
[TEST] 3907_1
[TESTLAB] ERCO GmbH
[ISSUEDATE] 02-12-2008
[MANUFAC] ERCO GmbH
[LUMCAT] 81051000
[LUMINAIRE] Lightcast Directional luminaire
[LAMP] HIT-CE 70W
TILT=NONE
1 6600 1 19 7 1 2 -0.127 -0.127 0
1.0 1.0 79
0 5 10 15 20 25 30 35 40 45 50 55 60
65 70 75 80 85 90
0 15 30 45 60 75 90
11501.82 8886.24 4579.74 2596.836 1430.154 810.546 487.8588 266.8446 163.6338
108.933 71.247 41.349 20.0178 10.2234 0 0 0 0
0
11501.82 8992.5 4689.564 2685.144 1510.806 853.512 524.139 292.0962 171.7056
113.3682 72.9366 43.0452 20.4006 10.0782 0 0 0 0
0
11501.82 9288.84 5057.58 2943.864 1719.432 987.162 595.7424 347.8464 193.71
120.1464 74.7186 45.5994 22.1232 9.8736 0 0 0 0
0
11501.82 9724.44 5794.14 3453.186 2080.782 1230.108 722.238 427.614 235.719
138.6726 83.4702 49.1502 24.0768 9.207 0 0 0 0
0
11501.82 10198.32 7048.8 4538.688 2758.668 1656.402 938.916 532.158 289.707
157.3836 89.9844 53.1366 24.783 8.1642 0 0 0 0
0
11501.82 10580.46 8413.02 6409.458 4582.182 2761.044 1490.742 710.754 335.8674
173.3754 96.4194 55.9944 26.4858 8.4678 0 0 0 0
0
11501.82 10746.12 9057.18 7549.74 6203.736 3923.898 1914.198 784.278 360.2148
177.9558 99.2772 57.8556 27.5748 8.976 0 0 0 0
0

View File

@ -1,24 +1,24 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 10495.0
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/150W ICETRON LAMP 2x2 DIRECT RECESSED LUMINAIRE
[LUMINAIRE] SPECULAR REFLECTOR w/PRISMATIC ACRYLIC PAT-12 LENS
[LUMINAIRE] SYLVANIA BALLAST #QT1x150/120-240 ICE WATTS=155
[LUMCAT]CATALOG NO. : MPG-S22-1/150I LER
[LAMPCAT]LAMP CODE : ICE150/835
TILT=NONE
1 12000. 1.000000 19 5 1 1 1.688 1.677 .000
1.0000 1.0000 155.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0
3962. 3933. 3802. 3619. 3384. 3120. 2804. 2463. 2013. 1517.
1089. 770. 568. 415. 333. 270. 189. 79. 0.
3962. 3912. 3776. 3603. 3409. 3178. 2885. 2522. 2071. 1569.
1115. 784. 573. 429. 343. 266. 185. 73. 0.
3962. 3918. 3798. 3612. 3402. 3195. 2919. 2615. 2199. 1693.
1203. 843. 601. 449. 337. 265. 179. 85. 0.
3962. 3901. 3765. 3603. 3418. 3210. 2932. 2592. 2147. 1660.
1183. 818. 577. 428. 333. 261. 179. 69. 0.
3962. 3920. 3792. 3613. 3430. 3266. 3056. 2776. 2335. 1816.
1338. 927. 640. 453. 342. 271. 182. 68. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 10495.0
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/150W ICETRON LAMP 2x2 DIRECT RECESSED LUMINAIRE
[LUMINAIRE] SPECULAR REFLECTOR w/PRISMATIC ACRYLIC PAT-12 LENS
[LUMINAIRE] SYLVANIA BALLAST #QT1x150/120-240 ICE WATTS=155
[LUMCAT]CATALOG NO. : MPG-S22-1/150I LER
[LAMPCAT]LAMP CODE : ICE150/835
TILT=NONE
1 12000. 1.000000 19 5 1 1 1.688 1.677 .000
1.0000 1.0000 155.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0
3962. 3933. 3802. 3619. 3384. 3120. 2804. 2463. 2013. 1517.
1089. 770. 568. 415. 333. 270. 189. 79. 0.
3962. 3912. 3776. 3603. 3409. 3178. 2885. 2522. 2071. 1569.
1115. 784. 573. 429. 343. 266. 185. 73. 0.
3962. 3918. 3798. 3612. 3402. 3195. 2919. 2615. 2199. 1693.
1203. 843. 601. 449. 337. 265. 179. 85. 0.
3962. 3901. 3765. 3603. 3418. 3210. 2932. 2592. 2147. 1660.
1183. 818. 577. 428. 333. 261. 179. 69. 0.
3962. 3920. 3792. 3613. 3430. 3266. 3056. 2776. 2335. 1816.
1338. 927. 640. 453. 342. 271. 182. 68. 0.

View File

@ -1,36 +1,36 @@
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14353.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 29-DEC-2008
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/250W ED28 PS MH LAMP 17x17x10"SQ AREA LUMINAIRE
[MORE] MIRO4 SPECULAR FORWARD THROW DISTRIBUTION REFLECTOR
[MORE] CLEAR FLAT GLASS LENS
[LUMCAT] OER1717-250PSMH120-TFT
[LAMPCAT] M153/E MH250W/H75/P
TILT=NONE
1 22000 1 25 21 1 1 1.11 1.11 0
1 1 250
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0 5 15 25 35 45 55 65 75 85 90 95 105 115 125 135 145 155 165 175 180
2698.00 3943.00 5458.00 6672.00 6831.00 7214.00 7080.00 5916.00 5057.00 5401.00 5200.00 3823.00 4642.00 4546.00 3326.00 4307.00 4716.00 3352.00 2186.00 1024.00 164.00 33.00 1.00 0.00 0.00
2698.00 3973.00 5563.00 7147.00 7067.00 7341.00 7279.00 6574.00 5462.00 5861.00 5381.00 3878.00 4745.00 4638.00 3478.00 4444.00 4903.00 3779.00 2312.00 1321.00 268.00 34.00 0.00 0.00 0.00
2698.00 4247.00 5895.00 7809.00 7305.00 7481.00 7591.00 7469.00 5914.00 5507.00 5457.00 3972.00 4789.00 4514.00 3983.00 4291.00 4333.00 4226.00 3418.00 1555.00 301.00 33.00 0.00 0.00 0.00
2698.00 3962.00 5992.00 8215.00 7325.00 7430.00 7666.00 6840.00 5236.00 4909.00 5078.00 4158.00 4647.00 4356.00 4229.00 3282.00 4660.00 3998.00 3538.00 1950.00 464.00 38.00 0.00 0.00 0.00
2698.00 3718.00 5991.00 8093.00 7644.00 7666.00 7065.00 6385.00 6315.00 4905.00 5666.00 4104.00 4832.00 6475.00 4871.00 2674.00 5890.00 4150.00 5346.00 2833.00 702.00 47.00 1.00 0.00 0.00
2698.00 3315.00 5882.00 7298.00 8906.00 7613.00 6407.00 6351.00 7849.00 5321.00 7181.00 4739.00 5685.00 4241.00 3129.00 2071.00 3098.00 3571.00 3435.00 2095.00 1203.00 271.00 0.00 0.00 0.00
2698.00 3110.00 4667.00 6205.00 7897.00 8795.00 6483.00 7120.00 6544.00 5762.00 10333.00 2340.00 3481.00 3706.00 3439.00 2736.00 1690.00 2207.00 2514.00 1436.00 644.00 109.00 0.00 0.00 0.00
2698.00 2701.00 3758.00 4788.00 6029.00 7687.00 8309.00 7108.00 5106.00 7821.00 3277.00 2142.00 2247.00 2162.00 2026.00 1480.00 1290.00 1412.00 387.00 543.00 182.00 117.00 0.00 0.00 0.00
2698.00 2771.00 2944.00 4037.00 4601.00 4975.00 5264.00 3669.00 4336.00 7602.00 3156.00 3270.00 2701.00 2160.00 2660.00 1389.00 1533.00 1199.00 1021.00 224.00 180.00 54.00 0.00 0.00 0.00
2698.00 2732.00 3015.00 3506.00 4038.00 3169.00 3471.00 2415.00 3423.00 7272.00 2935.00 1882.00 1764.00 1895.00 2225.00 1567.00 1584.00 1262.00 703.00 192.00 346.00 47.00 0.00 0.00 0.00
2698.00 2743.00 3286.00 4036.00 4457.00 3456.00 2094.00 2262.00 4356.00 7484.00 3955.00 1670.00 1163.00 1062.00 943.00 857.00 701.00 465.00 189.00 78.00 56.00 6.00 0.00 0.00 0.00
2698.00 2918.00 4025.00 5141.00 5140.00 3749.00 2006.00 1904.00 2552.00 2538.00 1859.00 1553.00 1125.00 1073.00 958.00 1141.00 672.00 478.00 182.00 64.00 25.00 0.00 0.00 0.00 0.00
2698.00 3464.00 4778.00 5035.00 4629.00 3210.00 2471.00 2042.00 3098.00 2579.00 1434.00 1252.00 1146.00 1423.00 982.00 1008.00 1184.00 353.00 97.00 35.00 5.00 0.00 0.00 0.00 0.00
2698.00 4025.00 4809.00 4376.00 3673.00 2601.00 1992.00 2043.00 1859.00 1968.00 2114.00 1492.00 1216.00 1066.00 686.00 354.00 220.00 95.00 53.00 17.00 4.00 0.00 0.00 0.00 0.00
2698.00 4236.00 4435.00 3765.00 2559.00 2564.00 1816.00 1794.00 1815.00 1890.00 1660.00 1338.00 687.00 351.00 558.00 101.00 59.00 55.00 61.00 41.00 10.00 0.00 0.00 0.00 0.00
2698.00 4418.00 4174.00 2760.00 2602.00 2238.00 1959.00 1846.00 1693.00 1664.00 1665.00 796.00 306.00 125.00 94.00 86.00 76.00 72.00 71.00 59.00 36.00 17.00 0.00 0.00 0.00
2698.00 4391.00 3812.00 2473.00 2438.00 2231.00 2219.00 1983.00 1899.00 1760.00 889.00 331.00 130.00 166.00 309.00 301.00 94.00 58.00 47.00 34.00 21.00 7.00 0.00 0.00 0.00
2698.00 4257.00 3531.00 2438.00 2319.00 2044.00 2167.00 2131.00 1947.00 1503.00 668.00 224.00 285.00 212.00 105.00 80.00 70.00 65.00 53.00 38.00 25.00 11.00 0.00 0.00 0.00
2698.00 4110.00 3488.00 2406.00 2227.00 2084.00 2068.00 2015.00 1882.00 1212.00 589.00 195.00 283.00 276.00 162.00 109.00 105.00 90.00 82.00 50.00 35.00 19.00 5.00 0.00 0.00
2698.00 4024.00 3228.00 2390.00 2172.00 2042.00 2014.00 1959.00 1846.00 1134.00 463.00 188.00 265.00 235.00 153.00 108.00 110.00 90.00 76.00 53.00 38.00 23.00 8.00 0.00 0.00
2698.00 3931.00 3193.00 2575.00 2140.00 2066.00 1998.00 1956.00 1841.00 1186.00 544.00 205.00 274.00 230.00 167.00 112.00 115.00 93.00 76.00 56.00 41.00 25.00 9.00 0.00 0.00
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14353.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 29-DEC-2008
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/250W ED28 PS MH LAMP 17x17x10"SQ AREA LUMINAIRE
[MORE] MIRO4 SPECULAR FORWARD THROW DISTRIBUTION REFLECTOR
[MORE] CLEAR FLAT GLASS LENS
[LUMCAT] OER1717-250PSMH120-TFT
[LAMPCAT] M153/E MH250W/H75/P
TILT=NONE
1 22000 1 25 21 1 1 1.11 1.11 0
1 1 250
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0 5 15 25 35 45 55 65 75 85 90 95 105 115 125 135 145 155 165 175 180
2698.00 3943.00 5458.00 6672.00 6831.00 7214.00 7080.00 5916.00 5057.00 5401.00 5200.00 3823.00 4642.00 4546.00 3326.00 4307.00 4716.00 3352.00 2186.00 1024.00 164.00 33.00 1.00 0.00 0.00
2698.00 3973.00 5563.00 7147.00 7067.00 7341.00 7279.00 6574.00 5462.00 5861.00 5381.00 3878.00 4745.00 4638.00 3478.00 4444.00 4903.00 3779.00 2312.00 1321.00 268.00 34.00 0.00 0.00 0.00
2698.00 4247.00 5895.00 7809.00 7305.00 7481.00 7591.00 7469.00 5914.00 5507.00 5457.00 3972.00 4789.00 4514.00 3983.00 4291.00 4333.00 4226.00 3418.00 1555.00 301.00 33.00 0.00 0.00 0.00
2698.00 3962.00 5992.00 8215.00 7325.00 7430.00 7666.00 6840.00 5236.00 4909.00 5078.00 4158.00 4647.00 4356.00 4229.00 3282.00 4660.00 3998.00 3538.00 1950.00 464.00 38.00 0.00 0.00 0.00
2698.00 3718.00 5991.00 8093.00 7644.00 7666.00 7065.00 6385.00 6315.00 4905.00 5666.00 4104.00 4832.00 6475.00 4871.00 2674.00 5890.00 4150.00 5346.00 2833.00 702.00 47.00 1.00 0.00 0.00
2698.00 3315.00 5882.00 7298.00 8906.00 7613.00 6407.00 6351.00 7849.00 5321.00 7181.00 4739.00 5685.00 4241.00 3129.00 2071.00 3098.00 3571.00 3435.00 2095.00 1203.00 271.00 0.00 0.00 0.00
2698.00 3110.00 4667.00 6205.00 7897.00 8795.00 6483.00 7120.00 6544.00 5762.00 10333.00 2340.00 3481.00 3706.00 3439.00 2736.00 1690.00 2207.00 2514.00 1436.00 644.00 109.00 0.00 0.00 0.00
2698.00 2701.00 3758.00 4788.00 6029.00 7687.00 8309.00 7108.00 5106.00 7821.00 3277.00 2142.00 2247.00 2162.00 2026.00 1480.00 1290.00 1412.00 387.00 543.00 182.00 117.00 0.00 0.00 0.00
2698.00 2771.00 2944.00 4037.00 4601.00 4975.00 5264.00 3669.00 4336.00 7602.00 3156.00 3270.00 2701.00 2160.00 2660.00 1389.00 1533.00 1199.00 1021.00 224.00 180.00 54.00 0.00 0.00 0.00
2698.00 2732.00 3015.00 3506.00 4038.00 3169.00 3471.00 2415.00 3423.00 7272.00 2935.00 1882.00 1764.00 1895.00 2225.00 1567.00 1584.00 1262.00 703.00 192.00 346.00 47.00 0.00 0.00 0.00
2698.00 2743.00 3286.00 4036.00 4457.00 3456.00 2094.00 2262.00 4356.00 7484.00 3955.00 1670.00 1163.00 1062.00 943.00 857.00 701.00 465.00 189.00 78.00 56.00 6.00 0.00 0.00 0.00
2698.00 2918.00 4025.00 5141.00 5140.00 3749.00 2006.00 1904.00 2552.00 2538.00 1859.00 1553.00 1125.00 1073.00 958.00 1141.00 672.00 478.00 182.00 64.00 25.00 0.00 0.00 0.00 0.00
2698.00 3464.00 4778.00 5035.00 4629.00 3210.00 2471.00 2042.00 3098.00 2579.00 1434.00 1252.00 1146.00 1423.00 982.00 1008.00 1184.00 353.00 97.00 35.00 5.00 0.00 0.00 0.00 0.00
2698.00 4025.00 4809.00 4376.00 3673.00 2601.00 1992.00 2043.00 1859.00 1968.00 2114.00 1492.00 1216.00 1066.00 686.00 354.00 220.00 95.00 53.00 17.00 4.00 0.00 0.00 0.00 0.00
2698.00 4236.00 4435.00 3765.00 2559.00 2564.00 1816.00 1794.00 1815.00 1890.00 1660.00 1338.00 687.00 351.00 558.00 101.00 59.00 55.00 61.00 41.00 10.00 0.00 0.00 0.00 0.00
2698.00 4418.00 4174.00 2760.00 2602.00 2238.00 1959.00 1846.00 1693.00 1664.00 1665.00 796.00 306.00 125.00 94.00 86.00 76.00 72.00 71.00 59.00 36.00 17.00 0.00 0.00 0.00
2698.00 4391.00 3812.00 2473.00 2438.00 2231.00 2219.00 1983.00 1899.00 1760.00 889.00 331.00 130.00 166.00 309.00 301.00 94.00 58.00 47.00 34.00 21.00 7.00 0.00 0.00 0.00
2698.00 4257.00 3531.00 2438.00 2319.00 2044.00 2167.00 2131.00 1947.00 1503.00 668.00 224.00 285.00 212.00 105.00 80.00 70.00 65.00 53.00 38.00 25.00 11.00 0.00 0.00 0.00
2698.00 4110.00 3488.00 2406.00 2227.00 2084.00 2068.00 2015.00 1882.00 1212.00 589.00 195.00 283.00 276.00 162.00 109.00 105.00 90.00 82.00 50.00 35.00 19.00 5.00 0.00 0.00
2698.00 4024.00 3228.00 2390.00 2172.00 2042.00 2014.00 1959.00 1846.00 1134.00 463.00 188.00 265.00 235.00 153.00 108.00 110.00 90.00 76.00 53.00 38.00 23.00 8.00 0.00 0.00
2698.00 3931.00 3193.00 2575.00 2140.00 2066.00 1998.00 1956.00 1841.00 1186.00 544.00 205.00 274.00 230.00 167.00 112.00 115.00 93.00 76.00 56.00 41.00 25.00 9.00 0.00 0.00

View File

@ -1,14 +1,14 @@
IESNA91
[MANUFAC] Halo,Recessed
[LUMCAT] H7t-301
[LUMINAIRE] Open Trim (75W R-30 Flood)
[LAMP]
[REPORT]
TILT=NONE
1 900.0 1.0 36 1 1 1 0.0 -0.32 0.0
1.0 1.0 75.0
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 17.5 20.0 22.5 25.0 27.5 30.0 32.5 35.0 37.5 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
0.0
1512.0 1516.0 1508.0 1487.0 1453.0 1409.0 1357.0 1294.0 1229.0 1158.0 1085.0 1008.0 934.0 862.0 795.0 727.0 578.0 459.0 368.0
304.0 256.0 222.0 197.0 177.0 163.0 153.0 141.0 124.0 73.0 28.0 23.0 18.0 13.0 9.0 4.0 1.0
IESNA91
[MANUFAC] Halo,Recessed
[LUMCAT] H7t-301
[LUMINAIRE] Open Trim (75W R-30 Flood)
[LAMP]
[REPORT]
TILT=NONE
1 900.0 1.0 36 1 1 1 0.0 -0.32 0.0
1.0 1.0 75.0
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 17.5 20.0 22.5 25.0 27.5 30.0 32.5 35.0 37.5 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
0.0
1512.0 1516.0 1508.0 1487.0 1453.0 1409.0 1357.0 1294.0 1229.0 1158.0 1085.0 1008.0 934.0 862.0 795.0 727.0 578.0 459.0 368.0
304.0 256.0 222.0 197.0 177.0 163.0 153.0 141.0 124.0 73.0 28.0 23.0 18.0 13.0 9.0 4.0 1.0

View File

@ -1,29 +1,29 @@
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
74216023+Q50MR16/C/CG55°-FNV.IES
-
-
-
-
-
-
TILT=NONE
1 825 .825 73 2 1 2 -.2 0 0
1.00 1.00 50
0 1.25 2.5 3.75 5 6.25 7.5 8.75 10 11.25 12.5 13.75 15 16.25 17.5 18.75 20
21.25 22.5 23.75 25 26.25 27.5 28.75 30 31.25 32.5 33.75 35 36.25 37.5 38.75
40 41.25 42.5 43.75 45 46.25 47.5 48.75 50 51.25 52.5 53.75 55 56.25 57.5
58.75 60 61.25 62.5 63.75 65 66.25 67.5 68.75 70 71.25 72.5 73.75 75 76.25
77.5 78.75 80 81.25 82.5 83.75 85 86.25 87.5 88.75 90
0 90
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
74216023+Q50MR16/C/CG55°-FNV.IES
-
-
-
-
-
-
TILT=NONE
1 825 .825 73 2 1 2 -.2 0 0
1.00 1.00 50
0 1.25 2.5 3.75 5 6.25 7.5 8.75 10 11.25 12.5 13.75 15 16.25 17.5 18.75 20
21.25 22.5 23.75 25 26.25 27.5 28.75 30 31.25 32.5 33.75 35 36.25 37.5 38.75
40 41.25 42.5 43.75 45 46.25 47.5 48.75 50 51.25 52.5 53.75 55 56.25 57.5
58.75 60 61.25 62.5 63.75 65 66.25 67.5 68.75 70 71.25 72.5 73.75 75 76.25
77.5 78.75 80 81.25 82.5 83.75 85 86.25 87.5 88.75 90
0 90
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97
1091 1113 1132 1160 1183 1206 1219 1223 1217 1207 1190 1162 1120 1063 995.2
919 837.6 753.2 666.7 579.4 495.8 418.3 338.2 250.3 175.8 135.5 123.9 128.9
138.2 142.1 140.9 137.1 133.3 131.4 129.6 125.5 116.4 100.9 81.69 62.57 47.27
38.54 35 34.26 33.94 32.17 29.22 25.91 23.03 21.2 20.24 19.77 19.39 18.83
18.14 17.47 16.97 16.74 16.74 16.85 16.97 17.03 17.03 17 16.97 16.95 16.95
16.96 16.97 16.97 16.97 16.97 16.97

View File

@ -1,48 +1,48 @@
IESNA91
[TEST] NO. 12296
[MANUFAC]LITHONIA - ESG MODEL HQM LAMPHEAD
[LUMCAT]ELA CDS N0606
[LUMINAIRE]SPECULAR REFLECTOR WITH TRANSLUCENT PLASTIC LENS
[LAMP]ONE GE#939 INCANDESCENT WEDGE MINIATURE LAMP.. LUMEN RATING = 68 LMS.
[MORE]6 VOLTS DC OPERATING AT .9 AMPS AND 5.4 WATTS
[OTHER]LITHONIA- ESG LIGHTING
[MORE]DECATUR, GA
[OTHER]Version: 4/1/97 - 12:00:00
TILT=NONE
1
68
1
37
5
1
1
.33
.33
.00
1
1
5.4000
0,2.5,5,7.5,10,12.5,15,17.5,20,22.5,25,27.5,30,32.5,35,37.5
40,42.5,45,47.5,50,52.5,55,57.5,60,62.5,65,67.5,70,72.5,75
77.5,80,82.5,85,87.5,90
0,22.5,45,67.5,90
166,160,125,88,53,40,27,19,14,11
9,7,7,6,6,5,5,5,5,4
4,4,3,3,3,3,3,2,2,1
1,1,1,1,0,0,0
166,158,124,89,59,40,26,18,13,10
8,7,6,6,5,5,5,5,4,4
4,4,4,3,3,2,2,2,1,1
1,1,1,0,0,0,0
166,153,120,85,56,37,24,17,12,9
8,7,6,5,5,5,5,4,4,4
4,4,3,3,3,2,2,2,1,1
1,1,1,0,0,0,0
166,148,114,80,52,34,22,15,11,9
7,6,6,6,5,5,5,4,4,4
4,4,3,3,3,2,2,2,1,1
1,1,1,0,0,0,0
166,142,108,75,49,32,21,15,11,9
7,6,6,6,5,5,5,5,4,4
4,4,3,3,3,2,2,2,1,1
1,1,1,0,0,0,0
IESNA91
[TEST] NO. 12296
[MANUFAC]LITHONIA - ESG MODEL HQM LAMPHEAD
[LUMCAT]ELA CDS N0606
[LUMINAIRE]SPECULAR REFLECTOR WITH TRANSLUCENT PLASTIC LENS
[LAMP]ONE GE#939 INCANDESCENT WEDGE MINIATURE LAMP.. LUMEN RATING = 68 LMS.
[MORE]6 VOLTS DC OPERATING AT .9 AMPS AND 5.4 WATTS
[OTHER]LITHONIA- ESG LIGHTING
[MORE]DECATUR, GA
[OTHER]Version: 4/1/97 - 12:00:00
TILT=NONE
1
68
1
37
5
1
1
.33
.33
.00
1
1
5.4000
0,2.5,5,7.5,10,12.5,15,17.5,20,22.5,25,27.5,30,32.5,35,37.5
40,42.5,45,47.5,50,52.5,55,57.5,60,62.5,65,67.5,70,72.5,75
77.5,80,82.5,85,87.5,90
0,22.5,45,67.5,90
166,160,125,88,53,40,27,19,14,11
9,7,7,6,6,5,5,5,5,4
4,4,3,3,3,3,3,2,2,1
1,1,1,1,0,0,0
166,158,124,89,59,40,26,18,13,10
8,7,6,6,5,5,5,5,4,4
4,4,4,3,3,2,2,2,1,1
1,1,1,0,0,0,0
166,153,120,85,56,37,24,17,12,9
8,7,6,5,5,5,5,4,4,4
4,4,3,3,3,2,2,2,1,1
1,1,1,0,0,0,0
166,148,114,80,52,34,22,15,11,9
7,6,6,6,5,5,5,4,4,4
4,4,3,3,3,2,2,2,1,1
1,1,1,0,0,0,0
166,142,108,75,49,32,21,15,11,9
7,6,6,6,5,5,5,5,4,4
4,4,3,3,3,2,2,2,1,1
1,1,1,0,0,0,0

View File

@ -1,16 +1,16 @@
IESNA:LM-63-1995
[TEST] 100071_0 BY: ERCO / LUM650
[DATE]02.12.2004
[MANUFAC] ERCO Leuchten GmbH
[LUMCAT] 22625000
[LUMINAIRE] Lightcast Directional luminaire
[LAMPCAT] QPAR30 75W 30°
TILT=NONE
1 1234 1 37 1 1 2 -.097 0 0
1.00 1.00 75
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120
125 130 135 140 145 150 155 160 165 170 175 180
0
2400.1 2237.2 1869.5 1201.9 501.0 362.8 273.9 155.5 125.9 108.6 100.0 86.4
50.6 28.4 18.5 11.1 10.4 4.9 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0
IESNA:LM-63-1995
[TEST] 100071_0 BY: ERCO / LUM650
[DATE]02.12.2004
[MANUFAC] ERCO Leuchten GmbH
[LUMCAT] 22625000
[LUMINAIRE] Lightcast Directional luminaire
[LAMPCAT] QPAR30 75W 30°
TILT=NONE
1 1234 1 37 1 1 2 -.097 0 0
1.00 1.00 75
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120
125 130 135 140 145 150 155 160 165 170 175 180
0
2400.1 2237.2 1869.5 1201.9 501.0 362.8 273.9 155.5 125.9 108.6 100.0 86.4
50.6 28.4 18.5 11.1 10.4 4.9 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0

View File

@ -1,13 +1,13 @@
IESNA:LM-63-1995
[TEST] 100069_0 BY: ERCO / LUM650
[DATE]02.12.2004
[MANUFAC] ERCO Leuchten GmbH
[LUMCAT] 22619000_83671000
[LUMINAIRE] Lightcast Downlight
[LAMPCAT] HIPAR-L30 70W 10°
TILT=NONE
1 4850 1 19 1 1 2 -.097 0 0
1.00 1.00 70
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0
68000 34008 6853 3982 936 582 543 514 349 189 92 58 44 34 0 0 0 0 0
IESNA:LM-63-1995
[TEST] 100069_0 BY: ERCO / LUM650
[DATE]02.12.2004
[MANUFAC] ERCO Leuchten GmbH
[LUMCAT] 22619000_83671000
[LUMINAIRE] Lightcast Downlight
[LAMPCAT] HIPAR-L30 70W 10°
TILT=NONE
1 4850 1 19 1 1 2 -.097 0 0
1.00 1.00 70
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0
68000 34008 6853 3982 936 582 543 514 349 189 92 58 44 34 0 0 0 0 0

View File

@ -1,32 +1,32 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 13700.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/175W CLEAR ED17 MH LAMP 16x16"DIRECT WALL MNT LUMINAIRE
[MORE] SEMI-SPECULAR REFLECTOR SYSTEMS w/BLACK BLADE BAFFLES
[MORE] .1875"THICK CLEAR TEMPERED GLASS LENS
[LUMCAT] WPSQ-MH-175-MED-120
[LAMPCAT] M57 (M175/U/MED)
TILT=NONE
1 12800. 1.000000 19 9 1 1 .943 .917 .000
1.0000 1.0000 175.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0 112.5 135.0 157.5 180.0
25790. 25293. 19946. 12741. 6548. 3620. 2037. 1395. 1016. 765.
587. 461. 338. 221. 19. 4. 0. 0. 0.
25790. 24593. 19253. 12080. 6261. 3230. 1942. 1387. 1049. 590.
231. 107. 49. 29. 9. 0. 0. 0. 0.
25790. 24242. 18086. 10203. 4745. 2374. 1247. 460. 193. 91.
54. 35. 10. 3. 2. 0. 0. 0. 0.
25790. 23677. 17161. 9024. 3716. 1603. 608. 256. 142. 94.
38. 10. 4. 6. 1. 0. 0. 0. 0.
25790. 23467. 16339. 7925. 3242. 1304. 490. 249. 131. 90.
29. 7. 4. 2. 1. 0. 0. 0. 0.
25790. 22684. 15653. 7409. 3273. 1538. 520. 213. 113. 83.
31. 7. 3. 4. 0. 0. 0. 0. 0.
25790. 22633. 16005. 7769. 3449. 2045. 1312. 474. 147. 72.
54. 45. 8. 2. 2. 0. 0. 0. 0.
25790. 22392. 15298. 8244. 3996. 2118. 1372. 1090. 986. 833.
486. 178. 62. 60. 7. 0. 0. 0. 0.
25790. 23109. 15969. 8525. 3888. 2119. 1337. 1025. 835. 699.
578. 473. 373. 251. 23. 7. 0. 0. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 13700.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/175W CLEAR ED17 MH LAMP 16x16"DIRECT WALL MNT LUMINAIRE
[MORE] SEMI-SPECULAR REFLECTOR SYSTEMS w/BLACK BLADE BAFFLES
[MORE] .1875"THICK CLEAR TEMPERED GLASS LENS
[LUMCAT] WPSQ-MH-175-MED-120
[LAMPCAT] M57 (M175/U/MED)
TILT=NONE
1 12800. 1.000000 19 9 1 1 .943 .917 .000
1.0000 1.0000 175.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0 112.5 135.0 157.5 180.0
25790. 25293. 19946. 12741. 6548. 3620. 2037. 1395. 1016. 765.
587. 461. 338. 221. 19. 4. 0. 0. 0.
25790. 24593. 19253. 12080. 6261. 3230. 1942. 1387. 1049. 590.
231. 107. 49. 29. 9. 0. 0. 0. 0.
25790. 24242. 18086. 10203. 4745. 2374. 1247. 460. 193. 91.
54. 35. 10. 3. 2. 0. 0. 0. 0.
25790. 23677. 17161. 9024. 3716. 1603. 608. 256. 142. 94.
38. 10. 4. 6. 1. 0. 0. 0. 0.
25790. 23467. 16339. 7925. 3242. 1304. 490. 249. 131. 90.
29. 7. 4. 2. 1. 0. 0. 0. 0.
25790. 22684. 15653. 7409. 3273. 1538. 520. 213. 113. 83.
31. 7. 3. 4. 0. 0. 0. 0. 0.
25790. 22633. 16005. 7769. 3449. 2045. 1312. 474. 147. 72.
54. 45. 8. 2. 2. 0. 0. 0. 0.
25790. 22392. 15298. 8244. 3996. 2118. 1372. 1090. 986. 833.
486. 178. 62. 60. 7. 0. 0. 0. 0.
25790. 23109. 15969. 8525. 3888. 2119. 1337. 1025. 835. 699.
578. 473. 373. 251. 23. 7. 0. 0. 0.

View File

@ -1,16 +1,16 @@
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14501.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 04-MAR-2009
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W CLEAR ED17PS MH HORIZ LAMP LS SERIES POST LUMINAIRE
[MORE] WHITE TOP REFLECTOR w/FROSTED GLASS CHIMNEY
[MORE] CLEAR ACRYLIC PANELS
[LUMCAT] HLSC15-100PSMH120-BLK
[LAMPCAT] M90
TILT=NONE
1 9000 1 35 1 1 1 0.885 0.885 0.781
1 1 100
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 95 105 115 125 135 145 155 165 175 180
0
67.00 113.00 238.00 460.00 973.00 1277.00 1388.00 1425.00 1408.00 1338.00 1199.00 1018.00 700.00 430.00 320.00 335.00 227.00 209.00 154.00 137.00 125.00 109.00 91.00 65.00 46.00 38.00 25.00 18.00 10.00 5.00 3.00 3.00 0.00 0.00 0.00
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14501.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 04-MAR-2009
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W CLEAR ED17PS MH HORIZ LAMP LS SERIES POST LUMINAIRE
[MORE] WHITE TOP REFLECTOR w/FROSTED GLASS CHIMNEY
[MORE] CLEAR ACRYLIC PANELS
[LUMCAT] HLSC15-100PSMH120-BLK
[LAMPCAT] M90
TILT=NONE
1 9000 1 35 1 1 1 0.885 0.885 0.781
1 1 100
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 95 105 115 125 135 145 155 165 175 180
0
67.00 113.00 238.00 460.00 973.00 1277.00 1388.00 1425.00 1408.00 1338.00 1199.00 1018.00 700.00 430.00 320.00 335.00 227.00 209.00 154.00 137.00 125.00 109.00 91.00 65.00 46.00 38.00 25.00 18.00 10.00 5.00 3.00 3.00 0.00 0.00 0.00

View File

@ -1,36 +1,36 @@
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14477.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 11-FEB-2009
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/400W CLEAR ED37 PS MH 18x17x9"WALL PACK AREA LUMINAIRE
[MORE] HAMMERTONE REFLECTOR w/FLAT CLEAR GLASS LENS
[MORE]
[LUMCAT] WPTZ3-PSMH-400-MED-FD-120
[LAMPCAT] M155/E MH400W/H75/P
TILT=NONE
1 40000 1 25 21 1 1 1.25 0.687 0
1 1 400
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0 5 15 25 35 45 55 65 75 85 90 95 105 115 125 135 145 155 165 175 180
9079.00 7777.00 6697.00 6001.00 5457.00 5017.00 5081.00 5849.00 6929.00 7921.00 7361.00 6753.00 4769.00 2896.00 2672.00 2472.00 2192.00 1720.00 1336.00 960.00 568.00 152.00 0.00 0.00 0.00
9079.00 7769.00 6681.00 6025.00 5425.00 5001.00 5057.00 5785.00 7089.00 8033.00 7569.00 6929.00 5697.00 3056.00 2712.00 2528.00 2224.00 1728.00 1400.00 1000.00 592.00 184.00 0.00 0.00 0.00
9079.00 7833.00 6849.00 6121.00 5481.00 4977.00 4889.00 5633.00 6945.00 8305.00 7953.00 7009.00 6313.00 3784.00 2840.00 2576.00 2328.00 1888.00 1504.00 1056.00 648.00 224.00 0.00 0.00 0.00
9079.00 7985.00 7001.00 6209.00 5465.00 4945.00 4680.00 5177.00 6281.00 7705.00 8033.00 6609.00 5681.00 4624.00 2296.00 1904.00 1616.00 1248.00 888.00 544.00 336.00 80.00 0.00 0.00 0.00
9079.00 8129.00 7257.00 6329.00 5489.00 4793.00 4368.00 4456.00 4985.00 5345.00 4905.00 3936.00 3416.00 3248.00 2616.00 696.00 536.00 400.00 264.00 152.00 64.00 8.00 0.00 0.00 0.00
9079.00 8281.00 7465.00 6505.00 5505.00 4737.00 4168.00 3896.00 3832.00 3744.00 3384.00 3136.00 2880.00 2176.00 1272.00 680.00 616.00 544.00 408.00 232.00 104.00 24.00 0.00 0.00 0.00
9079.00 8529.00 7793.00 6825.00 5745.00 4753.00 4016.00 3528.00 3224.00 3048.00 3088.00 3184.00 2536.00 1624.00 1064.00 832.00 712.00 616.00 528.00 320.00 144.00 32.00 0.00 0.00 0.00
9079.00 8689.00 8121.00 7353.00 6057.00 4969.00 4000.00 3456.00 3080.00 2864.00 2800.00 2800.00 2008.00 1512.00 1392.00 1200.00 928.00 616.00 440.00 272.00 136.00 40.00 0.00 0.00 0.00
9079.00 8961.00 8577.00 7841.00 6721.00 5553.00 4352.00 3560.00 3096.00 2872.00 2688.00 2464.00 1360.00 1128.00 1120.00 1072.00 976.00 824.00 640.00 392.00 200.00 64.00 0.00 0.00 0.00
9079.00 9089.00 8817.00 8161.00 7185.00 5953.00 4576.00 3664.00 3208.00 2992.00 2792.00 2472.00 1352.00 1048.00 1024.00 944.00 856.00 720.00 608.00 424.00 200.00 56.00 0.00 0.00 0.00
9079.00 9297.00 9121.00 8609.00 7737.00 6641.00 5129.00 3840.00 3344.00 3168.00 2976.00 2544.00 1368.00 1032.00 936.00 808.00 712.00 608.00 472.00 328.00 176.00 48.00 0.00 0.00 0.00
9079.00 9466.00 9401.00 8977.00 8161.00 7297.00 5513.00 3968.00 3448.00 3240.00 2848.00 2080.00 1224.00 1016.00 872.00 736.00 600.00 448.00 336.00 208.00 104.00 32.00 0.00 0.00 0.00
9079.00 9666.00 9706.00 9313.00 8473.00 7369.00 5313.00 2864.00 1744.00 1352.00 1344.00 1264.00 1016.00 856.00 752.00 584.00 472.00 320.00 224.00 128.00 64.00 16.00 0.00 0.00 0.00
9079.00 9874.00 10034.00 9642.00 8233.00 5769.00 3600.00 2352.00 1592.00 1256.00 1208.00 1240.00 904.00 696.00 536.00 384.00 272.00 168.00 104.00 56.00 24.00 0.00 0.00 0.00 0.00
9079.00 10002.00 10210.00 9225.00 6513.00 4504.00 3880.00 3464.00 2496.00 1456.00 984.00 792.00 504.00 360.00 272.00 200.00 160.00 104.00 80.00 32.00 16.00 0.00 0.00 0.00 0.00
9079.00 10162.00 10338.00 8361.00 5553.00 4721.00 4440.00 4256.00 3624.00 2056.00 768.00 456.00 280.00 200.00 160.00 120.00 96.00 56.00 40.00 16.00 8.00 0.00 0.00 0.00 0.00
9079.00 10242.00 10226.00 7433.00 5529.00 5033.00 4897.00 4560.00 3376.00 1536.00 568.00 312.00 200.00 152.00 120.00 88.00 80.00 40.00 32.00 16.00 8.00 0.00 0.00 0.00 0.00
9079.00 10330.00 9938.00 6873.00 5721.00 5409.00 5177.00 4352.00 2552.00 1032.00 544.00 360.00 248.00 176.00 136.00 96.00 72.00 40.00 32.00 24.00 8.00 0.00 0.00 0.00 0.00
9079.00 10234.00 9794.00 6873.00 5913.00 5641.00 5273.00 4016.00 2120.00 1120.00 736.00 552.00 384.00 280.00 184.00 112.00 80.00 48.00 40.00 24.00 8.00 0.00 0.00 0.00 0.00
9079.00 10242.00 9794.00 6825.00 5985.00 5777.00 5313.00 4000.00 2104.00 1160.00 840.00 640.00 456.00 320.00 232.00 152.00 104.00 56.00 48.00 24.00 16.00 0.00 0.00 0.00 0.00
9079.00 10298.00 9666.00 6905.00 6097.00 5849.00 5401.00 4152.00 2128.00 1248.00 904.00 720.00 488.00 352.00 248.00 168.00 120.00 64.00 48.00 32.00 24.00 8.00 0.00 0.00 0.00
IESNA:LM-63-2002
[TEST]BALLABS TEST NO. 14477.0
[TESTLAB] BUILDING ACOUSTICS & LIGHTING LABORATORIES, INC
[ISSUEDATE] 11-FEB-2009
[MANUFAC] H.E. WILLIAMS, INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/400W CLEAR ED37 PS MH 18x17x9"WALL PACK AREA LUMINAIRE
[MORE] HAMMERTONE REFLECTOR w/FLAT CLEAR GLASS LENS
[MORE]
[LUMCAT] WPTZ3-PSMH-400-MED-FD-120
[LAMPCAT] M155/E MH400W/H75/P
TILT=NONE
1 40000 1 25 21 1 1 1.25 0.687 0
1 1 400
0 5 10 15 20 25 30 35 40 45 50 55 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0 5 15 25 35 45 55 65 75 85 90 95 105 115 125 135 145 155 165 175 180
9079.00 7777.00 6697.00 6001.00 5457.00 5017.00 5081.00 5849.00 6929.00 7921.00 7361.00 6753.00 4769.00 2896.00 2672.00 2472.00 2192.00 1720.00 1336.00 960.00 568.00 152.00 0.00 0.00 0.00
9079.00 7769.00 6681.00 6025.00 5425.00 5001.00 5057.00 5785.00 7089.00 8033.00 7569.00 6929.00 5697.00 3056.00 2712.00 2528.00 2224.00 1728.00 1400.00 1000.00 592.00 184.00 0.00 0.00 0.00
9079.00 7833.00 6849.00 6121.00 5481.00 4977.00 4889.00 5633.00 6945.00 8305.00 7953.00 7009.00 6313.00 3784.00 2840.00 2576.00 2328.00 1888.00 1504.00 1056.00 648.00 224.00 0.00 0.00 0.00
9079.00 7985.00 7001.00 6209.00 5465.00 4945.00 4680.00 5177.00 6281.00 7705.00 8033.00 6609.00 5681.00 4624.00 2296.00 1904.00 1616.00 1248.00 888.00 544.00 336.00 80.00 0.00 0.00 0.00
9079.00 8129.00 7257.00 6329.00 5489.00 4793.00 4368.00 4456.00 4985.00 5345.00 4905.00 3936.00 3416.00 3248.00 2616.00 696.00 536.00 400.00 264.00 152.00 64.00 8.00 0.00 0.00 0.00
9079.00 8281.00 7465.00 6505.00 5505.00 4737.00 4168.00 3896.00 3832.00 3744.00 3384.00 3136.00 2880.00 2176.00 1272.00 680.00 616.00 544.00 408.00 232.00 104.00 24.00 0.00 0.00 0.00
9079.00 8529.00 7793.00 6825.00 5745.00 4753.00 4016.00 3528.00 3224.00 3048.00 3088.00 3184.00 2536.00 1624.00 1064.00 832.00 712.00 616.00 528.00 320.00 144.00 32.00 0.00 0.00 0.00
9079.00 8689.00 8121.00 7353.00 6057.00 4969.00 4000.00 3456.00 3080.00 2864.00 2800.00 2800.00 2008.00 1512.00 1392.00 1200.00 928.00 616.00 440.00 272.00 136.00 40.00 0.00 0.00 0.00
9079.00 8961.00 8577.00 7841.00 6721.00 5553.00 4352.00 3560.00 3096.00 2872.00 2688.00 2464.00 1360.00 1128.00 1120.00 1072.00 976.00 824.00 640.00 392.00 200.00 64.00 0.00 0.00 0.00
9079.00 9089.00 8817.00 8161.00 7185.00 5953.00 4576.00 3664.00 3208.00 2992.00 2792.00 2472.00 1352.00 1048.00 1024.00 944.00 856.00 720.00 608.00 424.00 200.00 56.00 0.00 0.00 0.00
9079.00 9297.00 9121.00 8609.00 7737.00 6641.00 5129.00 3840.00 3344.00 3168.00 2976.00 2544.00 1368.00 1032.00 936.00 808.00 712.00 608.00 472.00 328.00 176.00 48.00 0.00 0.00 0.00
9079.00 9466.00 9401.00 8977.00 8161.00 7297.00 5513.00 3968.00 3448.00 3240.00 2848.00 2080.00 1224.00 1016.00 872.00 736.00 600.00 448.00 336.00 208.00 104.00 32.00 0.00 0.00 0.00
9079.00 9666.00 9706.00 9313.00 8473.00 7369.00 5313.00 2864.00 1744.00 1352.00 1344.00 1264.00 1016.00 856.00 752.00 584.00 472.00 320.00 224.00 128.00 64.00 16.00 0.00 0.00 0.00
9079.00 9874.00 10034.00 9642.00 8233.00 5769.00 3600.00 2352.00 1592.00 1256.00 1208.00 1240.00 904.00 696.00 536.00 384.00 272.00 168.00 104.00 56.00 24.00 0.00 0.00 0.00 0.00
9079.00 10002.00 10210.00 9225.00 6513.00 4504.00 3880.00 3464.00 2496.00 1456.00 984.00 792.00 504.00 360.00 272.00 200.00 160.00 104.00 80.00 32.00 16.00 0.00 0.00 0.00 0.00
9079.00 10162.00 10338.00 8361.00 5553.00 4721.00 4440.00 4256.00 3624.00 2056.00 768.00 456.00 280.00 200.00 160.00 120.00 96.00 56.00 40.00 16.00 8.00 0.00 0.00 0.00 0.00
9079.00 10242.00 10226.00 7433.00 5529.00 5033.00 4897.00 4560.00 3376.00 1536.00 568.00 312.00 200.00 152.00 120.00 88.00 80.00 40.00 32.00 16.00 8.00 0.00 0.00 0.00 0.00
9079.00 10330.00 9938.00 6873.00 5721.00 5409.00 5177.00 4352.00 2552.00 1032.00 544.00 360.00 248.00 176.00 136.00 96.00 72.00 40.00 32.00 24.00 8.00 0.00 0.00 0.00 0.00
9079.00 10234.00 9794.00 6873.00 5913.00 5641.00 5273.00 4016.00 2120.00 1120.00 736.00 552.00 384.00 280.00 184.00 112.00 80.00 48.00 40.00 24.00 8.00 0.00 0.00 0.00 0.00
9079.00 10242.00 9794.00 6825.00 5985.00 5777.00 5313.00 4000.00 2104.00 1160.00 840.00 640.00 456.00 320.00 232.00 152.00 104.00 56.00 48.00 24.00 16.00 0.00 0.00 0.00 0.00
9079.00 10298.00 9666.00 6905.00 6097.00 5849.00 5401.00 4152.00 2128.00 1248.00 904.00 720.00 488.00 352.00 248.00 168.00 120.00 64.00 48.00 32.00 24.00 8.00 0.00 0.00 0.00

View File

@ -1,24 +1,24 @@
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 12447.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W ICETRON INDUCTION LAMP 20x15"AREALIGHT LUMINAIRE
[LUMINAIRE] MIRO4 HIGHLY SPEC FLOOD OPTICS w/CLEAR GLASS LENS
[LUMINAIRE] SYLVANIA BALLAST #QT1x150 ICE/UNV-T WATTS=145
[LUMCAT] ICE DC-150W/41K-FL/CGI-MTV @277VOLTS
[LAMPCAT] ICETRON100/QT150
TILT=NONE
1 11000. 1.000000 19 5 1 1 .938 1.266 .000
1.0000 1.0000 145.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0
5122. 5161. 5246. 5337. 5360. 5211. 4910. 4510. 3890. 3056.
1952. 1153. 451. 139. 30. 15. 3. 0. 0.
5122. 5138. 5234. 5291. 5289. 5129. 4754. 4318. 3676. 2838.
2069. 1240. 482. 172. 37. 11. 6. 1. 0.
5122. 5134. 5160. 5118. 4967. 4781. 4477. 3831. 2940. 1851.
1139. 685. 306. 85. 25. 13. 7. 1. 0.
5122. 5119. 5076. 4880. 4697. 4385. 3786. 2876. 1738. 1121.
711. 388. 120. 30. 11. 6. 4. 1. 0.
5122. 5113. 5032. 4843. 4615. 4130. 3464. 2374. 1519. 1017.
589. 293. 73. 27. 11. 6. 3. 1. 0.
IESNA:LM-63-1995
[TEST]BALLABS TEST NO. 12447.0
[MANUFAC] INFINITY LIGHTING INC - CARTHAGE, MISSOURI
[LUMINAIRE] 1/100W ICETRON INDUCTION LAMP 20x15"AREALIGHT LUMINAIRE
[LUMINAIRE] MIRO4 HIGHLY SPEC FLOOD OPTICS w/CLEAR GLASS LENS
[LUMINAIRE] SYLVANIA BALLAST #QT1x150 ICE/UNV-T WATTS=145
[LUMCAT] ICE DC-150W/41K-FL/CGI-MTV @277VOLTS
[LAMPCAT] ICETRON100/QT150
TILT=NONE
1 11000. 1.000000 19 5 1 1 .938 1.266 .000
1.0000 1.0000 145.0000
.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0
50.0 55.0 60.0 65.0 70.0 75.0 80.0 85.0 90.0
.0 22.5 45.0 67.5 90.0
5122. 5161. 5246. 5337. 5360. 5211. 4910. 4510. 3890. 3056.
1952. 1153. 451. 139. 30. 15. 3. 0. 0.
5122. 5138. 5234. 5291. 5289. 5129. 4754. 4318. 3676. 2838.
2069. 1240. 482. 172. 37. 11. 6. 1. 0.
5122. 5134. 5160. 5118. 4967. 4781. 4477. 3831. 2940. 1851.
1139. 685. 306. 85. 25. 13. 7. 1. 0.
5122. 5119. 5076. 4880. 4697. 4385. 3786. 2876. 1738. 1121.
711. 388. 120. 30. 11. 6. 4. 1. 0.
5122. 5113. 5032. 4843. 4615. 4130. 3464. 2374. 1519. 1017.
589. 293. 73. 27. 11. 6. 3. 1. 0.

View File

@ -1,15 +1,15 @@
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
73608023+Q100T3/12V/CL 70°.IES
-
-
-
-
-
-
TILT=NONE
1 2350 2.35 19 1 1 2 -.09 0 0
1.00 1.00 100
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0
270.9 258 264.8 271.4 288.6 330.7 402.9 109.6 6.511 5.297 3.399 1.846 1.063
.5676 .4306 .03262 0 0 0
ERCO Leuchten GmbH BY: ERCO/LUM650/8701
73608023+Q100T3/12V/CL 70°.IES
-
-
-
-
-
-
TILT=NONE
1 2350 2.35 19 1 1 2 -.09 0 0
1.00 1.00 100
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
0
270.9 258 264.8 271.4 288.6 330.7 402.9 109.6 6.511 5.297 3.399 1.846 1.063
.5676 .4306 .03262 0 0 0

View File

@ -1,13 +1,13 @@
IESNA:LM-63-1995
[TEST] BE1680
[DATE] 12-FEB-96
[MANUFAC] BEGA
[LUMCAT] 6340
[LUMINAIRE] SURFACE MOUNTED WALL LUMINAIRE
[LAMP] (1) 100W A-19 INC
TILT=NONE
1 1750 1.75 73 1 1 2 -.1 0 .05
1 1 100
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30 32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95 97.5 100 102.5 105 107.5 110 112.5 115 117.5 120 122.5 125 127.5 130 132.5 135 137.5 140 142.5 145 147.5 150 152.5 155 157.5 160 162.5 165 167.5 170 172.5 175 177.5 180
0
167.3 168.9 173 179.9 179.2 151.2 119.4 95.63 81.03 71.95 66.46 62.67 60.25 57.67 52.18 46.62 48.91 63.15 83.15 95.41 97.4 87.75 62.6 43.08 39.26 47.36 52.89 45.74 31.45 18.17 10.5 7.888 8.112 7.592 3.665 .6467 .498 .4252 .3735 .3185 .2765 .2279 .2199 .2021 .1746 .1407 .1358 .1277 .1326 .1342 .1406 .1374 .1358 .1375 .1488 .1488 .1536 .1925 .2183 .2328 .2345 .249 .2765 .3023 .3266 .3476 .3557 .3638 .3541 .3573 .3638 .3719 .3816
IESNA:LM-63-1995
[TEST] BE1680
[DATE] 12-FEB-96
[MANUFAC] BEGA
[LUMCAT] 6340
[LUMINAIRE] SURFACE MOUNTED WALL LUMINAIRE
[LAMP] (1) 100W A-19 INC
TILT=NONE
1 1750 1.75 73 1 1 2 -.1 0 .05
1 1 100
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30 32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95 97.5 100 102.5 105 107.5 110 112.5 115 117.5 120 122.5 125 127.5 130 132.5 135 137.5 140 142.5 145 147.5 150 152.5 155 157.5 160 162.5 165 167.5 170 172.5 175 177.5 180
0
167.3 168.9 173 179.9 179.2 151.2 119.4 95.63 81.03 71.95 66.46 62.67 60.25 57.67 52.18 46.62 48.91 63.15 83.15 95.41 97.4 87.75 62.6 43.08 39.26 47.36 52.89 45.74 31.45 18.17 10.5 7.888 8.112 7.592 3.665 .6467 .498 .4252 .3735 .3185 .2765 .2279 .2199 .2021 .1746 .1407 .1358 .1277 .1326 .1342 .1406 .1374 .1358 .1375 .1488 .1488 .1536 .1925 .2183 .2328 .2345 .249 .2765 .3023 .3266 .3476 .3557 .3638 .3541 .3573 .3638 .3719 .3816

View File

@ -1,13 +1,13 @@
IESNA:LM-63-1995
[TEST] BE1396
[DATE] 22-SEPT-96
[MANUFAC] BEGA
[LUMCAT] 6690
[LUMINAIRE] SURFACE MOUNTED WALL LUMINAIRE
[LAMP] (1) 100W A-19 INC
TILT=NONE
1 1750 1.75 37 1 1 2 -.12 0 0
1 1 100
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30 32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0
283.4 280.7 270 250.8 228 207.8 185.8 160.1 140.4 133 131.4 131.4 130.9 127.9 120.7 109.3 99.46 95.13 98.4 106.8 116 122.2 124.1 119.1 97.99 57.94 26.92 11.71 4.582 1.544 .9573 .6497 .4341 .2616 .1724 .04603 .005727
IESNA:LM-63-1995
[TEST] BE1396
[DATE] 22-SEPT-96
[MANUFAC] BEGA
[LUMCAT] 6690
[LUMINAIRE] SURFACE MOUNTED WALL LUMINAIRE
[LAMP] (1) 100W A-19 INC
TILT=NONE
1 1750 1.75 37 1 1 2 -.12 0 0
1 1 100
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30 32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90
0
283.4 280.7 270 250.8 228 207.8 185.8 160.1 140.4 133 131.4 131.4 130.9 127.9 120.7 109.3 99.46 95.13 98.4 106.8 116 122.2 124.1 119.1 97.99 57.94 26.92 11.71 4.582 1.544 .9573 .6497 .4341 .2616 .1724 .04603 .005727

View File

@ -1,13 +1,13 @@
IESNA:LM-63-1995
[TEST] BE1667
[DATE] 12-FEB-96
[MANUFAC] BEGA
[LUMCAT] 6339
[LUMINAIRE] SURFACE MOUNTED WALL LUMINAIRE
[LAMP] (1) 60W A-19 INC
TILT=NONE
1 890 .89 73 1 1 2 -.1 0 0
1 1 60
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30 32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95 97.5 100 102.5 105 107.5 110 112.5 115 117.5 120 122.5 125 127.5 130 132.5 135 137.5 140 142.5 145 147.5 150 152.5 155 157.5 160 162.5 165 167.5 170 172.5 175 177.5 180
0
178.4 176.7 170.8 160.9 147 133 114.6 96.13 80.57 67.13 56.54 47.61 40.87 36.97 36.86 39.76 45.47 54.35 66.39 75.84 79.96 73.53 62.87 52.35 44.33 39.14 36.31 33.87 29.1 22.59 15.67 9.13 5.317 2.654 1.382 .3416 .2 .09695 .2025 .175 .1518 .1455 .1328 .1307 .1139 .1097 .097 .1075 .1076 .07175 .1243 .1073 .1328 .1349 .1391 .1307 .1412 .1475 .156 .1813 .1876 .2087 .2466 .2466 .2782 .2993 .3035 .3035 .3035 .2993 .2993 .3035 .3035
IESNA:LM-63-1995
[TEST] BE1667
[DATE] 12-FEB-96
[MANUFAC] BEGA
[LUMCAT] 6339
[LUMINAIRE] SURFACE MOUNTED WALL LUMINAIRE
[LAMP] (1) 60W A-19 INC
TILT=NONE
1 890 .89 73 1 1 2 -.1 0 0
1 1 60
0 2.5 5 7.5 10 12.5 15 17.5 20 22.5 25 27.5 30 32.5 35 37.5 40 42.5 45 47.5 50 52.5 55 57.5 60 62.5 65 67.5 70 72.5 75 77.5 80 82.5 85 87.5 90 92.5 95 97.5 100 102.5 105 107.5 110 112.5 115 117.5 120 122.5 125 127.5 130 132.5 135 137.5 140 142.5 145 147.5 150 152.5 155 157.5 160 162.5 165 167.5 170 172.5 175 177.5 180
0
178.4 176.7 170.8 160.9 147 133 114.6 96.13 80.57 67.13 56.54 47.61 40.87 36.97 36.86 39.76 45.47 54.35 66.39 75.84 79.96 73.53 62.87 52.35 44.33 39.14 36.31 33.87 29.1 22.59 15.67 9.13 5.317 2.654 1.382 .3416 .2 .09695 .2025 .175 .1518 .1455 .1328 .1307 .1139 .1097 .097 .1075 .1076 .07175 .1243 .1073 .1328 .1349 .1391 .1307 .1412 .1475 .156 .1813 .1876 .2087 .2466 .2466 .2782 .2993 .3035 .3035 .3035 .2993 .2993 .3035 .3035

View File

@ -1,16 +1,16 @@
## Patches for Panda3D
This folder contains patches for the Panda3D Engine which have not yet made
it to the Panda3D-Repository, but are used by some render pipeline features.
**IMPORTANT**: After you applied a patch, delete it, so the render pipeline
knows the patch is available.
## List of patches
#### prev-model-view-matrix.diff
This patch adds the p3d_PrevModelViewMatrix to add support for per object
velocities. When this patch is enabled, moving objects recieve motion blur (per
object motion blur). Also don't forget to apply the second part of the patch, too.
## Patches for Panda3D
This folder contains patches for the Panda3D Engine which have not yet made
it to the Panda3D-Repository, but are used by some render pipeline features.
**IMPORTANT**: After you applied a patch, delete it, so the render pipeline
knows the patch is available.
## List of patches
#### prev-model-view-matrix.diff
This patch adds the p3d_PrevModelViewMatrix to add support for per object
velocities. When this patch is enabled, moving objects recieve motion blur (per
object motion blur). Also don't forget to apply the second part of the patch, too.

View File

@ -1,58 +1,58 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function, division
import os
import sys
from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
def _error(msg):
print("\n" * 4, file=sys.stderr)
print("ERROR:", msg, file=sys.stderr)
print("\n" * 4, file=sys.stderr)
sys.exit(1)
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
window-type offscreen
win-size 100 100
color-bits 0
depth-bits 0
back-buffers 0
print-pipe-types #f
""")
ShowBase.__init__(self)
if not self.win.gsg.supports_compute_shaders:
_error("Compute shaders not supported! Please update your driver, or get a newer gpu.")
print("All checks passed successfully")
Application()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function, division
import os
import sys
from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
def _error(msg):
print("\n" * 4, file=sys.stderr)
print("ERROR:", msg, file=sys.stderr)
print("\n" * 4, file=sys.stderr)
sys.exit(1)
class Application(ShowBase):
def __init__(self):
load_prc_file_data("", """
window-type offscreen
win-size 100 100
color-bits 0
depth-bits 0
back-buffers 0
print-pipe-types #f
""")
ShowBase.__init__(self)
if not self.win.gsg.supports_compute_shaders:
_error("Compute shaders not supported! Please update your driver, or get a newer gpu.")
print("All checks passed successfully")
Application()

View File

@ -1,28 +1,28 @@
# Terrain effect
# This effect uses prodecural shader splatting, you most likely want to modify
# it with your own texture-map generation code.
vertex:
inout: |
uniform samplerBuffer InstancingData;
transform: |
int data_index = gl_InstanceID * 4;
vec4 data_0 = texelFetch(InstancingData, data_index);
vec4 data_1 = texelFetch(InstancingData, data_index + 1);
vec4 data_2 = texelFetch(InstancingData, data_index + 2);
vec4 data_3 = texelFetch(InstancingData, data_index + 3);
mat4 transform_mat = mat4(data_0, data_1, data_2, data_3);
vOutput.position = (transform_mat * p3d_Vertex).xyz;
// Also transform normal, not 100% correct but works out nicely
vOutput.normal = mat3(transform_mat) * vOutput.normal;
fragment:
# Terrain effect
# This effect uses prodecural shader splatting, you most likely want to modify
# it with your own texture-map generation code.
vertex:
inout: |
uniform samplerBuffer InstancingData;
transform: |
int data_index = gl_InstanceID * 4;
vec4 data_0 = texelFetch(InstancingData, data_index);
vec4 data_1 = texelFetch(InstancingData, data_index + 1);
vec4 data_2 = texelFetch(InstancingData, data_index + 2);
vec4 data_3 = texelFetch(InstancingData, data_index + 3);
mat4 transform_mat = mat4(data_0, data_1, data_2, data_3);
vOutput.position = (transform_mat * p3d_Vertex).xyz;
// Also transform normal, not 100% correct but works out nicely
vOutput.normal = mat3(transform_mat) * vOutput.normal;
fragment:

View File

@ -1,3 +1,3 @@
# Default effect file, used for all objects if not overridden.
# This file actually contains no content, since no templates are overriden.
# Default effect file, used for all objects if not overridden.
# This file actually contains no content, since no templates are overriden.

View File

@ -1,89 +1,89 @@
# This effect blends 4 materials based on a material map
# The textures should be setup like in the 04-Material-Blending sample.
# The last material is the base material and thus has no blending. It will
# be wherever no other material is.
vertex:
fragment:
inout: |
uniform sampler2D p3d_Texture0; // Alpha - Map
uniform sampler2D p3d_Texture1; // M1 - Diffuse
uniform sampler2D p3d_Texture2; // M1 - Normal
uniform sampler2D p3d_Texture3; // M1 - Specular
uniform sampler2D p3d_Texture4; // M1 - Blendmap
uniform sampler2D p3d_Texture5; // M2 - Diffuse
uniform sampler2D p3d_Texture6; // M2 - Normal
uniform sampler2D p3d_Texture7; // M2 - Specular
uniform sampler2D p3d_Texture8; // M2 - Blendmap
uniform sampler2D p3d_Texture9; // M3 - Diffuse
uniform sampler2D p3d_Texture10; // M3 - Normal
uniform sampler2D p3d_Texture11; // M3 - Specular
uniform sampler2D p3d_Texture12; // M3 - Blendmap
uniform sampler2D p3d_Texture13; // M4 - Diffuse
uniform sampler2D p3d_Texture14; // M4 - Normal
uniform sampler2D p3d_Texture15; // M4 - Specular
uniform sampler2D p3d_Texture16; // M4 - Blendmap
uniform float detail_scale_factor;
uniform float material_0_pow;
uniform float material_0_add;
uniform float material_1_pow;
uniform float material_1_add;
uniform float material_2_pow;
uniform float material_2_add;
defines: |
#define DONT_FETCH_DEFAULT_TEXTURES 1
#define DONT_SET_MATERIAL_PROPERTIES 1
material: |
// Get detail coordinate
vec2 detail_coord = texcoord * detail_scale_factor;
vec4 layers = texture(p3d_Texture0, texcoord);
layers.xyz *= layers.w;
// Blend all materials
layers.x = blend_material(layers.x, texture(p3d_Texture4, detail_coord).x, material_0_add, material_0_pow);
layers.y = blend_material(layers.y, texture(p3d_Texture8, detail_coord).x, material_1_add, material_1_pow);
layers.z = blend_material(layers.z, texture(p3d_Texture12, detail_coord).x, material_2_add, material_2_pow);
layers.w = saturate(1.0 - dot(layers.xyz, vec3(1))); // More inituitive
// Diffuse
vec3 m_base = vec3(0);
m_base = texture(p3d_Texture1, detail_coord).xyz * layers.x;
m_base += texture(p3d_Texture5, detail_coord).xyz * layers.y;
m_base += texture(p3d_Texture9, detail_coord).xyz * layers.z;
m_base += texture(p3d_Texture13, detail_coord).xyz * layers.w;
// Normal
vec3 m_nrm = vec3(0);
m_nrm += unpack_texture_normal(texture(p3d_Texture2, detail_coord).xyz) * layers.x;
m_nrm += unpack_texture_normal(texture(p3d_Texture6, detail_coord).xyz) * layers.y;
m_nrm += unpack_texture_normal(texture(p3d_Texture10, detail_coord).xyz) * layers.z;
m_nrm += unpack_texture_normal(texture(p3d_Texture14, detail_coord).xyz) * layers.w;
// Specular
float spec = 0.0;
spec = texture(p3d_Texture3, detail_coord).x * layers.x;
spec += texture(p3d_Texture7, detail_coord).x * layers.y;
spec += texture(p3d_Texture11, detail_coord).x * layers.z;
spec += texture(p3d_Texture15, detail_coord).x * layers.w;
// Material properties
m.shading_model = mInput.shading_model;
m.basecolor = m_base * mInput.color;
m.normal = apply_normal_map(vOutput.normal, m_nrm, mInput.normalfactor);
m.specular_ior = blend_ior(mInput.specular_ior, spec);
m.roughness = mInput.roughness;
m.metallic = mInput.metallic;
m.shading_model_param0 = mInput.arbitrary0;
# This effect blends 4 materials based on a material map
# The textures should be setup like in the 04-Material-Blending sample.
# The last material is the base material and thus has no blending. It will
# be wherever no other material is.
vertex:
fragment:
inout: |
uniform sampler2D p3d_Texture0; // Alpha - Map
uniform sampler2D p3d_Texture1; // M1 - Diffuse
uniform sampler2D p3d_Texture2; // M1 - Normal
uniform sampler2D p3d_Texture3; // M1 - Specular
uniform sampler2D p3d_Texture4; // M1 - Blendmap
uniform sampler2D p3d_Texture5; // M2 - Diffuse
uniform sampler2D p3d_Texture6; // M2 - Normal
uniform sampler2D p3d_Texture7; // M2 - Specular
uniform sampler2D p3d_Texture8; // M2 - Blendmap
uniform sampler2D p3d_Texture9; // M3 - Diffuse
uniform sampler2D p3d_Texture10; // M3 - Normal
uniform sampler2D p3d_Texture11; // M3 - Specular
uniform sampler2D p3d_Texture12; // M3 - Blendmap
uniform sampler2D p3d_Texture13; // M4 - Diffuse
uniform sampler2D p3d_Texture14; // M4 - Normal
uniform sampler2D p3d_Texture15; // M4 - Specular
uniform sampler2D p3d_Texture16; // M4 - Blendmap
uniform float detail_scale_factor;
uniform float material_0_pow;
uniform float material_0_add;
uniform float material_1_pow;
uniform float material_1_add;
uniform float material_2_pow;
uniform float material_2_add;
defines: |
#define DONT_FETCH_DEFAULT_TEXTURES 1
#define DONT_SET_MATERIAL_PROPERTIES 1
material: |
// Get detail coordinate
vec2 detail_coord = texcoord * detail_scale_factor;
vec4 layers = texture(p3d_Texture0, texcoord);
layers.xyz *= layers.w;
// Blend all materials
layers.x = blend_material(layers.x, texture(p3d_Texture4, detail_coord).x, material_0_add, material_0_pow);
layers.y = blend_material(layers.y, texture(p3d_Texture8, detail_coord).x, material_1_add, material_1_pow);
layers.z = blend_material(layers.z, texture(p3d_Texture12, detail_coord).x, material_2_add, material_2_pow);
layers.w = saturate(1.0 - dot(layers.xyz, vec3(1))); // More inituitive
// Diffuse
vec3 m_base = vec3(0);
m_base = texture(p3d_Texture1, detail_coord).xyz * layers.x;
m_base += texture(p3d_Texture5, detail_coord).xyz * layers.y;
m_base += texture(p3d_Texture9, detail_coord).xyz * layers.z;
m_base += texture(p3d_Texture13, detail_coord).xyz * layers.w;
// Normal
vec3 m_nrm = vec3(0);
m_nrm += unpack_texture_normal(texture(p3d_Texture2, detail_coord).xyz) * layers.x;
m_nrm += unpack_texture_normal(texture(p3d_Texture6, detail_coord).xyz) * layers.y;
m_nrm += unpack_texture_normal(texture(p3d_Texture10, detail_coord).xyz) * layers.z;
m_nrm += unpack_texture_normal(texture(p3d_Texture14, detail_coord).xyz) * layers.w;
// Specular
float spec = 0.0;
spec = texture(p3d_Texture3, detail_coord).x * layers.x;
spec += texture(p3d_Texture7, detail_coord).x * layers.y;
spec += texture(p3d_Texture11, detail_coord).x * layers.z;
spec += texture(p3d_Texture15, detail_coord).x * layers.w;
// Material properties
m.shading_model = mInput.shading_model;
m.basecolor = m_base * mInput.color;
m.normal = apply_normal_map(vOutput.normal, m_nrm, mInput.normalfactor);
m.specular_ior = blend_ior(mInput.specular_ior, spec);
m.roughness = mInput.roughness;
m.metallic = mInput.metallic;
m.shading_model_param0 = mInput.arbitrary0;

View File

@ -1,20 +1,20 @@
# Skybox effect
vertex:
transform: |
// vOutput.position.xy += MainSceneData.camera_pos.xy;
fragment:
defines: |
#define DONT_FETCH_DEFAULT_TEXTURES 1
#define DONT_SET_MATERIAL_PROPERTIES 1
material: |
m.basecolor = vec3(0);
m.shading_model = SHADING_MODEL_EMISSIVE;
m.specular_ior = 1.0;
m.metallic = 0.0;
m.roughness = 1.0;
m.shading_model_param0 = 0.0;
m.normal = vOutput.normal;
# Skybox effect
vertex:
transform: |
// vOutput.position.xy += MainSceneData.camera_pos.xy;
fragment:
defines: |
#define DONT_FETCH_DEFAULT_TEXTURES 1
#define DONT_SET_MATERIAL_PROPERTIES 1
material: |
m.basecolor = vec3(0);
m.shading_model = SHADING_MODEL_EMISSIVE;
m.specular_ior = 1.0;
m.metallic = 0.0;
m.roughness = 1.0;
m.shading_model_param0 = 0.0;
m.normal = vOutput.normal;

View File

@ -0,0 +1,21 @@
# SSBO Instancing Effect
vertex:
includes: |
struct Transform {
mat4 model_mat;
};
#extension GL_ARB_shader_storage_buffer_object : enable
layout(std430, binding = 10) buffer ShaderBuffer {
Transform transforms[];
};
transform: |
// Overwrite position and normal using SSBO data
mat4 model_matrix = transforms[gl_InstanceID].model_mat;
vOutput.position = (model_matrix * p3d_Vertex).xyz;
// Transform normal (approximation assuming uniform scale for performance, otherwise use inverse transpose)
mat3 normal_matrix = mat3(model_matrix);
vOutput.normal = normalize(normal_matrix * p3d_Normal);

View File

@ -1,142 +1,142 @@
# Terrain effect
# This effect uses prodecural shader splatting, you most likely want to modify
# it with your own texture-map generation code.
vertex:
inout: |
uniform struct {
sampler2D data_texture;
sampler2D heightfield;
int view_index;
int terrain_size;
int chunk_size;
} ShaderTerrainMesh;
out vec2 terrain_uv;
transform: |
// Terrain data has the layout:
// x: x-pos, y: y-pos, z: size, w: clod
vec4 terrain_data = texelFetch(ShaderTerrainMesh.data_texture,
ivec2(gl_InstanceID, ShaderTerrainMesh.view_index), 0);
// Get initial chunk position in the (0, 0, 0), (1, 1, 0) range
vec3 chunk_position = p3d_Vertex.xyz;
// CLOD implementation
float clod_factor = smoothstep(0, 1, terrain_data.w);
chunk_position.xy -= clod_factor * fract(chunk_position.xy * ShaderTerrainMesh.chunk_size / 2.0)
* 2.0 / ShaderTerrainMesh.chunk_size;
// Scale the chunk
chunk_position *= terrain_data.z * float(ShaderTerrainMesh.chunk_size)
/ float(ShaderTerrainMesh.terrain_size);
chunk_position.z *= ShaderTerrainMesh.chunk_size;
// Offset the chunk, it is important that this happens after the scale
chunk_position.xy += terrain_data.xy / float(ShaderTerrainMesh.terrain_size);
// Compute the terrain UV coordinates
terrain_uv = chunk_position.xy;
// Sample the heightfield and offset the terrain - we do not need to multiply
// the height with anything since the terrain transform is included in the
// model view projection matrix.
chunk_position.z += texture(ShaderTerrainMesh.heightfield, terrain_uv).x;
// Lower the terrain on the borders - this ensures the shadow map is generated
// correctly.
if ( min(terrain_uv.x, terrain_uv.y) < 8.0 / ShaderTerrainMesh.terrain_size ||
max(terrain_uv.x, terrain_uv.y) > 1 - 9.0 / ShaderTerrainMesh.terrain_size) {
chunk_position.z = 0;
}
vOutput.position = (p3d_ModelMatrix * vec4(chunk_position, 1)).xyz;
fragment:
defines: |
#define DONT_FETCH_DEFAULT_TEXTURES 1
#define DONT_SET_MATERIAL_PROPERTIES 1
inout: |
layout(location=4) in vec2 terrain_uv;
layout(location=5) uniform struct {
sampler2D data_texture;
sampler2D heightfield;
int view_index;
int terrain_size;
int chunk_size;
} ShaderTerrainMesh;
material: |
// Compute terrain normal
const float terrain_height = 1000.0;
vec3 pixel_size = vec3(1.0, -1.0, 0) / textureSize(ShaderTerrainMesh.heightfield, 0).xxx;
float h_u0 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.yz).x * terrain_height;
float h_u1 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.xz).x * terrain_height;
float h_v0 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.zy).x * terrain_height;
float h_v1 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.zx).x * terrain_height;
vec3 tangent = normalize(vec3(1, 0, h_u1 - h_u0));
vec3 binormal = normalize(vec3(0, 1, h_v1 - h_v0));
vec3 normal = normalize(cross(tangent, binormal));
normal.x *= -1;
// normal.y *= -1;
// Material splatting
float height = (h_u0 + h_u1 + h_v0 + h_v1) / (4.0 * terrain_height); // xxx
float slope = 1.0 - normal.z;
float grass = 0.0;
float rock = 0.0;
float snow = 0.0;
{ // Snow
snow = saturate(4.0 * (height-0.49));
snow *= saturate(pow(saturate(1.0 - slope), 2.0)) * 12.0;
//snow -= 0.6;
//snow *= 0.5;
snow = saturate(snow);
snow = pow(snow, 2.0);
}
{ // Rock
rock = saturate((pow(slope, 1.2) * 12.0 - 0.02) * 4.5);
}
{ // Grass
grass = 1.0 - saturate(rock + snow);
}
// Material definitions
MaterialShaderOutput grass_mat = make_default_material_output();
grass_mat.basecolor = vec3(0.1, 0.2, 0.1);
grass_mat.roughness = 0.8;
MaterialShaderOutput rock_mat = make_default_material_output();
rock_mat.basecolor = vec3(0.13);
rock_mat.roughness = 0.8;
rock_mat.specular_ior = 1.4;
MaterialShaderOutput snow_mat = make_default_material_output();
snow_mat.basecolor = vec3(0.6, 0.6, 0.9);
snow_mat.roughness = 0.5;
snow_mat.specular_ior = 1.7;
m.basecolor = vec3(0);
m.shading_model = SHADING_MODEL_DEFAULT;
m.specular_ior = 0.0;
m.metallic = 0.0;
m.roughness = 0.0;
m.shading_model_param0 = 0.0;
m.normal = vec3(0);
merge_material_output(m, grass_mat, grass);
merge_material_output(m, rock_mat, rock);
merge_material_output(m, snow_mat, snow);
m.normal = normal;
# Terrain effect
# This effect uses prodecural shader splatting, you most likely want to modify
# it with your own texture-map generation code.
vertex:
inout: |
uniform struct {
sampler2D data_texture;
sampler2D heightfield;
int view_index;
int terrain_size;
int chunk_size;
} ShaderTerrainMesh;
out vec2 terrain_uv;
transform: |
// Terrain data has the layout:
// x: x-pos, y: y-pos, z: size, w: clod
vec4 terrain_data = texelFetch(ShaderTerrainMesh.data_texture,
ivec2(gl_InstanceID, ShaderTerrainMesh.view_index), 0);
// Get initial chunk position in the (0, 0, 0), (1, 1, 0) range
vec3 chunk_position = p3d_Vertex.xyz;
// CLOD implementation
float clod_factor = smoothstep(0, 1, terrain_data.w);
chunk_position.xy -= clod_factor * fract(chunk_position.xy * ShaderTerrainMesh.chunk_size / 2.0)
* 2.0 / ShaderTerrainMesh.chunk_size;
// Scale the chunk
chunk_position *= terrain_data.z * float(ShaderTerrainMesh.chunk_size)
/ float(ShaderTerrainMesh.terrain_size);
chunk_position.z *= ShaderTerrainMesh.chunk_size;
// Offset the chunk, it is important that this happens after the scale
chunk_position.xy += terrain_data.xy / float(ShaderTerrainMesh.terrain_size);
// Compute the terrain UV coordinates
terrain_uv = chunk_position.xy;
// Sample the heightfield and offset the terrain - we do not need to multiply
// the height with anything since the terrain transform is included in the
// model view projection matrix.
chunk_position.z += texture(ShaderTerrainMesh.heightfield, terrain_uv).x;
// Lower the terrain on the borders - this ensures the shadow map is generated
// correctly.
if ( min(terrain_uv.x, terrain_uv.y) < 8.0 / ShaderTerrainMesh.terrain_size ||
max(terrain_uv.x, terrain_uv.y) > 1 - 9.0 / ShaderTerrainMesh.terrain_size) {
chunk_position.z = 0;
}
vOutput.position = (p3d_ModelMatrix * vec4(chunk_position, 1)).xyz;
fragment:
defines: |
#define DONT_FETCH_DEFAULT_TEXTURES 1
#define DONT_SET_MATERIAL_PROPERTIES 1
inout: |
layout(location=4) in vec2 terrain_uv;
layout(location=5) uniform struct {
sampler2D data_texture;
sampler2D heightfield;
int view_index;
int terrain_size;
int chunk_size;
} ShaderTerrainMesh;
material: |
// Compute terrain normal
const float terrain_height = 1000.0;
vec3 pixel_size = vec3(1.0, -1.0, 0) / textureSize(ShaderTerrainMesh.heightfield, 0).xxx;
float h_u0 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.yz).x * terrain_height;
float h_u1 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.xz).x * terrain_height;
float h_v0 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.zy).x * terrain_height;
float h_v1 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.zx).x * terrain_height;
vec3 tangent = normalize(vec3(1, 0, h_u1 - h_u0));
vec3 binormal = normalize(vec3(0, 1, h_v1 - h_v0));
vec3 normal = normalize(cross(tangent, binormal));
normal.x *= -1;
// normal.y *= -1;
// Material splatting
float height = (h_u0 + h_u1 + h_v0 + h_v1) / (4.0 * terrain_height); // xxx
float slope = 1.0 - normal.z;
float grass = 0.0;
float rock = 0.0;
float snow = 0.0;
{ // Snow
snow = saturate(4.0 * (height-0.49));
snow *= saturate(pow(saturate(1.0 - slope), 2.0)) * 12.0;
//snow -= 0.6;
//snow *= 0.5;
snow = saturate(snow);
snow = pow(snow, 2.0);
}
{ // Rock
rock = saturate((pow(slope, 1.2) * 12.0 - 0.02) * 4.5);
}
{ // Grass
grass = 1.0 - saturate(rock + snow);
}
// Material definitions
MaterialShaderOutput grass_mat = make_default_material_output();
grass_mat.basecolor = vec3(0.1, 0.2, 0.1);
grass_mat.roughness = 0.8;
MaterialShaderOutput rock_mat = make_default_material_output();
rock_mat.basecolor = vec3(0.13);
rock_mat.roughness = 0.8;
rock_mat.specular_ior = 1.4;
MaterialShaderOutput snow_mat = make_default_material_output();
snow_mat.basecolor = vec3(0.6, 0.6, 0.9);
snow_mat.roughness = 0.5;
snow_mat.specular_ior = 1.7;
m.basecolor = vec3(0);
m.shading_model = SHADING_MODEL_DEFAULT;
m.specular_ior = 0.0;
m.metallic = 0.0;
m.roughness = 0.0;
m.shading_model_param0 = 0.0;
m.normal = vec3(0);
merge_material_output(m, grass_mat, grass);
merge_material_output(m, rock_mat, rock);
merge_material_output(m, snow_mat, snow);
m.normal = normal;

View File

@ -1,47 +1,47 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# flake8: noqa
__all__ = ("RenderPipeline", "SpotLight", "PointLight")
# This file includes all classes from the pipeline which are exposed
from rpcore.render_pipeline import RenderPipeline
from rpcore.native import SpotLight, PointLight
# Polyfill a set_shader_inputs function for older versions of Panda.
from panda3d.core import NodePath
from direct.extensions_native.extension_native_helpers import Dtool_funcToMethod
from rplibs.six import iteritems
if not hasattr(NodePath, 'set_shader_inputs'):
def set_shader_inputs(self, **inputs):
set_shader_input = self.set_shader_input
for args in iteritems(inputs):
set_shader_input(*args)
Dtool_funcToMethod(set_shader_inputs, NodePath)
del set_shader_inputs
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# flake8: noqa
__all__ = ("RenderPipeline", "SpotLight", "PointLight")
# This file includes all classes from the pipeline which are exposed
from rpcore.render_pipeline import RenderPipeline
from rpcore.native import SpotLight, PointLight
# Polyfill a set_shader_inputs function for older versions of Panda.
from panda3d.core import NodePath
from direct.extensions_native.extension_native_helpers import Dtool_funcToMethod
from rplibs.six import iteritems
if not hasattr(NodePath, 'set_shader_inputs'):
def set_shader_inputs(self, **inputs):
set_shader_input = self.set_shader_input
for args in iteritems(inputs):
set_shader_input(*args)
Dtool_funcToMethod(set_shader_inputs, NodePath)
del set_shader_inputs

View File

@ -1,246 +1,246 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from panda3d.core import CS_yup_right, CS_zup_right, invert, Vec3, Mat4, Vec4
from panda3d.core import SamplerState
from direct.stdpy.file import open
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
from rpcore.util.shader_input_blocks import GroupedInputBlock
class CommonResources(RPObject):
""" This class manages the loading and binding of commonly used resources,
such as textures, models, but also shader inputs """
def __init__(self, pipeline):
RPObject.__init__(self)
self._pipeline = pipeline
self._showbase = Globals.base
self._ptas = {}
self._load_fonts()
self._load_textures()
self._setup_inputs()
def _load_fonts(self):
""" Loads the default font used for rendering and assigns it to
Globals.font for further usage """
font = RPLoader.load_font("/$$rp/data/font/Roboto-Medium.ttf")
font.set_pixels_per_unit(35)
font.set_poly_margin(0.0)
font.set_texture_margin(1)
font.set_bg(Vec4(1, 1, 1, 0))
font.set_fg(Vec4(1, 1, 1, 1))
Globals.font = font
def _setup_inputs(self):
""" Creates commonly used shader inputs such as the current mvp and
registers them to the stage manager so they can be used for rendering """
self._input_ubo = GroupedInputBlock("MainSceneData")
inputs = (
("camera_pos", "vec3"),
("view_proj_mat_no_jitter", "mat4"),
("last_view_proj_mat_no_jitter", "mat4"),
("last_inv_view_proj_mat_no_jitter", "mat4"),
("view_mat_z_up", "mat4"),
("proj_mat", "mat4"),
("inv_proj_mat", "mat4"),
("view_mat_billboard", "mat4"),
("frame_delta", "float"),
("smooth_frame_delta", "float"),
("frame_time", "float"),
("current_film_offset", "vec2"),
("frame_index", "int"),
("screen_size", "ivec2"),
("native_screen_size", "ivec2"),
("lc_tile_count", "ivec2"),
("ws_frustum_directions", "mat4"),
("vs_frustum_directions", "mat4"),
)
for name, ipt_type in inputs:
self._input_ubo.register_pta(name, ipt_type)
self._pipeline.stage_mgr.input_blocks.append(self._input_ubo)
# Main camera and main render have to be regular inputs, since they are
# used in the shaders by that name.
self._pipeline.stage_mgr.inputs["mainCam"] = self._showbase.cam
self._pipeline.stage_mgr.inputs["mainRender"] = self._showbase.render
# Set the correct frame rate interval
Globals.clock.set_average_frame_rate_interval(3.0)
# Set initial value for view_proj_mat_no_jitter
view_mat = Globals.render.get_transform(self._showbase.cam).get_mat()
proj_mat = Mat4(self._showbase.camLens.get_projection_mat())
proj_mat.set_cell(1, 0, 0.0)
proj_mat.set_cell(1, 1, 0.0)
self._input_ubo.update_input("view_proj_mat_no_jitter", view_mat * proj_mat)
def write_config(self):
""" Generates the shader configuration for the common inputs """
content = self._input_ubo.generate_shader_code()
try:
# Try to write the temporary file
with open("/$$rptemp/$$main_scene_data.inc.glsl", "w") as handle:
handle.write(content)
except IOError as msg:
self.error("Failed to write common resources shader configuration!", msg)
def _load_textures(self):
""" Loads commonly used textures and makes them available via the
stage manager """
self._load_environment_cubemap()
self._load_prefilter_brdf()
self._load_skydome()
def _load_environment_cubemap(self):
""" Loads the default cubemap used for the environment, which is used
when no other environment data is available """
envmap = RPLoader.load_cube_map(
"/$$rp/data/default_cubemap/cubemap.txo", read_mipmaps=True)
envmap.set_minfilter(SamplerState.FT_linear_mipmap_linear)
# envmap.set_format(Image.F_rgba16)
envmap.set_magfilter(SamplerState.FT_linear)
envmap.set_wrap_u(SamplerState.WM_repeat)
envmap.set_wrap_v(SamplerState.WM_repeat)
envmap.set_wrap_w(SamplerState.WM_repeat)
self._pipeline.stage_mgr.inputs["DefaultEnvmap"] = envmap
def _load_prefilter_brdf(self):
""" Loads the prefiltered brdf """
luts = [
{"src": "slices/env_brdf_#.png", "input": "PrefilteredBRDF"},
{"src": "slices_metal/env_brdf.png", "input": "PrefilteredMetalBRDF"},
{"src": "slices_coat/env_brdf.png", "input": "PrefilteredCoatBRDF"},
]
for config in luts:
loader_method = RPLoader.load_texture
if "#" in config["src"]:
loader_method = RPLoader.load_3d_texture
brdf_tex = loader_method("/$$rp/data/environment_brdf/{}".format(config["src"]))
brdf_tex.set_minfilter(SamplerState.FT_linear)
brdf_tex.set_magfilter(SamplerState.FT_linear)
brdf_tex.set_wrap_u(SamplerState.WM_clamp)
brdf_tex.set_wrap_v(SamplerState.WM_clamp)
brdf_tex.set_wrap_w(SamplerState.WM_clamp)
brdf_tex.set_anisotropic_degree(0)
self._pipeline.stage_mgr.inputs[config["input"]] = brdf_tex
def _load_skydome(self):
""" Loads the skydome """
skydome = RPLoader.load_texture("/$$rp/data/builtin_models/skybox/skybox.txo")
skydome.set_wrap_u(SamplerState.WM_clamp)
skydome.set_wrap_v(SamplerState.WM_clamp)
self._pipeline.stage_mgr.inputs["DefaultSkydome"] = skydome
def load_default_skybox(self):
skybox = RPLoader.load_model("/$$rp/data/builtin_models/skybox/skybox.bam")
return skybox
def update(self):
""" Updates the commonly used resources, mostly the shader inputs """
update = self._input_ubo.update_input
# Get the current transform matrix of the camera
view_mat = Globals.render.get_transform(self._showbase.cam).get_mat()
# Compute the view matrix, but with a z-up coordinate system
zup_conversion = Mat4.convert_mat(CS_zup_right, CS_yup_right)
update("view_mat_z_up", view_mat * zup_conversion)
# Compute the view matrix without the camera rotation
view_mat_billboard = Mat4(view_mat)
view_mat_billboard.set_row(0, Vec3(1, 0, 0))
view_mat_billboard.set_row(1, Vec3(0, 1, 0))
view_mat_billboard.set_row(2, Vec3(0, 0, 1))
update("view_mat_billboard", view_mat_billboard)
update("camera_pos", self._showbase.camera.get_pos(Globals.render))
# Compute last view projection mat
curr_vp = self._input_ubo.get_input("view_proj_mat_no_jitter")
update("last_view_proj_mat_no_jitter", curr_vp)
curr_vp = Mat4(curr_vp)
curr_vp.invert_in_place()
curr_inv_vp = curr_vp
update("last_inv_view_proj_mat_no_jitter", curr_inv_vp)
proj_mat = Mat4(self._showbase.camLens.get_projection_mat())
# Set the projection matrix as an input, but convert it to the correct
# coordinate system before.
proj_mat_zup = Mat4.convert_mat(CS_yup_right, CS_zup_right) * proj_mat
update("proj_mat", proj_mat_zup)
# Set the inverse projection matrix
update("inv_proj_mat", invert(proj_mat_zup))
# Remove jitter and set the new view projection mat
proj_mat.set_cell(1, 0, 0.0)
proj_mat.set_cell(1, 1, 0.0)
update("view_proj_mat_no_jitter", view_mat * proj_mat)
# Store the frame delta
update("frame_delta", Globals.clock.get_dt())
update("smooth_frame_delta", 1.0 / max(1e-5, Globals.clock.get_average_frame_rate()))
update("frame_time", Globals.clock.get_frame_time())
# Store the current film offset, we use this to compute the pixel-perfect
# velocity, which is otherwise not possible. Usually this is always 0
# except when SMAA and reprojection is enabled
update("current_film_offset", self._showbase.camLens.get_film_offset())
update("frame_index", Globals.clock.get_frame_count())
# Compute frustum corners in the order BL, BR, TL, TR
ws_frustum_directions = Mat4()
vs_frustum_directions = Mat4()
inv_proj_mat = Globals.base.camLens.get_projection_mat_inv()
view_mat_inv = Mat4(view_mat)
view_mat_inv.invert_in_place()
for i, point in enumerate(((-1, -1), (1, -1), (-1, 1), (1, 1))):
result = inv_proj_mat.xform(Vec4(point[0], point[1], 1.0, 1.0))
vs_dir = (zup_conversion.xform(result)).xyz.normalized()
vs_frustum_directions.set_row(i, Vec4(vs_dir, 1))
ws_dir = view_mat_inv.xform(Vec4(result.xyz, 0))
ws_frustum_directions.set_row(i, ws_dir)
update("vs_frustum_directions", vs_frustum_directions)
update("ws_frustum_directions", ws_frustum_directions)
update("screen_size", Globals.resolution)
update("native_screen_size", Globals.native_resolution)
update("lc_tile_count", self._pipeline.light_mgr.num_tiles)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from panda3d.core import CS_yup_right, CS_zup_right, invert, Vec3, Mat4, Vec4
from panda3d.core import SamplerState
from direct.stdpy.file import open
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
from rpcore.util.shader_input_blocks import GroupedInputBlock
class CommonResources(RPObject):
""" This class manages the loading and binding of commonly used resources,
such as textures, models, but also shader inputs """
def __init__(self, pipeline):
RPObject.__init__(self)
self._pipeline = pipeline
self._showbase = Globals.base
self._ptas = {}
self._load_fonts()
self._load_textures()
self._setup_inputs()
def _load_fonts(self):
""" Loads the default font used for rendering and assigns it to
Globals.font for further usage """
font = RPLoader.load_font("/$$rp/data/font/Roboto-Medium.ttf")
font.set_pixels_per_unit(35)
font.set_poly_margin(0.0)
font.set_texture_margin(1)
font.set_bg(Vec4(1, 1, 1, 0))
font.set_fg(Vec4(1, 1, 1, 1))
Globals.font = font
def _setup_inputs(self):
""" Creates commonly used shader inputs such as the current mvp and
registers them to the stage manager so they can be used for rendering """
self._input_ubo = GroupedInputBlock("MainSceneData")
inputs = (
("camera_pos", "vec3"),
("view_proj_mat_no_jitter", "mat4"),
("last_view_proj_mat_no_jitter", "mat4"),
("last_inv_view_proj_mat_no_jitter", "mat4"),
("view_mat_z_up", "mat4"),
("proj_mat", "mat4"),
("inv_proj_mat", "mat4"),
("view_mat_billboard", "mat4"),
("frame_delta", "float"),
("smooth_frame_delta", "float"),
("frame_time", "float"),
("current_film_offset", "vec2"),
("frame_index", "int"),
("screen_size", "ivec2"),
("native_screen_size", "ivec2"),
("lc_tile_count", "ivec2"),
("ws_frustum_directions", "mat4"),
("vs_frustum_directions", "mat4"),
)
for name, ipt_type in inputs:
self._input_ubo.register_pta(name, ipt_type)
self._pipeline.stage_mgr.input_blocks.append(self._input_ubo)
# Main camera and main render have to be regular inputs, since they are
# used in the shaders by that name.
self._pipeline.stage_mgr.inputs["mainCam"] = self._showbase.cam
self._pipeline.stage_mgr.inputs["mainRender"] = self._showbase.render
# Set the correct frame rate interval
Globals.clock.set_average_frame_rate_interval(3.0)
# Set initial value for view_proj_mat_no_jitter
view_mat = Globals.render.get_transform(self._showbase.cam).get_mat()
proj_mat = Mat4(self._showbase.camLens.get_projection_mat())
proj_mat.set_cell(1, 0, 0.0)
proj_mat.set_cell(1, 1, 0.0)
self._input_ubo.update_input("view_proj_mat_no_jitter", view_mat * proj_mat)
def write_config(self):
""" Generates the shader configuration for the common inputs """
content = self._input_ubo.generate_shader_code()
try:
# Try to write the temporary file
with open("/$$rptemp/$$main_scene_data.inc.glsl", "w") as handle:
handle.write(content)
except IOError as msg:
self.error("Failed to write common resources shader configuration!", msg)
def _load_textures(self):
""" Loads commonly used textures and makes them available via the
stage manager """
self._load_environment_cubemap()
self._load_prefilter_brdf()
self._load_skydome()
def _load_environment_cubemap(self):
""" Loads the default cubemap used for the environment, which is used
when no other environment data is available """
envmap = RPLoader.load_cube_map(
"/$$rp/data/default_cubemap/cubemap.txo", read_mipmaps=True)
envmap.set_minfilter(SamplerState.FT_linear_mipmap_linear)
# envmap.set_format(Image.F_rgba16)
envmap.set_magfilter(SamplerState.FT_linear)
envmap.set_wrap_u(SamplerState.WM_repeat)
envmap.set_wrap_v(SamplerState.WM_repeat)
envmap.set_wrap_w(SamplerState.WM_repeat)
self._pipeline.stage_mgr.inputs["DefaultEnvmap"] = envmap
def _load_prefilter_brdf(self):
""" Loads the prefiltered brdf """
luts = [
{"src": "slices/env_brdf_#.png", "input": "PrefilteredBRDF"},
{"src": "slices_metal/env_brdf.png", "input": "PrefilteredMetalBRDF"},
{"src": "slices_coat/env_brdf.png", "input": "PrefilteredCoatBRDF"},
]
for config in luts:
loader_method = RPLoader.load_texture
if "#" in config["src"]:
loader_method = RPLoader.load_3d_texture
brdf_tex = loader_method("/$$rp/data/environment_brdf/{}".format(config["src"]))
brdf_tex.set_minfilter(SamplerState.FT_linear)
brdf_tex.set_magfilter(SamplerState.FT_linear)
brdf_tex.set_wrap_u(SamplerState.WM_clamp)
brdf_tex.set_wrap_v(SamplerState.WM_clamp)
brdf_tex.set_wrap_w(SamplerState.WM_clamp)
brdf_tex.set_anisotropic_degree(0)
self._pipeline.stage_mgr.inputs[config["input"]] = brdf_tex
def _load_skydome(self):
""" Loads the skydome """
skydome = RPLoader.load_texture("/$$rp/data/builtin_models/skybox/skybox.txo")
skydome.set_wrap_u(SamplerState.WM_clamp)
skydome.set_wrap_v(SamplerState.WM_clamp)
self._pipeline.stage_mgr.inputs["DefaultSkydome"] = skydome
def load_default_skybox(self):
skybox = RPLoader.load_model("/$$rp/data/builtin_models/skybox/skybox.bam")
return skybox
def update(self):
""" Updates the commonly used resources, mostly the shader inputs """
update = self._input_ubo.update_input
# Get the current transform matrix of the camera
view_mat = Globals.render.get_transform(self._showbase.cam).get_mat()
# Compute the view matrix, but with a z-up coordinate system
zup_conversion = Mat4.convert_mat(CS_zup_right, CS_yup_right)
update("view_mat_z_up", view_mat * zup_conversion)
# Compute the view matrix without the camera rotation
view_mat_billboard = Mat4(view_mat)
view_mat_billboard.set_row(0, Vec3(1, 0, 0))
view_mat_billboard.set_row(1, Vec3(0, 1, 0))
view_mat_billboard.set_row(2, Vec3(0, 0, 1))
update("view_mat_billboard", view_mat_billboard)
update("camera_pos", self._showbase.camera.get_pos(Globals.render))
# Compute last view projection mat
curr_vp = self._input_ubo.get_input("view_proj_mat_no_jitter")
update("last_view_proj_mat_no_jitter", curr_vp)
curr_vp = Mat4(curr_vp)
curr_vp.invert_in_place()
curr_inv_vp = curr_vp
update("last_inv_view_proj_mat_no_jitter", curr_inv_vp)
proj_mat = Mat4(self._showbase.camLens.get_projection_mat())
# Set the projection matrix as an input, but convert it to the correct
# coordinate system before.
proj_mat_zup = Mat4.convert_mat(CS_yup_right, CS_zup_right) * proj_mat
update("proj_mat", proj_mat_zup)
# Set the inverse projection matrix
update("inv_proj_mat", invert(proj_mat_zup))
# Remove jitter and set the new view projection mat
proj_mat.set_cell(1, 0, 0.0)
proj_mat.set_cell(1, 1, 0.0)
update("view_proj_mat_no_jitter", view_mat * proj_mat)
# Store the frame delta
update("frame_delta", Globals.clock.get_dt())
update("smooth_frame_delta", 1.0 / max(1e-5, Globals.clock.get_average_frame_rate()))
update("frame_time", Globals.clock.get_frame_time())
# Store the current film offset, we use this to compute the pixel-perfect
# velocity, which is otherwise not possible. Usually this is always 0
# except when SMAA and reprojection is enabled
update("current_film_offset", self._showbase.camLens.get_film_offset())
update("frame_index", Globals.clock.get_frame_count())
# Compute frustum corners in the order BL, BR, TL, TR
ws_frustum_directions = Mat4()
vs_frustum_directions = Mat4()
inv_proj_mat = Globals.base.camLens.get_projection_mat_inv()
view_mat_inv = Mat4(view_mat)
view_mat_inv.invert_in_place()
for i, point in enumerate(((-1, -1), (1, -1), (-1, 1), (1, 1))):
result = inv_proj_mat.xform(Vec4(point[0], point[1], 1.0, 1.0))
vs_dir = (zup_conversion.xform(result)).xyz.normalized()
vs_frustum_directions.set_row(i, Vec4(vs_dir, 1))
ws_dir = view_mat_inv.xform(Vec4(result.xyz, 0))
ws_frustum_directions.set_row(i, ws_dir)
update("vs_frustum_directions", vs_frustum_directions)
update("ws_frustum_directions", ws_frustum_directions)
update("screen_size", Globals.resolution)
update("native_screen_size", Globals.native_resolution)
update("lc_tile_count", self._pipeline.light_mgr.num_tiles)

View File

@ -1,307 +1,307 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from rplibs.six import iteritems, iterkeys
from rplibs.yaml import load_yaml_file
from panda3d.core import Filename
from direct.stdpy.file import open
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class Effect(RPObject):
""" This class represents an instance of a compiled effect. It can be loaded
from a file. """
# Configuration options which can be set per effect instance. These control
# which features are available in the effect, and which passes to render.
_DEFAULT_OPTIONS = {
"render_gbuffer": True,
"render_shadow": True,
"render_voxelize": True,
"render_envmap": True,
"render_forward": False,
"alpha_testing": True,
"normal_mapping": True,
"parallax_mapping": False,
}
# All supported render passes, should match the available passes in the
# TagStateManager class.
_PASSES = ("gbuffer", "shadow", "voxelize", "envmap", "forward")
# Effects are cached based on their source filename and options, this is
# the cache where compiled are effects stored.
_GLOBAL_CACHE = {}
# Global counter to store the amount of generated effects, used to create
# a unique id used for writing temporary files.
_EFFECT_ID = 0
@classmethod
def load(cls, filename, options):
""" Loads an effect from a given filename with the specified options.
This lookups in the global effect cache, and checks if a similar effect
(i.e. with the same hash) was already loaded, and in that case returns it.
Otherwise a new effect with the given options is created. """
effect_hash = cls._generate_hash(filename, options)
if effect_hash in cls._GLOBAL_CACHE:
return cls._GLOBAL_CACHE[effect_hash]
effect = cls()
effect.set_options(options)
if not effect.do_load(filename):
RPObject.global_error("Effect", "Could not load effect!")
return None
return effect
@classmethod
def _generate_hash(cls, filename, options):
""" Generates an unique hash for the effect. The effect hash is based
on the filename and the configured options, and is ensured to make the
effect unique. This is important to make sure the caching works as
intended. All options not present in options are set to the default value"""
# Set all options which are not present in the dict to its defaults
options = {k: options.get(k, v) for k, v in iteritems(cls._DEFAULT_OPTIONS)}
# Hash filename, make sure it has the right format and also resolve
# it to an absolute path, to make sure that relative paths are cached
# correctly (otherwise, specifying a different path to the same file
# will cause a cache miss)
filename = Filename(filename)
filename.make_absolute()
file_hash = str(hash(filename.to_os_generic()))
# Hash the options, that is, sort the keys to make sure the values
# are always in the same order, and then convert the flags to strings using
# '1' for a set flag, and '0' for a unset flag
options_hash = "".join(["1" if options[key] else "0" for key in sorted(iterkeys(options))])
return file_hash + "-" + options_hash
def __init__(self):
""" Constructs a new empty effect, this is a private constructor and
should not be called. Instead, use Effect.load() """
RPObject.__init__(self)
self.effect_id = Effect._EFFECT_ID
Effect._EFFECT_ID += 1
self.filename = None
self._options = self._DEFAULT_OPTIONS.copy()
self._generated_shader_paths = {}
self._shader_objs = {}
def get_option(self, name):
""" Returns a given option value by name """
return self._options[name]
def set_options(self, options):
""" Sets the effect options, overriding the default options """
for key, val in iteritems(options):
if key not in self._options:
self.error("Unkown option:", key)
continue
self._options[key] = val
def do_load(self, filename):
""" Internal method to load the effect from the given filename, do
not use this directly, instead use load(). """
self.filename = filename
self.effect_name = self._convert_filename_to_name(filename)
self.effect_hash = self._generate_hash(filename, self._options)
# Load the YAML file
parsed_yaml = load_yaml_file(filename) or {}
self._parse_content(parsed_yaml)
# Construct a shader object for each pass
for pass_id in self._PASSES:
vertex_src = self._generated_shader_paths["vertex-" + pass_id]
fragment_src = self._generated_shader_paths["fragment-" + pass_id]
self._shader_objs[pass_id] = RPLoader.load_shader(vertex_src, fragment_src)
return True
def get_shader_obj(self, pass_id):
""" Returns a handle to the compiled shader object for a given render
pass. """
if pass_id not in self._shader_objs:
self.warn("Pass '" + pass_id + "' not found!")
return False
return self._shader_objs[pass_id]
def _convert_filename_to_name(self, filename):
""" Constructs an effect name from a filename, this is used for writing
out temporary files """
return filename.replace(".yaml", "").replace("effects/", "")\
.replace("/", "_").replace("\\", "_").replace(".", "-")
def _parse_content(self, parsed_yaml):
""" Internal method to construct the effect from a yaml object """
vtx_data = parsed_yaml.get("vertex", None) or {}
frag_data = parsed_yaml.get("fragment", None) or {}
for pass_id in self._PASSES:
self._parse_shader_template(pass_id, "vertex", vtx_data)
self._parse_shader_template(pass_id, "fragment", frag_data)
def _parse_shader_template(self, pass_id, stage, data):
""" Parses a fragment template. This just finds the default template
for the shader, and redirects that to construct_shader_from_data """
if stage == "fragment":
shader_ext = {"vertex": "vert", "fragment": "frag"}[stage]
template_src = "/$$rp/shader/templates/{}.{}.glsl".format(pass_id, shader_ext)
elif stage == "vertex":
# Using a shared vertex shader
template_src = "/$$rp/shader/templates/vertex.vert.glsl"
shader_path = self._construct_shader_from_data(pass_id, stage, template_src, data)
self._generated_shader_paths[stage + "-" + pass_id] = shader_path
def _construct_shader_from_data(self, pass_id, stage, template_src, data): # noqa # pylint: disable=too-many-branches
""" Constructs a shader from a given dataset """
injects = {"defines": []}
for key, val in iteritems(self._options):
if isinstance(val, bool):
val_str = "1" if val else "0"
else:
val_str = str(val)
injects["defines"].append("#define OPT_{} {}".format(key.upper(), val_str))
injects["defines"].append("#define IN_" + stage.upper() + "_SHADER 1")
injects["defines"].append("#define IN_" + pass_id.upper() + "_SHADER 1")
injects["defines"].append("#define IN_RENDERING_PASS 1")
# Parse dependencies
if "dependencies" in data:
injects["includes"] = []
for dependency in data["dependencies"]:
include_str = "#pragma include \"{}\"".format(dependency)
injects["includes"].append(include_str)
del data["dependencies"]
# Append aditional injects
for key, val in iteritems(data):
if val is None:
self.warn("Empty insertion: '" + key + "'")
continue
if isinstance(val, (list, tuple)):
self.warn("Invalid syntax, you used a list but you should have used a string:")
self.warn(val)
continue
injects[key] = injects.get(key, []) + [i for i in val.split("\n")]
cache_key = self.effect_name + "@" + stage + "-" + pass_id + "@" + self.effect_hash
return self._process_shader_template(template_src, cache_key, injects)
def _process_shader_template(self, template_src, cache_key, injections): # noqa # pylint: disable=too-many-branches
""" Generates a compiled shader object from a given shader
source location and code injection definitions. """
with open(template_src, "r") as handle:
shader_lines = handle.readlines()
parsed_lines = ["\n\n"]
addline = parsed_lines.append
addline("/* Compiled Shader Template")
addline(" * generated from: '" + template_src + "'")
addline(" * cache key: '" + cache_key + "'")
addline(" *")
addline(" * !!! Autogenerated, do not edit! Your changes will be lost. !!!")
addline(" */\n\n")
# Store whether we are in the main function already - we need this
# to properly insert scoped code blocks
in_main = False
for line in shader_lines: # pylint: disable=too-many-nested-blocks
stripped_line = line.strip().lower()
# Check if we are already in the main function
if "void main()" in stripped_line:
in_main = True
# Check if the current line is a hook
if stripped_line.startswith("%") and stripped_line.endswith("%"):
# If the line is a hook, get the hook name and save the
# indent so we can indent all injected lines properly.
hook_name = stripped_line[1:-1]
indent = " " * (len(line) - len(line.lstrip()))
# Inject all registered template values into the hook
if hook_name in injections:
# Directly remove the value from the list so we can check which
# hooks were not found in the template
insertions = injections.pop(hook_name)
if len(insertions) > 0:
# When we are in the main function, we have to make sure we
# use a seperate scope, so there are no conflicts with variable
# declarations
header = indent + "/* Hook: " + hook_name + " */" + (" {" if in_main else "") # noqa # pylint: disable=line-too-long
addline(header)
for line_to_insert in insertions:
if line_to_insert is None:
self.warn("Empty insertion '" + hook_name + "'")
continue
if not isinstance(line_to_insert, str):
self.warn("Invalid line type: ", line_to_insert)
continue
# Dont indent defines and pragmas
if line_to_insert.startswith("#"):
addline(line_to_insert)
else:
addline(indent + line_to_insert)
if in_main:
addline(indent + "}")
else:
addline(line.rstrip())
# Add a closing newline to the file
addline("")
# Warn the user about all unused hooks
for key in injections:
self.warn("Hook '" + key + "' not found in template '" + template_src + "'!")
# Write the constructed shader and load it back
shader_content = "\n".join(parsed_lines)
temp_path = "/$$rptemp/$$effect-" + cache_key + ".glsl"
with open(temp_path, "w") as handle:
handle.write(shader_content)
return temp_path
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from rplibs.six import iteritems, iterkeys
from rplibs.yaml import load_yaml_file
from panda3d.core import Filename
from direct.stdpy.file import open
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class Effect(RPObject):
""" This class represents an instance of a compiled effect. It can be loaded
from a file. """
# Configuration options which can be set per effect instance. These control
# which features are available in the effect, and which passes to render.
_DEFAULT_OPTIONS = {
"render_gbuffer": True,
"render_shadow": True,
"render_voxelize": True,
"render_envmap": True,
"render_forward": False,
"alpha_testing": True,
"normal_mapping": True,
"parallax_mapping": False,
}
# All supported render passes, should match the available passes in the
# TagStateManager class.
_PASSES = ("gbuffer", "shadow", "voxelize", "envmap", "forward")
# Effects are cached based on their source filename and options, this is
# the cache where compiled are effects stored.
_GLOBAL_CACHE = {}
# Global counter to store the amount of generated effects, used to create
# a unique id used for writing temporary files.
_EFFECT_ID = 0
@classmethod
def load(cls, filename, options):
""" Loads an effect from a given filename with the specified options.
This lookups in the global effect cache, and checks if a similar effect
(i.e. with the same hash) was already loaded, and in that case returns it.
Otherwise a new effect with the given options is created. """
effect_hash = cls._generate_hash(filename, options)
if effect_hash in cls._GLOBAL_CACHE:
return cls._GLOBAL_CACHE[effect_hash]
effect = cls()
effect.set_options(options)
if not effect.do_load(filename):
RPObject.global_error("Effect", "Could not load effect!")
return None
return effect
@classmethod
def _generate_hash(cls, filename, options):
""" Generates an unique hash for the effect. The effect hash is based
on the filename and the configured options, and is ensured to make the
effect unique. This is important to make sure the caching works as
intended. All options not present in options are set to the default value"""
# Set all options which are not present in the dict to its defaults
options = {k: options.get(k, v) for k, v in iteritems(cls._DEFAULT_OPTIONS)}
# Hash filename, make sure it has the right format and also resolve
# it to an absolute path, to make sure that relative paths are cached
# correctly (otherwise, specifying a different path to the same file
# will cause a cache miss)
filename = Filename(filename)
filename.make_absolute()
file_hash = str(hash(filename.to_os_generic()))
# Hash the options, that is, sort the keys to make sure the values
# are always in the same order, and then convert the flags to strings using
# '1' for a set flag, and '0' for a unset flag
options_hash = "".join(["1" if options[key] else "0" for key in sorted(iterkeys(options))])
return file_hash + "-" + options_hash
def __init__(self):
""" Constructs a new empty effect, this is a private constructor and
should not be called. Instead, use Effect.load() """
RPObject.__init__(self)
self.effect_id = Effect._EFFECT_ID
Effect._EFFECT_ID += 1
self.filename = None
self._options = self._DEFAULT_OPTIONS.copy()
self._generated_shader_paths = {}
self._shader_objs = {}
def get_option(self, name):
""" Returns a given option value by name """
return self._options[name]
def set_options(self, options):
""" Sets the effect options, overriding the default options """
for key, val in iteritems(options):
if key not in self._options:
self.error("Unkown option:", key)
continue
self._options[key] = val
def do_load(self, filename):
""" Internal method to load the effect from the given filename, do
not use this directly, instead use load(). """
self.filename = filename
self.effect_name = self._convert_filename_to_name(filename)
self.effect_hash = self._generate_hash(filename, self._options)
# Load the YAML file
parsed_yaml = load_yaml_file(filename) or {}
self._parse_content(parsed_yaml)
# Construct a shader object for each pass
for pass_id in self._PASSES:
vertex_src = self._generated_shader_paths["vertex-" + pass_id]
fragment_src = self._generated_shader_paths["fragment-" + pass_id]
self._shader_objs[pass_id] = RPLoader.load_shader(vertex_src, fragment_src)
return True
def get_shader_obj(self, pass_id):
""" Returns a handle to the compiled shader object for a given render
pass. """
if pass_id not in self._shader_objs:
self.warn("Pass '" + pass_id + "' not found!")
return False
return self._shader_objs[pass_id]
def _convert_filename_to_name(self, filename):
""" Constructs an effect name from a filename, this is used for writing
out temporary files """
return filename.replace(".yaml", "").replace("effects/", "")\
.replace("/", "_").replace("\\", "_").replace(".", "-")
def _parse_content(self, parsed_yaml):
""" Internal method to construct the effect from a yaml object """
vtx_data = parsed_yaml.get("vertex", None) or {}
frag_data = parsed_yaml.get("fragment", None) or {}
for pass_id in self._PASSES:
self._parse_shader_template(pass_id, "vertex", vtx_data)
self._parse_shader_template(pass_id, "fragment", frag_data)
def _parse_shader_template(self, pass_id, stage, data):
""" Parses a fragment template. This just finds the default template
for the shader, and redirects that to construct_shader_from_data """
if stage == "fragment":
shader_ext = {"vertex": "vert", "fragment": "frag"}[stage]
template_src = "/$$rp/shader/templates/{}.{}.glsl".format(pass_id, shader_ext)
elif stage == "vertex":
# Using a shared vertex shader
template_src = "/$$rp/shader/templates/vertex.vert.glsl"
shader_path = self._construct_shader_from_data(pass_id, stage, template_src, data)
self._generated_shader_paths[stage + "-" + pass_id] = shader_path
def _construct_shader_from_data(self, pass_id, stage, template_src, data): # noqa # pylint: disable=too-many-branches
""" Constructs a shader from a given dataset """
injects = {"defines": []}
for key, val in iteritems(self._options):
if isinstance(val, bool):
val_str = "1" if val else "0"
else:
val_str = str(val)
injects["defines"].append("#define OPT_{} {}".format(key.upper(), val_str))
injects["defines"].append("#define IN_" + stage.upper() + "_SHADER 1")
injects["defines"].append("#define IN_" + pass_id.upper() + "_SHADER 1")
injects["defines"].append("#define IN_RENDERING_PASS 1")
# Parse dependencies
if "dependencies" in data:
injects["includes"] = []
for dependency in data["dependencies"]:
include_str = "#pragma include \"{}\"".format(dependency)
injects["includes"].append(include_str)
del data["dependencies"]
# Append aditional injects
for key, val in iteritems(data):
if val is None:
self.warn("Empty insertion: '" + key + "'")
continue
if isinstance(val, (list, tuple)):
self.warn("Invalid syntax, you used a list but you should have used a string:")
self.warn(val)
continue
injects[key] = injects.get(key, []) + [i for i in val.split("\n")]
cache_key = self.effect_name + "@" + stage + "-" + pass_id + "@" + self.effect_hash
return self._process_shader_template(template_src, cache_key, injects)
def _process_shader_template(self, template_src, cache_key, injections): # noqa # pylint: disable=too-many-branches
""" Generates a compiled shader object from a given shader
source location and code injection definitions. """
with open(template_src, "r") as handle:
shader_lines = handle.readlines()
parsed_lines = ["\n\n"]
addline = parsed_lines.append
addline("/* Compiled Shader Template")
addline(" * generated from: '" + template_src + "'")
addline(" * cache key: '" + cache_key + "'")
addline(" *")
addline(" * !!! Autogenerated, do not edit! Your changes will be lost. !!!")
addline(" */\n\n")
# Store whether we are in the main function already - we need this
# to properly insert scoped code blocks
in_main = False
for line in shader_lines: # pylint: disable=too-many-nested-blocks
stripped_line = line.strip().lower()
# Check if we are already in the main function
if "void main()" in stripped_line:
in_main = True
# Check if the current line is a hook
if stripped_line.startswith("%") and stripped_line.endswith("%"):
# If the line is a hook, get the hook name and save the
# indent so we can indent all injected lines properly.
hook_name = stripped_line[1:-1]
indent = " " * (len(line) - len(line.lstrip()))
# Inject all registered template values into the hook
if hook_name in injections:
# Directly remove the value from the list so we can check which
# hooks were not found in the template
insertions = injections.pop(hook_name)
if len(insertions) > 0:
# When we are in the main function, we have to make sure we
# use a seperate scope, so there are no conflicts with variable
# declarations
header = indent + "/* Hook: " + hook_name + " */" + (" {" if in_main else "") # noqa # pylint: disable=line-too-long
addline(header)
for line_to_insert in insertions:
if line_to_insert is None:
self.warn("Empty insertion '" + hook_name + "'")
continue
if not isinstance(line_to_insert, str):
self.warn("Invalid line type: ", line_to_insert)
continue
# Dont indent defines and pragmas
if line_to_insert.startswith("#"):
addline(line_to_insert)
else:
addline(indent + line_to_insert)
if in_main:
addline(indent + "}")
else:
addline(line.rstrip())
# Add a closing newline to the file
addline("")
# Warn the user about all unused hooks
for key in injections:
self.warn("Hook '" + key + "' not found in template '" + template_src + "'!")
# Write the constructed shader and load it back
shader_content = "\n".join(parsed_lines)
temp_path = "/$$rptemp/$$effect-" + cache_key + ".glsl"
with open(temp_path, "w") as handle:
handle.write(shader_content)
return temp_path

View File

@ -1,47 +1,47 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
__all__ = ("Globals",)
class Globals(object): # pylint: disable=too-few-public-methods
""" This class is a singleton to store globals widely used by the application.
This is a wrapper around Panda3D's globals since ShowBase writes to __builtins__
which is bad practice. This class also attempts to help IDEs to figure out
where the variables come from and where they are defined. """
__init__ = None
@staticmethod
def load(showbase):
""" Loads the globals from a given showbase """
Globals.base = showbase
Globals.render = showbase.render
Globals.clock = showbase.taskMgr.globalClock
Globals.font = None
Globals.resolution = None
Globals.native_resolution = None
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
__all__ = ("Globals",)
class Globals(object): # pylint: disable=too-few-public-methods
""" This class is a singleton to store globals widely used by the application.
This is a wrapper around Panda3D's globals since ShowBase writes to __builtins__
which is bad practice. This class also attempts to help IDEs to figure out
where the variables come from and where they are defined. """
__init__ = None
@staticmethod
def load(showbase):
""" Loads the globals from a given showbase """
Globals.base = showbase
Globals.render = showbase.render
Globals.clock = showbase.taskMgr.globalClock
Globals.font = None
Globals.resolution = None
Globals.native_resolution = None

View File

@ -1,117 +1,117 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import PTAInt
from rpcore.image import Image
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
from rpcore.render_target import RenderTarget
from rpcore.native import GPUCommand, GPUCommandList
class GPUCommandQueue(RPObject):
""" This class offers an interface to the gpu, allowing commands to be
pushed to a queue which then get executed on the gpu """
def __init__(self, pipeline):
RPObject.__init__(self)
self._pipeline = pipeline
self._commands_per_frame = 1024
self._command_list = GPUCommandList()
self._pta_num_commands = PTAInt.empty_array(1)
self._create_data_storage()
self._create_command_target()
self._commands = []
self._register_defines()
def clear_queue(self):
""" Clears all commands currently being in the queue """
raise NotImplementedError()
@property
def command_list(self):
""" Returns a handle to the command list """
return self._command_list
@property
def num_queued_commands(self):
""" Returns the amount of queued commands, which are waiting to get
executed on the gpu. This might be zero a lot of the time, because the
GPUCommandList clears the queue after executing, so you have to call
this after work was submitted. """
return self._command_list.num_commands
@property
def num_processed_commands(self):
""" Returns the amount of commands processed the last time when the
command queue was updated """
return self._pta_num_commands[0]
def process_queue(self):
""" Processes the n first commands of the queue """
pointer = self._data_texture.modify_ram_image()
num_commands_exec = self._command_list.write_commands_to(
pointer, self._commands_per_frame)
self._pta_num_commands[0] = num_commands_exec
def reload_shaders(self):
""" Reloads the command shader """
shader = RPLoader.load_shader(
"/$$rp/shader/default_post_process.vert.glsl",
"/$$rp/shader/process_command_queue.frag.glsl")
self._command_target.shader = shader
def register_input(self, key, val):
""" Registers an new shader input to the command target """
self._command_target.set_shader_input(key, val)
def _register_defines(self):
""" Registers all the command types as defines so they can be used
in a shader later on """
for attr in dir(GPUCommand):
if attr.startswith("CMD_"):
attr_val = getattr(GPUCommand, attr)
self._pipeline.stage_mgr.defines[attr] = attr_val
self._pipeline.stage_mgr.defines["GPU_CMD_INT_AS_FLOAT"] = \
GPUCommand.get_uses_integer_packing()
def _create_data_storage(self):
""" Creates the buffer used to transfer commands """
command_buffer_size = self._commands_per_frame * 32
self.debug("Allocating command buffer of size", command_buffer_size)
self._data_texture = Image.create_buffer("CommandQueue", command_buffer_size, "R32")
def _create_command_target(self):
""" Creates the target which processes the commands """
self._command_target = RenderTarget("ExecCommandTarget")
self._command_target.size = 1, 1
self._command_target.prepare_buffer()
self._command_target.set_shader_inputs(
CommandQueue=self._data_texture,
commandCount=self._pta_num_commands)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import PTAInt
from rpcore.image import Image
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
from rpcore.render_target import RenderTarget
from rpcore.native import GPUCommand, GPUCommandList
class GPUCommandQueue(RPObject):
""" This class offers an interface to the gpu, allowing commands to be
pushed to a queue which then get executed on the gpu """
def __init__(self, pipeline):
RPObject.__init__(self)
self._pipeline = pipeline
self._commands_per_frame = 1024
self._command_list = GPUCommandList()
self._pta_num_commands = PTAInt.empty_array(1)
self._create_data_storage()
self._create_command_target()
self._commands = []
self._register_defines()
def clear_queue(self):
""" Clears all commands currently being in the queue """
raise NotImplementedError()
@property
def command_list(self):
""" Returns a handle to the command list """
return self._command_list
@property
def num_queued_commands(self):
""" Returns the amount of queued commands, which are waiting to get
executed on the gpu. This might be zero a lot of the time, because the
GPUCommandList clears the queue after executing, so you have to call
this after work was submitted. """
return self._command_list.num_commands
@property
def num_processed_commands(self):
""" Returns the amount of commands processed the last time when the
command queue was updated """
return self._pta_num_commands[0]
def process_queue(self):
""" Processes the n first commands of the queue """
pointer = self._data_texture.modify_ram_image()
num_commands_exec = self._command_list.write_commands_to(
pointer, self._commands_per_frame)
self._pta_num_commands[0] = num_commands_exec
def reload_shaders(self):
""" Reloads the command shader """
shader = RPLoader.load_shader(
"/$$rp/shader/default_post_process.vert.glsl",
"/$$rp/shader/process_command_queue.frag.glsl")
self._command_target.shader = shader
def register_input(self, key, val):
""" Registers an new shader input to the command target """
self._command_target.set_shader_input(key, val)
def _register_defines(self):
""" Registers all the command types as defines so they can be used
in a shader later on """
for attr in dir(GPUCommand):
if attr.startswith("CMD_"):
attr_val = getattr(GPUCommand, attr)
self._pipeline.stage_mgr.defines[attr] = attr_val
self._pipeline.stage_mgr.defines["GPU_CMD_INT_AS_FLOAT"] = \
GPUCommand.get_uses_integer_packing()
def _create_data_storage(self):
""" Creates the buffer used to transfer commands """
command_buffer_size = self._commands_per_frame * 32
self.debug("Allocating command buffer of size", command_buffer_size)
self._data_texture = Image.create_buffer("CommandQueue", command_buffer_size, "R32")
def _create_command_target(self):
""" Creates the target which processes the commands """
self._command_target = RenderTarget("ExecCommandTarget")
self._command_target.size = 1, 1
self._command_target.prepare_buffer()
self._command_target.set_shader_inputs(
CommandQueue=self._data_texture,
commandCount=self._pta_num_commands)

View File

@ -1,6 +1,6 @@
## rp-gui
This folder only contains helper classes for the pipeline gui.
It is not really part of the pipeline, and thus also does not follow the
pipeline code conventions.
## rp-gui
This folder only contains helper classes for the pipeline gui.
It is not really part of the pipeline, and thus also does not follow the
pipeline code conventions.

View File

@ -1,255 +1,255 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from functools import partial
from panda3d.core import Texture, Vec3
from direct.gui.DirectFrame import DirectFrame
from direct.gui.DirectGui import DGG
from direct.gui.DirectScrolledFrame import DirectScrolledFrame
from rplibs.six import itervalues
from rpcore.image import Image
from rpcore.util.display_shader_builder import DisplayShaderBuilder
from rpcore.globals import Globals
from rpcore.render_target import RenderTarget
from rpcore.gui.texture_preview import TexturePreview
from rpcore.gui.sprite import Sprite
from rpcore.gui.labeled_checkbox import LabeledCheckbox
from rpcore.gui.text import Text
from rpcore.gui.draggable_window import DraggableWindow
class BufferViewer(DraggableWindow):
""" This class provides a view into the buffers to inspect them """
def __init__(self, pipeline, parent):
""" Constructs the buffer viewer """
DraggableWindow.__init__(self, width=1400, height=800, parent=parent,
title="Buffer- and Image-Browser")
self._pipeline = pipeline
self._scroll_height = 3000
self._display_images = False
self._stages = []
self._create_components()
self._tex_preview = TexturePreview(self._pipeline, parent)
self._tex_preview.hide()
self.hide()
def toggle(self):
""" Updates all the buffers and then toggles the buffer viewer """
if self._visible:
self._remove_components()
self.hide()
else:
self._perform_update()
self.show()
@property
def entries(self):
""" Returns a list of all registered entries """
return RenderTarget.REGISTERED_TARGETS + Image.REGISTERED_IMAGES
@property
def stage_information(self):
""" Returns the amount of attached stages, and also the memory consumed
in MiB in a tuple. """
count, memory = 0, 0
for entry in self.entries:
if isinstance(entry, Texture):
memory += entry.estimate_texture_memory()
count += 1
elif entry.__class__.__name__ == "RenderTarget":
for target in itervalues(entry.targets):
memory += target.estimate_texture_memory()
count += 1
else:
self.warn("Unkown type:", entry.__class__.__name__)
return memory, count
def _create_components(self):
""" Creates the window components """
DraggableWindow._create_components(self)
self._content_frame = DirectScrolledFrame(
frameSize=(0, self._width - 15, 0, self._height - 70),
canvasSize=(0, self._width - 80, 0, self._scroll_height),
autoHideScrollBars=False,
scrollBarWidth=12.0,
frameColor=(0, 0, 0, 0),
verticalScroll_relief=DGG.FLAT,
verticalScroll_incButton_relief=DGG.FLAT,
verticalScroll_decButton_relief=DGG.FLAT,
verticalScroll_thumb_relief=DGG.FLAT,
verticalScroll_frameColor=(0.05, 0.05, 0.05, 1),
verticalScroll_thumb_frameColor=(0.8, 0.8, 0.8, 1),
verticalScroll_incButton_frameColor=(0.6, 0.6, 0.6, 1),
verticalScroll_decButton_frameColor=(0.6, 0.6, 0.6, 1),
horizontalScroll_frameColor=(0, 0, 0, 0),
horizontalScroll_relief=False,
horizontalScroll_thumb_relief=False,
horizontalScroll_incButton_relief=False,
horizontalScroll_decButton_relief=False,
parent=self._node,
pos=(0, 1, -self._height))
self._content_node = self._content_frame.getCanvas().attach_new_node(
"BufferComponents")
self._content_node.set_scale(1, 1, -1)
self._content_node.set_z(self._scroll_height)
self._chb_show_images = LabeledCheckbox(
parent=self._node, x=10, y=43, chb_callback=self._set_show_images,
chb_checked=False, text="Display image resources",
text_color=Vec3(0.4), expand_width=330)
def _set_show_images(self, arg):
""" Sets whether images and textures will be shown """
self._display_images = arg
self._perform_update()
def _set_scroll_height(self, height):
""" Sets the maximum scroll height in the content frame """
self._scroll_height = height
self._content_frame["canvasSize"] = (0, self._width - 80, 0, self._scroll_height)
self._content_node.set_z(self._scroll_height)
def _remove_components(self):
""" Removes all components of the buffer viewer """
self._content_node.node().remove_all_children()
self._tex_preview.hide()
def _perform_update(self):
""" Collects all entries, extracts their images and re-renders the
window """
# Collect texture stages
self._stages = []
for entry in sorted(self.entries, key=lambda entry: entry.sort):
if isinstance(entry, Texture):
if self._display_images:
self._stages.append(entry)
# Can not use isinstance or we get circular import references
elif entry.__class__.__name__ == "RenderTarget":
for target in itervalues(entry.targets):
self._stages.append(target)
else:
self.warn("Unrecognized instance!", entry.__class__)
self._render_stages()
def _on_texture_hovered(self, hover_frame, evt=None): # pylint: disable=unused-argument
""" Internal method when a texture is hovered """
hover_frame["frameColor"] = (0, 0, 0, 0.1)
def _on_texture_blurred(self, hover_frame, evt=None): # pylint: disable=unused-argument
""" Internal method when a texture is blurred """
hover_frame["frameColor"] = (0, 0, 0, 0)
def _on_texture_clicked(self, tex_handle, evt=None): # pylint: disable=unused-argument
""" Internal method when a texture is blurred """
self._tex_preview.present(tex_handle)
def _render_stages(self):
""" Renders the stages to the window """
self._remove_components()
entries_per_row = 6
aspect = Globals.native_resolution.y / Globals.native_resolution.x
entry_width = 235
entry_height = (entry_width - 20) * aspect + 55
# Store already processed images
processed = set()
index = -1
# Iterate over all stages
for stage_tex in self._stages:
if stage_tex in processed:
continue
processed.add(stage_tex)
index += 1
stage_name = stage_tex.get_name()
xoffs = index % entries_per_row
yoffs = index // entries_per_row
node = self._content_node.attach_new_node("Preview")
node.set_sz(-1)
node.set_pos(10 + xoffs * (entry_width - 14), 1, yoffs * (entry_height - 14 + 10))
r, g, b = 0.2, 0.2, 0.2
if isinstance(stage_tex, Image):
r, g, b = 0.2, 0.4, 0.6
stage_name = stage_name.replace("render_pipeline_internal:", "")
parts = stage_name.split(":")
stage_name = parts[-1]
DirectFrame(
parent=node, frameSize=(7, entry_width - 17, -7, -entry_height + 17),
frameColor=(r, g, b, 1.0), pos=(0, 0, 0))
frame_hover = DirectFrame(
parent=node, frameSize=(0, entry_width - 10, 0, -entry_height + 10),
frameColor=(0, 0, 0, 0), pos=(0, 0, 0), state=DGG.NORMAL)
frame_hover.bind(
DGG.ENTER, partial(self._on_texture_hovered, frame_hover))
frame_hover.bind(
DGG.EXIT, partial(self._on_texture_blurred, frame_hover))
frame_hover.bind(
DGG.B1PRESS, partial(self._on_texture_clicked, stage_tex))
Text(text=stage_name, x=15, y=29, parent=node, size=12, color=Vec3(0.8))
# Scale image so it always fits
w, h = stage_tex.get_x_size(), stage_tex.get_y_size()
padd_x, padd_y = 24, 57
scale_x = (entry_width - padd_x) / max(1, w)
scale_y = (entry_height - padd_y) / max(1, h)
scale_factor = min(scale_x, scale_y)
if stage_tex.get_texture_type() == Image.TT_buffer_texture:
scale_factor = 1
w = entry_width - padd_x
h = entry_height - padd_y
preview = Sprite(
image=stage_tex, w=scale_factor * w, h=scale_factor * h,
any_filter=False, parent=node, x=7, y=40, transparent=False)
preview.set_shader_inputs(
mipmap=0,
slice=0,
brightness=1,
tonemap=False)
preview_shader = DisplayShaderBuilder.build(
stage_tex, scale_factor * w, scale_factor * h)
preview.set_shader(preview_shader)
num_rows = (index + entries_per_row) // entries_per_row
self._set_scroll_height(50 + (entry_height - 14 + 10) * num_rows)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from functools import partial
from panda3d.core import Texture, Vec3
from direct.gui.DirectFrame import DirectFrame
from direct.gui.DirectGui import DGG
from direct.gui.DirectScrolledFrame import DirectScrolledFrame
from rplibs.six import itervalues
from rpcore.image import Image
from rpcore.util.display_shader_builder import DisplayShaderBuilder
from rpcore.globals import Globals
from rpcore.render_target import RenderTarget
from rpcore.gui.texture_preview import TexturePreview
from rpcore.gui.sprite import Sprite
from rpcore.gui.labeled_checkbox import LabeledCheckbox
from rpcore.gui.text import Text
from rpcore.gui.draggable_window import DraggableWindow
class BufferViewer(DraggableWindow):
""" This class provides a view into the buffers to inspect them """
def __init__(self, pipeline, parent):
""" Constructs the buffer viewer """
DraggableWindow.__init__(self, width=1400, height=800, parent=parent,
title="Buffer- and Image-Browser")
self._pipeline = pipeline
self._scroll_height = 3000
self._display_images = False
self._stages = []
self._create_components()
self._tex_preview = TexturePreview(self._pipeline, parent)
self._tex_preview.hide()
self.hide()
def toggle(self):
""" Updates all the buffers and then toggles the buffer viewer """
if self._visible:
self._remove_components()
self.hide()
else:
self._perform_update()
self.show()
@property
def entries(self):
""" Returns a list of all registered entries """
return RenderTarget.REGISTERED_TARGETS + Image.REGISTERED_IMAGES
@property
def stage_information(self):
""" Returns the amount of attached stages, and also the memory consumed
in MiB in a tuple. """
count, memory = 0, 0
for entry in self.entries:
if isinstance(entry, Texture):
memory += entry.estimate_texture_memory()
count += 1
elif entry.__class__.__name__ == "RenderTarget":
for target in itervalues(entry.targets):
memory += target.estimate_texture_memory()
count += 1
else:
self.warn("Unkown type:", entry.__class__.__name__)
return memory, count
def _create_components(self):
""" Creates the window components """
DraggableWindow._create_components(self)
self._content_frame = DirectScrolledFrame(
frameSize=(0, self._width - 15, 0, self._height - 70),
canvasSize=(0, self._width - 80, 0, self._scroll_height),
autoHideScrollBars=False,
scrollBarWidth=12.0,
frameColor=(0, 0, 0, 0),
verticalScroll_relief=DGG.FLAT,
verticalScroll_incButton_relief=DGG.FLAT,
verticalScroll_decButton_relief=DGG.FLAT,
verticalScroll_thumb_relief=DGG.FLAT,
verticalScroll_frameColor=(0.05, 0.05, 0.05, 1),
verticalScroll_thumb_frameColor=(0.8, 0.8, 0.8, 1),
verticalScroll_incButton_frameColor=(0.6, 0.6, 0.6, 1),
verticalScroll_decButton_frameColor=(0.6, 0.6, 0.6, 1),
horizontalScroll_frameColor=(0, 0, 0, 0),
horizontalScroll_relief=False,
horizontalScroll_thumb_relief=False,
horizontalScroll_incButton_relief=False,
horizontalScroll_decButton_relief=False,
parent=self._node,
pos=(0, 1, -self._height))
self._content_node = self._content_frame.getCanvas().attach_new_node(
"BufferComponents")
self._content_node.set_scale(1, 1, -1)
self._content_node.set_z(self._scroll_height)
self._chb_show_images = LabeledCheckbox(
parent=self._node, x=10, y=43, chb_callback=self._set_show_images,
chb_checked=False, text="Display image resources",
text_color=Vec3(0.4), expand_width=330)
def _set_show_images(self, arg):
""" Sets whether images and textures will be shown """
self._display_images = arg
self._perform_update()
def _set_scroll_height(self, height):
""" Sets the maximum scroll height in the content frame """
self._scroll_height = height
self._content_frame["canvasSize"] = (0, self._width - 80, 0, self._scroll_height)
self._content_node.set_z(self._scroll_height)
def _remove_components(self):
""" Removes all components of the buffer viewer """
self._content_node.node().remove_all_children()
self._tex_preview.hide()
def _perform_update(self):
""" Collects all entries, extracts their images and re-renders the
window """
# Collect texture stages
self._stages = []
for entry in sorted(self.entries, key=lambda entry: entry.sort):
if isinstance(entry, Texture):
if self._display_images:
self._stages.append(entry)
# Can not use isinstance or we get circular import references
elif entry.__class__.__name__ == "RenderTarget":
for target in itervalues(entry.targets):
self._stages.append(target)
else:
self.warn("Unrecognized instance!", entry.__class__)
self._render_stages()
def _on_texture_hovered(self, hover_frame, evt=None): # pylint: disable=unused-argument
""" Internal method when a texture is hovered """
hover_frame["frameColor"] = (0, 0, 0, 0.1)
def _on_texture_blurred(self, hover_frame, evt=None): # pylint: disable=unused-argument
""" Internal method when a texture is blurred """
hover_frame["frameColor"] = (0, 0, 0, 0)
def _on_texture_clicked(self, tex_handle, evt=None): # pylint: disable=unused-argument
""" Internal method when a texture is blurred """
self._tex_preview.present(tex_handle)
def _render_stages(self):
""" Renders the stages to the window """
self._remove_components()
entries_per_row = 6
aspect = Globals.native_resolution.y / Globals.native_resolution.x
entry_width = 235
entry_height = (entry_width - 20) * aspect + 55
# Store already processed images
processed = set()
index = -1
# Iterate over all stages
for stage_tex in self._stages:
if stage_tex in processed:
continue
processed.add(stage_tex)
index += 1
stage_name = stage_tex.get_name()
xoffs = index % entries_per_row
yoffs = index // entries_per_row
node = self._content_node.attach_new_node("Preview")
node.set_sz(-1)
node.set_pos(10 + xoffs * (entry_width - 14), 1, yoffs * (entry_height - 14 + 10))
r, g, b = 0.2, 0.2, 0.2
if isinstance(stage_tex, Image):
r, g, b = 0.2, 0.4, 0.6
stage_name = stage_name.replace("render_pipeline_internal:", "")
parts = stage_name.split(":")
stage_name = parts[-1]
DirectFrame(
parent=node, frameSize=(7, entry_width - 17, -7, -entry_height + 17),
frameColor=(r, g, b, 1.0), pos=(0, 0, 0))
frame_hover = DirectFrame(
parent=node, frameSize=(0, entry_width - 10, 0, -entry_height + 10),
frameColor=(0, 0, 0, 0), pos=(0, 0, 0), state=DGG.NORMAL)
frame_hover.bind(
DGG.ENTER, partial(self._on_texture_hovered, frame_hover))
frame_hover.bind(
DGG.EXIT, partial(self._on_texture_blurred, frame_hover))
frame_hover.bind(
DGG.B1PRESS, partial(self._on_texture_clicked, stage_tex))
Text(text=stage_name, x=15, y=29, parent=node, size=12, color=Vec3(0.8))
# Scale image so it always fits
w, h = stage_tex.get_x_size(), stage_tex.get_y_size()
padd_x, padd_y = 24, 57
scale_x = (entry_width - padd_x) / max(1, w)
scale_y = (entry_height - padd_y) / max(1, h)
scale_factor = min(scale_x, scale_y)
if stage_tex.get_texture_type() == Image.TT_buffer_texture:
scale_factor = 1
w = entry_width - padd_x
h = entry_height - padd_y
preview = Sprite(
image=stage_tex, w=scale_factor * w, h=scale_factor * h,
any_filter=False, parent=node, x=7, y=40, transparent=False)
preview.set_shader_inputs(
mipmap=0,
slice=0,
brightness=1,
tonemap=False)
preview_shader = DisplayShaderBuilder.build(
stage_tex, scale_factor * w, scale_factor * h)
preview.set_shader(preview_shader)
num_rows = (index + entries_per_row) // entries_per_row
self._set_scroll_height(50 + (entry_height - 14 + 10) * num_rows)

View File

@ -1,130 +1,130 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import TransparencyAttrib, SamplerState
from direct.gui.DirectCheckBox import DirectCheckBox
import direct.gui.DirectGuiGlobals as DGG
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class Checkbox(RPObject):
""" This is a wrapper around DirectCheckBox, providing a simpler interface
and better visuals """
def __init__(self, parent=None, x=0, y=0, callback=None, extra_args=None,
radio=False, expand_width=100, checked=False, enabled=True):
RPObject.__init__(self)
prefix = "checkbox" if not radio else "radiobox"
if enabled:
checked_img = RPLoader.load_texture(
"/$$rp/data/gui/" + prefix + "_checked.png")
unchecked_img = RPLoader.load_texture(
"/$$rp/data/gui/" + prefix + "_default.png")
else:
checked_img = RPLoader.load_texture(
"/$$rp/data/gui/" + prefix + "_disabled.png")
unchecked_img = checked_img
# Set near filter, otherwise textures look like crap
for tex in [checked_img, unchecked_img]:
tex.set_minfilter(SamplerState.FT_linear)
tex.set_magfilter(SamplerState.FT_linear)
tex.set_wrap_u(SamplerState.WM_clamp)
tex.set_wrap_v(SamplerState.WM_clamp)
tex.set_anisotropic_degree(0)
self._node = DirectCheckBox(
parent=parent, pos=(x + 11, 1, -y - 8), scale=(10 / 2.0, 1, 10 / 2.0),
checkedImage=checked_img, uncheckedImage=unchecked_img,
image=unchecked_img, extraArgs=extra_args, state=DGG.NORMAL,
relief=DGG.FLAT, command=self._update_status)
self._node["frameColor"] = (0, 0, 0, 0)
self._node["frameSize"] = (-2.6, 2 + expand_width / 7.5, -2.35, 2.5)
self._node.set_transparency(TransparencyAttrib.M_alpha)
self._callback = callback
self._extra_args = extra_args
self._collection = None
if checked:
self.set_checked(True, False)
@property
def collection(self):
""" Returns a handle to the assigned checkbox collection, or None
if no collection was assigned """
return self._collection
@collection.setter
def collection(self, coll):
""" Internal method to add a checkbox to a checkbox collection, this
is used for radio-buttons """
self._collection = coll
@property
def checked(self):
""" Returns whether the node is currently checked """
return self._node["isChecked"]
@property
def node(self):
""" Returns a handle to the internally used node """
return self._node
def _update_status(self, status):
""" Internal method when another checkbox in the same radio group
changed it's value """
if not status and self._collection:
self._node.commandFunc(None)
return
if self._collection:
if status:
self._collection.on_checkbox_changed(self)
# A radio box can't be unchecked
# self._node["state"] = DGG.DISABLED
if self._callback is not None:
self._callback(*([status] + self._extra_args))
def set_checked(self, val, do_callback=True):
""" Internal method to check/uncheck the checkbox """
self._node["isChecked"] = val
if val:
self._node["image"] = self._node["checkedImage"]
else:
self._node["image"] = self._node["uncheckedImage"]
if do_callback and self._callback is not None:
self._callback(*([val] + self._extra_args))
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import TransparencyAttrib, SamplerState
from direct.gui.DirectCheckBox import DirectCheckBox
import direct.gui.DirectGuiGlobals as DGG
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class Checkbox(RPObject):
""" This is a wrapper around DirectCheckBox, providing a simpler interface
and better visuals """
def __init__(self, parent=None, x=0, y=0, callback=None, extra_args=None,
radio=False, expand_width=100, checked=False, enabled=True):
RPObject.__init__(self)
prefix = "checkbox" if not radio else "radiobox"
if enabled:
checked_img = RPLoader.load_texture(
"/$$rp/data/gui/" + prefix + "_checked.png")
unchecked_img = RPLoader.load_texture(
"/$$rp/data/gui/" + prefix + "_default.png")
else:
checked_img = RPLoader.load_texture(
"/$$rp/data/gui/" + prefix + "_disabled.png")
unchecked_img = checked_img
# Set near filter, otherwise textures look like crap
for tex in [checked_img, unchecked_img]:
tex.set_minfilter(SamplerState.FT_linear)
tex.set_magfilter(SamplerState.FT_linear)
tex.set_wrap_u(SamplerState.WM_clamp)
tex.set_wrap_v(SamplerState.WM_clamp)
tex.set_anisotropic_degree(0)
self._node = DirectCheckBox(
parent=parent, pos=(x + 11, 1, -y - 8), scale=(10 / 2.0, 1, 10 / 2.0),
checkedImage=checked_img, uncheckedImage=unchecked_img,
image=unchecked_img, extraArgs=extra_args, state=DGG.NORMAL,
relief=DGG.FLAT, command=self._update_status)
self._node["frameColor"] = (0, 0, 0, 0)
self._node["frameSize"] = (-2.6, 2 + expand_width / 7.5, -2.35, 2.5)
self._node.set_transparency(TransparencyAttrib.M_alpha)
self._callback = callback
self._extra_args = extra_args
self._collection = None
if checked:
self.set_checked(True, False)
@property
def collection(self):
""" Returns a handle to the assigned checkbox collection, or None
if no collection was assigned """
return self._collection
@collection.setter
def collection(self, coll):
""" Internal method to add a checkbox to a checkbox collection, this
is used for radio-buttons """
self._collection = coll
@property
def checked(self):
""" Returns whether the node is currently checked """
return self._node["isChecked"]
@property
def node(self):
""" Returns a handle to the internally used node """
return self._node
def _update_status(self, status):
""" Internal method when another checkbox in the same radio group
changed it's value """
if not status and self._collection:
self._node.commandFunc(None)
return
if self._collection:
if status:
self._collection.on_checkbox_changed(self)
# A radio box can't be unchecked
# self._node["state"] = DGG.DISABLED
if self._callback is not None:
self._callback(*([status] + self._extra_args))
def set_checked(self, val, do_callback=True):
""" Internal method to check/uncheck the checkbox """
self._node["isChecked"] = val
if val:
self._node["image"] = self._node["checkedImage"]
else:
self._node["image"] = self._node["uncheckedImage"]
if do_callback and self._callback is not None:
self._callback(*([val] + self._extra_args))

View File

@ -1,67 +1,67 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from rpcore.rpobject import RPObject
import direct.gui.DirectGuiGlobals as DGG
class CheckboxCollection(RPObject):
""" This is a container for multiple Checkboxes, controlling that
only one checkbox of this collection is checked at one time
(like a radio-button) """
def __init__(self):
RPObject.__init__(self)
self._items = []
def add(self, chb):
""" Adds a Checkbox to this collection """
if chb.collection is not None:
self.error(
"Can't add checkbox as it already belongs "
"to another collection!")
return
chb.collection = self
self._items.append(chb)
def remove(self, chb):
""" Removes a checkbox from this collection """
if chb.collection is not self:
self.error(
"Can't remove the checkbox from this collection as it is not "
"attached to this collection!")
return
chb.collection = None
self._items.remove(chb)
def on_checkbox_changed(self, chb):
""" Internal callback when a checkbox got changed """
for item in self._items:
if item is not chb:
item.set_checked(False)
item.node["state"] = DGG.NORMAL
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from rpcore.rpobject import RPObject
import direct.gui.DirectGuiGlobals as DGG
class CheckboxCollection(RPObject):
""" This is a container for multiple Checkboxes, controlling that
only one checkbox of this collection is checked at one time
(like a radio-button) """
def __init__(self):
RPObject.__init__(self)
self._items = []
def add(self, chb):
""" Adds a Checkbox to this collection """
if chb.collection is not None:
self.error(
"Can't add checkbox as it already belongs "
"to another collection!")
return
chb.collection = self
self._items.append(chb)
def remove(self, chb):
""" Removes a checkbox from this collection """
if chb.collection is not self:
self.error(
"Can't remove the checkbox from this collection as it is not "
"attached to this collection!")
return
chb.collection = None
self._items.remove(chb)
def on_checkbox_changed(self, chb):
""" Internal callback when a checkbox got changed """
for item in self._items:
if item is not chb:
item.set_checked(False)
item.node["state"] = DGG.NORMAL

View File

@ -1,336 +1,330 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
import os
import sys
import subprocess
from six.moves import range # pylint: disable=import-error
from panda3d.core import Vec4, Vec3, Vec2, RenderState, TransformState
from panda3d.core import TexturePool, SceneGraphAnalyzer
from direct.interval.IntervalGlobal import Sequence
from rpcore.gui.sprite import Sprite
from rpcore.gui.buffer_viewer import BufferViewer
from rpcore.gui.pipe_viewer import PipeViewer
from rpcore.gui.render_mode_selector import RenderModeSelector
from rpcore.gui.text_node import TextNode
from rpcore.gui.error_message_display import ErrorMessageDisplay
from rpcore.gui.exposure_widget import ExposureWidget
from rpcore.gui.fps_chart import FPSChart
from rpcore.gui.pixel_inspector import PixelInspector
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.native import NATIVE_CXX_LOADED
from rpcore.render_target import RenderTarget
from rpcore.image import Image
class Debugger(RPObject):
""" This class manages the onscreen control, and displays statistics. """
def __init__(self, pipeline):
RPObject.__init__(self)
self.debug("Creating debugger")
self.pipeline = pipeline
self.analyzer = SceneGraphAnalyzer()
self.fullscreen_node = Globals.base.pixel2d.attach_new_node("rp_debugger")
self.create_components()
self.init_keybindings()
if self.advanced_info:
Globals.base.doMethodLater(
0.5, lambda task: self.collect_scene_data(), "RPDebugger_collectSceneData_initial")
Globals.base.doMethodLater(0.1, self.update_stats, "RPDebugger_updateStats")
@property
def advanced_info(self):
return self.pipeline.settings["pipeline.advanced_debugging_info"]
def create_components(self):
""" Creates the gui components """
self.debugger_width = 460
self.debugger_visible = False
self.debugger_interval = None
self.create_stats()
self.create_hints()
self.pipeline_logo = Sprite(
image="/$$rp/data/gui/pipeline_logo_text.png", x=30, y=30,
parent=self.fullscreen_node)
if self.advanced_info:
self.exposure_node = self.fullscreen_node.attach_new_node("ExposureWidget")
self.exposure_widget = ExposureWidget(self.pipeline, self.exposure_node)
self.fps_node = self.fullscreen_node.attach_new_node("FPSChart")
self.fps_node.set_pos(Vec3(21, 1, -108 - 40))
self.fps_widget = FPSChart(self.pipeline, self.fps_node)
self.pixel_widget = PixelInspector(self.pipeline)
self.buffer_viewer = BufferViewer(self.pipeline, self.fullscreen_node)
self.pipe_viewer = PipeViewer(self.pipeline, self.fullscreen_node)
self.rm_selector = RenderModeSelector(self.pipeline, self.fullscreen_node)
self.error_msg_handler = ErrorMessageDisplay()
self.handle_window_resize()
def update(self):
""" Updates the gui """
self.error_msg_handler.update()
self.pixel_widget.update()
def collect_scene_data(self, task=None):
""" Analyzes the scene graph to provide useful information """
self.analyzer.clear()
for geom_node in Globals.base.render.find_all_matches("**/+GeomNode"):
self.analyzer.add_node(geom_node.node())
if task:
return task.again
def create_stats(self):
""" Creates the stats overlay """
self.overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
self.debug_lines = []
num_lines = 6 if self.advanced_info else 1
for i in range(num_lines):
self.debug_lines.append(TextNode(
pos=Vec2(0, -i * 0.046), parent=self.overlay_node, align="right", color=Vec3(0.7, 1, 1)))
self.debug_lines[0].color = Vec4(1, 1, 0, 1)
def create_hints(self):
""" Creates the hints like keybindings and when reloading shaders """
self.hint_reloading = Sprite(
image="/$$rp/data/gui/shader_reload_hint.png",
parent=self.fullscreen_node)
self.set_reload_hint_visible(False)
self.python_warning = None
if not NATIVE_CXX_LOADED:
# Warning when using the python version
self.python_warning = Sprite(
image="/$$rp/data/gui/python_warning.png",
parent=self.fullscreen_node)
Sequence(
self.python_warning.color_scale_interval(
0.7, Vec4(0.3, 1, 1, 0.7), blendType="easeOut"),
self.python_warning.color_scale_interval(
0.7, Vec4(1, 1, 1, 1.0), blendType="easeOut"),
).loop()
# Keybinding hints
self.keybinding_instructions = Sprite(
image="/$$rp/data/gui/keybindings.png",
parent=self.fullscreen_node, any_filter=False)
def set_reload_hint_visible(self, flag):
""" Sets whether the shader reload hint is visible """
if flag:
self.hint_reloading.show()
else:
self.hint_reloading.hide()
def handle_window_resize(self):
""" Handles the window resize, repositions the GUI elements to fit on
screen. """
# When using small resolutions, scale the GUI so its still useable,
# otherwise the sub-windows are bigger than the main window
self.gui_scale = max(0.65, min(1.0, Globals.native_resolution.x / 1920.0))
self.fullscreen_node.set_scale(self.gui_scale)
if self.advanced_info:
self.exposure_node.set_pos(
Globals.native_resolution.x // self.gui_scale - 200,
1, -Globals.native_resolution.y // self.gui_scale + 120)
self.hint_reloading.set_pos(
float((Globals.native_resolution.x) // 2) / self.gui_scale - 465 // 2, 220)
self.keybinding_instructions.set_pos(
30, Globals.native_resolution.y // self.gui_scale - 510.0,)
self.overlay_node.set_pos(Globals.base.get_aspect_ratio() - 0.07, 1, 1.0 - 0.07)
if self.python_warning:
self.python_warning.set_pos(
(Globals.native_resolution.x // self.gui_scale - 1054) // 2,
(Globals.native_resolution.y // self.gui_scale - 118 - 40))
for text in self.debug_lines:
text.set_pixel_size(16 * max(0.8, self.gui_scale))
self.buffer_viewer.center_on_screen()
self.pipe_viewer.center_on_screen()
self.rm_selector.center_on_screen()
def init_keybindings(self):
""" Inits the debugger keybindings """
Globals.base.accept("v", self.buffer_viewer.toggle)
Globals.base.accept("c", self.pipe_viewer.toggle)
Globals.base.accept("z", self.rm_selector.toggle)
Globals.base.accept("f5", self.toggle_gui_visible)
Globals.base.accept("f6", self.toggle_keybindings_visible)
Globals.base.accept("r", self.pipeline.reload_shaders)
Globals.base.accept("m", self.start_material_editor)
def start_material_editor(self):
""" Starts the material editor """
self.debug("Starting material editor")
pth = sys.executable
editor = os.path.dirname(os.path.realpath(__file__))
editor = os.path.join(editor, "..", "..", "toolkit", "material_editor", "main.py")
subprocess.Popen([pth, editor], shell=True)
def toggle_gui_visible(self):
""" Shows / Hides the gui """
if not self.fullscreen_node.is_hidden():
self.fullscreen_node.hide()
self.overlay_node.hide()
self.error_msg_handler.hide()
else:
self.fullscreen_node.show()
self.overlay_node.show()
self.error_msg_handler.show()
def hide_gui(self):
self.fullscreen_node.hide()
self.overlay_node.hide()
self.error_msg_handler.hide()
def toggle_keybindings_visible(self):
""" Shows / Hides the FPS graph """
if not self.keybinding_instructions.is_hidden():
self.keybinding_instructions.hide()
else:
self.keybinding_instructions.show()
def update_stats(self, task=None):
""" Updates the stats overlay """
clock = Globals.clock
self.debug_lines[0].text = "{:3.0f} fps | {:3.1f} ms | {:3.1f} ms max".format(
clock.get_average_frame_rate(),
1000.0 / max(0.001, clock.get_average_frame_rate()),
clock.get_max_frame_duration() * 1000.0)
if not self.advanced_info:
return task.again if task else None
text = "{:4d} states | {:4d} transforms "
text += "| {:4d} cmds | {:4d} lights | {:4d} shadows "
text += "| {:5.1f}% atlas usage"
self.debug_lines[1].text = text.format(
RenderState.get_num_states(), TransformState.get_num_states(),
self.pipeline.light_mgr.cmd_queue.num_processed_commands,
self.pipeline.light_mgr.num_lights,
self.pipeline.light_mgr.num_shadow_sources,
self.pipeline.light_mgr.shadow_atlas_coverage)
text = "Internal: {:3.0f} MB VRAM | {:5d} img | {:5d} tex | "
text += "{:5d} fbos | {:3d} plugins | {:2d} views ({:2d} active)"
tex_memory, tex_count = self.buffer_viewer.stage_information
views, active_views = 0, 0
for target in RenderTarget.REGISTERED_TARGETS:
if not target.create_default_region:
num_regions = target.internal_buffer.get_num_display_regions()
for i, region in enumerate(target.internal_buffer.get_display_regions()):
# Skip overlay display region
if i == 0 and num_regions > 1:
continue
views += 1
active_views += 1 if target.active and region.active else 0
self.debug_lines[2].text = text.format(
tex_memory / (1024**2), len(Image.REGISTERED_IMAGES), tex_count,
RenderTarget.NUM_ALLOCATED_BUFFERS,
len(self.pipeline.plugin_mgr.enabled_plugins),
views, active_views)
text = "Scene: {:4.0f} MB VRAM | {:3d} tex | {:4d} geoms "
text += "| {:4d} nodes | {:7,.0f} vertices"
scene_tex_size = 0
for tex in TexturePool.find_all_textures():
scene_tex_size += tex.estimate_texture_memory()
self.debug_lines[3].text = text.format(
scene_tex_size / (1024**2),
len(TexturePool.find_all_textures()),
self.analyzer.get_num_geoms(),
self.analyzer.get_num_nodes(),
self.analyzer.get_num_vertices(),
)
sun_vector = Vec3(0)
if self.pipeline.plugin_mgr.is_plugin_enabled("scattering"):
sun_vector = self.pipeline.plugin_mgr.instances["scattering"].sun_vector
text = "Time: {} ({:1.3f}) | Sun {:0.2f} {:0.2f} {:0.2f}"
text += " | X {:3.1f} Y {:3.1f} Z {:3.1f}"
text += " | {:2d} tasks | scheduled: {:2d}"
self.debug_lines[4].text = text.format(
self.pipeline.daytime_mgr.formatted_time,
self.pipeline.daytime_mgr.time,
sun_vector.x, sun_vector.y, sun_vector.z,
Globals.base.camera.get_x(Globals.base.render),
Globals.base.camera.get_y(Globals.base.render),
Globals.base.camera.get_z(Globals.base.render),
self.pipeline.task_scheduler.num_tasks,
self.pipeline.task_scheduler.num_scheduled_tasks,)
text = "Scene shadows: "
if "pssm" in self.pipeline.plugin_mgr.enabled_plugins:
focus = self.pipeline.plugin_mgr.instances["pssm"].scene_shadow_stage.last_focus
if focus is not None:
text += "{:3.1f} {:3.1f} {:3.1f} r {:3.1f}".format(
focus[0].x, focus[0].y, focus[0].z, focus[1])
else:
text += "none"
else:
text += "inactive"
text += " | HPR ({:3.1f}, {:3.1f}, {:3.1f}) | {:4d} x {:4d} pixels @ {:3.1f} %"
text += " | {:3d} x {:3d} tiles"
self.debug_lines[5].text = text.format(
Globals.base.camera.get_h(Globals.base.render),
Globals.base.camera.get_p(Globals.base.render),
Globals.base.camera.get_r(Globals.base.render),
Globals.native_resolution.x,
Globals.native_resolution.y,
self.pipeline.settings["pipeline.resolution_scale"] * 100.0,
self.pipeline.light_mgr.num_tiles.x,
self.pipeline.light_mgr.num_tiles.y,)
if task:
return task.again
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
import os
import sys
import subprocess
from rplibs.six.moves import range # pylint: disable=import-error
from panda3d.core import Vec4, Vec3, Vec2, RenderState, TransformState
from panda3d.core import TexturePool, SceneGraphAnalyzer
from direct.interval.IntervalGlobal import Sequence
from rpcore.gui.sprite import Sprite
from rpcore.gui.buffer_viewer import BufferViewer
from rpcore.gui.pipe_viewer import PipeViewer
from rpcore.gui.render_mode_selector import RenderModeSelector
from rpcore.gui.text_node import TextNode
from rpcore.gui.error_message_display import ErrorMessageDisplay
from rpcore.gui.exposure_widget import ExposureWidget
from rpcore.gui.fps_chart import FPSChart
from rpcore.gui.pixel_inspector import PixelInspector
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.native import NATIVE_CXX_LOADED
from rpcore.render_target import RenderTarget
from rpcore.image import Image
class Debugger(RPObject):
""" This class manages the onscreen control, and displays statistics. """
def __init__(self, pipeline):
RPObject.__init__(self)
self.debug("Creating debugger")
self.pipeline = pipeline
self.analyzer = SceneGraphAnalyzer()
self.fullscreen_node = Globals.base.pixel2d.attach_new_node("rp_debugger")
self.create_components()
self.init_keybindings()
if self.advanced_info:
Globals.base.doMethodLater(
0.5, lambda task: self.collect_scene_data(), "RPDebugger_collectSceneData_initial")
Globals.base.doMethodLater(0.1, self.update_stats, "RPDebugger_updateStats")
@property
def advanced_info(self):
return self.pipeline.settings["pipeline.advanced_debugging_info"]
def create_components(self):
""" Creates the gui components """
self.debugger_width = 460
self.debugger_visible = False
self.debugger_interval = None
self.create_stats()
self.create_hints()
self.pipeline_logo = Sprite(
image="/$$rp/data/gui/pipeline_logo_text.png", x=30, y=30,
parent=self.fullscreen_node)
if self.advanced_info:
self.exposure_node = self.fullscreen_node.attach_new_node("ExposureWidget")
self.exposure_widget = ExposureWidget(self.pipeline, self.exposure_node)
self.fps_node = self.fullscreen_node.attach_new_node("FPSChart")
self.fps_node.set_pos(Vec3(21, 1, -108 - 40))
self.fps_widget = FPSChart(self.pipeline, self.fps_node)
self.pixel_widget = PixelInspector(self.pipeline)
self.buffer_viewer = BufferViewer(self.pipeline, self.fullscreen_node)
self.pipe_viewer = PipeViewer(self.pipeline, self.fullscreen_node)
self.rm_selector = RenderModeSelector(self.pipeline, self.fullscreen_node)
self.error_msg_handler = ErrorMessageDisplay()
self.handle_window_resize()
def update(self):
""" Updates the gui """
self.error_msg_handler.update()
self.pixel_widget.update()
def collect_scene_data(self, task=None):
""" Analyzes the scene graph to provide useful information """
self.analyzer.clear()
for geom_node in Globals.base.render.find_all_matches("**/+GeomNode"):
self.analyzer.add_node(geom_node.node())
if task:
return task.again
def create_stats(self):
""" Creates the stats overlay """
self.overlay_node = Globals.base.aspect2d.attach_new_node("Overlay")
self.debug_lines = []
num_lines = 6 if self.advanced_info else 1
for i in range(num_lines):
self.debug_lines.append(TextNode(
pos=Vec2(0, -i * 0.046), parent=self.overlay_node, align="right", color=Vec3(0.7, 1, 1)))
self.debug_lines[0].color = Vec4(1, 1, 0, 1)
def create_hints(self):
""" Creates the hints like keybindings and when reloading shaders """
self.hint_reloading = Sprite(
image="/$$rp/data/gui/shader_reload_hint.png",
parent=self.fullscreen_node)
self.set_reload_hint_visible(False)
self.python_warning = None
if not NATIVE_CXX_LOADED:
# Warning when using the python version
self.python_warning = Sprite(
image="/$$rp/data/gui/python_warning.png",
parent=self.fullscreen_node)
Sequence(
self.python_warning.color_scale_interval(
0.7, Vec4(0.3, 1, 1, 0.7), blendType="easeOut"),
self.python_warning.color_scale_interval(
0.7, Vec4(1, 1, 1, 1.0), blendType="easeOut"),
).loop()
# Keybinding hints
self.keybinding_instructions = Sprite(
image="/$$rp/data/gui/keybindings.png",
parent=self.fullscreen_node, any_filter=False)
def set_reload_hint_visible(self, flag):
""" Sets whether the shader reload hint is visible """
if flag:
self.hint_reloading.show()
else:
self.hint_reloading.hide()
def handle_window_resize(self):
""" Handles the window resize, repositions the GUI elements to fit on
screen. """
# When using small resolutions, scale the GUI so its still useable,
# otherwise the sub-windows are bigger than the main window
self.gui_scale = max(0.65, min(1.0, Globals.native_resolution.x / 1920.0))
self.fullscreen_node.set_scale(self.gui_scale)
if self.advanced_info:
self.exposure_node.set_pos(
Globals.native_resolution.x // self.gui_scale - 200,
1, -Globals.native_resolution.y // self.gui_scale + 120)
self.hint_reloading.set_pos(
float((Globals.native_resolution.x) // 2) / self.gui_scale - 465 // 2, 220)
self.keybinding_instructions.set_pos(
30, Globals.native_resolution.y // self.gui_scale - 510.0,)
self.overlay_node.set_pos(Globals.base.get_aspect_ratio() - 0.07, 1, 1.0 - 0.07)
if self.python_warning:
self.python_warning.set_pos(
(Globals.native_resolution.x // self.gui_scale - 1054) // 2,
(Globals.native_resolution.y // self.gui_scale - 118 - 40))
for text in self.debug_lines:
text.set_pixel_size(16 * max(0.8, self.gui_scale))
self.buffer_viewer.center_on_screen()
self.pipe_viewer.center_on_screen()
self.rm_selector.center_on_screen()
def init_keybindings(self):
""" Inits the debugger keybindings """
Globals.base.accept("v", self.buffer_viewer.toggle)
Globals.base.accept("c", self.pipe_viewer.toggle)
Globals.base.accept("z", self.rm_selector.toggle)
Globals.base.accept("f5", self.toggle_gui_visible)
Globals.base.accept("f6", self.toggle_keybindings_visible)
Globals.base.accept("r", self.pipeline.reload_shaders)
Globals.base.accept("m", self.start_material_editor)
def start_material_editor(self):
""" Starts the material editor """
self.debug("Starting material editor")
pth = sys.executable
editor = os.path.dirname(os.path.realpath(__file__))
editor = os.path.join(editor, "..", "..", "toolkit", "material_editor", "main.py")
subprocess.Popen([pth, editor], shell=True)
def toggle_gui_visible(self):
""" Shows / Hides the gui """
if not self.fullscreen_node.is_hidden():
self.fullscreen_node.hide()
self.overlay_node.hide()
self.error_msg_handler.hide()
else:
self.fullscreen_node.show()
self.overlay_node.show()
self.error_msg_handler.show()
def toggle_keybindings_visible(self):
""" Shows / Hides the FPS graph """
if not self.keybinding_instructions.is_hidden():
self.keybinding_instructions.hide()
else:
self.keybinding_instructions.show()
def update_stats(self, task=None):
""" Updates the stats overlay """
clock = Globals.clock
self.debug_lines[0].text = "{:3.0f} fps | {:3.1f} ms | {:3.1f} ms max".format(
clock.get_average_frame_rate(),
1000.0 / max(0.001, clock.get_average_frame_rate()),
clock.get_max_frame_duration() * 1000.0)
if not self.advanced_info:
return task.again if task else None
text = "{:4d} states | {:4d} transforms "
text += "| {:4d} cmds | {:4d} lights | {:4d} shadows "
text += "| {:5.1f}% atlas usage"
self.debug_lines[1].text = text.format(
RenderState.get_num_states(), TransformState.get_num_states(),
self.pipeline.light_mgr.cmd_queue.num_processed_commands,
self.pipeline.light_mgr.num_lights,
self.pipeline.light_mgr.num_shadow_sources,
self.pipeline.light_mgr.shadow_atlas_coverage)
text = "Internal: {:3.0f} MB VRAM | {:5d} img | {:5d} tex | "
text += "{:5d} fbos | {:3d} plugins | {:2d} views ({:2d} active)"
tex_memory, tex_count = self.buffer_viewer.stage_information
views, active_views = 0, 0
for target in RenderTarget.REGISTERED_TARGETS:
if not target.create_default_region:
num_regions = target.internal_buffer.get_num_display_regions()
for i, region in enumerate(target.internal_buffer.get_display_regions()):
# Skip overlay display region
if i == 0 and num_regions > 1:
continue
views += 1
active_views += 1 if target.active and region.active else 0
self.debug_lines[2].text = text.format(
tex_memory / (1024**2), len(Image.REGISTERED_IMAGES), tex_count,
RenderTarget.NUM_ALLOCATED_BUFFERS,
len(self.pipeline.plugin_mgr.enabled_plugins),
views, active_views)
text = "Scene: {:4.0f} MB VRAM | {:3d} tex | {:4d} geoms "
text += "| {:4d} nodes | {:7,.0f} vertices"
scene_tex_size = 0
for tex in TexturePool.find_all_textures():
scene_tex_size += tex.estimate_texture_memory()
self.debug_lines[3].text = text.format(
scene_tex_size / (1024**2),
len(TexturePool.find_all_textures()),
self.analyzer.get_num_geoms(),
self.analyzer.get_num_nodes(),
self.analyzer.get_num_vertices(),
)
sun_vector = Vec3(0)
if self.pipeline.plugin_mgr.is_plugin_enabled("scattering"):
sun_vector = self.pipeline.plugin_mgr.instances["scattering"].sun_vector
text = "Time: {} ({:1.3f}) | Sun {:0.2f} {:0.2f} {:0.2f}"
text += " | X {:3.1f} Y {:3.1f} Z {:3.1f}"
text += " | {:2d} tasks | scheduled: {:2d}"
self.debug_lines[4].text = text.format(
self.pipeline.daytime_mgr.formatted_time,
self.pipeline.daytime_mgr.time,
sun_vector.x, sun_vector.y, sun_vector.z,
Globals.base.camera.get_x(Globals.base.render),
Globals.base.camera.get_y(Globals.base.render),
Globals.base.camera.get_z(Globals.base.render),
self.pipeline.task_scheduler.num_tasks,
self.pipeline.task_scheduler.num_scheduled_tasks,)
text = "Scene shadows: "
if "pssm" in self.pipeline.plugin_mgr.enabled_plugins:
focus = self.pipeline.plugin_mgr.instances["pssm"].scene_shadow_stage.last_focus
if focus is not None:
text += "{:3.1f} {:3.1f} {:3.1f} r {:3.1f}".format(
focus[0].x, focus[0].y, focus[0].z, focus[1])
else:
text += "none"
else:
text += "inactive"
text += " | HPR ({:3.1f}, {:3.1f}, {:3.1f}) | {:4d} x {:4d} pixels @ {:3.1f} %"
text += " | {:3d} x {:3d} tiles"
self.debug_lines[5].text = text.format(
Globals.base.camera.get_h(Globals.base.render),
Globals.base.camera.get_p(Globals.base.render),
Globals.base.camera.get_r(Globals.base.render),
Globals.native_resolution.x,
Globals.native_resolution.y,
self.pipeline.settings["pipeline.resolution_scale"] * 100.0,
self.pipeline.light_mgr.num_tiles.x,
self.pipeline.light_mgr.num_tiles.y,)
if task:
return task.again

View File

@ -1,166 +1,166 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec2, TransparencyAttrib, Vec3
from direct.gui.DirectFrame import DirectFrame
from direct.gui.DirectButton import DirectButton
from direct.gui.DirectGui import DGG
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
from rpcore.gui.text import Text
class DraggableWindow(RPObject):
""" This is a simple draggable but not resizeable window """
def __init__(self, width=800, height=500, title="Window", parent=None):
""" Constructs a new window with the given dimensions and title """
RPObject.__init__(self, "Window-" + title)
self._width = width
self._height = height
self._title = title
self._visible = True
self._parent = parent if parent else Globals.base.pixel2d
self._dragging = False
self._drag_offset = Vec2(0)
self._pos = Vec2(0)
def center_on_screen(self):
""" Centers the window on screen """
self._context_scale = 1.0 / self._parent.get_sx()
self._context_width = Globals.native_resolution.x * self._context_scale
self._context_height = Globals.native_resolution.y * self._context_scale
self._set_pos(Vec2((self._context_width - self._width) / 2,
(self._context_height - self._height) / 2))
def set_title(self, title):
""" Sets the window title """
self._title = title
self._window_title.set_text(title)
def show(self):
""" Shows the window """
self._visible = True
self.center_on_screen()
self._node.show()
def hide(self):
""" Hides the window """
self._visible = False
self._stop_drag()
self._node.hide()
def remove(self):
""" Removes the window from the scene graph. You should still delete the
instance """
self._stop_drag()
self._node.remove_node()
def _create_components(self):
""" Creates the window components """
self._node = self._parent.attach_new_node("Window")
self._node.set_pos(self._pos.x, 1, -self._pos.y)
border_px = 1
border_frame_size = (-border_px, self._width + border_px,
border_px, -self._height - border_px)
self._border_frame = DirectFrame(
pos=(0, 1, 0), frameSize=border_frame_size,
frameColor=(24 / 255.0, 131 / 255.0, 215 / 255.0, 1),
parent=self._node, state=DGG.NORMAL)
self._background = DirectFrame(
pos=(0, 1, 0), frameSize=(0, self._width, 0, -self._height),
frameColor=(0.1, 0.1, 0.1, 1.0), parent=self._node)
self._title_bar = DirectFrame(
pos=(0, 1, 0), frameSize=(0, self._width, 0, -25),
# frameColor=(0.058, 0.058, 0.058, 1),
frameColor=(1, 1, 1, 1),
parent=self._node,
state=DGG.NORMAL)
self._window_title = Text(
parent=self._node, x=8, y=17, text=self._title, size=13,
color=Vec3(0.15), may_change=True)
self._btn_close = DirectButton(
relief=DGG.FLAT, pressEffect=1, pos=(self._width - 22, 1, -12),
frameColor=(1.0, 0.2, 0.2, 0.5), parent=self._node,
scale=(45 / 2, 1, 24 / 2),
image="/$$rp/data/gui/close_window.png")
# Init bindings
self._btn_close.set_transparency(TransparencyAttrib.M_alpha)
self._btn_close.bind(DGG.B1CLICK, self._request_close)
self._btn_close.bind(DGG.WITHIN, self._on_close_btn_hover)
self._btn_close.bind(DGG.WITHOUT, self._on_close_btn_out)
self._title_bar.bind(DGG.B1PRESS, self._start_drag)
self._title_bar.bind(DGG.B1RELEASE, self._stop_drag)
def _start_drag(self, evt=None): # pylint: disable=unused-argument
""" Gets called when the user starts dragging the window """
self._dragging = True
self._node.detach_node()
self._node.reparent_to(self._parent)
Globals.base.taskMgr.add(self._on_tick, "UIWindowDrag",
uponDeath=self._stop_drag)
self._drag_offset = self._pos - self._get_mouse_pos()
def _on_close_btn_hover(self, evt=None): # pylint: disable=unused-argument
""" Internal method when the close button got hovered """
self._btn_close["image"] = "/$$rp/data/gui/close_window_hover.png"
def _on_close_btn_out(self, evt=None): # pylint: disable=unused-argument
""" Internal method when the close button is no longer hovered """
self._btn_close["image"] = "/$$rp/data/gui/close_window.png"
def _request_close(self, evt=None): # pylint: disable=unused-argument
""" This method gets called when the close button gets clicked """
self.hide()
def _stop_drag(self, evt=None): # pylint: disable=unused-argument
""" Gets called when the user stops dragging the window """
Globals.base.taskMgr.remove("UIWindowDrag")
self._dragging = False
def _get_mouse_pos(self):
""" Internal helper function to get the mouse position, scaled by
the context scale """
mouse_x, mouse_y = (Globals.base.win.get_pointer(0).x,
Globals.base.win.get_pointer(0).y)
return Vec2(mouse_x, mouse_y) * self._context_scale
def _set_pos(self, pos):
""" Moves the window to the specified position """
self._pos = pos
self._pos.x = max(self._pos.x, -self._width + 100)
self._pos.y = max(self._pos.y, 25)
self._pos.x = min(self._pos.x, self._context_width - 100)
self._pos.y = min(self._pos.y, self._context_height - 50)
self._node.set_pos(self._pos.x, 1, -self._pos.y)
def _on_tick(self, task):
""" Task which updates the window while being dragged """
self._set_pos(self._get_mouse_pos() + self._drag_offset)
return task.cont
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec2, TransparencyAttrib, Vec3
from direct.gui.DirectFrame import DirectFrame
from direct.gui.DirectButton import DirectButton
from direct.gui.DirectGui import DGG
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
from rpcore.gui.text import Text
class DraggableWindow(RPObject):
""" This is a simple draggable but not resizeable window """
def __init__(self, width=800, height=500, title="Window", parent=None):
""" Constructs a new window with the given dimensions and title """
RPObject.__init__(self, "Window-" + title)
self._width = width
self._height = height
self._title = title
self._visible = True
self._parent = parent if parent else Globals.base.pixel2d
self._dragging = False
self._drag_offset = Vec2(0)
self._pos = Vec2(0)
def center_on_screen(self):
""" Centers the window on screen """
self._context_scale = 1.0 / self._parent.get_sx()
self._context_width = Globals.native_resolution.x * self._context_scale
self._context_height = Globals.native_resolution.y * self._context_scale
self._set_pos(Vec2((self._context_width - self._width) / 2,
(self._context_height - self._height) / 2))
def set_title(self, title):
""" Sets the window title """
self._title = title
self._window_title.set_text(title)
def show(self):
""" Shows the window """
self._visible = True
self.center_on_screen()
self._node.show()
def hide(self):
""" Hides the window """
self._visible = False
self._stop_drag()
self._node.hide()
def remove(self):
""" Removes the window from the scene graph. You should still delete the
instance """
self._stop_drag()
self._node.remove_node()
def _create_components(self):
""" Creates the window components """
self._node = self._parent.attach_new_node("Window")
self._node.set_pos(self._pos.x, 1, -self._pos.y)
border_px = 1
border_frame_size = (-border_px, self._width + border_px,
border_px, -self._height - border_px)
self._border_frame = DirectFrame(
pos=(0, 1, 0), frameSize=border_frame_size,
frameColor=(24 / 255.0, 131 / 255.0, 215 / 255.0, 1),
parent=self._node, state=DGG.NORMAL)
self._background = DirectFrame(
pos=(0, 1, 0), frameSize=(0, self._width, 0, -self._height),
frameColor=(0.1, 0.1, 0.1, 1.0), parent=self._node)
self._title_bar = DirectFrame(
pos=(0, 1, 0), frameSize=(0, self._width, 0, -25),
# frameColor=(0.058, 0.058, 0.058, 1),
frameColor=(1, 1, 1, 1),
parent=self._node,
state=DGG.NORMAL)
self._window_title = Text(
parent=self._node, x=8, y=17, text=self._title, size=13,
color=Vec3(0.15), may_change=True)
self._btn_close = DirectButton(
relief=DGG.FLAT, pressEffect=1, pos=(self._width - 22, 1, -12),
frameColor=(1.0, 0.2, 0.2, 0.5), parent=self._node,
scale=(45 / 2, 1, 24 / 2),
image="/$$rp/data/gui/close_window.png")
# Init bindings
self._btn_close.set_transparency(TransparencyAttrib.M_alpha)
self._btn_close.bind(DGG.B1CLICK, self._request_close)
self._btn_close.bind(DGG.WITHIN, self._on_close_btn_hover)
self._btn_close.bind(DGG.WITHOUT, self._on_close_btn_out)
self._title_bar.bind(DGG.B1PRESS, self._start_drag)
self._title_bar.bind(DGG.B1RELEASE, self._stop_drag)
def _start_drag(self, evt=None): # pylint: disable=unused-argument
""" Gets called when the user starts dragging the window """
self._dragging = True
self._node.detach_node()
self._node.reparent_to(self._parent)
Globals.base.taskMgr.add(self._on_tick, "UIWindowDrag",
uponDeath=self._stop_drag)
self._drag_offset = self._pos - self._get_mouse_pos()
def _on_close_btn_hover(self, evt=None): # pylint: disable=unused-argument
""" Internal method when the close button got hovered """
self._btn_close["image"] = "/$$rp/data/gui/close_window_hover.png"
def _on_close_btn_out(self, evt=None): # pylint: disable=unused-argument
""" Internal method when the close button is no longer hovered """
self._btn_close["image"] = "/$$rp/data/gui/close_window.png"
def _request_close(self, evt=None): # pylint: disable=unused-argument
""" This method gets called when the close button gets clicked """
self.hide()
def _stop_drag(self, evt=None): # pylint: disable=unused-argument
""" Gets called when the user stops dragging the window """
Globals.base.taskMgr.remove("UIWindowDrag")
self._dragging = False
def _get_mouse_pos(self):
""" Internal helper function to get the mouse position, scaled by
the context scale """
mouse_x, mouse_y = (Globals.base.win.get_pointer(0).x,
Globals.base.win.get_pointer(0).y)
return Vec2(mouse_x, mouse_y) * self._context_scale
def _set_pos(self, pos):
""" Moves the window to the specified position """
self._pos = pos
self._pos.x = max(self._pos.x, -self._width + 100)
self._pos.y = max(self._pos.y, 25)
self._pos.x = min(self._pos.x, self._context_width - 100)
self._pos.y = min(self._pos.y, self._context_height - 50)
self._node.set_pos(self._pos.x, 1, -self._pos.y)
def _on_tick(self, task):
""" Task which updates the window while being dragged """
self._set_pos(self._get_mouse_pos() + self._drag_offset)
return task.cont

View File

@ -1,101 +1,101 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function
from panda3d.core import Notify, LineStream, Vec3
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.gui.text import Text
class ErrorMessageDisplay(RPObject):
""" This is a gui element which listens to the panda output stream
and shows errors """
def __init__(self):
RPObject.__init__(self)
self._num_errors = 0
self._error_node = Globals.base.pixel2d.attach_new_node("ErrorDisplay")
self._error_node.set_z(-180)
self._notify_stream = None
def _init_notify(self):
""" Internal method to init the stream to catch all notify messages """
self._notify_stream = LineStream()
Notify.ptr().set_ostream_ptr(self._notify_stream, False)
def update(self):
""" Updates the error display, fetching all new messages from the notify
stream """
if not self._notify_stream:
self._init_notify()
while self._notify_stream.is_text_available():
line = self._notify_stream.get_line().strip()
if "warning" in line:
RPObject.global_warn("Panda3D", line)
# self.add_warning(line)
elif "error" in line:
RPObject.global_error("Panda3D", line)
self.add_error(line)
else:
RPObject.global_debug("Panda3D", line)
def add_error(self, msg):
""" Adds a new error message """
self.add_text(msg, Vec3(1, 0.2, 0.2))
def add_warning(self, msg):
""" Adds a new warning message """
self.add_text(msg, Vec3(1, 1, 0.2))
def add_text(self, text, color):
""" Internal method to add a new text to the output """
Text(
x=Globals.native_resolution.x - 30, y=self._num_errors * 23,
align="right", text=text, size=12, parent=self._error_node, color=color)
self._num_errors += 1
if self._num_errors > 30:
self.clear_messages()
self.add_error("Error count exceeded. Cleared errors ..")
def clear_messages(self):
""" Clears all messages / removes them """
self._error_node.node().remove_all_children()
self._num_errors = 0
def show(self):
self._error_node.show()
def hide(self):
self._error_node.hide()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function
from panda3d.core import Notify, LineStream, Vec3
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.gui.text import Text
class ErrorMessageDisplay(RPObject):
""" This is a gui element which listens to the panda output stream
and shows errors """
def __init__(self):
RPObject.__init__(self)
self._num_errors = 0
self._error_node = Globals.base.pixel2d.attach_new_node("ErrorDisplay")
self._error_node.set_z(-180)
self._notify_stream = None
def _init_notify(self):
""" Internal method to init the stream to catch all notify messages """
self._notify_stream = LineStream()
Notify.ptr().set_ostream_ptr(self._notify_stream, False)
def update(self):
""" Updates the error display, fetching all new messages from the notify
stream """
if not self._notify_stream:
self._init_notify()
while self._notify_stream.is_text_available():
line = self._notify_stream.get_line().strip()
if "warning" in line:
RPObject.global_warn("Panda3D", line)
# self.add_warning(line)
elif "error" in line:
RPObject.global_error("Panda3D", line)
self.add_error(line)
else:
RPObject.global_debug("Panda3D", line)
def add_error(self, msg):
""" Adds a new error message """
self.add_text(msg, Vec3(1, 0.2, 0.2))
def add_warning(self, msg):
""" Adds a new warning message """
self.add_text(msg, Vec3(1, 1, 0.2))
def add_text(self, text, color):
""" Internal method to add a new text to the output """
Text(
x=Globals.native_resolution.x - 30, y=self._num_errors * 23,
align="right", text=text, size=12, parent=self._error_node, color=color)
self._num_errors += 1
if self._num_errors > 30:
self.clear_messages()
self.add_error("Error count exceeded. Cleared errors ..")
def clear_messages(self):
""" Clears all messages / removes them """
self._error_node.node().remove_all_children()
self._num_errors = 0
def show(self):
self._error_node.show()
def hide(self):
self._error_node.hide()

View File

@ -1,101 +1,101 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from panda3d.core import ComputeNode, Vec4, Vec3
from direct.gui.DirectFrame import DirectFrame
from rpcore.gui.sprite import Sprite
from rpcore.gui.text import Text
from rpcore.rpobject import RPObject
from rpcore.image import Image
from rpcore.globals import Globals
from rpcore.loader import RPLoader
class ExposureWidget(RPObject):
""" Widget to show the current exposure """
def __init__(self, pipeline, parent):
""" Inits the widget """
RPObject.__init__(self)
self._pipeline = pipeline
self._parent = parent
self._node = self._parent.attach_new_node("ExposureWidgetNode")
self._create_components()
def _create_components(self):
""" Internal method to init the widgets components """
self._node.hide()
# Create the texture where the gui component is rendered inside
self._storage_tex = Image.create_2d("ExposureDisplay", 140, 20, "RGBA8")
self._storage_tex.set_clear_color(Vec4(0.2, 0.6, 1.0, 1.0))
self._storage_tex.clear_image()
self._bg_frame = DirectFrame(
parent=self._node, frameColor=(0.1, 0.1, 0.1, 1.0),
frameSize=(200, 0, -10, -85), pos=(0, 0, 0))
self._display_img = Sprite(
image=self._storage_tex, parent=self._node, w=140, h=20, x=20, y=50)
self._display_txt = Text(
text="Current Exposure".upper(), parent=self._node, x=160, y=40,
size=13, color=Vec3(0.8), align="right")
# Create the shader which generates the visualization texture
self._cshader_node = ComputeNode("ExposureWidget")
self._cshader_node.add_dispatch(140 // 10, 20 // 4, 1)
self._cshader_np = self._node.attach_new_node(self._cshader_node)
# Defer the further loading
Globals.base.taskMgr.doMethodLater(1.0, self._late_init, "ExposureLateInit")
def _late_init(self, task):
""" Gets called after the pipeline initialized, this extracts the
exposure texture from the stage manager """
stage_mgr = self._pipeline.stage_mgr
if "Exposure" not in stage_mgr.pipes:
self.debug("Disabling exposure widget, could not find the exposure data.")
self._node.remove_node()
return
self._node.show()
exposure_tex = stage_mgr.pipes["Exposure"]
self._cshader = RPLoader.load_shader("/$$rp/shader/visualize_exposure.compute.glsl")
self._cshader_np.set_shader(self._cshader)
self._cshader_np.set_shader_inputs(
DestTex=self._storage_tex,
ExposureTex=exposure_tex)
return task.done
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from panda3d.core import ComputeNode, Vec4, Vec3
from direct.gui.DirectFrame import DirectFrame
from rpcore.gui.sprite import Sprite
from rpcore.gui.text import Text
from rpcore.rpobject import RPObject
from rpcore.image import Image
from rpcore.globals import Globals
from rpcore.loader import RPLoader
class ExposureWidget(RPObject):
""" Widget to show the current exposure """
def __init__(self, pipeline, parent):
""" Inits the widget """
RPObject.__init__(self)
self._pipeline = pipeline
self._parent = parent
self._node = self._parent.attach_new_node("ExposureWidgetNode")
self._create_components()
def _create_components(self):
""" Internal method to init the widgets components """
self._node.hide()
# Create the texture where the gui component is rendered inside
self._storage_tex = Image.create_2d("ExposureDisplay", 140, 20, "RGBA8")
self._storage_tex.set_clear_color(Vec4(0.2, 0.6, 1.0, 1.0))
self._storage_tex.clear_image()
self._bg_frame = DirectFrame(
parent=self._node, frameColor=(0.1, 0.1, 0.1, 1.0),
frameSize=(200, 0, -10, -85), pos=(0, 0, 0))
self._display_img = Sprite(
image=self._storage_tex, parent=self._node, w=140, h=20, x=20, y=50)
self._display_txt = Text(
text="Current Exposure".upper(), parent=self._node, x=160, y=40,
size=13, color=Vec3(0.8), align="right")
# Create the shader which generates the visualization texture
self._cshader_node = ComputeNode("ExposureWidget")
self._cshader_node.add_dispatch(140 // 10, 20 // 4, 1)
self._cshader_np = self._node.attach_new_node(self._cshader_node)
# Defer the further loading
Globals.base.taskMgr.doMethodLater(1.0, self._late_init, "ExposureLateInit")
def _late_init(self, task):
""" Gets called after the pipeline initialized, this extracts the
exposure texture from the stage manager """
stage_mgr = self._pipeline.stage_mgr
if "Exposure" not in stage_mgr.pipes:
self.debug("Disabling exposure widget, could not find the exposure data.")
self._node.remove_node()
return
self._node.show()
exposure_tex = stage_mgr.pipes["Exposure"]
self._cshader = RPLoader.load_shader("/$$rp/shader/visualize_exposure.compute.glsl")
self._cshader_np.set_shader(self._cshader)
self._cshader_np.set_shader_inputs(
DestTex=self._storage_tex,
ExposureTex=exposure_tex)
return task.done

View File

@ -1,133 +1,133 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from panda3d.core import ComputeNode, Vec4, Vec3, PTAInt, PTAFloat
from rpcore.gui.sprite import Sprite
from rpcore.gui.text import Text
from rpcore.rpobject import RPObject
from rpcore.image import Image
from rpcore.globals import Globals
from rpcore.loader import RPLoader
class FPSChart(RPObject):
""" Widget to show the FPS as a chart """
def __init__(self, pipeline, parent):
""" Inits the widget """
RPObject.__init__(self)
self._pipeline = pipeline
self._parent = parent
self._node = self._parent.attach_new_node("FPSChartNode")
self._create_components()
def _create_components(self):
""" Internal method to init the widgets components """
# Create the buffer which stores the last FPS values
self._storage_buffer = Image.create_buffer("FPSValues", 250, "R16")
self._storage_buffer.set_clear_color(Vec4(0))
self._storage_buffer.clear_image()
self._store_index = PTAInt.empty_array(1)
self._store_index[0] = 0
self._current_ftime = PTAFloat.empty_array(1)
self._current_ftime[0] = 16.0
self._chart_ms_max = PTAFloat.empty_array(1)
self._chart_ms_max[0] = 40
# Create the texture where the gui component is rendered inside
self._display_tex = Image.create_2d("FPSChartRender", 250, 120, "RGBA8")
self._display_tex.set_clear_color(Vec4(0))
self._display_tex.clear_image()
self._display_img = Sprite(
image=self._display_tex, parent=self._node, w=250, h=120, x=10, y=10)
# Defer the further loading
Globals.base.taskMgr.doMethodLater(0.3, self._late_init, "FPSChartInit")
def _late_init(self, task):
""" Gets called after the pipeline was initialized """
self._display_txt = Text(
text="40 ms", parent=self._node, x=20, y=25,
size=13, color=Vec3(1), may_change=True)
self._display_txt_bottom = Text(
text="0 ms", parent=self._node, x=20, y=120,
size=13, color=Vec3(1), may_change=True)
# Create the shader which generates the visualization texture
self._cshader_node = ComputeNode("FPSChartUpdateChart")
self._cshader_node.add_dispatch(250 // 10, 120 // 4, 1)
self._cshader_np = self._node.attach_new_node(self._cshader_node)
self._cshader = RPLoader.load_shader("/$$rp/shader/fps_chart.compute.glsl")
self._cshader_np.set_shader(self._cshader)
self._cshader_np.set_shader_inputs(
DestTex=self._display_tex,
FPSValues=self._storage_buffer,
index=self._store_index,
maxMs=self._chart_ms_max)
self._update_shader_node = ComputeNode("FPSChartUpdateValues")
self._update_shader_node.add_dispatch(1, 1, 1)
self._update_shader_np = self._node.attach_new_node(self._update_shader_node)
self._ushader = RPLoader.load_shader("/$$rp/shader/fps_chart_update.compute.glsl")
self._update_shader_np.set_shader(self._ushader)
self._update_shader_np.set_shader_inputs(
DestTex=self._storage_buffer,
index=self._store_index,
currentData=self._current_ftime)
Globals.base.addTask(self._update, "UpdateFPSChart", sort=-50)
return task.done
def _update(self, task):
""" Updates the widget """
self._store_index[0] = (self._store_index[0] + 1) % 250
self._current_ftime[0] = Globals.clock.get_dt() * 1000.0
avg_fps = Globals.clock.get_average_frame_rate()
if avg_fps > 122:
self._chart_ms_max[0] = 10.0
elif avg_fps > 62:
self._chart_ms_max[0] = 20.0
elif avg_fps > 32:
self._chart_ms_max[0] = 40.0
elif avg_fps > 15:
self._chart_ms_max[0] = 70.0
else:
self._chart_ms_max[0] = 200.0
self._display_txt.set_text(str(int(self._chart_ms_max[0])) + " ms")
return task.cont
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from panda3d.core import ComputeNode, Vec4, Vec3, PTAInt, PTAFloat
from rpcore.gui.sprite import Sprite
from rpcore.gui.text import Text
from rpcore.rpobject import RPObject
from rpcore.image import Image
from rpcore.globals import Globals
from rpcore.loader import RPLoader
class FPSChart(RPObject):
""" Widget to show the FPS as a chart """
def __init__(self, pipeline, parent):
""" Inits the widget """
RPObject.__init__(self)
self._pipeline = pipeline
self._parent = parent
self._node = self._parent.attach_new_node("FPSChartNode")
self._create_components()
def _create_components(self):
""" Internal method to init the widgets components """
# Create the buffer which stores the last FPS values
self._storage_buffer = Image.create_buffer("FPSValues", 250, "R16")
self._storage_buffer.set_clear_color(Vec4(0))
self._storage_buffer.clear_image()
self._store_index = PTAInt.empty_array(1)
self._store_index[0] = 0
self._current_ftime = PTAFloat.empty_array(1)
self._current_ftime[0] = 16.0
self._chart_ms_max = PTAFloat.empty_array(1)
self._chart_ms_max[0] = 40
# Create the texture where the gui component is rendered inside
self._display_tex = Image.create_2d("FPSChartRender", 250, 120, "RGBA8")
self._display_tex.set_clear_color(Vec4(0))
self._display_tex.clear_image()
self._display_img = Sprite(
image=self._display_tex, parent=self._node, w=250, h=120, x=10, y=10)
# Defer the further loading
Globals.base.taskMgr.doMethodLater(0.3, self._late_init, "FPSChartInit")
def _late_init(self, task):
""" Gets called after the pipeline was initialized """
self._display_txt = Text(
text="40 ms", parent=self._node, x=20, y=25,
size=13, color=Vec3(1), may_change=True)
self._display_txt_bottom = Text(
text="0 ms", parent=self._node, x=20, y=120,
size=13, color=Vec3(1), may_change=True)
# Create the shader which generates the visualization texture
self._cshader_node = ComputeNode("FPSChartUpdateChart")
self._cshader_node.add_dispatch(250 // 10, 120 // 4, 1)
self._cshader_np = self._node.attach_new_node(self._cshader_node)
self._cshader = RPLoader.load_shader("/$$rp/shader/fps_chart.compute.glsl")
self._cshader_np.set_shader(self._cshader)
self._cshader_np.set_shader_inputs(
DestTex=self._display_tex,
FPSValues=self._storage_buffer,
index=self._store_index,
maxMs=self._chart_ms_max)
self._update_shader_node = ComputeNode("FPSChartUpdateValues")
self._update_shader_node.add_dispatch(1, 1, 1)
self._update_shader_np = self._node.attach_new_node(self._update_shader_node)
self._ushader = RPLoader.load_shader("/$$rp/shader/fps_chart_update.compute.glsl")
self._update_shader_np.set_shader(self._ushader)
self._update_shader_np.set_shader_inputs(
DestTex=self._storage_buffer,
index=self._store_index,
currentData=self._current_ftime)
Globals.base.addTask(self._update, "UpdateFPSChart", sort=-50)
return task.done
def _update(self, task):
""" Updates the widget """
self._store_index[0] = (self._store_index[0] + 1) % 250
self._current_ftime[0] = Globals.clock.get_dt() * 1000.0
avg_fps = Globals.clock.get_average_frame_rate()
if avg_fps > 122:
self._chart_ms_max[0] = 10.0
elif avg_fps > 62:
self._chart_ms_max[0] = 20.0
elif avg_fps > 32:
self._chart_ms_max[0] = 40.0
elif avg_fps > 15:
self._chart_ms_max[0] = 70.0
else:
self._chart_ms_max[0] = 200.0
self._display_txt.set_text(str(int(self._chart_ms_max[0])) + " ms")
return task.cont

View File

@ -1,86 +1,86 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec3
import direct.gui.DirectGuiGlobals as DGG
from rpcore.rpobject import RPObject
from rpcore.gui.checkbox import Checkbox
from rpcore.gui.text import Text
class LabeledCheckbox(RPObject):
""" This is a checkbox, combined with a label. The arguments are
equal to the Checkbox and OnscreenText arguments. """
def __init__(self, parent=None, x=0, y=0, chb_callback=None,
chb_args=None, chb_checked=True, text="", text_size=16,
radio=False, text_color=None, expand_width=100, enabled=True):
""" Constructs a new checkbox, forwarding most of the elements to the
underlying Checkbox and Text. """
RPObject.__init__(self)
if chb_args is None:
chb_args = []
if text_color is None:
text_color = Vec3(1)
if not enabled:
text_color = Vec3(1.0, 0, 0.28)
self.text_color = text_color
self._checkbox = Checkbox(
parent=parent, x=x, y=y, enabled=enabled, callback=chb_callback,
extra_args=chb_args, checked=chb_checked, radio=radio,
expand_width=expand_width)
self._text = Text(
x=x + 26, y=y + 9 + text_size // 4, text=text, align="left",
parent=parent, size=text_size, color=text_color, may_change=True)
if enabled:
self._checkbox.node.bind(DGG.WITHIN, self._on_node_enter)
self._checkbox.node.bind(DGG.WITHOUT, self._on_node_leave)
def _on_node_enter(self, *args): # pylint: disable=unused-argument
""" Internal callback when the node gets hovered """
self._text.node["fg"] = (self.text_color.x + 0.1, self.text_color.y + 0.1,
self.text_color.z + 0.1, 1.0)
def _on_node_leave(self, *args): # pylint: disable=unused-argument
""" Internal callback when the node gets no longer hovered """
self._text.node["fg"] = (self.text_color.x, self.text_color.y, self.text_color.z, 1.0)
@property
def checkbox(self):
""" Returns a handle to the checkbox """
return self._checkbox
@property
def label(self):
""" Returns a handle to the label """
return self._text
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec3
import direct.gui.DirectGuiGlobals as DGG
from rpcore.rpobject import RPObject
from rpcore.gui.checkbox import Checkbox
from rpcore.gui.text import Text
class LabeledCheckbox(RPObject):
""" This is a checkbox, combined with a label. The arguments are
equal to the Checkbox and OnscreenText arguments. """
def __init__(self, parent=None, x=0, y=0, chb_callback=None,
chb_args=None, chb_checked=True, text="", text_size=16,
radio=False, text_color=None, expand_width=100, enabled=True):
""" Constructs a new checkbox, forwarding most of the elements to the
underlying Checkbox and Text. """
RPObject.__init__(self)
if chb_args is None:
chb_args = []
if text_color is None:
text_color = Vec3(1)
if not enabled:
text_color = Vec3(1.0, 0, 0.28)
self.text_color = text_color
self._checkbox = Checkbox(
parent=parent, x=x, y=y, enabled=enabled, callback=chb_callback,
extra_args=chb_args, checked=chb_checked, radio=radio,
expand_width=expand_width)
self._text = Text(
x=x + 26, y=y + 9 + text_size // 4, text=text, align="left",
parent=parent, size=text_size, color=text_color, may_change=True)
if enabled:
self._checkbox.node.bind(DGG.WITHIN, self._on_node_enter)
self._checkbox.node.bind(DGG.WITHOUT, self._on_node_leave)
def _on_node_enter(self, *args): # pylint: disable=unused-argument
""" Internal callback when the node gets hovered """
self._text.node["fg"] = (self.text_color.x + 0.1, self.text_color.y + 0.1,
self.text_color.z + 0.1, 1.0)
def _on_node_leave(self, *args): # pylint: disable=unused-argument
""" Internal callback when the node gets no longer hovered """
self._text.node["fg"] = (self.text_color.x, self.text_color.y, self.text_color.z, 1.0)
@property
def checkbox(self):
""" Returns a handle to the checkbox """
return self._checkbox
@property
def label(self):
""" Returns a handle to the label """
return self._text

View File

@ -1,70 +1,70 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from six.moves import range # pylint: disable=import-error
from rpcore.gui.sprite import Sprite
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
class LoadingScreen(RPObject):
""" This is the default loading screen used by the pipeline. It provides
the ability to display a simple image during loading. The image should be
in the format 16:9 and not too small, to avoid being blurred out. """
def __init__(self, pipeline, image_source="/$$rp/data/gui/loading_screen_bg.txo"):
""" Inits the loading screen with a given image source. By default,
this is the pipeline loading screen, but it can be overridden. """
RPObject.__init__(self)
self.pipeline = pipeline
self.image_source = image_source
def create(self):
""" Creates the gui components """
screen_w, screen_h = Globals.native_resolution.x, Globals.native_resolution.y
self.fullscreen_node = Globals.base.pixel2dp.attach_new_node("LoadingScreen")
self.fullscreen_node.set_bin("fixed", 10)
self.fullscreen_node.set_depth_test(False)
scale_w = screen_w / 1920.0
scale_h = screen_h / 1080.0
scale = max(scale_w, scale_h)
self.fullscreen_bg = Sprite(
image=self.image_source, x=(screen_w - 1920.0 * scale) // 2,
y=(screen_h - 1080.0 * scale) // 2, w=int(1920 * scale),
h=int(1080 * scale), parent=self.fullscreen_node, near_filter=False)
for _ in range(2):
Globals.base.graphicsEngine.render_frame()
def remove(self):
""" Removes the loading screen """
self.fullscreen_bg.node["image"].get_texture().release_all()
self.fullscreen_node.remove_node()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from rplibs.six.moves import range # pylint: disable=import-error
from rpcore.gui.sprite import Sprite
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
class LoadingScreen(RPObject):
""" This is the default loading screen used by the pipeline. It provides
the ability to display a simple image during loading. The image should be
in the format 16:9 and not too small, to avoid being blurred out. """
def __init__(self, pipeline, image_source="/$$rp/data/gui/loading_screen_bg.txo"):
""" Inits the loading screen with a given image source. By default,
this is the pipeline loading screen, but it can be overridden. """
RPObject.__init__(self)
self.pipeline = pipeline
self.image_source = image_source
def create(self):
""" Creates the gui components """
screen_w, screen_h = Globals.native_resolution.x, Globals.native_resolution.y
self.fullscreen_node = Globals.base.pixel2dp.attach_new_node("LoadingScreen")
self.fullscreen_node.set_bin("fixed", 10)
self.fullscreen_node.set_depth_test(False)
scale_w = screen_w / 1920.0
scale_h = screen_h / 1080.0
scale = max(scale_w, scale_h)
self.fullscreen_bg = Sprite(
image=self.image_source, x=(screen_w - 1920.0 * scale) // 2,
y=(screen_h - 1080.0 * scale) // 2, w=int(1920 * scale),
h=int(1080 * scale), parent=self.fullscreen_node, near_filter=False)
for _ in range(2):
Globals.base.graphicsEngine.render_frame()
def remove(self):
""" Removes the loading screen """
self.fullscreen_bg.node["image"].get_texture().release_all()
self.fullscreen_node.remove_node()

View File

@ -1,217 +1,217 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from rplibs.six import iteritems
from panda3d.core import Texture, Vec3
from direct.gui.DirectScrolledFrame import DirectScrolledFrame
from direct.gui.DirectFrame import DirectFrame
from rpcore.globals import Globals
from rpcore.util.generic import rgb_from_string
from rpcore.util.display_shader_builder import DisplayShaderBuilder
from rpcore.util.shader_input_blocks import SimpleInputBlock, GroupedInputBlock
from rpcore.gui.draggable_window import DraggableWindow
from rpcore.gui.text import Text
from rpcore.gui.sprite import Sprite
class PipeViewer(DraggableWindow):
""" Small tool which displays the order of the graphic pipes """
_STAGE_MGR = None
@classmethod
def register_stage_mgr(cls, mgr):
""" Sets the stage manager, this is a workaround to prevent
circular imports, since the pipe viewer is already included
from the StageManager """
cls._STAGE_MGR = mgr
def __init__(self, pipeline, parent):
""" Constructs the pipe viewer """
DraggableWindow.__init__(self, width=1300, height=900, parent=parent,
title="Pipeline Visualizer")
self._pipeline = pipeline
self._scroll_width = 8000
self._scroll_height = 3000
self._created = False
self._create_components()
self.hide()
def toggle(self):
""" Toggles the pipe viewer """
if self._visible:
Globals.base.taskMgr.remove("RP_GUI_UpdatePipeViewer")
self.hide()
else:
Globals.base.taskMgr.add(self._update_task, "RP_GUI_UpdatePipeViewer")
if not self._created:
self._populate_content()
self.show()
def _update_task(self, task=None):
""" Updates the viewer """
scroll_value = self._content_frame.horizontalScroll["value"]
scroll_value *= 2.45
self._pipe_descriptions.set_x(scroll_value * 2759.0)
return task.cont
def _populate_content(self): # pylint: disable=too-many-branches,too-many-statements
""" Reads the pipes and stages from the stage manager and renders those
into the window """
self._created = True
self._pipe_node = self._content_node.attach_new_node("pipes")
self._pipe_node.set_scale(1, 1, -1)
self._stage_node = self._content_node.attach_new_node("stages")
current_pipes = []
pipe_pixel_size = 3
pipe_height = 100
# Generate stages
for offs, stage in enumerate(self._STAGE_MGR.stages):
node = self._content_node.attach_new_node("stage")
node.set_pos(220 + offs * 200.0, 0, 20)
node.set_scale(1, 1, -1)
DirectFrame(parent=node, frameSize=(10, 150, 0, -3600),
frameColor=(0.2, 0.2, 0.2, 1))
Text(text=str(stage.debug_name.replace("Stage", "")),
parent=node, x=20, y=25, size=15)
for output_pipe, pipe_tex in iteritems(stage.produced_pipes):
pipe_idx = 0
r, g, b = rgb_from_string(output_pipe)
if output_pipe in current_pipes:
pipe_idx = current_pipes.index(output_pipe)
else:
current_pipes.append(output_pipe)
pipe_idx = len(current_pipes) - 1
DirectFrame(parent=node,
frameSize=(0, 8000, pipe_pixel_size / 2,
-pipe_pixel_size / 2),
frameColor=(r, g, b, 1),
pos=(10, 1, -95 - pipe_idx * pipe_height))
w = 160
h = Globals.native_resolution.y /\
float(Globals.native_resolution.x) * w
DirectFrame(parent=node,
frameSize=(-pipe_pixel_size, w + pipe_pixel_size,
h / 2 + pipe_pixel_size,
-h / 2 - pipe_pixel_size),
frameColor=(r, g, b, 1),
pos=(0, 1, -95 - pipe_idx * pipe_height))
if isinstance(pipe_tex, (list, tuple)):
pipe_tex = pipe_tex[0]
if isinstance(pipe_tex, (SimpleInputBlock, GroupedInputBlock)):
icon_file = "/$$rp/data/gui/icon_ubo.png"
elif pipe_tex.get_z_size() > 1:
icon_file = "/$$rp/data/gui/icon_texture.png"
elif pipe_tex.get_texture_type() == Texture.TT_buffer_texture:
icon_file = "/$$rp/data/gui/icon_buffer_texture.png"
else:
icon_file = None
preview = Sprite(
image=pipe_tex, parent=node, x=0,
y=50 + pipe_idx * pipe_height, w=w, h=h, any_filter=False,
transparent=False)
preview_shader = DisplayShaderBuilder.build(pipe_tex, int(w), int(h))
preview.set_shader(preview_shader)
preview.set_shader_inputs(
mipmap=0,
slice=0,
brightness=1,
tonemap=False)
if icon_file:
Sprite(image=icon_file, parent=node,
x=55, y=65 + pipe_idx * pipe_height,
w=48, h=48, near_filter=False,
transparent=True)
if isinstance(pipe_tex, (SimpleInputBlock, GroupedInputBlock)):
tex_desc = "UBO"
else:
tex_desc = pipe_tex.format_texture_type(pipe_tex.get_texture_type())
tex_desc += " - " + pipe_tex.format_format(pipe_tex.get_format()).upper()
Text(text=tex_desc, parent=node, x=55 + 48 / 2,
y=130 + pipe_idx * pipe_height, color=Vec3(0.2),
size=12, align="center")
for input_pipe in stage.required_pipes:
if input_pipe not in current_pipes:
self.warn("Pipe not found:", input_pipe)
continue
idx = current_pipes.index(input_pipe)
r, g, b = rgb_from_string(input_pipe)
DirectFrame(parent=node, frameSize=(0, 10, 40, -40),
frameColor=(r, g, b, 1),
pos=(5, 1, -95 - idx * pipe_height))
self._pipe_descriptions = self._content_node.attach_new_node(
"PipeDescriptions")
self._pipe_descriptions.set_scale(1, 1, -1)
DirectFrame(parent=self._pipe_descriptions, frameSize=(0, 190, 0, -5000),
frameColor=(0.1, 0.1, 0.1, 1.0))
# Generate the pipe descriptions
for idx, pipe in enumerate(current_pipes):
r, g, b = rgb_from_string(pipe)
DirectFrame(parent=self._pipe_descriptions,
frameSize=(0, 180, -95, -135),
frameColor=(r, g, b, 1.0), pos=(0, 1, -idx * pipe_height))
Text(parent=self._pipe_descriptions, text=pipe,
x=42, y=121 + idx * pipe_height, size=15,
color=Vec3(0.1))
Sprite(parent=self._pipe_descriptions, x=9, y=103 + idx * pipe_height,
image="/$$rp/data/gui/icon_pipe.png",
transparent=True, near_filter=False)
def _create_components(self):
""" Internal method to create the window components """
DraggableWindow._create_components(self)
self._content_frame = DirectScrolledFrame(
frameSize=(0, self._width - 40, 0, self._height - 80),
canvasSize=(0, self._scroll_width, 0, self._scroll_height),
autoHideScrollBars=False,
scrollBarWidth=20.0,
frameColor=(0, 0, 0, 0),
verticalScroll_relief=False,
horizontalScroll_relief=False,
parent=self._node,
pos=(20, 1, -self._height + 20))
self._content_node = self._content_frame.getCanvas().attach_new_node("PipeComponents")
self._content_node.set_scale(1, 1, -1)
self._content_node.set_z(self._scroll_height)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from rplibs.six import iteritems
from panda3d.core import Texture, Vec3
from direct.gui.DirectScrolledFrame import DirectScrolledFrame
from direct.gui.DirectFrame import DirectFrame
from rpcore.globals import Globals
from rpcore.util.generic import rgb_from_string
from rpcore.util.display_shader_builder import DisplayShaderBuilder
from rpcore.util.shader_input_blocks import SimpleInputBlock, GroupedInputBlock
from rpcore.gui.draggable_window import DraggableWindow
from rpcore.gui.text import Text
from rpcore.gui.sprite import Sprite
class PipeViewer(DraggableWindow):
""" Small tool which displays the order of the graphic pipes """
_STAGE_MGR = None
@classmethod
def register_stage_mgr(cls, mgr):
""" Sets the stage manager, this is a workaround to prevent
circular imports, since the pipe viewer is already included
from the StageManager """
cls._STAGE_MGR = mgr
def __init__(self, pipeline, parent):
""" Constructs the pipe viewer """
DraggableWindow.__init__(self, width=1300, height=900, parent=parent,
title="Pipeline Visualizer")
self._pipeline = pipeline
self._scroll_width = 8000
self._scroll_height = 3000
self._created = False
self._create_components()
self.hide()
def toggle(self):
""" Toggles the pipe viewer """
if self._visible:
Globals.base.taskMgr.remove("RP_GUI_UpdatePipeViewer")
self.hide()
else:
Globals.base.taskMgr.add(self._update_task, "RP_GUI_UpdatePipeViewer")
if not self._created:
self._populate_content()
self.show()
def _update_task(self, task=None):
""" Updates the viewer """
scroll_value = self._content_frame.horizontalScroll["value"]
scroll_value *= 2.45
self._pipe_descriptions.set_x(scroll_value * 2759.0)
return task.cont
def _populate_content(self): # pylint: disable=too-many-branches,too-many-statements
""" Reads the pipes and stages from the stage manager and renders those
into the window """
self._created = True
self._pipe_node = self._content_node.attach_new_node("pipes")
self._pipe_node.set_scale(1, 1, -1)
self._stage_node = self._content_node.attach_new_node("stages")
current_pipes = []
pipe_pixel_size = 3
pipe_height = 100
# Generate stages
for offs, stage in enumerate(self._STAGE_MGR.stages):
node = self._content_node.attach_new_node("stage")
node.set_pos(220 + offs * 200.0, 0, 20)
node.set_scale(1, 1, -1)
DirectFrame(parent=node, frameSize=(10, 150, 0, -3600),
frameColor=(0.2, 0.2, 0.2, 1))
Text(text=str(stage.debug_name.replace("Stage", "")),
parent=node, x=20, y=25, size=15)
for output_pipe, pipe_tex in iteritems(stage.produced_pipes):
pipe_idx = 0
r, g, b = rgb_from_string(output_pipe)
if output_pipe in current_pipes:
pipe_idx = current_pipes.index(output_pipe)
else:
current_pipes.append(output_pipe)
pipe_idx = len(current_pipes) - 1
DirectFrame(parent=node,
frameSize=(0, 8000, pipe_pixel_size / 2,
-pipe_pixel_size / 2),
frameColor=(r, g, b, 1),
pos=(10, 1, -95 - pipe_idx * pipe_height))
w = 160
h = Globals.native_resolution.y /\
float(Globals.native_resolution.x) * w
DirectFrame(parent=node,
frameSize=(-pipe_pixel_size, w + pipe_pixel_size,
h / 2 + pipe_pixel_size,
-h / 2 - pipe_pixel_size),
frameColor=(r, g, b, 1),
pos=(0, 1, -95 - pipe_idx * pipe_height))
if isinstance(pipe_tex, (list, tuple)):
pipe_tex = pipe_tex[0]
if isinstance(pipe_tex, (SimpleInputBlock, GroupedInputBlock)):
icon_file = "/$$rp/data/gui/icon_ubo.png"
elif pipe_tex.get_z_size() > 1:
icon_file = "/$$rp/data/gui/icon_texture.png"
elif pipe_tex.get_texture_type() == Texture.TT_buffer_texture:
icon_file = "/$$rp/data/gui/icon_buffer_texture.png"
else:
icon_file = None
preview = Sprite(
image=pipe_tex, parent=node, x=0,
y=50 + pipe_idx * pipe_height, w=w, h=h, any_filter=False,
transparent=False)
preview_shader = DisplayShaderBuilder.build(pipe_tex, int(w), int(h))
preview.set_shader(preview_shader)
preview.set_shader_inputs(
mipmap=0,
slice=0,
brightness=1,
tonemap=False)
if icon_file:
Sprite(image=icon_file, parent=node,
x=55, y=65 + pipe_idx * pipe_height,
w=48, h=48, near_filter=False,
transparent=True)
if isinstance(pipe_tex, (SimpleInputBlock, GroupedInputBlock)):
tex_desc = "UBO"
else:
tex_desc = pipe_tex.format_texture_type(pipe_tex.get_texture_type())
tex_desc += " - " + pipe_tex.format_format(pipe_tex.get_format()).upper()
Text(text=tex_desc, parent=node, x=55 + 48 / 2,
y=130 + pipe_idx * pipe_height, color=Vec3(0.2),
size=12, align="center")
for input_pipe in stage.required_pipes:
if input_pipe not in current_pipes:
self.warn("Pipe not found:", input_pipe)
continue
idx = current_pipes.index(input_pipe)
r, g, b = rgb_from_string(input_pipe)
DirectFrame(parent=node, frameSize=(0, 10, 40, -40),
frameColor=(r, g, b, 1),
pos=(5, 1, -95 - idx * pipe_height))
self._pipe_descriptions = self._content_node.attach_new_node(
"PipeDescriptions")
self._pipe_descriptions.set_scale(1, 1, -1)
DirectFrame(parent=self._pipe_descriptions, frameSize=(0, 190, 0, -5000),
frameColor=(0.1, 0.1, 0.1, 1.0))
# Generate the pipe descriptions
for idx, pipe in enumerate(current_pipes):
r, g, b = rgb_from_string(pipe)
DirectFrame(parent=self._pipe_descriptions,
frameSize=(0, 180, -95, -135),
frameColor=(r, g, b, 1.0), pos=(0, 1, -idx * pipe_height))
Text(parent=self._pipe_descriptions, text=pipe,
x=42, y=121 + idx * pipe_height, size=15,
color=Vec3(0.1))
Sprite(parent=self._pipe_descriptions, x=9, y=103 + idx * pipe_height,
image="/$$rp/data/gui/icon_pipe.png",
transparent=True, near_filter=False)
def _create_components(self):
""" Internal method to create the window components """
DraggableWindow._create_components(self)
self._content_frame = DirectScrolledFrame(
frameSize=(0, self._width - 40, 0, self._height - 80),
canvasSize=(0, self._scroll_width, 0, self._scroll_height),
autoHideScrollBars=False,
scrollBarWidth=20.0,
frameColor=(0, 0, 0, 0),
verticalScroll_relief=False,
horizontalScroll_relief=False,
parent=self._node,
pos=(20, 1, -self._height + 20))
self._content_node = self._content_frame.getCanvas().attach_new_node("PipeComponents")
self._content_node.set_scale(1, 1, -1)
self._content_node.set_z(self._scroll_height)

View File

@ -1,81 +1,81 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import CardMaker, Vec2, GraphicsWindow
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
from rpcore.loader import RPLoader
class PixelInspector(RPObject):
""" Widget to analyze the rendered pixels, by zooming in """
def __init__(self, pipeline):
RPObject.__init__(self)
self._pipeline = pipeline
self._node = Globals.base.pixel2d.attach_new_node("ExposureWidgetNode")
self._create_components()
self.hide()
def _create_components(self):
""" Internal method to init the widgets components """
card_maker = CardMaker("PixelInspector")
card_maker.set_frame(-200, 200, -150, 150)
self._zoomer = self._node.attach_new_node(card_maker.generate())
# Defer the further loading
Globals.base.taskMgr.doMethodLater(
1.0, self._late_init, "PixelInspectorLateInit")
Globals.base.accept("q", self.show)
Globals.base.accept("q-up", self.hide)
def show(self):
""" Shows the inspector """
self._node.show()
def hide(self):
""" Shows the inspector """
self._node.hide()
def _late_init(self, task):
""" Gets called after the pipeline got initialized """
scene_tex = self._pipeline.stage_mgr.pipes["ShadedScene"]
self._zoomer.set_shader(RPLoader.load_shader(
"/$$rp/shader/default_gui_shader.vert.glsl",
"/$$rp/shader/pixel_inspector.frag.glsl"))
self._zoomer.set_shader_input("SceneTex", scene_tex)
return task.done
def update(self):
""" Updates the pixel preview """
if isinstance(Globals.base.win, GraphicsWindow):
mouse = Globals.base.win.get_pointer(0)
if mouse.get_in_window():
pos = mouse.get_x(), 1, -mouse.get_y()
rel_mouse_pos = Vec2(mouse.get_x(), Globals.native_resolution.y - mouse.get_y())
self._node.set_pos(pos)
self._zoomer.set_shader_input("mousePos", rel_mouse_pos)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import CardMaker, Vec2, GraphicsWindow
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
from rpcore.loader import RPLoader
class PixelInspector(RPObject):
""" Widget to analyze the rendered pixels, by zooming in """
def __init__(self, pipeline):
RPObject.__init__(self)
self._pipeline = pipeline
self._node = Globals.base.pixel2d.attach_new_node("ExposureWidgetNode")
self._create_components()
self.hide()
def _create_components(self):
""" Internal method to init the widgets components """
card_maker = CardMaker("PixelInspector")
card_maker.set_frame(-200, 200, -150, 150)
self._zoomer = self._node.attach_new_node(card_maker.generate())
# Defer the further loading
Globals.base.taskMgr.doMethodLater(
1.0, self._late_init, "PixelInspectorLateInit")
Globals.base.accept("q", self.show)
Globals.base.accept("q-up", self.hide)
def show(self):
""" Shows the inspector """
self._node.show()
def hide(self):
""" Shows the inspector """
self._node.hide()
def _late_init(self, task):
""" Gets called after the pipeline got initialized """
scene_tex = self._pipeline.stage_mgr.pipes["ShadedScene"]
self._zoomer.set_shader(RPLoader.load_shader(
"/$$rp/shader/default_gui_shader.vert.glsl",
"/$$rp/shader/pixel_inspector.frag.glsl"))
self._zoomer.set_shader_input("SceneTex", scene_tex)
return task.done
def update(self):
""" Updates the pixel preview """
if isinstance(Globals.base.win, GraphicsWindow):
mouse = Globals.base.win.get_pointer(0)
if mouse.get_in_window():
pos = mouse.get_x(), 1, -mouse.get_y()
rel_mouse_pos = Vec2(mouse.get_x(), Globals.native_resolution.y - mouse.get_y())
self._node.set_pos(pos)
self._zoomer.set_shader_input("mousePos", rel_mouse_pos)

View File

@ -1,132 +1,132 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from functools import partial
from panda3d.core import Vec3
from rplibs.yaml import load_yaml_file
from rpcore.native import NATIVE_CXX_LOADED
from rpcore.gui.draggable_window import DraggableWindow
from rpcore.gui.labeled_checkbox import LabeledCheckbox
from rpcore.gui.checkbox_collection import CheckboxCollection
class RenderModeSelector(DraggableWindow):
""" Window which offers the user to select a render mode to apply """
def __init__(self, pipeline, parent):
DraggableWindow.__init__(self, width=690, height=340, parent=parent,
title="Select render mode")
self._pipeline = pipeline
self._selected_mode = ""
self._create_components()
self.hide()
def _create_components(self):
""" Internal method to init the components """
DraggableWindow._create_components(self)
self._content_node = self._node.attach_new_node("content")
self._populate_content()
def _populate_content(self):
""" Populates the windows content """
self._content_node.node().remove_all_children()
# Reload config each time the window is opened so its easy to add new
# render modes
config = load_yaml_file("/$$rpconfig/debugging.yaml")
debugger_content = self._content_node.attach_new_node("RenderModes")
debugger_content.set_z(-20)
debugger_content.set_x(20)
render_modes = [("Default", "", False, "", False)]
# Read modes from configuration
for mode in config["render_modes"]:
data = [mode["name"], mode["key"]]
data.append(mode.get("cxx_only", False))
data.append(mode.get("requires", ""))
data.append(mode.get("special", False))
render_modes.append(data)
collection = CheckboxCollection()
max_column_height = 9
for idx, (mode, mode_id, requires_cxx, requires_plugin, special) in enumerate(render_modes):
offs_y = (idx % max_column_height) * 24 + 35
offs_x = (idx // max_column_height) * 220
enabled = True
if requires_cxx and not NATIVE_CXX_LOADED:
enabled = False
if requires_plugin:
if not self._pipeline.plugin_mgr.is_plugin_enabled(requires_plugin):
enabled = False
box = LabeledCheckbox(
parent=debugger_content, x=offs_x, y=offs_y, text=mode.upper(),
text_color=Vec3(0.4), radio=True, chb_checked=(mode_id == self._selected_mode),
chb_callback=partial(self._set_render_mode, mode_id, special),
text_size=14, expand_width=230, enabled=enabled)
collection.add(box.checkbox)
def _set_render_mode(self, mode_id, special, value):
""" Callback which gets called when a render mode got selected """
if not value:
return
to_remove = []
for define in self._pipeline.stage_mgr.defines:
if define.startswith("_RM_"):
to_remove.append(define)
for define in to_remove:
del self._pipeline.stage_mgr.defines[define]
if mode_id == "":
self._pipeline.stage_mgr.defines["ANY_DEBUG_MODE"] = 0
else:
# Don't activate the generic debugging mode for special modes. This
# is for modes like luminance which expect the scene to be rendered
# unaltered.
self._pipeline.stage_mgr.defines["ANY_DEBUG_MODE"] = 0 if special else 1
self._pipeline.stage_mgr.defines["_RM_" + mode_id] = 1
self._selected_mode = mode_id
self._pipeline.reload_shaders()
def toggle(self):
""" Toggles the visibility of this windows """
if self._visible:
self.hide()
else:
self._populate_content()
self.show()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import division
from functools import partial
from panda3d.core import Vec3
from rplibs.yaml import load_yaml_file
from rpcore.native import NATIVE_CXX_LOADED
from rpcore.gui.draggable_window import DraggableWindow
from rpcore.gui.labeled_checkbox import LabeledCheckbox
from rpcore.gui.checkbox_collection import CheckboxCollection
class RenderModeSelector(DraggableWindow):
""" Window which offers the user to select a render mode to apply """
def __init__(self, pipeline, parent):
DraggableWindow.__init__(self, width=690, height=340, parent=parent,
title="Select render mode")
self._pipeline = pipeline
self._selected_mode = ""
self._create_components()
self.hide()
def _create_components(self):
""" Internal method to init the components """
DraggableWindow._create_components(self)
self._content_node = self._node.attach_new_node("content")
self._populate_content()
def _populate_content(self):
""" Populates the windows content """
self._content_node.node().remove_all_children()
# Reload config each time the window is opened so its easy to add new
# render modes
config = load_yaml_file("/$$rpconfig/debugging.yaml")
debugger_content = self._content_node.attach_new_node("RenderModes")
debugger_content.set_z(-20)
debugger_content.set_x(20)
render_modes = [("Default", "", False, "", False)]
# Read modes from configuration
for mode in config["render_modes"]:
data = [mode["name"], mode["key"]]
data.append(mode.get("cxx_only", False))
data.append(mode.get("requires", ""))
data.append(mode.get("special", False))
render_modes.append(data)
collection = CheckboxCollection()
max_column_height = 9
for idx, (mode, mode_id, requires_cxx, requires_plugin, special) in enumerate(render_modes):
offs_y = (idx % max_column_height) * 24 + 35
offs_x = (idx // max_column_height) * 220
enabled = True
if requires_cxx and not NATIVE_CXX_LOADED:
enabled = False
if requires_plugin:
if not self._pipeline.plugin_mgr.is_plugin_enabled(requires_plugin):
enabled = False
box = LabeledCheckbox(
parent=debugger_content, x=offs_x, y=offs_y, text=mode.upper(),
text_color=Vec3(0.4), radio=True, chb_checked=(mode_id == self._selected_mode),
chb_callback=partial(self._set_render_mode, mode_id, special),
text_size=14, expand_width=230, enabled=enabled)
collection.add(box.checkbox)
def _set_render_mode(self, mode_id, special, value):
""" Callback which gets called when a render mode got selected """
if not value:
return
to_remove = []
for define in self._pipeline.stage_mgr.defines:
if define.startswith("_RM_"):
to_remove.append(define)
for define in to_remove:
del self._pipeline.stage_mgr.defines[define]
if mode_id == "":
self._pipeline.stage_mgr.defines["ANY_DEBUG_MODE"] = 0
else:
# Don't activate the generic debugging mode for special modes. This
# is for modes like luminance which expect the scene to be rendered
# unaltered.
self._pipeline.stage_mgr.defines["ANY_DEBUG_MODE"] = 0 if special else 1
self._pipeline.stage_mgr.defines["_RM_" + mode_id] = 1
self._selected_mode = mode_id
self._pipeline.reload_shaders()
def toggle(self):
""" Toggles the visibility of this windows """
if self._visible:
self.hide()
else:
self._populate_content()
self.show()

View File

@ -1,68 +1,68 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import direct.gui.DirectGuiGlobals as DGG
from direct.gui.DirectSlider import DirectSlider
from rpcore.rpobject import RPObject
class Slider(RPObject):
""" This is a simple wrapper around DirectSlider, providing a simpler
interface """
def __init__(self, x=0, y=0, parent=None, size=100, min_value=0,
max_value=100, value=50, page_size=1, callback=None,
extra_args=None):
""" Inits the slider """
RPObject.__init__(self)
if extra_args is None:
extra_args = []
# Scale has to be 2.0, otherwise there will be an error.
self._node = DirectSlider(
pos=(size * 0.5 + x, 1, -y), parent=parent, range=(min_value, max_value),
value=value, pageSize=page_size, scale=2.0, command=callback,
extraArgs=extra_args, frameColor=(0.0, 0.0, 0.0, 1),
frameSize=(-size * 0.25, size * 0.25, -5, 5), relief=DGG.FLAT,
thumb_frameColor=(0.35, 0.53, 0.2, 1.0), thumb_relief=DGG.FLAT,
thumb_frameSize=(-2.5, 2.5, -5.0, 5.0),)
@property
def value(self):
""" Returns the currently assigned value """
return self._node["value"]
@value.setter
def value(self, value):
""" Sets the value of the slider """
self._node["value"] = value
@property
def node(self):
""" Returns a handle to the internally used node """
return self._node
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import direct.gui.DirectGuiGlobals as DGG
from direct.gui.DirectSlider import DirectSlider
from rpcore.rpobject import RPObject
class Slider(RPObject):
""" This is a simple wrapper around DirectSlider, providing a simpler
interface """
def __init__(self, x=0, y=0, parent=None, size=100, min_value=0,
max_value=100, value=50, page_size=1, callback=None,
extra_args=None):
""" Inits the slider """
RPObject.__init__(self)
if extra_args is None:
extra_args = []
# Scale has to be 2.0, otherwise there will be an error.
self._node = DirectSlider(
pos=(size * 0.5 + x, 1, -y), parent=parent, range=(min_value, max_value),
value=value, pageSize=page_size, scale=2.0, command=callback,
extraArgs=extra_args, frameColor=(0.0, 0.0, 0.0, 1),
frameSize=(-size * 0.25, size * 0.25, -5, 5), relief=DGG.FLAT,
thumb_frameColor=(0.35, 0.53, 0.2, 1.0), thumb_relief=DGG.FLAT,
thumb_frameSize=(-2.5, 2.5, -5.0, 5.0),)
@property
def value(self):
""" Returns the currently assigned value """
return self._node["value"]
@value.setter
def value(self, value):
""" Sets the value of the slider """
self._node["value"] = value
@property
def node(self):
""" Returns a handle to the internally used node """
return self._node

View File

@ -1,153 +1,153 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import TransparencyAttrib, Vec3, Texture, SamplerState
from direct.gui.OnscreenImage import OnscreenImage
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class Sprite(RPObject):
""" Simple wrapper arround OnscreenImage, providing a simpler interface """
def __init__(self, image=None, parent=None, x=0, y=0, w=None, h=None,
transparent=True, near_filter=True, any_filter=True):
""" Creates a new image, taking (x,y) as topleft coordinates.
When near_filter is set to true, a near filter will be set to the
texture passed. This provides sharper images.
When any_filter is set to false, the passed image won't be modified at
all. This enables you to display existing textures, otherwise the
texture would get a near filter in the 3D View, too. """
RPObject.__init__(self)
if not isinstance(image, Texture):
if not isinstance(image, str):
self.warn("Invalid argument to image parameter:", image)
return
image = RPLoader.load_texture(image)
if w is None or h is None:
w, h = image.get_x_size(), image.get_y_size()
else:
if w is None or h is None:
w = 10
h = 10
self._width, self._height = w, h
self._initial_pos = self._translate_pos(x, y)
self.node = OnscreenImage(
image=image, parent=parent, pos=self._initial_pos,
scale=(self._width / 2.0, 1, self._height / 2.0))
if transparent:
self.node.set_transparency(TransparencyAttrib.M_alpha)
tex = self.node.get_texture()
# Apply a near filter, but only if the parent has no scale, otherwise
# it will look weird
if near_filter and any_filter and parent.get_sx() == 1.0:
tex.set_minfilter(SamplerState.FT_nearest)
tex.set_magfilter(SamplerState.FT_nearest)
if any_filter:
tex.set_anisotropic_degree(8)
tex.set_wrap_u(SamplerState.WM_clamp)
tex.set_wrap_v(SamplerState.WM_clamp)
def get_initial_pos(self):
""" Returns the initial position of the image. This can be used for
animations """
return self._initial_pos
def pos_interval(self, *args, **kwargs):
""" Returns a pos interval, this is a wrapper around
NodePath.posInterval """
return self.node.posInterval(*args, **kwargs)
def hpr_interval(self, *args, **kwargs):
""" Returns a hpr interval, this is a wrapper around
NodePath.hprInterval """
return self.node.hprInterval(*args, **kwargs)
def color_scale_interval(self, *args, **kwargs):
""" Returns a color scale interval, this is a wrapper around
NodePath.colorScaleInterval """
return self.node.colorScaleInterval(*args, **kwargs)
def set_image(self, img):
""" Sets the current image """
self.node.set_image(img)
def get_width(self):
""" Returns the width of the image in pixels """
return self._width
def get_height(self):
""" Returns the height of the image in pixels """
return self._height
def set_pos(self, x, y):
""" Sets the position """
self.node.set_pos(self._translate_pos(x, y))
def _translate_pos(self, x, y):
""" Converts 2d coordinates to pandas coordinate system """
return Vec3(x + self._width / 2.0, 1, -y - self._height / 2.0)
def set_shader(self, shader):
""" Sets a shader to be used for rendering the image """
self.node.set_shader(shader)
def set_shader_input(self, *args):
""" Sets a shader input on the image """
self.node.set_shader_input(*args)
def set_shader_inputs(self, **kwargs):
""" Sets multiple shader inputs on the image """
self.node.set_shader_inputs(**kwargs)
def remove(self):
""" Removes the image """
self.node.remove()
def hide(self):
""" Hides the image """
self.node.hide()
def show(self):
""" Shows the image if it was previously hidden """
self.node.show()
def is_hidden(self):
""" Returns whether the image is hidden """
return self.node.is_hidden()
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import TransparencyAttrib, Vec3, Texture, SamplerState
from direct.gui.OnscreenImage import OnscreenImage
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class Sprite(RPObject):
""" Simple wrapper arround OnscreenImage, providing a simpler interface """
def __init__(self, image=None, parent=None, x=0, y=0, w=None, h=None,
transparent=True, near_filter=True, any_filter=True):
""" Creates a new image, taking (x,y) as topleft coordinates.
When near_filter is set to true, a near filter will be set to the
texture passed. This provides sharper images.
When any_filter is set to false, the passed image won't be modified at
all. This enables you to display existing textures, otherwise the
texture would get a near filter in the 3D View, too. """
RPObject.__init__(self)
if not isinstance(image, Texture):
if not isinstance(image, str):
self.warn("Invalid argument to image parameter:", image)
return
image = RPLoader.load_texture(image)
if w is None or h is None:
w, h = image.get_x_size(), image.get_y_size()
else:
if w is None or h is None:
w = 10
h = 10
self._width, self._height = w, h
self._initial_pos = self._translate_pos(x, y)
self.node = OnscreenImage(
image=image, parent=parent, pos=self._initial_pos,
scale=(self._width / 2.0, 1, self._height / 2.0))
if transparent:
self.node.set_transparency(TransparencyAttrib.M_alpha)
tex = self.node.get_texture()
# Apply a near filter, but only if the parent has no scale, otherwise
# it will look weird
if near_filter and any_filter and parent.get_sx() == 1.0:
tex.set_minfilter(SamplerState.FT_nearest)
tex.set_magfilter(SamplerState.FT_nearest)
if any_filter:
tex.set_anisotropic_degree(8)
tex.set_wrap_u(SamplerState.WM_clamp)
tex.set_wrap_v(SamplerState.WM_clamp)
def get_initial_pos(self):
""" Returns the initial position of the image. This can be used for
animations """
return self._initial_pos
def pos_interval(self, *args, **kwargs):
""" Returns a pos interval, this is a wrapper around
NodePath.posInterval """
return self.node.posInterval(*args, **kwargs)
def hpr_interval(self, *args, **kwargs):
""" Returns a hpr interval, this is a wrapper around
NodePath.hprInterval """
return self.node.hprInterval(*args, **kwargs)
def color_scale_interval(self, *args, **kwargs):
""" Returns a color scale interval, this is a wrapper around
NodePath.colorScaleInterval """
return self.node.colorScaleInterval(*args, **kwargs)
def set_image(self, img):
""" Sets the current image """
self.node.set_image(img)
def get_width(self):
""" Returns the width of the image in pixels """
return self._width
def get_height(self):
""" Returns the height of the image in pixels """
return self._height
def set_pos(self, x, y):
""" Sets the position """
self.node.set_pos(self._translate_pos(x, y))
def _translate_pos(self, x, y):
""" Converts 2d coordinates to pandas coordinate system """
return Vec3(x + self._width / 2.0, 1, -y - self._height / 2.0)
def set_shader(self, shader):
""" Sets a shader to be used for rendering the image """
self.node.set_shader(shader)
def set_shader_input(self, *args):
""" Sets a shader input on the image """
self.node.set_shader_input(*args)
def set_shader_inputs(self, **kwargs):
""" Sets multiple shader inputs on the image """
self.node.set_shader_inputs(**kwargs)
def remove(self):
""" Removes the image """
self.node.remove()
def hide(self):
""" Hides the image """
self.node.hide()
def show(self):
""" Shows the image if it was previously hidden """
self.node.show()
def is_hidden(self):
""" Returns whether the image is hidden """
return self.node.is_hidden()

View File

@ -1,83 +1,83 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec2, Vec3, TextNode, Vec4
from direct.gui.OnscreenText import OnscreenText
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
class Text(RPObject):
""" Simple wrapper around OnscreenText, providing a simpler interface """
def __init__(self, text="", parent=None, x=0, y=0, size=10, align="left",
color=None, may_change=False, font=None):
""" Constructs a new text. The parameters are almost equal to the
parameters of OnscreenText """
RPObject.__init__(self)
if color is None:
color = Vec3(1)
align_mode = TextNode.A_left
if align == "center":
align_mode = TextNode.A_center
elif align == "right":
align_mode = TextNode.A_right
if font is None:
font = Globals.font
# Should always have a global font. Never use the default panda font!
assert font
self._initial_pos = Vec2(x, -y)
self._node = OnscreenText(
text=text, parent=parent, pos=self._initial_pos, scale=size,
align=align_mode, fg=Vec4(color.x, color.y, color.z, 1.0),
font=font, mayChange=may_change)
@property
def node(self):
""" Returns a handle to the internlally used node """
return self._node
def set_text(self, text):
""" Changes the text, remember to pass may_change to the constructor,
otherwise this method does not work. """
self._node["text"] = text
def get_initial_pos(self):
""" Returns the initial position of the text. This can be used for
animations """
return self._initial_pos
def pos_interval(self, *args, **kwargs):
""" Returns a pos interval, this is a wrapper around
NodePath.pos_interval """
return self._node.pos_interval(*args, **kwargs)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec2, Vec3, TextNode, Vec4
from direct.gui.OnscreenText import OnscreenText
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
class Text(RPObject):
""" Simple wrapper around OnscreenText, providing a simpler interface """
def __init__(self, text="", parent=None, x=0, y=0, size=10, align="left",
color=None, may_change=False, font=None):
""" Constructs a new text. The parameters are almost equal to the
parameters of OnscreenText """
RPObject.__init__(self)
if color is None:
color = Vec3(1)
align_mode = TextNode.A_left
if align == "center":
align_mode = TextNode.A_center
elif align == "right":
align_mode = TextNode.A_right
if font is None:
font = Globals.font
# Should always have a global font. Never use the default panda font!
assert font
self._initial_pos = Vec2(x, -y)
self._node = OnscreenText(
text=text, parent=parent, pos=self._initial_pos, scale=size,
align=align_mode, fg=Vec4(color.x, color.y, color.z, 1.0),
font=font, mayChange=may_change)
@property
def node(self):
""" Returns a handle to the internlally used node """
return self._node
def set_text(self, text):
""" Changes the text, remember to pass may_change to the constructor,
otherwise this method does not work. """
self._node["text"] = text
def get_initial_pos(self):
""" Returns the initial position of the text. This can be used for
animations """
return self._initial_pos
def pos_interval(self, *args, **kwargs):
""" Returns a pos interval, this is a wrapper around
NodePath.pos_interval """
return self._node.pos_interval(*args, **kwargs)

View File

@ -1,87 +1,87 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec2, Vec3, Vec4
from panda3d.core import TextNode as TextNodeImpl
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class TextNode(RPObject):
""" Interface for the Panda3D TextNode. """
def __init__(self, font="/$$rp/data/font/Roboto-Bold.ttf", pixel_size=16, align="left",
pos=Vec2(0), color=Vec3(1), parent=None):
""" Constructs a new text node, forwaring the parameters to the internal
panda3d implementation """
RPObject.__init__(self)
self._node = TextNodeImpl('FTN')
self._node.set_text("")
self._node.set_align(getattr(TextNodeImpl, "A_" + align))
self._node.set_text_color(color.x, color.y, color.z, 1)
if parent is None:
parent = Globals.base.aspect2d
self._nodepath = parent.attach_new_node(self._node)
self._nodepath.set_pos(pos.x, 0, pos.y)
font = RPLoader.load_font(font)
# font.set_outline(Vec4(0, 0, 0, 0.78), 1.6, 0.37)
font.set_outline(Vec4(0, 0, 0, 1), 1.6, 0.37)
font.set_scale_factor(1.0)
font.set_texture_margin(int(pixel_size / 4.0 * 2.0))
font.set_bg(Vec4(0, 0, 0, 0))
self._node.set_font(font)
self.set_pixel_size(pixel_size)
@property
def text(self):
""" Returns the current text """
return self._node.get_text()
@text.setter
def text(self, text):
""" Sets the current text """
self._node.set_text(text)
@property
def color(self):
""" Returns the current text color """
return self._node.get_text_color()
@color.setter
def color(self, val):
""" Sets the current text color """
self._node.set_text_color(val)
def set_pixel_size(self, size):
""" Sets the text size in pixels """
self._nodepath.set_scale(size * 2.0 / float(Globals.native_resolution.y))
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec2, Vec3, Vec4
from panda3d.core import TextNode as TextNodeImpl
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
from rpcore.loader import RPLoader
class TextNode(RPObject):
""" Interface for the Panda3D TextNode. """
def __init__(self, font="/$$rp/data/font/Roboto-Bold.ttf", pixel_size=16, align="left",
pos=Vec2(0), color=Vec3(1), parent=None):
""" Constructs a new text node, forwaring the parameters to the internal
panda3d implementation """
RPObject.__init__(self)
self._node = TextNodeImpl('FTN')
self._node.set_text("")
self._node.set_align(getattr(TextNodeImpl, "A_" + align))
self._node.set_text_color(color.x, color.y, color.z, 1)
if parent is None:
parent = Globals.base.aspect2d
self._nodepath = parent.attach_new_node(self._node)
self._nodepath.set_pos(pos.x, 0, pos.y)
font = RPLoader.load_font(font)
# font.set_outline(Vec4(0, 0, 0, 0.78), 1.6, 0.37)
font.set_outline(Vec4(0, 0, 0, 1), 1.6, 0.37)
font.set_scale_factor(1.0)
font.set_texture_margin(int(pixel_size / 4.0 * 2.0))
font.set_bg(Vec4(0, 0, 0, 0))
self._node.set_font(font)
self.set_pixel_size(pixel_size)
@property
def text(self):
""" Returns the current text """
return self._node.get_text()
@text.setter
def text(self, text):
""" Sets the current text """
self._node.set_text(text)
@property
def color(self):
""" Returns the current text color """
return self._node.get_text_color()
@color.setter
def color(self, val):
""" Sets the current text color """
self._node.set_text_color(val)
def set_pixel_size(self, size):
""" Sets the text size in pixels """
self._nodepath.set_scale(size * 2.0 / float(Globals.native_resolution.y))

View File

@ -1,182 +1,182 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec3
from rpcore.image import Image
from rpcore.gui.draggable_window import DraggableWindow
from rpcore.gui.sprite import Sprite
from rpcore.gui.text import Text
from rpcore.gui.slider import Slider
from rpcore.gui.labeled_checkbox import LabeledCheckbox
from rpcore.util.display_shader_builder import DisplayShaderBuilder
class TexturePreview(DraggableWindow):
""" Small window which provides a preview of a texture """
def __init__(self, pipeline, parent):
DraggableWindow.__init__(self, width=1600, height=900, parent=parent,
title="Texture Viewer")
self._pipeline = pipeline
self._current_tex = None
self._mip_slider = None
self._mip_text = None
self._slice_slider = None
self._slice_text = None
self._preview_image = None
self._create_components()
def present(self, tex):
""" "Presents" a given texture and shows the window """
self._current_tex = tex
self.set_title(tex.get_name())
# tex.write(tex.get_name() + ".png")
# Remove old content
self._content_node.node().remove_all_children()
w, h = tex.get_x_size(), tex.get_y_size()
if h > 1:
scale_x = (self._width - 40.0) / w
scale_y = (self._height - 110.0) / h
scale_f = min(scale_x, scale_y)
display_w = scale_f * w
display_h = scale_f * h
else:
display_w = self._width - 40
display_h = self._height - 110
image = Sprite(
image=tex, parent=self._content_node, x=20, y=90, w=display_w,
h=display_h, any_filter=False, transparent=False)
description = ""
# Image size
description += "{:d} x {:d} x {:d}".format(
tex.get_x_size(), tex.get_y_size(), tex.get_z_size())
# Image type
description += ", {:s}, {:s}".format(
Image.format_format(tex.get_format()).upper(),
Image.format_component_type(tex.get_component_type()).upper())
Text(text=description, parent=self._content_node, x=17, y=70,
size=16, color=Vec3(0.6, 0.6, 0.6))
estimated_bytes = tex.estimate_texture_memory()
size_desc = "Estimated memory: {:2.2f} MB".format(
estimated_bytes / (1024.0 ** 2))
Text(text=size_desc, parent=self._content_node, x=self._width - 20.0,
y=70, size=18, color=Vec3(0.34, 0.564, 0.192), align="right")
x_pos = len(size_desc) * 9 + 140
# Slider for viewing different mipmaps
if tex.uses_mipmaps():
max_mips = tex.get_expected_num_mipmap_levels() - 1
self._mip_slider = Slider(
parent=self._content_node, size=140, min_value=0, max_value=max_mips,
callback=self._set_mip, x=x_pos, y=65, value=0)
x_pos += 140 + 5
self._mip_text = Text(
text="MIP: 5", parent=self._content_node, x=x_pos, y=72, size=18,
color=Vec3(1, 0.4, 0.4), may_change=1)
x_pos += 50 + 30
# Slider for viewing different Z-layers
if tex.get_z_size() > 1:
self._slice_slider = Slider(
parent=self._content_node, size=250, min_value=0,
max_value=tex.get_z_size() - 1, callback=self._set_slice, x=x_pos,
y=65, value=0)
x_pos += 250 + 5
self._slice_text = Text(
text="Z: 5", parent=self._content_node, x=x_pos, y=72, size=18,
color=Vec3(0.4, 1, 0.4), may_change=1)
x_pos += 50 + 30
# Slider to adjust brightness
self._bright_slider = Slider(
parent=self._content_node, size=140, min_value=-14, max_value=14,
callback=self._set_brightness, x=x_pos, y=65, value=0)
x_pos += 140 + 5
self._bright_text = Text(
text="Bright: 1", parent=self._content_node, x=x_pos, y=72, size=18,
color=Vec3(0.4, 0.4, 1), may_change=1)
x_pos += 100 + 30
# Slider to enable reinhard tonemapping
self._tonemap_box = LabeledCheckbox(
parent=self._content_node, x=x_pos, y=60, text="Tonemap",
text_color=Vec3(1, 0.4, 0.4), chb_checked=False,
chb_callback=self._set_enable_tonemap,
text_size=18, expand_width=90)
x_pos += 90 + 30
image.set_shader_inputs(
slice=0,
mipmap=0,
brightness=1,
tonemap=False)
preview_shader = DisplayShaderBuilder.build(tex, display_w, display_h)
image.set_shader(preview_shader)
self._preview_image = image
self.show()
def _set_slice(self):
idx = int(self._slice_slider.value)
self._preview_image.set_shader_input("slice", idx)
self._slice_text.set_text("Z: " + str(idx))
def _set_mip(self):
idx = int(self._mip_slider.value)
self._preview_image.set_shader_input("mipmap", idx)
self._mip_text.set_text("MIP " + str(idx))
def _set_brightness(self):
val = self._bright_slider.value
scale = 2 ** val
self._bright_text.set_text("Bright: " + str(round(scale, 3)))
self._preview_image.set_shader_input("brightness", scale)
def _set_enable_tonemap(self, enable_tonemap):
self._preview_image.set_shader_input("tonemap", enable_tonemap)
def _create_components(self):
""" Internal method to init the components """
DraggableWindow._create_components(self)
self._content_node = self._node.attach_new_node("content")
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Vec3
from rpcore.image import Image
from rpcore.gui.draggable_window import DraggableWindow
from rpcore.gui.sprite import Sprite
from rpcore.gui.text import Text
from rpcore.gui.slider import Slider
from rpcore.gui.labeled_checkbox import LabeledCheckbox
from rpcore.util.display_shader_builder import DisplayShaderBuilder
class TexturePreview(DraggableWindow):
""" Small window which provides a preview of a texture """
def __init__(self, pipeline, parent):
DraggableWindow.__init__(self, width=1600, height=900, parent=parent,
title="Texture Viewer")
self._pipeline = pipeline
self._current_tex = None
self._mip_slider = None
self._mip_text = None
self._slice_slider = None
self._slice_text = None
self._preview_image = None
self._create_components()
def present(self, tex):
""" "Presents" a given texture and shows the window """
self._current_tex = tex
self.set_title(tex.get_name())
# tex.write(tex.get_name() + ".png")
# Remove old content
self._content_node.node().remove_all_children()
w, h = tex.get_x_size(), tex.get_y_size()
if h > 1:
scale_x = (self._width - 40.0) / w
scale_y = (self._height - 110.0) / h
scale_f = min(scale_x, scale_y)
display_w = scale_f * w
display_h = scale_f * h
else:
display_w = self._width - 40
display_h = self._height - 110
image = Sprite(
image=tex, parent=self._content_node, x=20, y=90, w=display_w,
h=display_h, any_filter=False, transparent=False)
description = ""
# Image size
description += "{:d} x {:d} x {:d}".format(
tex.get_x_size(), tex.get_y_size(), tex.get_z_size())
# Image type
description += ", {:s}, {:s}".format(
Image.format_format(tex.get_format()).upper(),
Image.format_component_type(tex.get_component_type()).upper())
Text(text=description, parent=self._content_node, x=17, y=70,
size=16, color=Vec3(0.6, 0.6, 0.6))
estimated_bytes = tex.estimate_texture_memory()
size_desc = "Estimated memory: {:2.2f} MB".format(
estimated_bytes / (1024.0 ** 2))
Text(text=size_desc, parent=self._content_node, x=self._width - 20.0,
y=70, size=18, color=Vec3(0.34, 0.564, 0.192), align="right")
x_pos = len(size_desc) * 9 + 140
# Slider for viewing different mipmaps
if tex.uses_mipmaps():
max_mips = tex.get_expected_num_mipmap_levels() - 1
self._mip_slider = Slider(
parent=self._content_node, size=140, min_value=0, max_value=max_mips,
callback=self._set_mip, x=x_pos, y=65, value=0)
x_pos += 140 + 5
self._mip_text = Text(
text="MIP: 5", parent=self._content_node, x=x_pos, y=72, size=18,
color=Vec3(1, 0.4, 0.4), may_change=1)
x_pos += 50 + 30
# Slider for viewing different Z-layers
if tex.get_z_size() > 1:
self._slice_slider = Slider(
parent=self._content_node, size=250, min_value=0,
max_value=tex.get_z_size() - 1, callback=self._set_slice, x=x_pos,
y=65, value=0)
x_pos += 250 + 5
self._slice_text = Text(
text="Z: 5", parent=self._content_node, x=x_pos, y=72, size=18,
color=Vec3(0.4, 1, 0.4), may_change=1)
x_pos += 50 + 30
# Slider to adjust brightness
self._bright_slider = Slider(
parent=self._content_node, size=140, min_value=-14, max_value=14,
callback=self._set_brightness, x=x_pos, y=65, value=0)
x_pos += 140 + 5
self._bright_text = Text(
text="Bright: 1", parent=self._content_node, x=x_pos, y=72, size=18,
color=Vec3(0.4, 0.4, 1), may_change=1)
x_pos += 100 + 30
# Slider to enable reinhard tonemapping
self._tonemap_box = LabeledCheckbox(
parent=self._content_node, x=x_pos, y=60, text="Tonemap",
text_color=Vec3(1, 0.4, 0.4), chb_checked=False,
chb_callback=self._set_enable_tonemap,
text_size=18, expand_width=90)
x_pos += 90 + 30
image.set_shader_inputs(
slice=0,
mipmap=0,
brightness=1,
tonemap=False)
preview_shader = DisplayShaderBuilder.build(tex, display_w, display_h)
image.set_shader(preview_shader)
self._preview_image = image
self.show()
def _set_slice(self):
idx = int(self._slice_slider.value)
self._preview_image.set_shader_input("slice", idx)
self._slice_text.set_text("Z: " + str(idx))
def _set_mip(self):
idx = int(self._mip_slider.value)
self._preview_image.set_shader_input("mipmap", idx)
self._mip_text.set_text("MIP " + str(idx))
def _set_brightness(self):
val = self._bright_slider.value
scale = 2 ** val
self._bright_text.set_text("Bright: " + str(round(scale, 3)))
self._preview_image.set_shader_input("brightness", scale)
def _set_enable_tonemap(self, enable_tonemap):
self._preview_image.set_shader_input("tonemap", enable_tonemap)
def _create_components(self):
""" Internal method to init the components """
DraggableWindow._create_components(self)
self._content_node = self._node.attach_new_node("content")

View File

@ -1,158 +1,158 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Texture, GeomEnums
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
from rpcore.render_target import RenderTarget
class ImageFormatTypes(object): # pylint: disable=too-few-public-methods
""" This is a small helper class to prevent pylint errors about the Image
class not defining the enums. This class just copies the enum properties
from panda3d's builtin Texture class. """
T_float = Texture.T_float
T_unsigned_byte = Texture.T_unsigned_byte
T_int = Texture.T_int
T_unsigned_short = Texture.T_unsigned_short
T_unsigned_int_24_8 = Texture.T_unsigned_int_24_8
TT_buffer_texture = Texture.TT_buffer_texture
TT_2d_texture = Texture.TT_2d_texture
TT_3d_texture = Texture.TT_3d_texture
TT_cube_map = Texture.TT_cube_map
TT_cube_map_array = Texture.TT_cube_map_array
TT_2d_texture_array = Texture.TT_2d_texture_array
format_format = Texture.format_format
format_component_type = Texture.format_component_type
class Image(RPObject, Texture, ImageFormatTypes):
""" This is a wrapper arround the Texture class from Panda3D, which keeps
track of all images and registers / unregisters them aswell as counting
the memory used. This is used by all classes instead of pandas builtin
Texture class. """
# All registered images
REGISTERED_IMAGES = []
# String formats
FORMAT_MAPPINGS = {
"R11G11B10": (Texture.T_float, Texture.F_r11_g11_b10),
"RGBA8": (Texture.T_unsigned_byte, Texture.F_rgba8),
"RGBA16": (Texture.T_float, Texture.F_rgba16),
"RGBA32": (Texture.T_float, Texture.F_rgba32),
"R8": (Texture.T_unsigned_byte, Texture.F_red),
"R8UI": (Texture.T_unsigned_byte, Texture.F_red),
"R16": (Texture.T_float, Texture.F_r16),
"R16UI": (Texture.T_unsigned_short, Texture.F_r16i),
"R32": (Texture.T_float, Texture.F_r32),
"R32I": (Texture.T_int, Texture.F_r32i),
}
@classmethod
def create_buffer(cls, name, size, component_format):
""" Creates a new buffer texture """
img = cls("ImgBuffer-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_buffer_texture(size, comp_type, comp_format, GeomEnums.UH_static)
return img
@classmethod
def create_counter(cls, name):
""" Creates a new 1x1 R32I texture to be used as an atomic counter """
return cls.create_buffer(name, 1, "R32I")
@classmethod
def create_2d(cls, name, w, h, component_format):
""" Creates a new 2D texture """
img = cls("Img2D-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_2d_texture(w, h, comp_type, comp_format)
return img
@classmethod
def create_2d_array(cls, name, w, h, slices, component_format):
""" Creates a new 2D-array texture """
img = cls("Img2DArr-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_2d_texture_array(w, h, slices, comp_type, comp_format)
return img
@classmethod
def create_3d(cls, name, w, h, slices, component_format):
""" Creates a new 3D texture """
img = cls("Img3D-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_3d_texture(w, h, slices, comp_type, comp_format)
return img
@classmethod
def create_cube(cls, name, size, component_format):
""" Creates a new cubemap """
img = cls("ImgCube-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_cube_map(size, comp_type, comp_format)
return img
@classmethod
def create_cube_array(cls, name, size, num_cubemaps, component_format):
""" Creates a new cubemap """
img = cls("ImgCubeArr-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_cube_map_array(size, num_cubemaps, comp_type, comp_format)
return img
@classmethod
def convert_texture_format(cls, comp_type):
""" Converts a string like 'RGBA8' to a texture type and format """
return cls.FORMAT_MAPPINGS[comp_type]
def __init__(self, name):
""" Internal method to create a new image """
RPObject.__init__(self, name)
Texture.__init__(self, name)
Image.REGISTERED_IMAGES.append(self)
self.set_clear_color(0)
self.clear_image()
self.sort = RenderTarget.CURRENT_SORT
def __del__(self):
""" Destroys the image """
self.warn("Image destructor not implemented yet")
def write(self, pth):
""" Writes the image to disk """
Globals.base.graphicsEngine.extract_texture_data(self, Globals.base.win.gsg)
if self.get_texture_type() in [Texture.TT_3d_texture, Texture.TT_cube_map]:
Texture.write(self, "#_" + pth, 0, 0, True, False)
else:
Texture.write(self, pth)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from panda3d.core import Texture, GeomEnums
from rpcore.rpobject import RPObject
from rpcore.globals import Globals
from rpcore.render_target import RenderTarget
class ImageFormatTypes(object): # pylint: disable=too-few-public-methods
""" This is a small helper class to prevent pylint errors about the Image
class not defining the enums. This class just copies the enum properties
from panda3d's builtin Texture class. """
T_float = Texture.T_float
T_unsigned_byte = Texture.T_unsigned_byte
T_int = Texture.T_int
T_unsigned_short = Texture.T_unsigned_short
T_unsigned_int_24_8 = Texture.T_unsigned_int_24_8
TT_buffer_texture = Texture.TT_buffer_texture
TT_2d_texture = Texture.TT_2d_texture
TT_3d_texture = Texture.TT_3d_texture
TT_cube_map = Texture.TT_cube_map
TT_cube_map_array = Texture.TT_cube_map_array
TT_2d_texture_array = Texture.TT_2d_texture_array
format_format = Texture.format_format
format_component_type = Texture.format_component_type
class Image(RPObject, Texture, ImageFormatTypes):
""" This is a wrapper arround the Texture class from Panda3D, which keeps
track of all images and registers / unregisters them aswell as counting
the memory used. This is used by all classes instead of pandas builtin
Texture class. """
# All registered images
REGISTERED_IMAGES = []
# String formats
FORMAT_MAPPINGS = {
"R11G11B10": (Texture.T_float, Texture.F_r11_g11_b10),
"RGBA8": (Texture.T_unsigned_byte, Texture.F_rgba8),
"RGBA16": (Texture.T_float, Texture.F_rgba16),
"RGBA32": (Texture.T_float, Texture.F_rgba32),
"R8": (Texture.T_unsigned_byte, Texture.F_red),
"R8UI": (Texture.T_unsigned_byte, Texture.F_red),
"R16": (Texture.T_float, Texture.F_r16),
"R16UI": (Texture.T_unsigned_short, Texture.F_r16i),
"R32": (Texture.T_float, Texture.F_r32),
"R32I": (Texture.T_int, Texture.F_r32i),
}
@classmethod
def create_buffer(cls, name, size, component_format):
""" Creates a new buffer texture """
img = cls("ImgBuffer-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_buffer_texture(size, comp_type, comp_format, GeomEnums.UH_static)
return img
@classmethod
def create_counter(cls, name):
""" Creates a new 1x1 R32I texture to be used as an atomic counter """
return cls.create_buffer(name, 1, "R32I")
@classmethod
def create_2d(cls, name, w, h, component_format):
""" Creates a new 2D texture """
img = cls("Img2D-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_2d_texture(w, h, comp_type, comp_format)
return img
@classmethod
def create_2d_array(cls, name, w, h, slices, component_format):
""" Creates a new 2D-array texture """
img = cls("Img2DArr-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_2d_texture_array(w, h, slices, comp_type, comp_format)
return img
@classmethod
def create_3d(cls, name, w, h, slices, component_format):
""" Creates a new 3D texture """
img = cls("Img3D-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_3d_texture(w, h, slices, comp_type, comp_format)
return img
@classmethod
def create_cube(cls, name, size, component_format):
""" Creates a new cubemap """
img = cls("ImgCube-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_cube_map(size, comp_type, comp_format)
return img
@classmethod
def create_cube_array(cls, name, size, num_cubemaps, component_format):
""" Creates a new cubemap """
img = cls("ImgCubeArr-" + name)
comp_type, comp_format = cls.convert_texture_format(component_format)
img.setup_cube_map_array(size, num_cubemaps, comp_type, comp_format)
return img
@classmethod
def convert_texture_format(cls, comp_type):
""" Converts a string like 'RGBA8' to a texture type and format """
return cls.FORMAT_MAPPINGS[comp_type]
def __init__(self, name):
""" Internal method to create a new image """
RPObject.__init__(self, name)
Texture.__init__(self, name)
Image.REGISTERED_IMAGES.append(self)
self.set_clear_color(0)
self.clear_image()
self.sort = RenderTarget.CURRENT_SORT
def __del__(self):
""" Destroys the image """
self.warn("Image destructor not implemented yet")
def write(self, pth):
""" Writes the image to disk """
Globals.base.graphicsEngine.extract_texture_data(self, Globals.base.win.gsg)
if self.get_texture_type() in [Texture.TT_3d_texture, Texture.TT_cube_map]:
Texture.write(self, "#_" + pth, 0, 0, True, False)
else:
Texture.write(self, pth)

View File

@ -1,210 +1,207 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import math
from panda3d.core import LVecBase2i, PTAInt
from rpcore.globals import Globals
from rpcore.gpu_command_queue import GPUCommandQueue
from rpcore.image import Image
from rpcore.native import InternalLightManager, PointLight, ShadowManager
from rpcore.rpobject import RPObject
from rpcore.stages.apply_lights_stage import ApplyLightsStage
from rpcore.stages.collect_used_cells_stage import CollectUsedCellsStage
from rpcore.stages.cull_lights_stage import CullLightsStage
from rpcore.stages.flag_used_cells_stage import FlagUsedCellsStage
from rpcore.stages.shadow_stage import ShadowStage
class LightManager(RPObject):
""" This class is a wrapper around the InternalLightManager, and provides
additional functionality like setting up all required stages and defines."""
# Maximum amount of lights, has to match the definitions in the native code
MAX_LIGHTS = 65535
# Maximum amount of shadow sources
MAX_SOURCES = 2048
def __init__(self, pipeline):
""" Constructs the light manager """
RPObject.__init__(self)
self.pipeline = pipeline
self.compute_tile_size()
self.init_internal_manager()
self.init_command_queue()
self.init_shadow_manager()
self.init_stages()
@property
def total_tiles(self):
""" Returns the total amount of tiles """
return self.num_tiles.x * self.num_tiles.y * \
self.pipeline.settings["lighting.culling_grid_slices"]
@property
def num_lights(self):
""" Returns the amount of stored lights """
return self.internal_mgr.num_lights
@property
def num_shadow_sources(self):
""" Returns the amount of stored shadow sources """
return self.internal_mgr.num_shadow_sources
@property
def shadow_atlas_coverage(self):
""" Returns the shadow atlas coverage in percentage """
return self.internal_mgr.shadow_manager.atlas.coverage * 100.0
def add_light(self, light):
""" Adds a new light """
self.internal_mgr.add_light(light)
self.pta_max_light_index[0] = self.internal_mgr.max_light_index
def remove_light(self, light):
""" Removes a light """
# from RenderPipelineFile.rpcore.pynative.internal_light_manager import InternalLightManager
# inter = InternalLightManager()
# inter.remove_light(light)
self.internal_mgr.remove_light(light)
self.pta_max_light_index[0] = self.internal_mgr.max_light_index
def update(self):
""" Main update method to process the GPU commands """
self.internal_mgr.set_camera_pos(
Globals.base.camera.get_pos(Globals.base.render))
self.internal_mgr.update()
self.shadow_manager.update()
self.cmd_queue.process_queue()
def reload_shaders(self):
""" Reloads all assigned shaders """
self.cmd_queue.reload_shaders()
def compute_tile_size(self):
""" Computes how many tiles there are on screen """
self.tile_size = LVecBase2i(
self.pipeline.settings["lighting.culling_grid_size_x"],
self.pipeline.settings["lighting.culling_grid_size_y"])
num_tiles_x = int(math.ceil(Globals.resolution.x / float(self.tile_size.x)))
num_tiles_y = int(math.ceil(Globals.resolution.y / float(self.tile_size.y)))
self.debug("Tile size =", self.tile_size.x, "x", self.tile_size.y,
", Num tiles =", num_tiles_x, "x", num_tiles_y)
self.num_tiles = LVecBase2i(num_tiles_x, num_tiles_y)
def init_command_queue(self):
""" Inits the command queue """
self.cmd_queue = GPUCommandQueue(self.pipeline)
self.cmd_queue.register_input("LightData", self.img_light_data)
self.cmd_queue.register_input("SourceData", self.img_source_data)
self.internal_mgr.set_command_list(self.cmd_queue.command_list)
def init_shadow_manager(self):
""" Inits the shadow manager """
self.shadow_manager = ShadowManager()
self.shadow_manager.set_max_updates(self.pipeline.settings["shadows.max_updates"])
self.shadow_manager.set_scene(Globals.base.render)
self.shadow_manager.set_tag_state_manager(self.pipeline.tag_mgr)
self.shadow_manager.atlas_size = self.pipeline.settings["shadows.atlas_size"]
self.internal_mgr.shadow_manager = self.shadow_manager
def init_shadows(self):
""" Inits the shadows, this has to get called after the stages were
created, because we need the GraphicsOutput of the shadow atlas, which
is not available earlier """
self.shadow_manager.set_atlas_graphics_output(self.shadow_stage.atlas_buffer)
self.shadow_manager.init()
def init_internal_manager(self):
""" Creates the light storage manager and the buffer to store the light data """
self.internal_mgr = InternalLightManager()
self.internal_mgr.set_shadow_update_distance(
self.pipeline.settings["shadows.max_update_distance"])
# Storage for the Lights
per_light_vec4s = 4
self.img_light_data = Image.create_buffer(
"LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16")
self.img_light_data.clear_image()
self.pta_max_light_index = PTAInt.empty_array(1)
self.pta_max_light_index[0] = 0
# Storage for the shadow sources
per_source_vec4s = 5
# IMPORTANT: RGBA32 is really required here. Otherwise artifacts and bad
# shadow filtering occur due to precision issues
self.img_source_data = Image.create_buffer(
"ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA32")
self.img_light_data.clear_image()
# Register the buffer
inputs = self.pipeline.stage_mgr.inputs
inputs["AllLightsData"] = self.img_light_data
inputs["ShadowSourceData"] = self.img_source_data
inputs["maxLightIndex"] = self.pta_max_light_index
def init_stages(self):
""" Inits all required stages for the lighting """
add_stage = self.pipeline.stage_mgr.add_stage
self.flag_cells_stage = FlagUsedCellsStage(self.pipeline)
add_stage(self.flag_cells_stage)
self.collect_cells_stage = CollectUsedCellsStage(self.pipeline)
add_stage(self.collect_cells_stage)
self.cull_lights_stage = CullLightsStage(self.pipeline)
add_stage(self.cull_lights_stage)
self.apply_lights_stage = ApplyLightsStage(self.pipeline)
add_stage(self.apply_lights_stage)
self.shadow_stage = ShadowStage(self.pipeline)
self.shadow_stage.size = self.shadow_manager.get_atlas_size()
add_stage(self.shadow_stage)
def init_defines(self):
""" Inits the common defines """
defines = self.pipeline.stage_mgr.defines
defines["LC_TILE_SIZE_X"] = self.tile_size.x
defines["LC_TILE_SIZE_Y"] = self.tile_size.y
defines["LC_TILE_SLICES"] = self.pipeline.settings["lighting.culling_grid_slices"]
defines["LC_MAX_DISTANCE"] = self.pipeline.settings["lighting.culling_max_distance"]
defines["LC_CULLING_SLICE_WIDTH"] = self.pipeline.settings["lighting.culling_slice_width"]
defines["LC_MAX_LIGHTS_PER_CELL"] = self.pipeline.settings["lighting.max_lights_per_cell"]
defines["SHADOW_ATLAS_SIZE"] = self.pipeline.settings["shadows.atlas_size"]
# Register all light types as defines
for attr in dir(PointLight):
if attr.startswith("LT_"):
defines[attr.upper()] = getattr(PointLight, attr)
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import math
from panda3d.core import LVecBase2i, PTAInt
from rpcore.globals import Globals
from rpcore.gpu_command_queue import GPUCommandQueue
from rpcore.image import Image
from rpcore.native import InternalLightManager, PointLight, ShadowManager
from rpcore.rpobject import RPObject
from rpcore.stages.apply_lights_stage import ApplyLightsStage
from rpcore.stages.collect_used_cells_stage import CollectUsedCellsStage
from rpcore.stages.cull_lights_stage import CullLightsStage
from rpcore.stages.flag_used_cells_stage import FlagUsedCellsStage
from rpcore.stages.shadow_stage import ShadowStage
class LightManager(RPObject):
""" This class is a wrapper around the InternalLightManager, and provides
additional functionality like setting up all required stages and defines."""
# Maximum amount of lights, has to match the definitions in the native code
MAX_LIGHTS = 65535
# Maximum amount of shadow sources
MAX_SOURCES = 2048
def __init__(self, pipeline):
""" Constructs the light manager """
RPObject.__init__(self)
self.pipeline = pipeline
self.compute_tile_size()
self.init_internal_manager()
self.init_command_queue()
self.init_shadow_manager()
self.init_stages()
@property
def total_tiles(self):
""" Returns the total amount of tiles """
return self.num_tiles.x * self.num_tiles.y * \
self.pipeline.settings["lighting.culling_grid_slices"]
@property
def num_lights(self):
""" Returns the amount of stored lights """
return self.internal_mgr.num_lights
@property
def num_shadow_sources(self):
""" Returns the amount of stored shadow sources """
return self.internal_mgr.num_shadow_sources
@property
def shadow_atlas_coverage(self):
""" Returns the shadow atlas coverage in percentage """
return self.internal_mgr.shadow_manager.atlas.coverage * 100.0
def add_light(self, light):
""" Adds a new light """
self.internal_mgr.add_light(light)
self.pta_max_light_index[0] = self.internal_mgr.max_light_index
def remove_light(self, light):
""" Removes a light """
self.internal_mgr.remove_light(light)
self.pta_max_light_index[0] = self.internal_mgr.max_light_index
def update(self):
""" Main update method to process the GPU commands """
self.internal_mgr.set_camera_pos(
Globals.base.camera.get_pos(Globals.base.render))
self.internal_mgr.update()
self.shadow_manager.update()
self.cmd_queue.process_queue()
def reload_shaders(self):
""" Reloads all assigned shaders """
self.cmd_queue.reload_shaders()
def compute_tile_size(self):
""" Computes how many tiles there are on screen """
self.tile_size = LVecBase2i(
self.pipeline.settings["lighting.culling_grid_size_x"],
self.pipeline.settings["lighting.culling_grid_size_y"])
num_tiles_x = int(math.ceil(Globals.resolution.x / float(self.tile_size.x)))
num_tiles_y = int(math.ceil(Globals.resolution.y / float(self.tile_size.y)))
self.debug("Tile size =", self.tile_size.x, "x", self.tile_size.y,
", Num tiles =", num_tiles_x, "x", num_tiles_y)
self.num_tiles = LVecBase2i(num_tiles_x, num_tiles_y)
def init_command_queue(self):
""" Inits the command queue """
self.cmd_queue = GPUCommandQueue(self.pipeline)
self.cmd_queue.register_input("LightData", self.img_light_data)
self.cmd_queue.register_input("SourceData", self.img_source_data)
self.internal_mgr.set_command_list(self.cmd_queue.command_list)
def init_shadow_manager(self):
""" Inits the shadow manager """
self.shadow_manager = ShadowManager()
self.shadow_manager.set_max_updates(self.pipeline.settings["shadows.max_updates"])
self.shadow_manager.set_scene(Globals.base.render)
self.shadow_manager.set_tag_state_manager(self.pipeline.tag_mgr)
self.shadow_manager.atlas_size = self.pipeline.settings["shadows.atlas_size"]
self.internal_mgr.shadow_manager = self.shadow_manager
def init_shadows(self):
""" Inits the shadows, this has to get called after the stages were
created, because we need the GraphicsOutput of the shadow atlas, which
is not available earlier """
self.shadow_manager.set_atlas_graphics_output(self.shadow_stage.atlas_buffer)
self.shadow_manager.init()
def init_internal_manager(self):
""" Creates the light storage manager and the buffer to store the light data """
self.internal_mgr = InternalLightManager()
self.internal_mgr.set_shadow_update_distance(
self.pipeline.settings["shadows.max_update_distance"])
# Storage for the Lights
per_light_vec4s = 4
self.img_light_data = Image.create_buffer(
"LightData", self.MAX_LIGHTS * per_light_vec4s, "RGBA16")
self.img_light_data.clear_image()
self.pta_max_light_index = PTAInt.empty_array(1)
self.pta_max_light_index[0] = 0
# Storage for the shadow sources
per_source_vec4s = 5
# IMPORTANT: RGBA32 is really required here. Otherwise artifacts and bad
# shadow filtering occur due to precision issues
self.img_source_data = Image.create_buffer(
"ShadowSourceData", self.MAX_SOURCES * per_source_vec4s, "RGBA32")
self.img_light_data.clear_image()
# Register the buffer
inputs = self.pipeline.stage_mgr.inputs
inputs["AllLightsData"] = self.img_light_data
inputs["ShadowSourceData"] = self.img_source_data
inputs["maxLightIndex"] = self.pta_max_light_index
def init_stages(self):
""" Inits all required stages for the lighting """
add_stage = self.pipeline.stage_mgr.add_stage
self.flag_cells_stage = FlagUsedCellsStage(self.pipeline)
add_stage(self.flag_cells_stage)
self.collect_cells_stage = CollectUsedCellsStage(self.pipeline)
add_stage(self.collect_cells_stage)
self.cull_lights_stage = CullLightsStage(self.pipeline)
add_stage(self.cull_lights_stage)
self.apply_lights_stage = ApplyLightsStage(self.pipeline)
add_stage(self.apply_lights_stage)
self.shadow_stage = ShadowStage(self.pipeline)
self.shadow_stage.size = self.shadow_manager.get_atlas_size()
add_stage(self.shadow_stage)
def init_defines(self):
""" Inits the common defines """
defines = self.pipeline.stage_mgr.defines
defines["LC_TILE_SIZE_X"] = self.tile_size.x
defines["LC_TILE_SIZE_Y"] = self.tile_size.y
defines["LC_TILE_SLICES"] = self.pipeline.settings["lighting.culling_grid_slices"]
defines["LC_MAX_DISTANCE"] = self.pipeline.settings["lighting.culling_max_distance"]
defines["LC_CULLING_SLICE_WIDTH"] = self.pipeline.settings["lighting.culling_slice_width"]
defines["LC_MAX_LIGHTS_PER_CELL"] = self.pipeline.settings["lighting.max_lights_per_cell"]
defines["SHADOW_ATLAS_SIZE"] = self.pipeline.settings["shadows.atlas_size"]
# Register all light types as defines
for attr in dir(PointLight):
if attr.startswith("LT_"):
defines[attr.upper()] = getattr(PointLight, attr)

View File

@ -1,148 +1,148 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function
import time
from panda3d.core import PNMImage, VirtualFileSystem, VirtualFileMountRamdisk
from panda3d.core import Shader
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
__all__ = ("RPLoader",)
class timed_loading_operation(object): # noqa # pylint: disable=invalid-name,too-few-public-methods
""" Context manager for a synchronous loading operation, keeping track
on how much time elapsed during the loading process, and warning about
long loading times. """
WARNING_COUNT = 0
def __init__(self, resource):
self.resource = resource
if isinstance(self.resource, (list, tuple)):
self.resource = ', '.join(self.resource)
def __enter__(self):
self.start_time = time.process_time()
def __exit__(self, *args):
duration = (time.process_time() - self.start_time) * 1000.0
if duration > 80.0 and timed_loading_operation.WARNING_COUNT < 5:
RPObject.global_warn(
"RPLoader", "Loading '" + self.resource + "' took", round(duration, 2), "ms")
timed_loading_operation.WARNING_COUNT += 1
if timed_loading_operation.WARNING_COUNT == 5:
RPObject.global_warn(
"RPLoader", "Skipping further loading warnings (max warning count reached)")
class RPLoader(RPObject):
""" Generic loader class used by the pipeline. All loading of assets happens
here, which enables us to keep track of used resources """
@classmethod
def load_texture(cls, filename):
""" Loads a 2D-texture from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_texture(filename)
@classmethod
def load_cube_map(cls, filename, read_mipmaps=False):
""" Loads a cube map from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_cube_map(filename, readMipmaps=read_mipmaps)
@classmethod
def load_3d_texture(cls, filename):
""" Loads a 3D-texture from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_3d_texture(filename)
@classmethod
def load_font(cls, filename):
""" Loads a font from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_font(filename)
@classmethod
def load_shader(cls, *args):
""" Loads a shader from disk """
with timed_loading_operation(args):
if len(args) == 1:
return Shader.load_compute(Shader.SL_GLSL, args[0])
return Shader.load(Shader.SL_GLSL, *args)
@classmethod
def load_model(cls, filename):
""" Loads a model from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_model(filename)
@classmethod
def load_sliced_3d_texture(cls, fname, tile_size_x, tile_size_y=None, num_tiles=None):
""" Loads a texture from the given filename and dimensions. If only
one dimensions is specified, the other dimensions are assumed to be
equal. This internally loads the texture into ram, splits it into smaller
sub-images, and then calls the load_3d_texture from the Panda loader """
tempfile_name = "/$$slice_loader_temp-" + str(time.time()) + "/"
tile_size_y = tile_size_x if tile_size_y is None else tile_size_y
num_tiles = tile_size_x if num_tiles is None else num_tiles
# Load sliced image from disk
tex_handle = cls.load_texture(fname)
source = PNMImage()
tex_handle.store(source)
width = source.get_x_size()
# Find slice properties
num_cols = width // tile_size_x
temp_img = PNMImage(
tile_size_x, tile_size_y, source.get_num_channels(), source.get_maxval())
# Construct a ramdisk to write the files to
vfs = VirtualFileSystem.get_global_ptr()
ramdisk = VirtualFileMountRamdisk()
vfs.mount(ramdisk, tempfile_name, 0)
# Extract all slices and write them to the virtual disk
for z_slice in range(num_tiles):
slice_x = (z_slice % num_cols) * tile_size_x
slice_y = (z_slice // num_cols) * tile_size_y
temp_img.copy_sub_image(source, 0, 0, slice_x, slice_y, tile_size_x, tile_size_y)
temp_img.write(tempfile_name + str(z_slice) + ".png")
# Load the de-sliced texture from the ramdisk
texture_handle = cls.load_3d_texture(tempfile_name + "/#.png")
vfs.unmount(ramdisk)
return texture_handle
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from __future__ import print_function
import time
from panda3d.core import PNMImage, VirtualFileSystem, VirtualFileMountRamdisk
from panda3d.core import Shader
from rpcore.globals import Globals
from rpcore.rpobject import RPObject
__all__ = ("RPLoader",)
class timed_loading_operation(object): # noqa # pylint: disable=invalid-name,too-few-public-methods
""" Context manager for a synchronous loading operation, keeping track
on how much time elapsed during the loading process, and warning about
long loading times. """
WARNING_COUNT = 0
def __init__(self, resource):
self.resource = resource
if isinstance(self.resource, (list, tuple)):
self.resource = ', '.join(self.resource)
def __enter__(self):
self.start_time = time.process_time()
def __exit__(self, *args):
duration = (time.process_time() - self.start_time) * 1000.0
if duration > 80.0 and timed_loading_operation.WARNING_COUNT < 5:
RPObject.global_warn(
"RPLoader", "Loading '" + self.resource + "' took", round(duration, 2), "ms")
timed_loading_operation.WARNING_COUNT += 1
if timed_loading_operation.WARNING_COUNT == 5:
RPObject.global_warn(
"RPLoader", "Skipping further loading warnings (max warning count reached)")
class RPLoader(RPObject):
""" Generic loader class used by the pipeline. All loading of assets happens
here, which enables us to keep track of used resources """
@classmethod
def load_texture(cls, filename):
""" Loads a 2D-texture from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_texture(filename)
@classmethod
def load_cube_map(cls, filename, read_mipmaps=False):
""" Loads a cube map from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_cube_map(filename, readMipmaps=read_mipmaps)
@classmethod
def load_3d_texture(cls, filename):
""" Loads a 3D-texture from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_3d_texture(filename)
@classmethod
def load_font(cls, filename):
""" Loads a font from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_font(filename)
@classmethod
def load_shader(cls, *args):
""" Loads a shader from disk """
with timed_loading_operation(args):
if len(args) == 1:
return Shader.load_compute(Shader.SL_GLSL, args[0])
return Shader.load(Shader.SL_GLSL, *args)
@classmethod
def load_model(cls, filename):
""" Loads a model from disk """
with timed_loading_operation(filename):
return Globals.base.loader.load_model(filename)
@classmethod
def load_sliced_3d_texture(cls, fname, tile_size_x, tile_size_y=None, num_tiles=None):
""" Loads a texture from the given filename and dimensions. If only
one dimensions is specified, the other dimensions are assumed to be
equal. This internally loads the texture into ram, splits it into smaller
sub-images, and then calls the load_3d_texture from the Panda loader """
tempfile_name = "/$$slice_loader_temp-" + str(time.time()) + "/"
tile_size_y = tile_size_x if tile_size_y is None else tile_size_y
num_tiles = tile_size_x if num_tiles is None else num_tiles
# Load sliced image from disk
tex_handle = cls.load_texture(fname)
source = PNMImage()
tex_handle.store(source)
width = source.get_x_size()
# Find slice properties
num_cols = width // tile_size_x
temp_img = PNMImage(
tile_size_x, tile_size_y, source.get_num_channels(), source.get_maxval())
# Construct a ramdisk to write the files to
vfs = VirtualFileSystem.get_global_ptr()
ramdisk = VirtualFileMountRamdisk()
vfs.mount(ramdisk, tempfile_name, 0)
# Extract all slices and write them to the virtual disk
for z_slice in range(num_tiles):
slice_x = (z_slice % num_cols) * tile_size_x
slice_y = (z_slice // num_cols) * tile_size_y
temp_img.copy_sub_image(source, 0, 0, slice_x, slice_y, tile_size_x, tile_size_y)
temp_img.write(tempfile_name + str(z_slice) + ".png")
# Load the de-sliced texture from the ramdisk
texture_handle = cls.load_3d_texture(tempfile_name + "/#.png")
vfs.unmount(ramdisk)
return texture_handle

View File

@ -1,316 +1,316 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import os
import atexit
from panda3d.core import Filename, VirtualFileSystem, get_model_path
from panda3d.core import VirtualFileMountRamdisk
from direct.stdpy.file import join, isdir, isfile
from rpcore.rpobject import RPObject
class MountManager(RPObject):
""" This classes mounts the required directories for the pipeline to run.
This is important if the pipeline is in a subdirectory for example. The
mount manager also handles the lock, storing the current PID into a file
named instance.pid and ensuring that there is only 1 instance of the
pipeline running at one time. """
def __init__(self, pipeline):
""" Creates a new mount manager """
RPObject.__init__(self)
self._pipeline = pipeline
self._base_path = self._find_basepath()
self._lock_file = "instance.pid"
self._model_paths = []
self._write_path = None
self._mounted = False
self._do_cleanup = True
self._config_dir = None
self.debug("Auto-Detected base path to", self._base_path)
atexit.register(self._on_exit_cleanup)
@property
def write_path(self):
""" Returns the write path previously set with set_write_path, or None
if no write path has been set yet. """
return self._write_path
@write_path.setter
def write_path(self, pth):
""" Set a writable directory for generated files. This can be a string
path name or a multifile with openReadWrite(). If no pathname is set
then the root directory is used.
This feature is usually only used for debugging, the pipeline will dump
all generated shaders and other temporary files to that directory.
If you don't need this, you can use set_virtual_write_path(), which
will create the temporary path in the VirtualFileSystem, thus not
writing any files to disk. """
if pth is None:
self._write_path = None
self._lock_file = "instance.pid"
else:
self._write_path = Filename.from_os_specific(pth).get_fullpath()
self._lock_file = join(self._write_path, "instance.pid")
@property
def base_path(self):
""" Returns the base path of the pipeline. This returns the path previously
set with set_base_path, or the auto detected base path if no path was
set yet """
return self._base_path
@base_path.setter
def base_path(self, pth):
""" Sets the path where the base shaders and models on are contained. This
is usually the root of the rendering pipeline folder """
self.debug("Set base path to '" + pth + "'")
self._base_path = Filename.from_os_specific(pth).get_fullpath()
@property
def config_dir(self):
""" Returns the config directory previously set with set_config_dir, or
None if no directory was set yet """
@config_dir.setter
def config_dir(self, pth):
""" Sets the path to the config directory. Usually this is the config/
directory located in the pipeline root directory. However, if you want
to load your own configuration files, you can specify a custom config
directory here. Your configuration directory should contain the
pipeline.yaml, plugins.yaml, daytime.yaml and configuration.prc.
It is highly recommended you use the pipeline provided config files, modify
them to your needs, and as soon as you think they are in a final version,
copy them over. Please also notice that you should keep your config files
up-to-date, e.g. when new configuration variables are added.
Also, specifying a custom configuration_dir disables the functionality
of the PluginConfigurator and DayTime editor, since they operate on the
pipelines default config files.
Set the directory to None to use the default directory. """
self._config_dir = Filename.from_os_specific(pth).get_fullpath()
@property
def do_cleanup(self):
""" Returns whether the mount manager will attempt to cleanup the
generated files after the application stopped running """
return self._do_cleanup
@do_cleanup.setter
def do_cleanup(self, cleanup):
""" Sets whether to cleanup the tempfolder after the application stopped.
This is mostly useful for debugging, to analyze the generated tempfiles
even after the pipeline stopped running """
self._do_cleanup = cleanup
def get_lock(self):
""" Checks if we are the only instance running. If there is no instance
running, write the current PID to the instance.pid file. If the
instance file exists, checks if the specified process still runs. This
way only 1 instance of the pipeline can be run at one time. """
# Check if there is a lockfile at all
if isfile(self._lock_file):
# Read process id from lockfile
try:
with open(self._lock_file, "r") as handle:
pid = int(handle.readline())
except IOError as msg:
self.error("Failed to read lockfile:", msg)
return False
# Check if the process is still running
if self._is_pid_running(pid):
self.error("Found running instance")
return False
# Process is not running anymore, we can write the lockfile
self._write_lock()
return True
else:
# When there is no lockfile, just create it and continue
self._write_lock()
return True
def _find_basepath(self):
""" Attempts to find the pipeline base path by looking at the location
of this file """
pth = os.path.abspath(join(os.path.dirname(os.path.realpath(__file__)), ".."))
return Filename.from_os_specific(pth).get_fullpath()
def _is_pid_running(self, pid):
""" Checks if a pid is still running """
# Code snippet from:
# http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
if os.name == 'posix':
import errno
if pid < 0:
return False
try:
os.kill(pid, 0)
except OSError as err:
return err.errno == errno.EPERM
else:
return True
else:
import ctypes
kernel32 = ctypes.windll.kernel32
process = kernel32.OpenProcess(0x100000, 0, pid)
if process != 0:
kernel32.CloseHandle(process)
return True
else:
return False
def _write_lock(self):
""" Internal method to write the current process id to the instance.pid
lockfile. This is used to ensure no second instance of the pipeline is
running. """
with open(self._lock_file, "w") as handle:
handle.write(str(os.getpid()))
def _try_remove(self, fname):
""" Tries to remove the specified filename, returns either True or False
depending if we had success or not """
try:
os.remove(fname)
return True
except (IOError, OSError):
pass
return False
def _on_exit_cleanup(self):
""" Gets called when the application exists """
if self._do_cleanup:
self.debug("Cleaning up ..")
if self._write_path is not None:
# Try removing the lockfile
self._try_remove(self._lock_file)
# Check for further tempfiles in the write path
# We explicitely use os.listdir here instead of pandas listdir,
# to work with actual paths
for fname in os.listdir(self._write_path):
pth = join(self._write_path, fname)
# Tempfiles from the pipeline start with "$$" to distinguish
# them from user created files
if isfile(pth) and fname.startswith("$$"):
self._try_remove(pth)
# Delete the write path if no files are left
if len(os.listdir(self._write_path)) < 1:
try:
os.removedirs(self._write_path)
except IOError:
pass
@property
def is_mounted(self):
""" Returns whether the MountManager was already mounted by calling
mount() """
return self._mounted
def mount(self):
""" Inits the VFS Mounts. This creates the following virtual directory
structure, from which all files can be located:
/$$rp/ (Mounted from the render pipeline base directory)
+ rpcore/
+ shader/
+ ...
/$rpconfig/ (Mounted from config/, may be set by user)
+ pipeline.yaml
+ ...
/$$rptemp/ (Either ramdisk or user specified)
+ day_time_config
+ shader_auto_config
+ ...
/$$rpshader/ (Link to /$$rp/rpcore/shader)
"""
self.debug("Setting up virtual filesystem")
self._mounted = True
def convert_path(pth):
return Filename.from_os_specific(pth).get_fullpath()
vfs = VirtualFileSystem.get_global_ptr()
# Mount config dir as $$rpconf
if self._config_dir is None:
config_dir = convert_path(join(self._base_path, "config/"))
self.debug("Mounting auto-detected config dir:", config_dir)
vfs.mount(config_dir, "/$$rpconfig", 0)
else:
self.debug("Mounting custom config dir:", self._config_dir)
vfs.mount(convert_path(self._config_dir), "/$$rpconfig", 0)
# Mount directory structure
vfs.mount(convert_path(self._base_path), "/$$rp", 0)
vfs.mount(convert_path(join(self._base_path, "rpcore/shader")), "/$$rp/shader", 0)
vfs.mount(convert_path(join(self._base_path, "effects")), "effects", 0)
# Mount the pipeline temp path:
# If no write path is specified, use a virtual ramdisk
if self._write_path is None:
self.debug("Mounting ramdisk as /$$rptemp")
vfs.mount(VirtualFileMountRamdisk(), "/$$rptemp", 0)
else:
# In case an actual write path is specified:
# Ensure the pipeline write path exists, and if not, create it
if not isdir(self._write_path):
self.debug("Creating temporary path, since it does not exist yet")
try:
os.makedirs(self._write_path)
except IOError as msg:
self.fatal("Failed to create temporary path:", msg)
self.debug("Mounting", self._write_path, "as /$$rptemp")
vfs.mount(convert_path(self._write_path), '/$$rptemp', 0)
get_model_path().prepend_directory("/$$rp")
get_model_path().prepend_directory("/$$rp/shader")
get_model_path().prepend_directory("/$$rptemp")
def unmount(self):
""" Unmounts the VFS """
raise NotImplementedError("TODO")
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import os
import atexit
from panda3d.core import Filename, VirtualFileSystem, get_model_path
from panda3d.core import VirtualFileMountRamdisk
from direct.stdpy.file import join, isdir, isfile
from rpcore.rpobject import RPObject
class MountManager(RPObject):
""" This classes mounts the required directories for the pipeline to run.
This is important if the pipeline is in a subdirectory for example. The
mount manager also handles the lock, storing the current PID into a file
named instance.pid and ensuring that there is only 1 instance of the
pipeline running at one time. """
def __init__(self, pipeline):
""" Creates a new mount manager """
RPObject.__init__(self)
self._pipeline = pipeline
self._base_path = self._find_basepath()
self._lock_file = "instance.pid"
self._model_paths = []
self._write_path = None
self._mounted = False
self._do_cleanup = True
self._config_dir = None
self.debug("Auto-Detected base path to", self._base_path)
atexit.register(self._on_exit_cleanup)
@property
def write_path(self):
""" Returns the write path previously set with set_write_path, or None
if no write path has been set yet. """
return self._write_path
@write_path.setter
def write_path(self, pth):
""" Set a writable directory for generated files. This can be a string
path name or a multifile with openReadWrite(). If no pathname is set
then the root directory is used.
This feature is usually only used for debugging, the pipeline will dump
all generated shaders and other temporary files to that directory.
If you don't need this, you can use set_virtual_write_path(), which
will create the temporary path in the VirtualFileSystem, thus not
writing any files to disk. """
if pth is None:
self._write_path = None
self._lock_file = "instance.pid"
else:
self._write_path = Filename.from_os_specific(pth).get_fullpath()
self._lock_file = join(self._write_path, "instance.pid")
@property
def base_path(self):
""" Returns the base path of the pipeline. This returns the path previously
set with set_base_path, or the auto detected base path if no path was
set yet """
return self._base_path
@base_path.setter
def base_path(self, pth):
""" Sets the path where the base shaders and models on are contained. This
is usually the root of the rendering pipeline folder """
self.debug("Set base path to '" + pth + "'")
self._base_path = Filename.from_os_specific(pth).get_fullpath()
@property
def config_dir(self):
""" Returns the config directory previously set with set_config_dir, or
None if no directory was set yet """
@config_dir.setter
def config_dir(self, pth):
""" Sets the path to the config directory. Usually this is the config/
directory located in the pipeline root directory. However, if you want
to load your own configuration files, you can specify a custom config
directory here. Your configuration directory should contain the
pipeline.yaml, plugins.yaml, daytime.yaml and configuration.prc.
It is highly recommended you use the pipeline provided config files, modify
them to your needs, and as soon as you think they are in a final version,
copy them over. Please also notice that you should keep your config files
up-to-date, e.g. when new configuration variables are added.
Also, specifying a custom configuration_dir disables the functionality
of the PluginConfigurator and DayTime editor, since they operate on the
pipelines default config files.
Set the directory to None to use the default directory. """
self._config_dir = Filename.from_os_specific(pth).get_fullpath()
@property
def do_cleanup(self):
""" Returns whether the mount manager will attempt to cleanup the
generated files after the application stopped running """
return self._do_cleanup
@do_cleanup.setter
def do_cleanup(self, cleanup):
""" Sets whether to cleanup the tempfolder after the application stopped.
This is mostly useful for debugging, to analyze the generated tempfiles
even after the pipeline stopped running """
self._do_cleanup = cleanup
def get_lock(self):
""" Checks if we are the only instance running. If there is no instance
running, write the current PID to the instance.pid file. If the
instance file exists, checks if the specified process still runs. This
way only 1 instance of the pipeline can be run at one time. """
# Check if there is a lockfile at all
if isfile(self._lock_file):
# Read process id from lockfile
try:
with open(self._lock_file, "r") as handle:
pid = int(handle.readline())
except IOError as msg:
self.error("Failed to read lockfile:", msg)
return False
# Check if the process is still running
if self._is_pid_running(pid):
self.error("Found running instance")
return False
# Process is not running anymore, we can write the lockfile
self._write_lock()
return True
else:
# When there is no lockfile, just create it and continue
self._write_lock()
return True
def _find_basepath(self):
""" Attempts to find the pipeline base path by looking at the location
of this file """
pth = os.path.abspath(join(os.path.dirname(os.path.realpath(__file__)), ".."))
return Filename.from_os_specific(pth).get_fullpath()
def _is_pid_running(self, pid):
""" Checks if a pid is still running """
# Code snippet from:
# http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
if os.name == 'posix':
import errno
if pid < 0:
return False
try:
os.kill(pid, 0)
except OSError as err:
return err.errno == errno.EPERM
else:
return True
else:
import ctypes
kernel32 = ctypes.windll.kernel32
process = kernel32.OpenProcess(0x100000, 0, pid)
if process != 0:
kernel32.CloseHandle(process)
return True
else:
return False
def _write_lock(self):
""" Internal method to write the current process id to the instance.pid
lockfile. This is used to ensure no second instance of the pipeline is
running. """
with open(self._lock_file, "w") as handle:
handle.write(str(os.getpid()))
def _try_remove(self, fname):
""" Tries to remove the specified filename, returns either True or False
depending if we had success or not """
try:
os.remove(fname)
return True
except (IOError, OSError):
pass
return False
def _on_exit_cleanup(self):
""" Gets called when the application exists """
if self._do_cleanup:
self.debug("Cleaning up ..")
if self._write_path is not None:
# Try removing the lockfile
self._try_remove(self._lock_file)
# Check for further tempfiles in the write path
# We explicitely use os.listdir here instead of pandas listdir,
# to work with actual paths
for fname in os.listdir(self._write_path):
pth = join(self._write_path, fname)
# Tempfiles from the pipeline start with "$$" to distinguish
# them from user created files
if isfile(pth) and fname.startswith("$$"):
self._try_remove(pth)
# Delete the write path if no files are left
if len(os.listdir(self._write_path)) < 1:
try:
os.removedirs(self._write_path)
except IOError:
pass
@property
def is_mounted(self):
""" Returns whether the MountManager was already mounted by calling
mount() """
return self._mounted
def mount(self):
""" Inits the VFS Mounts. This creates the following virtual directory
structure, from which all files can be located:
/$$rp/ (Mounted from the render pipeline base directory)
+ rpcore/
+ shader/
+ ...
/$rpconfig/ (Mounted from config/, may be set by user)
+ pipeline.yaml
+ ...
/$$rptemp/ (Either ramdisk or user specified)
+ day_time_config
+ shader_auto_config
+ ...
/$$rpshader/ (Link to /$$rp/rpcore/shader)
"""
self.debug("Setting up virtual filesystem")
self._mounted = True
def convert_path(pth):
return Filename.from_os_specific(pth).get_fullpath()
vfs = VirtualFileSystem.get_global_ptr()
# Mount config dir as $$rpconf
if self._config_dir is None:
config_dir = convert_path(join(self._base_path, "config/"))
self.debug("Mounting auto-detected config dir:", config_dir)
vfs.mount(config_dir, "/$$rpconfig", 0)
else:
self.debug("Mounting custom config dir:", self._config_dir)
vfs.mount(convert_path(self._config_dir), "/$$rpconfig", 0)
# Mount directory structure
vfs.mount(convert_path(self._base_path), "/$$rp", 0)
vfs.mount(convert_path(join(self._base_path, "rpcore/shader")), "/$$rp/shader", 0)
vfs.mount(convert_path(join(self._base_path, "effects")), "effects", 0)
# Mount the pipeline temp path:
# If no write path is specified, use a virtual ramdisk
if self._write_path is None:
self.debug("Mounting ramdisk as /$$rptemp")
vfs.mount(VirtualFileMountRamdisk(), "/$$rptemp", 0)
else:
# In case an actual write path is specified:
# Ensure the pipeline write path exists, and if not, create it
if not isdir(self._write_path):
self.debug("Creating temporary path, since it does not exist yet")
try:
os.makedirs(self._write_path)
except IOError as msg:
self.fatal("Failed to create temporary path:", msg)
self.debug("Mounting", self._write_path, "as /$$rptemp")
vfs.mount(convert_path(self._write_path), '/$$rptemp', 0)
get_model_path().prepend_directory("/$$rp")
get_model_path().prepend_directory("/$$rp/shader")
get_model_path().prepend_directory("/$$rptemp")
def unmount(self):
""" Unmounts the VFS """
raise NotImplementedError("TODO")

View File

@ -1,19 +1,19 @@
# Prefab gitignore which can be used by the user to ignore the files generated
# by the module builder
*.pyd
*.pyc
*.so
*.pdb
# Various output names
win_*/
linux_*/
source/interrogate*
# Source and script files
scripts/
CMakeLists.txt
build.py
LICENSE
# Prefab gitignore which can be used by the user to ignore the files generated
# by the module builder
*.pyd
*.pyc
*.so
*.pdb
# Various output names
win_*/
linux_*/
source/interrogate*
# Source and script files
scripts/
CMakeLists.txt
build.py
LICENSE

View File

@ -1,96 +1,95 @@
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# pylint: disable=invalid-name
# This file includes all modules from the native module.
from __future__ import print_function
import sys
from os.path import dirname, realpath
from direct.stdpy.file import join, isfile
from rpcore.rpobject import RPObject
# Store a global flag, indicating whether the C++ modules were loaded or the python
# implemetation of them
NATIVE_CXX_LOADED = False
# Read the configuration from the flag-file
current_path = dirname(realpath(__file__))
cxx_flag_path = join(current_path, "use_cxx.flag")
if not isfile(cxx_flag_path):
RPObject.global_error("CORE", "Could not find cxx flag, please run the setup.py!")
sys.exit(1)
else:
with open(join(current_path, "use_cxx.flag"), "r") as handle:
NATIVE_CXX_LOADED = handle.read().strip() == "1"
# The native module should only be imported once, and that by the internal pipeline code
assert __package__ == "rpcore.native", "You have included the pipeline in the wrong way!"
# Classes which should get imported
classes_to_import = [
"GPUCommand",
"GPUCommandList",
"ShadowManager",
"InternalLightManager",
"PSSMCameraRig",
"IESDataset",
"TagStateManager",
]
# Classes which should get imported and renamed
classes_to_import_and_rename = {
"RPPointLight": "PointLight",
"RPSpotLight": "SpotLight"
}
native_module = None
# If the module was built, use it, otherwise use the python wrappers
if NATIVE_CXX_LOADED:
try:
from panda3d import _rplight as _native_module # pylint: disable=wrong-import-position
RPObject.global_debug("CORE", "Using panda3d-supplied core module")
except ImportError:
RPObject.global_debug("CORE", "Using native core module")
from rpcore.native import native_ as _native_module # pylint: disable=wrong-import-position
else:
print(f'343434343434343434343434343')
from rpcore import pynative as _native_module # pylint: disable=wrong-import-position
RPObject.global_debug("CORE", "Using simulated python-wrapper module")
# Import all classes
for v in classes_to_import + list(classes_to_import_and_rename.keys()):
if hasattr(_native_module, v):
v_name = classes_to_import_and_rename[v] if v in classes_to_import_and_rename else v
globals()[v_name] = getattr(_native_module, v)
else:
print("ERROR: could not import class", v, "from", _native_module.__name__)
# Don't export all variables, only the required ones
__all__ = classes_to_import + list(classes_to_import_and_rename.values()) + ["NATIVE_CXX_LOADED"]
"""
RenderPipeline
Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# pylint: disable=invalid-name
# This file includes all modules from the native module.
from __future__ import print_function
import sys
from os.path import dirname, realpath
from direct.stdpy.file import join, isfile
from rpcore.rpobject import RPObject
# Store a global flag, indicating whether the C++ modules were loaded or the python
# implemetation of them
NATIVE_CXX_LOADED = False
# Read the configuration from the flag-file
current_path = dirname(realpath(__file__))
cxx_flag_path = join(current_path, "use_cxx.flag")
if not isfile(cxx_flag_path):
RPObject.global_error("CORE", "Could not find cxx flag, please run the setup.py!")
sys.exit(1)
else:
with open(join(current_path, "use_cxx.flag"), "r") as handle:
NATIVE_CXX_LOADED = handle.read().strip() == "1"
# The native module should only be imported once, and that by the internal pipeline code
assert __package__ == "rpcore.native", "You have included the pipeline in the wrong way!"
# Classes which should get imported
classes_to_import = [
"GPUCommand",
"GPUCommandList",
"ShadowManager",
"InternalLightManager",
"PSSMCameraRig",
"IESDataset",
"TagStateManager",
]
# Classes which should get imported and renamed
classes_to_import_and_rename = {
"RPPointLight": "PointLight",
"RPSpotLight": "SpotLight"
}
native_module = None
# If the module was built, use it, otherwise use the python wrappers
if NATIVE_CXX_LOADED:
try:
from panda3d import _rplight as _native_module # pylint: disable=wrong-import-position
RPObject.global_debug("CORE", "Using panda3d-supplied core module")
except ImportError:
RPObject.global_debug("CORE", "Using native core module")
from rpcore.native import native_ as _native_module # pylint: disable=wrong-import-position
else:
from rpcore import pynative as _native_module # pylint: disable=wrong-import-position
RPObject.global_debug("CORE", "Using simulated python-wrapper module")
# Import all classes
for v in classes_to_import + list(classes_to_import_and_rename.keys()):
if hasattr(_native_module, v):
v_name = classes_to_import_and_rename[v] if v in classes_to_import_and_rename else v
globals()[v_name] = getattr(_native_module, v)
else:
print("ERROR: could not import class", v, "from", _native_module.__name__)
# Don't export all variables, only the required ones
__all__ = classes_to_import + list(classes_to_import_and_rename.values()) + ["NATIVE_CXX_LOADED"]

View File

@ -1,2 +1,2 @@
generate_pdb=1
module_name=native_
generate_pdb=1
module_name=native_

View File

@ -1,7 +1,7 @@
## Render Pipeline Native
This contains the source code of the native C++ modules
of the RenderPipeline.
The documentation of the
modules can be found <a href="http://tobspr.me/renderpipeline/docs/html/">here</a>.
## Render Pipeline Native
This contains the source code of the native C++ modules
of the RenderPipeline.
The documentation of the
modules can be found <a href="http://tobspr.me/renderpipeline/docs/html/">here</a>.

View File

@ -1,5 +1,5 @@
forcetype GPUCommandList
forcetype GPUCommand
forcetype RPLight
forcetype ShadowManager
forcetype TagStateManager
forcetype GPUCommandList
forcetype GPUCommand
forcetype RPLight
forcetype ShadowManager
forcetype TagStateManager

Some files were not shown because too many files have changed in this diff Show More