Merge branch 'bf-blender' into mb-0001-operator-repeat
This commit is contained in:
commit
2c66749a9e
|
@ -30,7 +30,7 @@ CHECKER_EXCLUDE_SOURCE_FILES = set(os.path.join(*f.split("/")) for f in (
|
|||
"source/blender/draw/engines/eevee_next/eevee_lut.cc",
|
||||
))
|
||||
|
||||
CHECKER_ARGS = [
|
||||
CHECKER_ARGS = (
|
||||
# Speed up execution.
|
||||
# As Blender has many defines, the total number of configurations is large making execution unreasonably slow.
|
||||
# This could be increased but do so with care.
|
||||
|
@ -39,9 +39,15 @@ CHECKER_ARGS = [
|
|||
# Enable this when includes are missing.
|
||||
# "--check-config",
|
||||
|
||||
# This is slower, for a comprehensive output it is needed.
|
||||
"--check-level=exhaustive",
|
||||
|
||||
# Shows many pedantic issues, some are quite useful.
|
||||
"--enable=all",
|
||||
|
||||
# Generates many warnings, CPPCHECK known about system includes without resolving them.
|
||||
"--suppress=missingIncludeSystem",
|
||||
|
||||
# Also shows useful messages, even if some are false-positives.
|
||||
"--inconclusive",
|
||||
|
||||
|
@ -50,7 +56,15 @@ CHECKER_ARGS = [
|
|||
*(() if USE_VERBOSE else ("--quiet",))
|
||||
|
||||
# NOTE: `--cppcheck-build-dir=<dir>` is added later as a temporary directory.
|
||||
]
|
||||
)
|
||||
|
||||
CHECKER_ARGS_C = (
|
||||
"--std=c11",
|
||||
)
|
||||
|
||||
CHECKER_ARGS_CXX = (
|
||||
"--std=c++17",
|
||||
)
|
||||
|
||||
|
||||
def source_info_filter(
|
||||
|
@ -74,22 +88,50 @@ def source_info_filter(
|
|||
return source_info_result
|
||||
|
||||
|
||||
def cppcheck() -> None:
|
||||
def cppcheck(temp_dir: str) -> None:
|
||||
temp_build_dir = os.path.join(temp_dir, "build")
|
||||
temp_source_dir = os.path.join(temp_dir, "source")
|
||||
del temp_dir
|
||||
|
||||
os.mkdir(temp_build_dir)
|
||||
os.mkdir(temp_source_dir)
|
||||
|
||||
source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX)
|
||||
source_defines = project_source_info.build_defines_as_args()
|
||||
cppcheck_compiler_h = os.path.join(temp_source_dir, "cppcheck_compiler.h")
|
||||
with open(cppcheck_compiler_h, "w", encoding="utf-8") as fh:
|
||||
fh.write(project_source_info.build_defines_as_source())
|
||||
|
||||
# Add additional defines.
|
||||
fh.write("\n")
|
||||
# Python's `pyport.h` errors without this.
|
||||
fh.write("#define UCHAR_MAX 255\n")
|
||||
# `intern/atomic/intern/atomic_ops_utils.h` errors with `Cannot find int size` without this.
|
||||
fh.write("#define UINT_MAX 0xFFFFFFFF\n")
|
||||
|
||||
# Apply exclusion.
|
||||
source_info = source_info_filter(source_info)
|
||||
|
||||
check_commands = []
|
||||
for c, inc_dirs, defs in source_info:
|
||||
if c.endswith(".c"):
|
||||
checker_args_extra = CHECKER_ARGS_C
|
||||
else:
|
||||
checker_args_extra = CHECKER_ARGS_CXX
|
||||
|
||||
cmd = (
|
||||
[CHECKER_BIN] +
|
||||
CHECKER_ARGS +
|
||||
[c] +
|
||||
[("-I%s" % i) for i in inc_dirs] +
|
||||
[("-D%s" % d) for d in defs] +
|
||||
source_defines
|
||||
CHECKER_BIN,
|
||||
*CHECKER_ARGS,
|
||||
*checker_args_extra,
|
||||
"--cppcheck-build-dir=" + temp_build_dir,
|
||||
"--include=" + cppcheck_compiler_h,
|
||||
# NOTE: for some reason failing to include this crease a large number of syntax errors
|
||||
# from `intern/guardedalloc/MEM_guardedalloc.h`. Include directly to resolve.
|
||||
"--include=" + os.path.join(
|
||||
project_source_info.SOURCE_DIR, "source", "blender", "blenlib", "BLI_compiler_attrs.h",
|
||||
),
|
||||
c,
|
||||
*[("-I%s" % i) for i in inc_dirs],
|
||||
*[("-D%s" % d) for d in defs],
|
||||
)
|
||||
|
||||
check_commands.append((c, cmd))
|
||||
|
@ -119,8 +161,7 @@ def cppcheck() -> None:
|
|||
|
||||
def main() -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
CHECKER_ARGS.append("--cppcheck-build-dir=" + temp_dir)
|
||||
cppcheck()
|
||||
cppcheck(temp_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -24,12 +24,12 @@ from typing import (
|
|||
Any,
|
||||
Callable,
|
||||
Generator,
|
||||
IO,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
import shlex
|
||||
|
@ -120,12 +120,13 @@ def makefile_log() -> List[str]:
|
|||
time.sleep(1)
|
||||
|
||||
# We know this is always true based on the input arguments to `Popen`.
|
||||
stdout: IO[bytes] = process.stdout # type: ignore
|
||||
assert process.stdout is not None
|
||||
stdout: IO[bytes] = process.stdout
|
||||
|
||||
out = stdout.read()
|
||||
stdout.close()
|
||||
print("done!", len(out), "bytes")
|
||||
return cast(List[str], out.decode("utf-8", errors="ignore").split("\n"))
|
||||
return out.decode("utf-8", errors="ignore").split("\n")
|
||||
|
||||
|
||||
def build_info(
|
||||
|
@ -211,9 +212,10 @@ def build_defines_as_source() -> str:
|
|||
)
|
||||
|
||||
# We know this is always true based on the input arguments to `Popen`.
|
||||
stdout: IO[bytes] = process.stdout # type: ignore
|
||||
assert process.stdout is not None
|
||||
stdout: IO[bytes] = process.stdout
|
||||
|
||||
return cast(str, stdout.read().strip().decode('ascii'))
|
||||
return stdout.read().strip().decode('ascii')
|
||||
|
||||
|
||||
def build_defines_as_args() -> List[str]:
|
||||
|
|
|
@ -33,7 +33,7 @@ def main() -> None:
|
|||
blender_srcdir = Path(__file__).absolute().parent.parent.parent
|
||||
|
||||
cli_parser = argparse.ArgumentParser(
|
||||
description=f"Create a tarball of the Blender sources, optionally including sources of dependencies.",
|
||||
description="Create a tarball of the Blender sources, optionally including sources of dependencies.",
|
||||
epilog="This script is intended to be run by `make source_archive_complete`.",
|
||||
)
|
||||
cli_parser.add_argument(
|
||||
|
|
|
@ -393,7 +393,7 @@ def floating_checkout_add_origin_if_needed(
|
|||
upstream_url = make_utils.git_get_remote_url(args.git_command, "upstream")
|
||||
|
||||
call((args.git_command, "remote", "rename", "upstream", "origin"))
|
||||
make_utils.git_set_config(args.git_command, f"remote.origin.url", origin_external_url)
|
||||
make_utils.git_set_config(args.git_command, "remote.origin.url", origin_external_url)
|
||||
|
||||
call((args.git_command, "remote", "add", "upstream", upstream_url))
|
||||
finally:
|
||||
|
|
|
@ -115,7 +115,8 @@ def git_branch(git_command: str) -> str:
|
|||
|
||||
try:
|
||||
branch = subprocess.check_output([git_command, "rev-parse", "--abbrev-ref", "HEAD"])
|
||||
except subprocess.CalledProcessError as e:
|
||||
except subprocess.CalledProcessError:
|
||||
# No need to print the exception, error text is written to the output already.
|
||||
sys.stderr.write("Failed to get Blender git branch\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
# SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import time
|
||||
|
||||
|
||||
def has_module(module_name):
|
||||
found = False
|
||||
try:
|
||||
__import__(module_name)
|
||||
found = True
|
||||
except ModuleNotFoundError as ex:
|
||||
if ex.name != module_name:
|
||||
raise ex
|
||||
return found
|
||||
|
||||
|
||||
# These are substituted when this file is copied to the build directory.
|
||||
BLENDER_VERSION_STRING = "${BLENDER_VERSION_STRING}"
|
||||
BLENDER_VERSION_DOTS = "${BLENDER_VERSION_DOTS}"
|
||||
BLENDER_REVISION = "${BLENDER_REVISION}"
|
||||
BLENDER_REVISION_TIMESTAMP = "${BLENDER_REVISION_TIMESTAMP}"
|
||||
BLENDER_VERSION_DATE = time.strftime(
|
||||
"%d/%m/%Y",
|
||||
time.localtime(int(BLENDER_REVISION_TIMESTAMP) if BLENDER_REVISION_TIMESTAMP != "0" else None),
|
||||
)
|
||||
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 GIT hash.
|
||||
BLENDER_VERSION_HASH = BLENDER_REVISION
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://projects.blender.org/blender/blender/commit/%s>%s</a>" % (
|
||||
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH)
|
||||
else:
|
||||
# Fallback: Should not be used.
|
||||
BLENDER_VERSION_HASH = "Hash Unknown"
|
||||
BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
|
||||
|
||||
extensions = ["sphinx.ext.intersphinx"]
|
||||
intersphinx_mapping = {"blender_manual": ("https://docs.blender.org/manual/en/dev/", None)}
|
||||
|
||||
|
||||
# Provides copy button next to code-blocks (nice to have but not essential).
|
||||
if has_module("sphinx_copybutton"):
|
||||
extensions.append("sphinx_copybutton")
|
||||
|
||||
# Exclude line numbers, prompts, and console text.
|
||||
copybutton_exclude = ".linenos, .gp, .go"
|
||||
|
||||
|
||||
project = "Blender %s Python API" % BLENDER_VERSION_STRING
|
||||
root_doc = "index"
|
||||
copyright = "Blender Authors"
|
||||
version = BLENDER_VERSION_DOTS
|
||||
release = BLENDER_VERSION_DOTS
|
||||
|
||||
# Set this as the default is a super-set of Python3.
|
||||
highlight_language = "python3"
|
||||
# No need to detect encoding.
|
||||
highlight_options = {"default": {"encoding": "utf-8"}}
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
exclude_patterns = [
|
||||
"include__bmesh.rst",
|
||||
]
|
||||
|
||||
html_title = "Blender Python API"
|
||||
|
||||
# The fallback to a built-in theme when `furo` is not found.
|
||||
html_theme = "default"
|
||||
|
||||
if has_module("furo"):
|
||||
html_theme = "furo"
|
||||
html_theme_options = {
|
||||
"light_css_variables": {
|
||||
"color-brand-primary": "#265787",
|
||||
"color-brand-content": "#265787",
|
||||
},
|
||||
}
|
||||
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"sidebar/brand.html",
|
||||
"sidebar/search.html",
|
||||
"sidebar/scroll-start.html",
|
||||
"sidebar/navigation.html",
|
||||
"sidebar/scroll-end.html",
|
||||
"sidebar/variant-selector.html",
|
||||
]
|
||||
}
|
||||
|
||||
# Not helpful since the source is generated, adds to upload size.
|
||||
html_copy_source = False
|
||||
html_show_sphinx = False
|
||||
html_baseurl = "https://docs.blender.org/api/current/"
|
||||
html_use_opensearch = "https://docs.blender.org/api/current"
|
||||
html_show_search_summary = True
|
||||
html_split_index = True
|
||||
html_static_path = ["static"]
|
||||
templates_path = ["templates"]
|
||||
html_context = {"commit": "%s - %s" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE)}
|
||||
html_extra_path = ["static"]
|
||||
html_favicon = "static/favicon.ico"
|
||||
html_logo = "static/blender_logo.svg"
|
||||
# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
|
||||
html_last_updated_fmt = None
|
||||
if html_theme == "furo":
|
||||
html_css_files = ["css/theme_overrides.css", "css/version_switch.css"]
|
||||
html_js_files = ["js/version_switch.js"]
|
||||
|
||||
# Needed for latex, PDF generation.
|
||||
latex_elements = {
|
||||
"papersize": "a4paper",
|
||||
}
|
||||
|
||||
latex_documents = [
|
||||
("contents", "contents.tex", "Blender Index", "Blender Foundation", "manual"),
|
||||
]
|
||||
|
||||
# Workaround for useless links leading to compile errors
|
||||
# See https://github.com/sphinx-doc/sphinx/issues/3866
|
||||
from sphinx.domains.python import PythonDomain
|
||||
|
||||
|
||||
class PatchedPythonDomain(PythonDomain):
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
if "refspecific" in node:
|
||||
del node["refspecific"]
|
||||
return super(PatchedPythonDomain, self).resolve_xref(
|
||||
env, fromdocname, builder, typ, target, node, contnode)
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_domain(PatchedPythonDomain, override=True)
|
|
@ -17,10 +17,10 @@ animation or modifiers into account:
|
|||
|
||||
When is used on evaluated object all modifiers are taken into account.
|
||||
|
||||
.. note:: The result mesh is owned by the object. It can be freed by calling `object.to_mesh_clear()`.
|
||||
.. note:: The result mesh is owned by the object. It can be freed by calling :meth:`~Object.to_mesh_clear`.
|
||||
.. note::
|
||||
The result mesh must be treated as temporary, and cannot be referenced from objects in the main
|
||||
database. If the mesh intended to be used in a persistent manner use bpy.data.meshes.new_from_object()
|
||||
database. If the mesh intended to be used in a persistent manner use :meth:`~BlendDataMeshes.new_from_object`
|
||||
instead.
|
||||
.. note:: If object does not have geometry (i.e. camera) the functions returns None.
|
||||
"""
|
||||
|
|
|
@ -15,7 +15,7 @@ If the object is a text object. The text will be converted into a 3D curve and r
|
|||
never applied on text objects and apply_modifiers will be ignored. If the object is neither a curve nor
|
||||
a text object, an error will be reported.
|
||||
|
||||
.. note:: The resulting curve is owned by the object. It can be freed by calling `object.to_curve_clear()`.
|
||||
.. note:: The resulting curve is owned by the object. It can be freed by calling :meth:`~Object.to_curve_clear`.
|
||||
.. note::
|
||||
The resulting curve must be treated as temporary, and cannot be referenced from objects in the main
|
||||
database.
|
||||
|
|
|
@ -16,10 +16,11 @@ This ``directory`` and ``files`` properties now will be used by the
|
|||
"""
|
||||
|
||||
import bpy
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
from mathutils import Vector
|
||||
|
||||
|
||||
class ShaderScriptImport(bpy.types.Operator):
|
||||
class ShaderScriptImport(bpy.types.Operator, ImportHelper):
|
||||
"""Test importer that creates scripts nodes from .txt files"""
|
||||
bl_idname = "shader.script_import"
|
||||
bl_label = "Import a text file as a script node"
|
||||
|
@ -28,8 +29,11 @@ class ShaderScriptImport(bpy.types.Operator):
|
|||
This Operator can import multiple .txt files, we need following directory and files
|
||||
properties that the file handler will use to set files path data
|
||||
"""
|
||||
directory: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'})
|
||||
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'SKIP_SAVE'})
|
||||
directory: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE', 'HIDDEN'})
|
||||
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'SKIP_SAVE', 'HIDDEN'})
|
||||
|
||||
"""Allow the user to select if the node's label is set or not"""
|
||||
set_label: bpy.props.BoolProperty(name="Set Label", default=False)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -57,23 +61,26 @@ class ShaderScriptImport(bpy.types.Operator):
|
|||
filepath = os.path.join(self.directory, file.name)
|
||||
text_node.filepath = filepath
|
||||
text_node.location = Vector((x, y))
|
||||
|
||||
# Set the node's title to the file name
|
||||
if self.set_label:
|
||||
text_node.label = file.name
|
||||
|
||||
x += 20.0
|
||||
y -= 20.0
|
||||
return {'FINISHED'}
|
||||
|
||||
"""
|
||||
By default the file handler invokes the operator with the directory and files properties set.
|
||||
In this example if this properties are set the operator is executed, if not the
|
||||
file select window is invoked.
|
||||
This depends on setting ``options={'SKIP_SAVE'}`` to the properties options to avoid
|
||||
to reuse filepath data between operator calls.
|
||||
Use ImportHelper's invoke_popup() to handle the invocation so that this operator's properties
|
||||
are shown in a popup. This allows the user to configure additional settings on the operator like
|
||||
the `set_label` property. Consider having a draw() method on the operator in order to layout the
|
||||
properties in the UI appropriately.
|
||||
|
||||
If filepath information is not provided the file select window will be invoked instead.
|
||||
"""
|
||||
|
||||
def invoke(self, context, event):
|
||||
if self.directory:
|
||||
return self.execute(context)
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
return self.invoke_popup(context)
|
||||
|
||||
|
||||
class SHADER_FH_script_import(bpy.types.FileHandler):
|
||||
|
|
|
@ -136,8 +136,9 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
|
|||
def filter_items(self, context, data, propname):
|
||||
# This function gets the collection property (as the usual tuple (data, propname)), and must return two lists:
|
||||
# * The first one is for filtering, it must contain 32bit integers were self.bitflag_filter_item marks the
|
||||
# matching item as filtered (i.e. to be shown), and 31 other bits are free for custom needs. Here we use the
|
||||
# first one to mark VGROUP_EMPTY.
|
||||
# matching item as filtered (i.e. to be shown). The upper 16 bits (including self.bitflag_filter_item) are
|
||||
# reserved for internal use, the lower 16 bits are free for custom use. Here we use the first bit to mark
|
||||
# VGROUP_EMPTY.
|
||||
# * The second one is for reordering, it must return a list containing the new indices of the items (which
|
||||
# gives us a mapping org_idx -> new_idx).
|
||||
# Please note that the default UI_UL_list defines helper functions for common tasks (see its doc for more info).
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
sphinx==7.1.2
|
||||
sphinx==7.2.6
|
||||
|
||||
# Sphinx dependencies that are important
|
||||
Jinja2==3.1.2
|
||||
Pygments==2.16.1
|
||||
docutils==0.18.1
|
||||
Jinja2==3.1.3
|
||||
Pygments==2.17.2
|
||||
docutils==0.20.1
|
||||
snowballstemmer==2.2.0
|
||||
requests==2.31.0
|
||||
|
||||
|
@ -11,3 +11,6 @@ requests==2.31.0
|
|||
# Without this theme, the default theme will be used.
|
||||
furo==2024.1.29
|
||||
sphinx-basic-ng==1.0.0b2
|
||||
|
||||
# Show a copy button (convenience only).
|
||||
sphinx-copybutton==0.5.2
|
||||
|
|
|
@ -61,7 +61,6 @@ import os
|
|||
import sys
|
||||
import inspect
|
||||
import shutil
|
||||
import time
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
|
@ -486,19 +485,6 @@ BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp
|
|||
BLENDER_VERSION_STRING = bpy.app.version_string
|
||||
BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 Git hash
|
||||
BLENDER_VERSION_HASH = BLENDER_REVISION
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://projects.blender.org/blender/blender/commit/%s>%s</a>" % (
|
||||
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH,
|
||||
)
|
||||
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
|
||||
else:
|
||||
# Fallback: Should not be used
|
||||
BLENDER_VERSION_HASH = "Hash Unknown"
|
||||
BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
|
||||
BLENDER_VERSION_DATE = time.strftime("%Y-%m-%d")
|
||||
|
||||
# Example: `2_83`.
|
||||
BLENDER_VERSION_PATH = "%d_%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
|
||||
|
@ -1712,7 +1698,7 @@ def pyrna2sphinx(basepath):
|
|||
lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier))
|
||||
|
||||
if lines:
|
||||
fw(".. rubric:: Inherited Properties\n\n")
|
||||
fw(title_string("Inherited Properties", "-"))
|
||||
|
||||
fw(".. hlist::\n")
|
||||
fw(" :columns: 2\n\n")
|
||||
|
@ -1738,7 +1724,7 @@ def pyrna2sphinx(basepath):
|
|||
lines.append(" * :class:`%s.%s`\n" % (base.identifier, identifier))
|
||||
|
||||
if lines:
|
||||
fw(".. rubric:: Inherited Functions\n\n")
|
||||
fw(title_string("Inherited Functions", "-"))
|
||||
|
||||
fw(".. hlist::\n")
|
||||
fw(" :columns: 2\n\n")
|
||||
|
@ -1750,8 +1736,7 @@ def pyrna2sphinx(basepath):
|
|||
del lines[:]
|
||||
|
||||
if struct.references:
|
||||
# use this otherwise it gets in the index for a normal heading.
|
||||
fw(".. rubric:: References\n\n")
|
||||
fw(title_string("References", "-"))
|
||||
|
||||
fw(".. hlist::\n")
|
||||
fw(" :columns: 2\n\n")
|
||||
|
@ -1896,111 +1881,6 @@ def pyrna2sphinx(basepath):
|
|||
write_ops()
|
||||
|
||||
|
||||
def write_sphinx_conf_py(basepath):
|
||||
"""
|
||||
Write sphinx's ``conf.py``.
|
||||
"""
|
||||
filepath = os.path.join(basepath, "conf.py")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
fw("import sys, os\n\n")
|
||||
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
|
||||
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
|
||||
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_STRING)
|
||||
fw("root_doc = 'index'\n")
|
||||
fw("copyright = 'Blender Authors'\n")
|
||||
fw("version = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
fw("release = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
|
||||
# Set this as the default is a super-set of Python3.
|
||||
fw("highlight_language = 'python3'\n")
|
||||
# No need to detect encoding.
|
||||
fw("highlight_options = {'default': {'encoding': 'utf-8'}}\n\n")
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
fw("exclude_patterns = [\n")
|
||||
fw(" 'include__bmesh.rst',\n")
|
||||
fw("]\n\n")
|
||||
|
||||
fw("html_title = 'Blender Python API'\n")
|
||||
|
||||
fw("html_theme = 'default'\n")
|
||||
# The theme 'sphinx_rtd_theme' is no longer distributed with sphinx by default, only use when available.
|
||||
fw(r"""
|
||||
try:
|
||||
import furo
|
||||
html_theme = "furo"
|
||||
del furo
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
if html_theme == "furo":
|
||||
html_theme_options = {
|
||||
"light_css_variables": {
|
||||
"color-brand-primary": "#265787",
|
||||
"color-brand-content": "#265787",
|
||||
},
|
||||
}
|
||||
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"sidebar/brand.html",
|
||||
"sidebar/search.html",
|
||||
"sidebar/scroll-start.html",
|
||||
"sidebar/navigation.html",
|
||||
"sidebar/scroll-end.html",
|
||||
# "sidebar/variant-selector.html",
|
||||
]
|
||||
}
|
||||
""")
|
||||
|
||||
# not helpful since the source is generated, adds to upload size.
|
||||
fw("html_copy_source = False\n")
|
||||
fw("html_show_sphinx = False\n")
|
||||
fw("html_baseurl = 'https://docs.blender.org/api/current/'\n")
|
||||
fw("html_use_opensearch = 'https://docs.blender.org/api/current'\n")
|
||||
fw("html_show_search_summary = True\n")
|
||||
fw("html_split_index = True\n")
|
||||
fw("html_static_path = ['static']\n")
|
||||
fw("templates_path = ['templates']\n")
|
||||
fw("html_context = {'commit': '%s - %s'}\n" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE))
|
||||
fw("html_extra_path = ['static/favicon.ico', 'static/blender_logo.svg']\n")
|
||||
fw("html_favicon = 'static/favicon.ico'\n")
|
||||
fw("html_logo = 'static/blender_logo.svg'\n")
|
||||
# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
|
||||
fw("html_last_updated_fmt = None\n\n")
|
||||
fw("if html_theme == 'furo':\n")
|
||||
fw(" html_css_files = ['css/version_switch.css']\n")
|
||||
fw(" html_js_files = ['js/version_switch.js']\n")
|
||||
|
||||
# needed for latex, pdf gen
|
||||
fw("latex_elements = {\n")
|
||||
fw(" 'papersize': 'a4paper',\n")
|
||||
fw("}\n\n")
|
||||
|
||||
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
|
||||
|
||||
# Workaround for useless links leading to compile errors
|
||||
# See https://github.com/sphinx-doc/sphinx/issues/3866
|
||||
fw(r"""
|
||||
from sphinx.domains.python import PythonDomain
|
||||
|
||||
class PatchedPythonDomain(PythonDomain):
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
if 'refspecific' in node:
|
||||
del node['refspecific']
|
||||
return super(PatchedPythonDomain, self).resolve_xref(
|
||||
env, fromdocname, builder, typ, target, node, contnode)
|
||||
""")
|
||||
# end workaround
|
||||
|
||||
fw("def setup(app):\n")
|
||||
fw(" app.add_css_file('css/theme_overrides.css')\n")
|
||||
fw(" app.add_domain(PatchedPythonDomain, override=True)\n\n")
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
def write_rst_index(basepath):
|
||||
"""
|
||||
Write the RST file of the main page, needed for sphinx: ``index.html``.
|
||||
|
@ -2239,7 +2119,6 @@ def write_rst_enum_items(basepath, key, key_no_prefix, enum_items):
|
|||
fw(".. _%s:\n\n" % key)
|
||||
|
||||
fw(title_string(key_no_prefix.replace("_", " ").title(), "#"))
|
||||
# fw(".. rubric:: %s\n\n" % key_no_prefix.replace("_", " ").title())
|
||||
|
||||
for item in enum_items:
|
||||
identifier = item.identifier
|
||||
|
@ -2414,7 +2293,7 @@ def copy_handwritten_extra(basepath):
|
|||
shutil.copy2(f_src, f_dst)
|
||||
|
||||
|
||||
def copy_theme_assets(basepath):
|
||||
def copy_sphinx_files(basepath):
|
||||
shutil.copytree(
|
||||
os.path.join(SCRIPT_DIR, "static"),
|
||||
os.path.join(basepath, "static"),
|
||||
|
@ -2426,17 +2305,38 @@ def copy_theme_assets(basepath):
|
|||
copy_function=shutil.copy,
|
||||
)
|
||||
|
||||
shutil.copy2(os.path.join(SCRIPT_DIR, "conf.py"), basepath, )
|
||||
|
||||
|
||||
def format_config(basepath):
|
||||
"""
|
||||
Updates ``conf.py`` with context information from Blender.
|
||||
"""
|
||||
from string import Template
|
||||
|
||||
# Ensure the string literals can contain any characters by closing the surrounding quotes
|
||||
# and declare a separate literal via `repr()`.
|
||||
def declare_in_quotes(string):
|
||||
return "\" %r \"" % (string)
|
||||
|
||||
substitutions = {
|
||||
"BLENDER_VERSION_STRING": declare_in_quotes(BLENDER_VERSION_STRING),
|
||||
"BLENDER_VERSION_DOTS": declare_in_quotes(BLENDER_VERSION_DOTS),
|
||||
"BLENDER_REVISION_TIMESTAMP": declare_in_quotes(str(BLENDER_REVISION_TIMESTAMP)),
|
||||
"BLENDER_REVISION": declare_in_quotes(BLENDER_REVISION),
|
||||
}
|
||||
|
||||
filepath = os.path.join(basepath, "conf.py")
|
||||
|
||||
# Read the template string from the template file.
|
||||
with open(filepath, 'r', encoding="utf-8") as fh:
|
||||
template_file = fh.read()
|
||||
|
||||
with open(filepath, 'w', encoding="utf-8") as fh:
|
||||
fh.write(Template(template_file).substitute(substitutions))
|
||||
|
||||
|
||||
def rna2sphinx(basepath):
|
||||
|
||||
try:
|
||||
os.mkdir(basepath)
|
||||
except:
|
||||
pass
|
||||
|
||||
# sphinx setup
|
||||
write_sphinx_conf_py(basepath)
|
||||
|
||||
# main page
|
||||
write_rst_index(basepath)
|
||||
|
||||
|
@ -2463,9 +2363,6 @@ def rna2sphinx(basepath):
|
|||
# copy source files referenced
|
||||
copy_handwritten_extra(basepath)
|
||||
|
||||
# copy extra files needed for theme
|
||||
copy_theme_assets(basepath)
|
||||
|
||||
|
||||
def align_sphinx_in_to_sphinx_in_tmp(dir_src, dir_dst):
|
||||
"""
|
||||
|
@ -2586,10 +2483,22 @@ def main():
|
|||
copy_function=shutil.copy,
|
||||
)
|
||||
|
||||
# Dump the API in RST files.
|
||||
# start from a clean directory everytime
|
||||
if os.path.exists(SPHINX_IN_TMP):
|
||||
shutil.rmtree(SPHINX_IN_TMP, True)
|
||||
|
||||
try:
|
||||
os.mkdir(SPHINX_IN_TMP)
|
||||
except:
|
||||
pass
|
||||
|
||||
# copy extra files needed for theme
|
||||
copy_sphinx_files(SPHINX_IN_TMP)
|
||||
|
||||
# write infromation needed for 'conf.py'
|
||||
format_config(SPHINX_IN_TMP)
|
||||
|
||||
# Dump the API in RST files.
|
||||
rna2sphinx(SPHINX_IN_TMP)
|
||||
|
||||
if ARGS.changelog:
|
||||
|
|
|
@ -67,10 +67,16 @@ dl dt {
|
|||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(80%, 95%);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
dl.field-list > dd > p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media (max-width: calc(67em / 2)) {
|
||||
dl.field-list {
|
||||
grid-template-columns: unset;
|
||||
}
|
||||
}
|
||||
|
||||
/* TABLE & FIGURE */
|
||||
|
@ -94,6 +100,12 @@ figcaption {
|
|||
}
|
||||
}
|
||||
|
||||
/* Allow horizontal lists to collapse on narrow screens */
|
||||
.hlist tr {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
/* End TABLE & FIGURE. */
|
||||
|
||||
/* Force admonition to span the full width if close to a figure */
|
||||
|
@ -141,6 +153,11 @@ a {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Break long code references onto a second line */
|
||||
a > code.docutils {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
/* Quotes for Fig. "link". */
|
||||
a[href^="#fig-"]::before {
|
||||
content: "\201c";
|
||||
|
|
|
@ -32,6 +32,7 @@ endif()
|
|||
add_subdirectory(rangetree)
|
||||
add_subdirectory(nanosvg)
|
||||
add_subdirectory(wcwidth)
|
||||
add_subdirectory(xxhash)
|
||||
|
||||
if(WITH_BULLET)
|
||||
if(NOT WITH_SYSTEM_BULLET)
|
||||
|
@ -104,10 +105,6 @@ if(WITH_MOD_FLUID)
|
|||
add_subdirectory(mantaflow)
|
||||
endif()
|
||||
|
||||
if(WITH_COMPOSITOR_CPU)
|
||||
add_subdirectory(smaa_areatex)
|
||||
endif()
|
||||
|
||||
if(WITH_VULKAN_BACKEND)
|
||||
add_subdirectory(vulkan_memory_allocator)
|
||||
endif()
|
||||
|
|
|
@ -124,13 +124,12 @@ void PulseAudioDevice::playing(bool playing)
|
|||
|
||||
AUD_pa_threaded_mainloop_lock(m_mainloop);
|
||||
AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
|
||||
if(!playing)
|
||||
{
|
||||
AUD_pa_stream_flush(m_stream, nullptr, nullptr);
|
||||
m_clear = true;
|
||||
}
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
}
|
||||
|
||||
PulseAudioDevice::PulseAudioDevice(const std::string &name, DeviceSpecs specs, int buffersize) :
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2017 Blender Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
add_executable(smaa_areatex smaa_areatex.cpp)
|
|
@ -1,5 +0,0 @@
|
|||
Project: smaa-cpp
|
||||
URL: https://github.com/iRi-E/smaa-cpp
|
||||
License: MIT
|
||||
Upstream version: 0.4.0
|
||||
Local modifications:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
PUBLIC .
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
xxhash.c
|
||||
xxhash.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
)
|
||||
|
||||
blender_add_lib(extern_xxhash "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
add_library(bf::extern::xxhash ALIAS extern_xxhash)
|
|
@ -0,0 +1,26 @@
|
|||
xxHash Library
|
||||
Copyright (c) 2012-2021 Yann Collet
|
||||
All rights reserved.
|
||||
|
||||
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,6 @@
|
|||
Project: xxHash
|
||||
URL: https://xxhash.com/
|
||||
License: BSD 2-Clause
|
||||
Upstream version: v0.8.2 (2023-07-21)
|
||||
Local modifications:
|
||||
* None
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* xxHash - Extremely Fast Hash algorithm
|
||||
* Copyright (C) 2012-2021 Yann Collet
|
||||
*
|
||||
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* You can contact the author at:
|
||||
* - xxHash homepage: https://www.xxhash.com
|
||||
* - xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* xxhash.c instantiates functions defined in xxhash.h
|
||||
*/
|
||||
|
||||
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
|
||||
#define XXH_IMPLEMENTATION /* access definitions */
|
||||
|
||||
#include "xxhash.h"
|
File diff suppressed because it is too large
Load Diff
|
@ -109,12 +109,12 @@ typedef struct CLG_LogRef {
|
|||
struct CLG_LogRef *next;
|
||||
} CLG_LogRef;
|
||||
|
||||
void CLG_log_str(CLG_LogType *lg,
|
||||
void CLG_log_str(const CLG_LogType *lg,
|
||||
enum CLG_Severity severity,
|
||||
const char *file_line,
|
||||
const char *fn,
|
||||
const char *message) _CLOG_ATTR_NONNULL(1, 3, 4, 5);
|
||||
void CLG_logf(CLG_LogType *lg,
|
||||
void CLG_logf(const CLG_LogType *lg,
|
||||
enum CLG_Severity severity,
|
||||
const char *file_line,
|
||||
const char *fn,
|
||||
|
@ -156,7 +156,7 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
|
|||
|
||||
#define CLOG_AT_SEVERITY(clg_ref, severity, verbose_level, ...) \
|
||||
{ \
|
||||
CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
|
||||
const CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
|
||||
if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || \
|
||||
(severity >= CLG_SEVERITY_WARN)) \
|
||||
{ \
|
||||
|
@ -167,7 +167,7 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
|
|||
|
||||
#define CLOG_STR_AT_SEVERITY(clg_ref, severity, verbose_level, str) \
|
||||
{ \
|
||||
CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
|
||||
const CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
|
||||
if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || \
|
||||
(severity >= CLG_SEVERITY_WARN)) \
|
||||
{ \
|
||||
|
|
|
@ -175,9 +175,8 @@ static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args)
|
|||
{
|
||||
/* Use limit because windows may use '-1' for a formatting error. */
|
||||
const uint len_max = 65535;
|
||||
uint len_avail = cstr->len_alloc - cstr->len;
|
||||
while (true) {
|
||||
uint len_avail = cstr->len_alloc - cstr->len;
|
||||
|
||||
va_list args_cpy;
|
||||
va_copy(args_cpy, args);
|
||||
int retval = vsnprintf(cstr->data + cstr->len, len_avail, fmt, args_cpy);
|
||||
|
@ -188,22 +187,23 @@ static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args)
|
|||
* message. */
|
||||
break;
|
||||
}
|
||||
else if ((uint)retval <= len_avail) {
|
||||
|
||||
if ((uint)retval <= len_avail) {
|
||||
/* Copy was successful. */
|
||||
cstr->len += (uint)retval;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* vsnprintf was not successful, due to lack of allocated space, retval contains expected
|
||||
* length of the formatted string, use it to allocate required amount of memory. */
|
||||
uint len_alloc = cstr->len + (uint)retval;
|
||||
if (len_alloc >= len_max) {
|
||||
/* Safe upper-limit, just in case... */
|
||||
break;
|
||||
}
|
||||
clg_str_reserve(cstr, len_alloc);
|
||||
len_avail = cstr->len_alloc - cstr->len;
|
||||
|
||||
/* `vsnprintf` was not successful, due to lack of allocated space, `retval` contains expected
|
||||
* length of the formatted string, use it to allocate required amount of memory. */
|
||||
uint len_alloc = cstr->len + (uint)retval;
|
||||
if (len_alloc >= len_max) {
|
||||
/* Safe upper-limit, just in case... */
|
||||
break;
|
||||
}
|
||||
|
||||
clg_str_reserve(cstr, len_alloc);
|
||||
len_avail = cstr->len_alloc - cstr->len;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,7 +429,7 @@ static void write_severity(CLogStringBuf *cstr, enum CLG_Severity severity, bool
|
|||
}
|
||||
}
|
||||
|
||||
static void write_type(CLogStringBuf *cstr, CLG_LogType *lg)
|
||||
static void write_type(CLogStringBuf *cstr, const CLG_LogType *lg)
|
||||
{
|
||||
clg_str_append(cstr, " (");
|
||||
clg_str_append(cstr, lg->identifier);
|
||||
|
@ -460,7 +460,7 @@ static void write_file_line_fn(CLogStringBuf *cstr,
|
|||
clg_str_append(cstr, ": ");
|
||||
}
|
||||
|
||||
void CLG_log_str(CLG_LogType *lg,
|
||||
void CLG_log_str(const CLG_LogType *lg,
|
||||
enum CLG_Severity severity,
|
||||
const char *file_line,
|
||||
const char *fn,
|
||||
|
@ -498,7 +498,7 @@ void CLG_log_str(CLG_LogType *lg,
|
|||
}
|
||||
}
|
||||
|
||||
void CLG_logf(CLG_LogType *lg,
|
||||
void CLG_logf(const CLG_LogType *lg,
|
||||
enum CLG_Severity severity,
|
||||
const char *file_line,
|
||||
const char *fn,
|
||||
|
|
|
@ -219,10 +219,6 @@ endif()
|
|||
|
||||
if(WITH_CYCLES_OSL)
|
||||
add_definitions(-DWITH_OSL)
|
||||
# osl 1.9.x
|
||||
add_definitions(-DOSL_STATIC_BUILD)
|
||||
# pre 1.9
|
||||
add_definitions(-DOSL_STATIC_LIBRARY)
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${OSL_INCLUDE_DIR}
|
||||
|
|
|
@ -142,6 +142,12 @@ if(WITH_OPENIMAGEDENOISE)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB
|
||||
${OSL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
add_dependencies(bf_intern_cycles bf_rna)
|
||||
|
|
|
@ -235,8 +235,8 @@ def enum_preview_denoiser(self, context):
|
|||
items = [
|
||||
('AUTO',
|
||||
"Automatic",
|
||||
("Use the fastest available denoiser for viewport rendering "
|
||||
"(OptiX if available, OpenImageDenoise otherwise)"),
|
||||
("Use GPU accelerated denoising if supported, for the best performance. "
|
||||
"Prefer OpenImageDenoise over OptiX"),
|
||||
0)]
|
||||
else:
|
||||
items = [('AUTO', "None", "Blender was compiled without a viewport denoiser", 0)]
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "GPU_context.h"
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_state.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_context.hh"
|
||||
#include "GPU_immediate.hh"
|
||||
#include "GPU_shader.hh"
|
||||
#include "GPU_state.hh"
|
||||
#include "GPU_texture.hh"
|
||||
|
||||
#include "RE_engine.h"
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "util/tbb.h"
|
||||
#include "util/types.h"
|
||||
|
||||
#include "GPU_state.h"
|
||||
#include "GPU_state.hh"
|
||||
|
||||
#ifdef WITH_OSL
|
||||
# include "scene/osl.h"
|
||||
|
|
|
@ -203,6 +203,13 @@ if(WITH_OPENIMAGEDENOISE)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB
|
||||
${OSL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
|
|
|
@ -124,7 +124,8 @@ class DeviceInfo {
|
|||
/* Multiple Devices with the same ID would be very bad. */
|
||||
assert(id != info.id ||
|
||||
(type == info.type && num == info.num && description == info.description));
|
||||
return id == info.id;
|
||||
return id == info.id && use_hardware_raytracing == info.use_hardware_raytracing &&
|
||||
kernel_optimization_level == info.kernel_optimization_level;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ struct ShaderCache {
|
|||
|
||||
friend ShaderCache *get_shader_cache(id<MTLDevice> mtlDevice);
|
||||
|
||||
void compile_thread_func(int thread_index);
|
||||
void compile_thread_func();
|
||||
|
||||
using PipelineCollection = std::vector<unique_ptr<MetalKernelPipeline>>;
|
||||
|
||||
|
@ -174,7 +174,7 @@ void ShaderCache::wait_for_all()
|
|||
}
|
||||
}
|
||||
|
||||
void ShaderCache::compile_thread_func(int /*thread_index*/)
|
||||
void ShaderCache::compile_thread_func()
|
||||
{
|
||||
while (running) {
|
||||
|
||||
|
@ -309,7 +309,7 @@ void ShaderCache::load_kernel(DeviceKernel device_kernel,
|
|||
|
||||
metal_printf("Spawning %d Cycles kernel compilation threads\n", max_mtlcompiler_threads);
|
||||
for (int i = 0; i < max_mtlcompiler_threads; i++) {
|
||||
compile_threads.push_back(std::thread([&] { compile_thread_func(i); }));
|
||||
compile_threads.push_back(std::thread([this] { this->compile_thread_func(); }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -773,8 +773,9 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
|
|||
size_t &kernel_local_size)
|
||||
{
|
||||
assert(queue);
|
||||
|
||||
const static size_t preferred_work_group_size_intersect_shading = 32;
|
||||
const static size_t preferred_work_group_size_intersect = 128;
|
||||
const static size_t preferred_work_group_size_shading = 256;
|
||||
const static size_t preferred_work_group_size_shading_simd8 = 64;
|
||||
/* Shader evaluation kernels seems to use some amount of shared memory, so better
|
||||
* to avoid usage of maximum work group sizes for them. */
|
||||
const static size_t preferred_work_group_size_shader_evaluation = 256;
|
||||
|
@ -783,6 +784,9 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
|
|||
const static size_t preferred_work_group_size_cryptomatte = 512;
|
||||
const static size_t preferred_work_group_size_default = 1024;
|
||||
|
||||
const sycl::device &device = reinterpret_cast<sycl::queue *>(queue)->get_device();
|
||||
const size_t max_work_group_size = device.get_info<sycl::info::device::max_work_group_size>();
|
||||
|
||||
size_t preferred_work_group_size = 0;
|
||||
switch (kernel) {
|
||||
case DEVICE_KERNEL_INTEGRATOR_INIT_FROM_CAMERA:
|
||||
|
@ -792,6 +796,9 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
|
|||
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK:
|
||||
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_DEDICATED_LIGHT:
|
||||
preferred_work_group_size = preferred_work_group_size_intersect;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE:
|
||||
|
@ -799,9 +806,13 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
|
|||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_DEDICATED_LIGHT:
|
||||
preferred_work_group_size = preferred_work_group_size_intersect_shading;
|
||||
break;
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_DEDICATED_LIGHT: {
|
||||
const bool device_is_simd8 =
|
||||
(device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) &&
|
||||
device.get_info<sycl::ext::intel::info::device::gpu_eu_simd_width>() == 8);
|
||||
preferred_work_group_size = (device_is_simd8) ? preferred_work_group_size_shading_simd8 :
|
||||
preferred_work_group_size_shading;
|
||||
} break;
|
||||
|
||||
case DEVICE_KERNEL_CRYPTOMATTE_POSTPROCESS:
|
||||
preferred_work_group_size = preferred_work_group_size_cryptomatte;
|
||||
|
@ -829,11 +840,7 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
|
|||
preferred_work_group_size = preferred_work_group_size_default;
|
||||
}
|
||||
|
||||
const size_t limit_work_group_size = reinterpret_cast<sycl::queue *>(queue)
|
||||
->get_device()
|
||||
.get_info<sycl::info::device::max_work_group_size>();
|
||||
|
||||
kernel_local_size = std::min(limit_work_group_size, preferred_work_group_size);
|
||||
kernel_local_size = std::min(max_work_group_size, preferred_work_group_size);
|
||||
|
||||
/* NOTE(@nsirgien): As for now non-uniform work-groups don't work on most oneAPI devices,
|
||||
* we extend work size to fit uniformity requirements. */
|
||||
|
|
|
@ -46,7 +46,7 @@ static const char *oidn_device_type_to_string(const OIDNDeviceType type)
|
|||
return "HIP";
|
||||
# endif
|
||||
|
||||
/* The Metal support was added in OIDN 2.2.*/
|
||||
/* The Metal support was added in OIDN 2.2. */
|
||||
# if (OIDN_VERSION_MAJOR > 2) || ((OIDN_VERSION_MAJOR == 2) && (OIDN_VERSION_MINOR >= 2))
|
||||
case OIDN_DEVICE_TYPE_METAL:
|
||||
return "METAL";
|
||||
|
|
|
@ -224,18 +224,24 @@ ccl_device void camera_sample_orthographic(KernelGlobals kg,
|
|||
|
||||
/* Panorama Camera */
|
||||
|
||||
ccl_device_inline float3 camera_panorama_direction(ccl_constant KernelCamera *cam,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
const ProjectionTransform rastertocamera = cam->rastertocamera;
|
||||
float3 Pcamera = transform_perspective(&rastertocamera, make_float3(x, y, 0.0f));
|
||||
return panorama_to_direction(cam, Pcamera.x, Pcamera.y);
|
||||
}
|
||||
|
||||
ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
|
||||
ccl_global const DecomposedTransform *cam_motion,
|
||||
const float2 raster,
|
||||
const float2 rand_lens,
|
||||
ccl_private Ray *ray)
|
||||
{
|
||||
ProjectionTransform rastertocamera = cam->rastertocamera;
|
||||
float3 Pcamera = transform_perspective(&rastertocamera, float2_to_float3(raster));
|
||||
|
||||
/* create ray form raster position */
|
||||
float3 P = zero_float3();
|
||||
float3 D = panorama_to_direction(cam, Pcamera.x, Pcamera.y);
|
||||
float3 D = camera_panorama_direction(cam, raster.x, raster.y);
|
||||
|
||||
/* indicates ray should not receive any light, outside of the lens */
|
||||
if (is_zero(D)) {
|
||||
|
@ -246,6 +252,11 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
|
|||
/* modify ray for depth of field */
|
||||
float aperturesize = cam->aperturesize;
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
/* keep pre-DoF value for differentials later */
|
||||
float3 Dcenter = D;
|
||||
#endif
|
||||
|
||||
if (aperturesize > 0.0f) {
|
||||
/* sample point on aperture */
|
||||
float2 lens_uv = camera_sample_aperture(cam, rand_lens) * aperturesize;
|
||||
|
@ -289,38 +300,32 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
|
|||
* because we don't want to be affected by depth of field. We compute
|
||||
* ray origin and direction for the center and two neighboring pixels
|
||||
* and simply take their differences. */
|
||||
float3 Pcenter = Pcamera;
|
||||
float3 Dcenter = panorama_to_direction(cam, Pcenter.x, Pcenter.y);
|
||||
float3 Dx = camera_panorama_direction(cam, raster.x + 1.0f, raster.y);
|
||||
float3 Dy = camera_panorama_direction(cam, raster.x, raster.y + 1.0f);
|
||||
|
||||
if (use_stereo) {
|
||||
float3 Pcenter = zero_float3();
|
||||
float3 Px = zero_float3();
|
||||
float3 Py = zero_float3();
|
||||
spherical_stereo_transform(cam, &Pcenter, &Dcenter);
|
||||
}
|
||||
Pcenter = transform_point(&cameratoworld, Pcenter);
|
||||
Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
|
||||
|
||||
float3 Px = transform_perspective(&rastertocamera, make_float3(raster.x + 1.0f, raster.y, 0.0f));
|
||||
float3 Dx = panorama_to_direction(cam, Px.x, Px.y);
|
||||
if (use_stereo) {
|
||||
spherical_stereo_transform(cam, &Px, &Dx);
|
||||
}
|
||||
Px = transform_point(&cameratoworld, Px);
|
||||
Dx = normalize(transform_direction(&cameratoworld, Dx));
|
||||
|
||||
differential3 dP, dD;
|
||||
dP.dx = Px - Pcenter;
|
||||
dD.dx = Dx - Dcenter;
|
||||
|
||||
float3 Py = transform_perspective(&rastertocamera, make_float3(raster.x, raster.y + 1.0f, 0.0f));
|
||||
float3 Dy = panorama_to_direction(cam, Py.x, Py.y);
|
||||
if (use_stereo) {
|
||||
spherical_stereo_transform(cam, &Py, &Dy);
|
||||
}
|
||||
Py = transform_point(&cameratoworld, Py);
|
||||
Dy = normalize(transform_direction(&cameratoworld, Dy));
|
||||
|
||||
dP.dy = Py - Pcenter;
|
||||
dD.dy = Dy - Dcenter;
|
||||
differential3 dP;
|
||||
Pcenter = transform_point(&cameratoworld, Pcenter);
|
||||
dP.dx = transform_point(&cameratoworld, Px) - Pcenter;
|
||||
dP.dy = transform_point(&cameratoworld, Py) - Pcenter;
|
||||
ray->dP = differential_make_compact(dP);
|
||||
}
|
||||
else {
|
||||
ray->dP = differential_zero_compact();
|
||||
}
|
||||
|
||||
differential3 dD;
|
||||
Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
|
||||
dD.dx = normalize(transform_direction(&cameratoworld, Dx)) - Dcenter;
|
||||
dD.dy = normalize(transform_direction(&cameratoworld, Dy)) - Dcenter;
|
||||
ray->dD = differential_make_compact(dD);
|
||||
ray->dP = differential_make_compact(dP);
|
||||
#endif
|
||||
|
||||
/* clipping */
|
||||
|
|
|
@ -18,7 +18,7 @@ typedef struct HuangHairExtra {
|
|||
/* Optional modulation factors. */
|
||||
float R, TT, TRT;
|
||||
|
||||
/* Local coordinate system. X is stored as `bsdf->N`.*/
|
||||
/* Local coordinate system. X is stored as `bsdf->N`. */
|
||||
float3 Y, Z;
|
||||
|
||||
/* Incident direction in local coordinate system. */
|
||||
|
|
|
@ -18,15 +18,20 @@ typedef struct ToonBsdf {
|
|||
|
||||
static_assert(sizeof(ShaderClosure) >= sizeof(ToonBsdf), "ToonBsdf is too large!");
|
||||
|
||||
ccl_device_inline int bsdf_toon_setup_common(ccl_private ToonBsdf *bsdf)
|
||||
{
|
||||
bsdf->size = clamp(bsdf->size, 1e-5f, 1.0f) * M_PI_2_F;
|
||||
bsdf->smooth = saturatef(bsdf->smooth) * M_PI_2_F;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
/* DIFFUSE TOON */
|
||||
|
||||
ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
|
||||
bsdf->size = saturatef(bsdf->size);
|
||||
bsdf->smooth = saturatef(bsdf->smooth);
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
return bsdf_toon_setup_common(bsdf);
|
||||
}
|
||||
|
||||
ccl_device float bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
|
||||
|
@ -57,19 +62,17 @@ ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc,
|
|||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size;
|
||||
float smooth = bsdf->smooth;
|
||||
float cosNO = dot(bsdf->N, wo);
|
||||
|
||||
if (cosNO >= 0.0f) {
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
float smooth = bsdf->smooth * M_PI_2_F;
|
||||
float angle = safe_acosf(fmaxf(cosNO, 0.0f));
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
|
||||
if (eval > 0.0f) {
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
if (angle < sample_angle) {
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
*pdf = M_1_2PI_F / one_minus_cos(sample_angle);
|
||||
return make_spectrum(*pdf * eval);
|
||||
}
|
||||
}
|
||||
|
@ -87,29 +90,22 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
|
|||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
float smooth = bsdf->smooth * M_PI_2_F;
|
||||
float max_angle = bsdf->size;
|
||||
float smooth = bsdf->smooth;
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
float angle = sample_angle * rand.x;
|
||||
|
||||
if (sample_angle > 0.0f) {
|
||||
float unused;
|
||||
*wo = sample_uniform_cone(bsdf->N, one_minus_cos(sample_angle), rand, &unused, pdf);
|
||||
float cosNO;
|
||||
*wo = sample_uniform_cone(bsdf->N, one_minus_cos(sample_angle), rand, &cosNO, pdf);
|
||||
|
||||
if (dot(Ng, *wo) > 0.0f) {
|
||||
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
|
||||
}
|
||||
else {
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
if (dot(Ng, *wo) > 0.0f) {
|
||||
float angle = acosf(cosNO);
|
||||
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
/* GLOSSY TOON */
|
||||
|
@ -117,10 +113,7 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
|
|||
ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
|
||||
bsdf->size = saturatef(bsdf->size);
|
||||
bsdf->smooth = saturatef(bsdf->smooth);
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
return bsdf_toon_setup_common(bsdf);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
|
||||
|
@ -129,8 +122,8 @@ ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
|
|||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
float smooth = bsdf->smooth * M_PI_2_F;
|
||||
float max_angle = bsdf->size;
|
||||
float smooth = bsdf->smooth;
|
||||
float cosNI = dot(bsdf->N, wi);
|
||||
float cosNO = dot(bsdf->N, wo);
|
||||
|
||||
|
@ -140,12 +133,13 @@ ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
|
|||
float cosRO = dot(R, wo);
|
||||
|
||||
float angle = safe_acosf(fmaxf(cosRO, 0.0f));
|
||||
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
return make_spectrum(*pdf * eval);
|
||||
if (angle < sample_angle) {
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
*pdf = M_1_2PI_F / one_minus_cos(sample_angle);
|
||||
return make_spectrum(*pdf * eval);
|
||||
}
|
||||
}
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
|
@ -160,8 +154,8 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
|||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
float smooth = bsdf->smooth * M_PI_2_F;
|
||||
float max_angle = bsdf->size;
|
||||
float smooth = bsdf->smooth;
|
||||
float cosNI = dot(bsdf->N, wi);
|
||||
|
||||
if (cosNI > 0) {
|
||||
|
@ -169,30 +163,21 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
|||
float3 R = (2 * cosNI) * bsdf->N - wi;
|
||||
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
float angle = sample_angle * rand.x;
|
||||
|
||||
float unused;
|
||||
*wo = sample_uniform_cone(R, one_minus_cos(sample_angle), rand, &unused, pdf);
|
||||
float cosRO;
|
||||
*wo = sample_uniform_cone(R, one_minus_cos(sample_angle), rand, &cosRO, pdf);
|
||||
|
||||
if (dot(Ng, *wo) > 0.0f) {
|
||||
float cosNO = dot(bsdf->N, *wo);
|
||||
|
||||
/* make sure the direction we chose is still in the right hemisphere */
|
||||
if (cosNO > 0) {
|
||||
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
/* make sure the direction we chose is still in the right hemisphere */
|
||||
if (dot(Ng, *wo) > 0.0f && dot(bsdf->N, *wo) > 0.0f) {
|
||||
float angle = acosf(cosRO);
|
||||
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
|
||||
return LABEL_GLOSSY | LABEL_REFLECT;
|
||||
}
|
||||
}
|
||||
|
||||
return LABEL_GLOSSY | LABEL_REFLECT;
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
#include "util/texture.h"
|
||||
#include "util/types.h"
|
||||
|
||||
/* On x86_64, versions of glibc < 2.16 have an issue where expf is
|
||||
* much slower than the double version. This was fixed in glibc 2.16.
|
||||
*/
|
||||
/* On x86_64, versions of GLIBC < 2.16 have an issue where `expf` is
|
||||
* much slower than the double version. This was fixed in GLIBC 2.16. */
|
||||
#if !defined(__KERNEL_GPU__) && defined(__x86_64__) && defined(__x86_64__) && \
|
||||
defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
|
||||
(__GLIBC__ <= 2 && __GLIBC_MINOR__ < 16)
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define ccl_global
|
||||
#define ccl_always_inline __attribute__((always_inline))
|
||||
#define ccl_device_inline inline
|
||||
#define ccl_noinline __attribute__((noinline))
|
||||
#define ccl_noinline
|
||||
#define ccl_inline_constant const constexpr
|
||||
#define ccl_device_constant static constexpr
|
||||
#define ccl_static_constexpr static constexpr
|
||||
|
|
|
@ -64,6 +64,11 @@ typedef struct VolumeShaderCoefficients {
|
|||
Spectrum emission;
|
||||
} VolumeShaderCoefficients;
|
||||
|
||||
typedef struct EquiangularCoefficients {
|
||||
float3 P;
|
||||
float2 t_range;
|
||||
} EquiangularCoefficients;
|
||||
|
||||
/* Evaluate shader to get extinction coefficient at P. */
|
||||
ccl_device_inline bool shadow_volume_shader_sample(KernelGlobals kg,
|
||||
IntegratorShadowState state,
|
||||
|
@ -264,18 +269,18 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg,
|
|||
# define VOLUME_SAMPLE_PDF_CUTOFF 1e-8f
|
||||
|
||||
ccl_device float volume_equiangular_sample(ccl_private const Ray *ccl_restrict ray,
|
||||
const float3 light_P,
|
||||
ccl_private const EquiangularCoefficients &coeffs,
|
||||
const float xi,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
const float tmin = ray->tmin;
|
||||
const float tmax = ray->tmax;
|
||||
const float delta = dot((light_P - ray->P), ray->D);
|
||||
const float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
|
||||
const float delta = dot((coeffs.P - ray->P), ray->D);
|
||||
const float D = safe_sqrtf(len_squared(coeffs.P - ray->P) - delta * delta);
|
||||
if (UNLIKELY(D == 0.0f)) {
|
||||
*pdf = 0.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
const float tmin = coeffs.t_range.x;
|
||||
const float tmax = coeffs.t_range.y;
|
||||
const float theta_a = atan2f(tmin - delta, D);
|
||||
const float theta_b = atan2f(tmax - delta, D);
|
||||
const float t_ = D * tanf((xi * theta_b) + (1 - xi) * theta_a);
|
||||
|
@ -289,17 +294,17 @@ ccl_device float volume_equiangular_sample(ccl_private const Ray *ccl_restrict r
|
|||
}
|
||||
|
||||
ccl_device float volume_equiangular_pdf(ccl_private const Ray *ccl_restrict ray,
|
||||
const float3 light_P,
|
||||
ccl_private const EquiangularCoefficients &coeffs,
|
||||
const float sample_t)
|
||||
{
|
||||
const float delta = dot((light_P - ray->P), ray->D);
|
||||
const float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
|
||||
const float delta = dot((coeffs.P - ray->P), ray->D);
|
||||
const float D = safe_sqrtf(len_squared(coeffs.P - ray->P) - delta * delta);
|
||||
if (UNLIKELY(D == 0.0f)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const float tmin = ray->tmin;
|
||||
const float tmax = ray->tmax;
|
||||
const float tmin = coeffs.t_range.x;
|
||||
const float tmax = coeffs.t_range.y;
|
||||
const float t_ = sample_t - delta;
|
||||
|
||||
const float theta_a = atan2f(tmin - delta, D);
|
||||
|
@ -313,6 +318,29 @@ ccl_device float volume_equiangular_pdf(ccl_private const Ray *ccl_restrict ray,
|
|||
return pdf;
|
||||
}
|
||||
|
||||
ccl_device_inline bool volume_equiangular_valid_ray_segment(KernelGlobals kg,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
ccl_private float2 *t_range,
|
||||
const ccl_private LightSample *ls)
|
||||
{
|
||||
if (ls->type == LIGHT_SPOT) {
|
||||
ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
|
||||
return spot_light_valid_ray_segment(klight, ray_P, ray_D, t_range);
|
||||
}
|
||||
if (ls->type == LIGHT_AREA) {
|
||||
ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
|
||||
return area_light_valid_ray_segment(&klight->area, ray_P - klight->co, ray_D, t_range);
|
||||
}
|
||||
if (ls->type == LIGHT_TRIANGLE) {
|
||||
return triangle_light_valid_ray_segment(kg, ray_P - ls->P, ray_D, t_range, ls);
|
||||
}
|
||||
|
||||
/* Point light, the whole range of the ray is visible. */
|
||||
kernel_assert(ls->type == LIGHT_POINT);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Distance sampling */
|
||||
|
||||
ccl_device float volume_distance_sample(float max_t,
|
||||
|
@ -403,7 +431,7 @@ typedef struct VolumeIntegrateState {
|
|||
ccl_device_forceinline void volume_integrate_step_scattering(
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private const Ray *ray,
|
||||
const float3 equiangular_light_P,
|
||||
ccl_private const EquiangularCoefficients &equiangular_coeffs,
|
||||
ccl_private const VolumeShaderCoefficients &ccl_restrict coeff,
|
||||
const Spectrum transmittance,
|
||||
ccl_private VolumeIntegrateState &ccl_restrict vstate,
|
||||
|
@ -474,7 +502,7 @@ ccl_device_forceinline void volume_integrate_step_scattering(
|
|||
|
||||
/* Multiple importance sampling. */
|
||||
if (vstate.use_mis) {
|
||||
const float equiangular_pdf = volume_equiangular_pdf(ray, equiangular_light_P, new_t);
|
||||
const float equiangular_pdf = volume_equiangular_pdf(ray, equiangular_coeffs, new_t);
|
||||
const float mis_weight = power_heuristic(vstate.distance_pdf * distance_pdf,
|
||||
equiangular_pdf);
|
||||
result.direct_throughput *= 2.0f * mis_weight;
|
||||
|
@ -509,7 +537,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
|||
ccl_global float *ccl_restrict render_buffer,
|
||||
const float object_step_size,
|
||||
const VolumeSampleMethod direct_sample_method,
|
||||
const float3 equiangular_light_P,
|
||||
ccl_private const EquiangularCoefficients &equiangular_coeffs,
|
||||
ccl_private VolumeIntegrateResult &result)
|
||||
{
|
||||
PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_INTEGRATE);
|
||||
|
@ -560,7 +588,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
|||
/* Equiangular sampling: compute distance and PDF in advance. */
|
||||
if (vstate.direct_sample_method == VOLUME_SAMPLE_EQUIANGULAR) {
|
||||
result.direct_t = volume_equiangular_sample(
|
||||
ray, equiangular_light_P, vstate.rscatter, &vstate.equiangular_pdf);
|
||||
ray, equiangular_coeffs, vstate.rscatter, &vstate.equiangular_pdf);
|
||||
}
|
||||
# ifdef __PATH_GUIDING__
|
||||
result.direct_sample_method = vstate.direct_sample_method;
|
||||
|
@ -614,7 +642,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
|||
|
||||
/* Scattering and absorption. */
|
||||
volume_integrate_step_scattering(
|
||||
sd, ray, equiangular_light_P, coeff, transmittance, vstate, result);
|
||||
sd, ray, equiangular_coeffs, coeff, transmittance, vstate, result);
|
||||
}
|
||||
else {
|
||||
/* Absorption only. */
|
||||
|
@ -673,7 +701,8 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
|
|||
ccl_private const Ray *ccl_restrict ray,
|
||||
ccl_private const ShaderData *ccl_restrict sd,
|
||||
ccl_private const RNGState *ccl_restrict rng_state,
|
||||
ccl_private float3 *ccl_restrict P)
|
||||
ccl_private EquiangularCoefficients *ccl_restrict equiangular_coeffs,
|
||||
ccl_private LightSample &ccl_restrict ls)
|
||||
{
|
||||
/* Test if there is a light or BSDF that needs direct light. */
|
||||
if (!kernel_data.integrator.use_direct_light) {
|
||||
|
@ -685,7 +714,6 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
|
|||
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
|
||||
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
|
||||
|
||||
LightSample ls ccl_optional_struct_init;
|
||||
if (!light_sample_from_volume_segment(kg,
|
||||
rand_light,
|
||||
sd->time,
|
||||
|
@ -708,9 +736,10 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
|
|||
return false;
|
||||
}
|
||||
|
||||
*P = ls.P;
|
||||
equiangular_coeffs->P = ls.P;
|
||||
|
||||
return true;
|
||||
return volume_equiangular_valid_ray_segment(
|
||||
kg, ray->P, ray->D, &equiangular_coeffs->t_range, &ls);
|
||||
}
|
||||
|
||||
/* Path tracing: sample point on light and evaluate light shader, then
|
||||
|
@ -725,41 +754,26 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
|||
# ifdef __PATH_GUIDING__
|
||||
ccl_private const Spectrum unlit_throughput,
|
||||
# endif
|
||||
ccl_private const Spectrum throughput)
|
||||
ccl_private const Spectrum throughput,
|
||||
ccl_private LightSample &ccl_restrict ls)
|
||||
{
|
||||
PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_DIRECT_LIGHT);
|
||||
|
||||
if (!kernel_data.integrator.use_direct_light) {
|
||||
if (!kernel_data.integrator.use_direct_light || ls.emitter_id == EMITTER_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sample position on the same light again, now from the shading point where we scattered.
|
||||
*
|
||||
* Note that this means we sample the light tree twice when equiangular sampling is used.
|
||||
* We could consider sampling the light tree just once and use the same light position again.
|
||||
*
|
||||
* This would make the PDFs for MIS weights more complicated due to having to account for
|
||||
* both distance/equiangular and direct/indirect light sampling, but could be more accurate.
|
||||
* Additionally we could end up behind the light or outside a spot light cone, which might
|
||||
* waste a sample. Though on the other hand it would be possible to prevent that with
|
||||
* equiangular sampling restricted to a smaller sub-segment where the light has influence. */
|
||||
LightSample ls ccl_optional_struct_init;
|
||||
/* Sample position on the same light again, now from the shading point where we scattered. */
|
||||
{
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
|
||||
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
|
||||
const float3 N = zero_float3();
|
||||
const int object_receiver = light_link_receiver_nee(kg, sd);
|
||||
const int shader_flags = SD_BSDF_HAS_TRANSMISSION;
|
||||
|
||||
if (!light_sample_from_position(kg,
|
||||
rng_state,
|
||||
rand_light,
|
||||
sd->time,
|
||||
P,
|
||||
zero_float3(),
|
||||
light_link_receiver_nee(kg, sd),
|
||||
SD_BSDF_HAS_TRANSMISSION,
|
||||
bounce,
|
||||
path_flag,
|
||||
&ls))
|
||||
if (!light_sample<false>(
|
||||
kg, rand_light, sd->time, P, N, object_receiver, shader_flags, bounce, path_flag, &ls))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -877,6 +891,7 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
|||
KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private const Ray *ray,
|
||||
ccl_private const RNGState *rng_state,
|
||||
ccl_private const ShaderVolumePhases *phases)
|
||||
{
|
||||
|
@ -929,6 +944,9 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
|||
INTEGRATOR_STATE_WRITE(state, ray, P) = sd->P;
|
||||
INTEGRATOR_STATE_WRITE(state, ray, D) = normalize(phase_wo);
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmin) = 0.0f;
|
||||
# ifdef __LIGHT_TREE__
|
||||
INTEGRATOR_STATE_WRITE(state, ray, previous_dt) = ray->tmax - ray->tmin;
|
||||
# endif
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX;
|
||||
# ifdef __RAY_DIFFERENTIALS__
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP);
|
||||
|
@ -957,7 +975,8 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
|||
|
||||
/* Update path state */
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = phase_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_origin_n) = zero_float3();
|
||||
const float3 previous_P = ray->P + ray->D * ray->tmin;
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_origin_n) = sd->P - previous_P;
|
||||
INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = fminf(
|
||||
unguided_phase_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
|
||||
|
||||
|
@ -989,11 +1008,15 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
|||
|
||||
/* Sample light ahead of volume stepping, for equiangular sampling. */
|
||||
/* TODO: distant lights are ignored now, but could instead use even distribution. */
|
||||
LightSample ls ccl_optional_struct_init;
|
||||
ls.emitter_id = EMITTER_NONE;
|
||||
const bool need_light_sample = !(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_TERMINATE);
|
||||
float3 equiangular_P = zero_float3();
|
||||
const bool have_equiangular_sample = need_light_sample &&
|
||||
integrate_volume_equiangular_sample_light(
|
||||
kg, state, ray, &sd, &rng_state, &equiangular_P);
|
||||
|
||||
EquiangularCoefficients equiangular_coeffs = {zero_float3(), make_float2(ray->tmin, ray->tmax)};
|
||||
|
||||
const bool have_equiangular_sample =
|
||||
need_light_sample && integrate_volume_equiangular_sample_light(
|
||||
kg, state, ray, &sd, &rng_state, &equiangular_coeffs, ls);
|
||||
|
||||
VolumeSampleMethod direct_sample_method = (have_equiangular_sample) ?
|
||||
volume_stack_sample_method(kg, state) :
|
||||
|
@ -1023,7 +1046,7 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
|||
render_buffer,
|
||||
step_size,
|
||||
direct_sample_method,
|
||||
equiangular_P,
|
||||
equiangular_coeffs,
|
||||
result);
|
||||
|
||||
/* Perform path termination. The intersect_closest will have already marked this path
|
||||
|
@ -1091,7 +1114,8 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
|||
# ifdef __PATH_GUIDING__
|
||||
unlit_throughput,
|
||||
# endif
|
||||
result.direct_throughput);
|
||||
result.direct_throughput,
|
||||
ls);
|
||||
}
|
||||
|
||||
/* Indirect light.
|
||||
|
@ -1130,7 +1154,7 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
|||
# endif
|
||||
# endif
|
||||
|
||||
if (integrate_volume_phase_scatter(kg, state, &sd, &rng_state, &result.indirect_phases)) {
|
||||
if (integrate_volume_phase_scatter(kg, state, &sd, ray, &rng_state, &result.indirect_phases)) {
|
||||
return VOLUME_PATH_SCATTERED;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -75,6 +75,9 @@ KERNEL_STRUCT_MEMBER(ray, float, tmax, KERNEL_FEATURE_PATH_TRACING)
|
|||
KERNEL_STRUCT_MEMBER(ray, float, time, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER(ray, float, dP, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER(ray, float, dD, KERNEL_FEATURE_PATH_TRACING)
|
||||
#ifdef __LIGHT_TREE__
|
||||
KERNEL_STRUCT_MEMBER(ray, float, previous_dt, KERNEL_FEATURE_PATH_TRACING)
|
||||
#endif
|
||||
KERNEL_STRUCT_END(ray)
|
||||
|
||||
/*************************** Intersection result ******************************/
|
||||
|
|
|
@ -233,6 +233,11 @@ ccl_device bool area_light_spread_clamp_light(const float3 P,
|
|||
return true;
|
||||
}
|
||||
|
||||
ccl_device_forceinline bool area_light_is_ellipse(const ccl_global KernelAreaLight *light)
|
||||
{
|
||||
return light->invarea < 0.0f;
|
||||
}
|
||||
|
||||
/* Common API. */
|
||||
/* Compute `eval_fac` and `pdf`. Also sample a new position on the light if `sample_coord`. */
|
||||
template<bool in_volume_segment>
|
||||
|
@ -338,7 +343,7 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
|
|||
const float light_v = dot(inplane, klight->area.axis_v) / klight->area.len_v;
|
||||
|
||||
if (!in_volume_segment) {
|
||||
const bool is_ellipse = (klight->area.invarea < 0.0f);
|
||||
const bool is_ellipse = area_light_is_ellipse(&klight->area);
|
||||
|
||||
/* Sampled point lies outside of the area light. */
|
||||
if (is_ellipse && (sqr(light_u) + sqr(light_v) > 0.25f)) {
|
||||
|
@ -380,7 +385,7 @@ ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight
|
|||
{
|
||||
/* Area light. */
|
||||
const float invarea = fabsf(klight->area.invarea);
|
||||
const bool is_ellipse = (klight->area.invarea < 0.0f);
|
||||
const bool is_ellipse = area_light_is_ellipse(&klight->area);
|
||||
if (invarea == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
@ -428,6 +433,55 @@ ccl_device_inline bool area_light_sample_from_intersection(
|
|||
return area_light_eval<false>(klight, ray_P, &light_P, ls, zero_float2(), false);
|
||||
}
|
||||
|
||||
/* Returns the maximal distance between the light center and the boundary. */
|
||||
ccl_device_forceinline float area_light_max_extent(const ccl_global KernelAreaLight *light)
|
||||
{
|
||||
return 0.5f * (area_light_is_ellipse(light) ? fmaxf(light->len_u, light->len_v) :
|
||||
len(make_float2(light->len_u, light->len_v)));
|
||||
}
|
||||
|
||||
/* Find the ray segment lit by the area light. */
|
||||
ccl_device_inline bool area_light_valid_ray_segment(const ccl_global KernelAreaLight *light,
|
||||
float3 P,
|
||||
float3 D,
|
||||
ccl_private float2 *t_range)
|
||||
{
|
||||
bool valid;
|
||||
const float tan_half_spread = light->tan_half_spread;
|
||||
float3 axis = light->dir;
|
||||
|
||||
const bool angle_almost_zero = (tan_half_spread < 1e-5f);
|
||||
if (angle_almost_zero) {
|
||||
/* Map to local coordinate of the light. Do not use `itfm` in `KernelLight` as there might be
|
||||
* additional scaling in the light size. */
|
||||
const Transform tfm = make_transform(light->axis_u, light->axis_v, axis);
|
||||
P = transform_point(&tfm, P);
|
||||
D = transform_direction(&tfm, D);
|
||||
axis = make_float3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
const float half_len_u = 0.5f * light->len_u;
|
||||
const float half_len_v = 0.5f * light->len_v;
|
||||
if (area_light_is_ellipse(light)) {
|
||||
valid = ray_infinite_cylinder_intersect(P, D, half_len_u, half_len_v, t_range);
|
||||
}
|
||||
else {
|
||||
const float3 bbox_min = make_float3(-half_len_u, -half_len_v, 0.0f);
|
||||
const float3 bbox_max = make_float3(half_len_u, half_len_v, FLT_MAX);
|
||||
valid = ray_aabb_intersect(bbox_min, bbox_max, P, D, t_range);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Conservative estimation with the smallest possible cone covering the whole spread. */
|
||||
const float3 apex_to_point = P + area_light_max_extent(light) / tan_half_spread * axis;
|
||||
const float cos_angle_sq = 1.0f / (1.0f + sqr(tan_half_spread));
|
||||
|
||||
valid = ray_cone_intersect(axis, apex_to_point, D, cos_angle_sq, t_range);
|
||||
}
|
||||
|
||||
/* Limit the range to the positive side of the area light. */
|
||||
return valid && ray_plane_intersect(axis, P, D, t_range);
|
||||
}
|
||||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLight *klight,
|
||||
const float3 centroid,
|
||||
|
@ -438,13 +492,11 @@ ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLi
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
if (!in_volume_segment) {
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it
|
||||
* worth the overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
}
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it worth the
|
||||
* overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
|
||||
cos_theta_u = FLT_MAX;
|
||||
|
||||
|
@ -464,9 +516,8 @@ ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLi
|
|||
const bool shape_above_surface = dot(N, centroid - P) + fabsf(dot(N, extentu)) +
|
||||
fabsf(dot(N, extentv)) >
|
||||
0;
|
||||
const bool in_volume = is_zero(N);
|
||||
|
||||
return (front_facing && shape_above_surface) || in_volume;
|
||||
return front_facing && shape_above_surface;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -12,9 +12,9 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
typedef struct LightSample {
|
||||
float3 P; /* position on light, or direction for distant light */
|
||||
float3 Ng; /* normal on light */
|
||||
float3 D; /* direction from shading point to light */
|
||||
packed_float3 Ng; /* normal on light */
|
||||
float t; /* distance to light (FLT_MAX for distant light) */
|
||||
float3 D; /* direction from shading point to light */
|
||||
float u, v; /* parametric coordinate on primitive */
|
||||
float pdf; /* pdf for selecting light and point on light */
|
||||
float pdf_selection; /* pdf for selecting light */
|
||||
|
@ -25,6 +25,7 @@ typedef struct LightSample {
|
|||
int lamp; /* lamp id */
|
||||
int group; /* lightgroup */
|
||||
LightType type; /* type of light */
|
||||
int emitter_id; /* index in the emitter array */
|
||||
} LightSample;
|
||||
|
||||
/* Utilities */
|
||||
|
|
|
@ -41,36 +41,14 @@ ccl_device int light_distribution_sample(KernelGlobals kg, const float rand)
|
|||
return index;
|
||||
}
|
||||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
|
||||
const float3 rand,
|
||||
const float time,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const int object_receiver,
|
||||
const int shader_flags,
|
||||
const int bounce,
|
||||
const uint32_t path_flag,
|
||||
const float rand,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
/* Sample light index from distribution. */
|
||||
/* The first two dimensions of the Sobol sequence have better stratification. */
|
||||
const int index = light_distribution_sample(kg, rand.z);
|
||||
const float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
|
||||
const float2 rand_uv = float3_to_float2(rand);
|
||||
return light_sample<in_volume_segment>(kg,
|
||||
rand_uv,
|
||||
time,
|
||||
P,
|
||||
N,
|
||||
object_receiver,
|
||||
shader_flags,
|
||||
bounce,
|
||||
path_flag,
|
||||
index,
|
||||
0,
|
||||
pdf_selection,
|
||||
ls);
|
||||
ls->emitter_id = light_distribution_sample(kg, rand);
|
||||
ls->pdf_selection = kernel_data.integrator.distribution_pdf_lights;
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg)
|
||||
|
|
|
@ -177,7 +177,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
|
|||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_noinline bool light_sample(KernelGlobals kg,
|
||||
const float2 rand,
|
||||
const float3 rand_light,
|
||||
const float time,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
|
@ -185,33 +185,31 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
|
|||
const int shader_flags,
|
||||
const int bounce,
|
||||
const uint32_t path_flag,
|
||||
const int emitter_index,
|
||||
const int object_id,
|
||||
const float pdf_selection,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
/* The first two dimensions of the Sobol sequence have better stratification, use them to sample
|
||||
* position on the light. */
|
||||
const float2 rand = float3_to_float2(rand_light);
|
||||
|
||||
int prim;
|
||||
MeshLight mesh_light;
|
||||
#ifdef __LIGHT_TREE__
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
|
||||
emitter_index);
|
||||
ls->emitter_id);
|
||||
prim = kemitter->light.id;
|
||||
mesh_light.shader_flag = kemitter->mesh_light.shader_flag;
|
||||
mesh_light.object_id = object_id;
|
||||
mesh_light.object_id = ls->object;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(
|
||||
light_distribution, emitter_index);
|
||||
light_distribution, ls->emitter_id);
|
||||
prim = kdistribution->prim;
|
||||
mesh_light = kdistribution->mesh_light;
|
||||
}
|
||||
|
||||
/* A different value would be assigned in `triangle_light_sample()` if `!use_light_tree`. */
|
||||
ls->pdf_selection = pdf_selection;
|
||||
|
||||
if (prim >= 0) {
|
||||
/* Mesh light. */
|
||||
const int object = mesh_light.object_id;
|
||||
|
|
|
@ -196,21 +196,22 @@ ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelL
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = min_distance * one_float2();
|
||||
|
||||
if (in_volume_segment) {
|
||||
cos_theta_u = 1.0f; /* Any value in [-1, 1], irrelevant since theta = 0 */
|
||||
return true;
|
||||
}
|
||||
|
||||
float dist_point_to_centroid;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &dist_point_to_centroid);
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
if (klight->spot.is_sphere) {
|
||||
if (dist_point_to_centroid > radius) {
|
||||
if (min_distance > radius) {
|
||||
/* Equivalent to a disk light with the same angular span. */
|
||||
cos_theta_u = cos_from_sin(radius / dist_point_to_centroid);
|
||||
distance = dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f);
|
||||
cos_theta_u = cos_from_sin(radius / min_distance);
|
||||
distance.x = min_distance / cos_theta_u;
|
||||
}
|
||||
else {
|
||||
/* Similar to background light. */
|
||||
|
@ -220,10 +221,10 @@ ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelL
|
|||
}
|
||||
}
|
||||
else {
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(dist_point_to_centroid));
|
||||
cos_theta_u = dist_point_to_centroid / hypotenus;
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
|
||||
cos_theta_u = min_distance / hypotenus;
|
||||
|
||||
distance = make_float2(hypotenus, dist_point_to_centroid);
|
||||
distance.x = hypotenus;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -329,17 +329,25 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
|
|||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
const int shader_flags = SD_BSDF_HAS_TRANSMISSION;
|
||||
|
||||
#ifdef __LIGHT_TREE__
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
return light_tree_sample<true>(
|
||||
kg, rand, time, P, D, t, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
|
||||
if (!light_tree_sample<true>(kg, rand.z, P, D, t, object_receiver, shader_flags, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return light_distribution_sample<true>(
|
||||
kg, rand, time, P, D, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
|
||||
if (!light_distribution_sample(kg, rand.z, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sample position on the selected light. */
|
||||
return light_sample<true>(
|
||||
kg, rand, time, P, D, object_receiver, shader_flags, bounce, path_flag, ls);
|
||||
}
|
||||
|
||||
ccl_device bool light_sample_from_position(KernelGlobals kg,
|
||||
|
@ -354,17 +362,24 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
|
|||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
/* Randomly select a light. */
|
||||
#ifdef __LIGHT_TREE__
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
return light_tree_sample<false>(
|
||||
kg, rand, time, P, N, 0.0f, object_receiver, shader_flags, bounce, path_flag, ls);
|
||||
if (!light_tree_sample<false>(kg, rand.z, P, N, 0.0f, object_receiver, shader_flags, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return light_distribution_sample<false>(
|
||||
kg, rand, time, P, N, object_receiver, shader_flags, bounce, path_flag, ls);
|
||||
if (!light_distribution_sample(kg, rand.z, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sample position on the selected light. */
|
||||
return light_sample<false>(
|
||||
kg, rand, time, P, N, object_receiver, shader_flags, bounce, path_flag, ls);
|
||||
}
|
||||
|
||||
/* Update light sample with new shading point position for MNEE. The position on the light is fixed
|
||||
|
@ -415,13 +430,15 @@ ccl_device_inline float light_sample_mis_weight_forward_surface(KernelGlobals kg
|
|||
#ifdef __LIGHT_TREE__
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
float3 ray_P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float dt = INTEGRATOR_STATE(state, ray, previous_dt);
|
||||
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
|
||||
|
||||
uint lookup_offset = kernel_data_fetch(object_lookup_offset, sd->object);
|
||||
uint prim_offset = kernel_data_fetch(object_prim_offset, sd->object);
|
||||
uint triangle = kernel_data_fetch(triangle_to_tree, sd->prim - prim_offset + lookup_offset);
|
||||
|
||||
pdf *= light_tree_pdf(
|
||||
kg, ray_P, N, path_flag, sd->object, triangle, light_link_receiver_forward(kg, state));
|
||||
kg, ray_P, N, dt, path_flag, sd->object, triangle, light_link_receiver_forward(kg, state));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -445,9 +462,11 @@ ccl_device_inline float light_sample_mis_weight_forward_lamp(KernelGlobals kg,
|
|||
#ifdef __LIGHT_TREE__
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
|
||||
const float dt = INTEGRATOR_STATE(state, ray, previous_dt);
|
||||
pdf *= light_tree_pdf(kg,
|
||||
P,
|
||||
N,
|
||||
dt,
|
||||
path_flag,
|
||||
0,
|
||||
kernel_data_fetch(light_to_tree, ls->lamp),
|
||||
|
@ -485,9 +504,10 @@ ccl_device_inline float light_sample_mis_weight_forward_background(KernelGlobals
|
|||
#ifdef __LIGHT_TREE__
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
|
||||
const float dt = INTEGRATOR_STATE(state, ray, previous_dt);
|
||||
uint light = kernel_data_fetch(light_to_tree, kernel_data.background.light_index);
|
||||
pdf *= light_tree_pdf(
|
||||
kg, ray_P, N, path_flag, 0, light, light_link_receiver_forward(kg, state));
|
||||
kg, ray_P, N, dt, path_flag, 0, light, light_link_receiver_forward(kg, state));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -265,6 +265,24 @@ ccl_device_inline bool spot_light_sample_from_intersection(
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Find the ray segment lit by the spot light. */
|
||||
ccl_device_inline bool spot_light_valid_ray_segment(const ccl_global KernelLight *klight,
|
||||
const float3 P,
|
||||
const float3 D,
|
||||
ccl_private float2 *t_range)
|
||||
{
|
||||
/* Convert to local space of the spot light. */
|
||||
const Transform itfm = klight->itfm;
|
||||
float3 local_P = P + klight->spot.dir * klight->spot.ray_segment_dp;
|
||||
local_P = transform_point(&itfm, local_P);
|
||||
const float3 local_D = transform_direction(&itfm, D);
|
||||
const float3 axis = make_float3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
/* Intersect the ray with the smallest enclosing cone of the light spread. */
|
||||
return ray_cone_intersect(
|
||||
axis, local_P, local_D, sqr(klight->spot.cos_half_spot_angle), t_range);
|
||||
}
|
||||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLight *klight,
|
||||
const float3 centroid,
|
||||
|
@ -273,35 +291,32 @@ ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLi
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
float dist_point_to_centroid;
|
||||
const float3 point_to_centroid_ = safe_normalize_len(centroid - P, &dist_point_to_centroid);
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = min_distance * one_float2();
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
if (klight->spot.is_sphere) {
|
||||
cos_theta_u = (dist_point_to_centroid > radius) ?
|
||||
cos_from_sin(radius / dist_point_to_centroid) :
|
||||
-1.0f;
|
||||
cos_theta_u = (min_distance > radius) ? cos_from_sin(radius / min_distance) : -1.0f;
|
||||
|
||||
if (in_volume_segment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
distance = (dist_point_to_centroid > radius) ?
|
||||
dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f) :
|
||||
one_float2() * radius / M_SQRT2_F;
|
||||
distance = (min_distance > radius) ? min_distance * make_float2(1.0f / cos_theta_u, 1.0f) :
|
||||
one_float2() * radius / M_SQRT2_F;
|
||||
}
|
||||
else {
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(dist_point_to_centroid));
|
||||
cos_theta_u = dist_point_to_centroid / hypotenus;
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
|
||||
cos_theta_u = min_distance / hypotenus;
|
||||
|
||||
if (in_volume_segment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
distance = make_float2(hypotenus, dist_point_to_centroid);
|
||||
distance.x = hypotenus;
|
||||
}
|
||||
point_to_centroid = point_to_centroid_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -148,10 +148,7 @@ ccl_device void light_tree_importance(const float3 N_or_D,
|
|||
float cos_min_incidence_angle = 1.0f;
|
||||
float cos_max_incidence_angle = 1.0f;
|
||||
|
||||
/* When sampling the light tree for the second time in `shade_volume.h` and when query the pdf in
|
||||
* `sample.h`. */
|
||||
const bool in_volume = is_zero(N_or_D);
|
||||
if (!in_volume_segment && !in_volume) {
|
||||
if (!in_volume_segment) {
|
||||
const float3 N = N_or_D;
|
||||
const float cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
|
||||
dot(point_to_centroid, N);
|
||||
|
@ -197,7 +194,7 @@ ccl_device void light_tree_importance(const float3 N_or_D,
|
|||
float cos_min_outgoing_angle;
|
||||
if ((cos_theta >= cos_theta_u) || (cos_theta_minus_theta_u >= cos_theta_o)) {
|
||||
/* theta - theta_o - theta_u <= 0 */
|
||||
kernel_assert((fast_acosf(cos_theta) - bcone.theta_o - fast_acosf(cos_theta_u)) < 5e-4f);
|
||||
kernel_assert((fast_acosf(cos_theta) - bcone.theta_o - fast_acosf(cos_theta_u)) < 1e-3f);
|
||||
cos_min_outgoing_angle = 1.0f;
|
||||
}
|
||||
else if ((bcone.theta_o + bcone.theta_e > M_PI_F) ||
|
||||
|
@ -221,9 +218,9 @@ ccl_device void light_tree_importance(const float3 N_or_D,
|
|||
max_importance = fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle /
|
||||
(in_volume_segment ? min_distance : sqr(min_distance)));
|
||||
|
||||
/* TODO: also min importance for volume? */
|
||||
/* TODO: compute proper min importance for volume. */
|
||||
if (in_volume_segment) {
|
||||
min_importance = max_importance;
|
||||
min_importance = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -270,10 +267,10 @@ ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg,
|
|||
/* Arbitrary centroid and direction. */
|
||||
centroid = make_float3(0.0f, 0.0f, 1.0f);
|
||||
dir = make_float3(0.0f, 0.0f, -1.0f);
|
||||
return !in_volume_segment;
|
||||
break;
|
||||
case LIGHT_DISTANT:
|
||||
dir = centroid;
|
||||
return !in_volume_segment;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -323,23 +320,27 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
|
|||
float cos_theta_u;
|
||||
float distance;
|
||||
if (knode->type == LIGHT_TREE_DISTANT) {
|
||||
if (in_volume_segment) {
|
||||
return;
|
||||
}
|
||||
point_to_centroid = -bcone.axis;
|
||||
cos_theta_u = fast_cosf(bcone.theta_o + bcone.theta_e);
|
||||
distance = 1.0f;
|
||||
if (t == FLT_MAX) {
|
||||
/* In world volume, distant light has no contribution. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const float3 centroid = 0.5f * (bbox.min + bbox.max);
|
||||
|
||||
if (in_volume_segment) {
|
||||
const float3 D = N_or_D;
|
||||
const float3 closest_point = P + dot(centroid - P, D) * D;
|
||||
const float closest_t = clamp(dot(centroid - P, D), 0.0f, t);
|
||||
const float3 closest_point = P + D * closest_t;
|
||||
/* Minimal distance of the ray to the cluster. */
|
||||
distance = len(centroid - closest_point);
|
||||
/* Vector that forms a minimal angle with the emitter centroid. */
|
||||
point_to_centroid = -compute_v(centroid, P, D, bcone.axis, t);
|
||||
cos_theta_u = light_tree_cos_bounding_box_angle(bbox, closest_point, point_to_centroid);
|
||||
cos_theta_u = light_tree_cos_bounding_box_angle(
|
||||
bbox, closest_point, normalize(centroid - closest_point));
|
||||
}
|
||||
else {
|
||||
const float3 N = N_or_D;
|
||||
|
@ -404,8 +405,8 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
bcone.theta_o = kemitter->theta_o;
|
||||
bcone.theta_e = kemitter->theta_e;
|
||||
float cos_theta_u;
|
||||
float2 distance; /* distance.x = max_distance, distance.y = mix_distance */
|
||||
float3 centroid, point_to_centroid, P_c;
|
||||
float2 distance; /* distance.x = max_distance, distance.y = min_distance */
|
||||
float3 centroid, point_to_centroid, P_c = P;
|
||||
|
||||
if (!compute_emitter_centroid_and_dir<in_volume_segment>(kg, kemitter, P, centroid, bcone.axis))
|
||||
{
|
||||
|
@ -414,15 +415,9 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
|
||||
if (in_volume_segment) {
|
||||
const float3 D = N_or_D;
|
||||
/* Closest point. */
|
||||
P_c = P + dot(centroid - P, D) * D;
|
||||
/* Minimal distance of the ray to the cluster. */
|
||||
distance.x = len(centroid - P_c);
|
||||
distance.y = distance.x;
|
||||
point_to_centroid = -compute_v(centroid, P, D, bcone.axis, t);
|
||||
}
|
||||
else {
|
||||
P_c = P;
|
||||
/* Closest point from ray to the emitter centroid. */
|
||||
const float closest_t = clamp(dot(centroid - P, D), 0.0f, t);
|
||||
P_c += D * closest_t;
|
||||
}
|
||||
|
||||
/* Early out if the emitter is guaranteed to be invisible. */
|
||||
|
@ -456,6 +451,9 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
case LIGHT_DISTANT:
|
||||
is_visible = distant_light_tree_parameters(
|
||||
centroid, bcone.theta_e, cos_theta_u, distance, point_to_centroid);
|
||||
if (in_volume_segment) {
|
||||
centroid = P - bcone.axis;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -467,6 +465,11 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
return;
|
||||
}
|
||||
|
||||
if (in_volume_segment) {
|
||||
/* Vector that forms a minimal angle with the emitter centroid. */
|
||||
point_to_centroid = -compute_v(centroid, P, N_or_D, bcone.axis, t);
|
||||
}
|
||||
|
||||
light_tree_importance<in_volume_segment>(N_or_D,
|
||||
has_transmission,
|
||||
point_to_centroid,
|
||||
|
@ -697,17 +700,16 @@ ccl_device int light_tree_root_node_index(KernelGlobals kg, const int object_rec
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Pick a random light from the light tree from a given shading point P, write to the picked light
|
||||
* index and the probability of picking the light. */
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
|
||||
const float3 rand,
|
||||
const float time,
|
||||
const float rand,
|
||||
const float3 P,
|
||||
float3 N_or_D,
|
||||
float t,
|
||||
const int object_receiver,
|
||||
const int shader_flags,
|
||||
const int bounce,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
if (!kernel_data.integrator.use_direct_light) {
|
||||
|
@ -718,10 +720,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
|
|||
float pdf_leaf = 1.0f;
|
||||
float pdf_selection = 1.0f;
|
||||
int selected_emitter = -1;
|
||||
int object_emitter = 0;
|
||||
int node_index = light_tree_root_node_index(kg, object_receiver);
|
||||
/* The first two dimensions of the Sobol sequence have better stratification. */
|
||||
float rand_selection = rand.z;
|
||||
float rand_selection = rand;
|
||||
|
||||
float3 local_P = P;
|
||||
|
||||
|
@ -743,7 +743,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* Continue with the picked mesh light. */
|
||||
object_emitter = kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
|
||||
ls->object = kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -766,27 +766,18 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
|
|||
pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
|
||||
}
|
||||
|
||||
pdf_selection *= pdf_leaf;
|
||||
ls->emitter_id = selected_emitter;
|
||||
ls->pdf_selection = pdf_selection * pdf_leaf;
|
||||
|
||||
return light_sample<in_volume_segment>(kg,
|
||||
float3_to_float2(rand),
|
||||
time,
|
||||
P,
|
||||
N_or_D,
|
||||
object_receiver,
|
||||
shader_flags,
|
||||
bounce,
|
||||
path_flag,
|
||||
selected_emitter,
|
||||
object_emitter,
|
||||
pdf_selection,
|
||||
ls);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We need to be able to find the probability of selecting a given light for MIS. */
|
||||
template<bool in_volume_segment>
|
||||
ccl_device float light_tree_pdf(KernelGlobals kg,
|
||||
float3 P,
|
||||
float3 N,
|
||||
const float dt,
|
||||
const int path_flag,
|
||||
const int object_emitter,
|
||||
const uint index_emitter,
|
||||
|
@ -796,7 +787,7 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
|
|||
|
||||
ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
|
||||
index_emitter);
|
||||
int root_index;
|
||||
int subtree_root_index;
|
||||
uint bit_trail, target_emitter;
|
||||
|
||||
if (is_triangle(kemitter)) {
|
||||
|
@ -805,16 +796,17 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
|
|||
target_emitter = kernel_data_fetch(object_to_tree, object_emitter);
|
||||
ccl_global const KernelLightTreeEmitter *kmesh = &kernel_data_fetch(light_tree_emitters,
|
||||
target_emitter);
|
||||
root_index = kmesh->mesh.node_id;
|
||||
ccl_global const KernelLightTreeNode *kroot = &kernel_data_fetch(light_tree_nodes, root_index);
|
||||
subtree_root_index = kmesh->mesh.node_id;
|
||||
ccl_global const KernelLightTreeNode *kroot = &kernel_data_fetch(light_tree_nodes,
|
||||
subtree_root_index);
|
||||
bit_trail = kroot->bit_trail;
|
||||
|
||||
if (kroot->type == LIGHT_TREE_INSTANCE) {
|
||||
root_index = kroot->instance.reference;
|
||||
subtree_root_index = kroot->instance.reference;
|
||||
}
|
||||
}
|
||||
else {
|
||||
root_index = 0;
|
||||
subtree_root_index = -1;
|
||||
bit_trail = kemitter->bit_trail;
|
||||
target_emitter = index_emitter;
|
||||
}
|
||||
|
@ -836,8 +828,8 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
|
|||
for (int i = 0; i < knode->num_emitters; i++) {
|
||||
const int emitter = knode->leaf.first_emitter + i;
|
||||
float max_importance, min_importance;
|
||||
light_tree_emitter_importance<false>(
|
||||
kg, P, N, 0, has_transmission, emitter, max_importance, min_importance);
|
||||
light_tree_emitter_importance<in_volume_segment>(
|
||||
kg, P, N, dt, has_transmission, emitter, max_importance, min_importance);
|
||||
num_has_importance += (max_importance > 0);
|
||||
if (emitter == target_emitter) {
|
||||
target_max_importance = max_importance;
|
||||
|
@ -856,13 +848,13 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
if (root_index) {
|
||||
if (subtree_root_index != -1) {
|
||||
/* Arrived at the mesh light. Continue with the subtree. */
|
||||
float unused;
|
||||
light_tree_to_local_space<false>(kg, object_emitter, P, N, unused);
|
||||
light_tree_to_local_space<in_volume_segment>(kg, object_emitter, P, N, unused);
|
||||
|
||||
node_index = root_index;
|
||||
root_index = 0;
|
||||
node_index = subtree_root_index;
|
||||
subtree_root_index = -1;
|
||||
target_emitter = index_emitter;
|
||||
bit_trail = kemitter->bit_trail;
|
||||
continue;
|
||||
|
@ -877,8 +869,8 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
|
|||
const int right_index = knode->inner.right_child;
|
||||
|
||||
float left_prob;
|
||||
if (!get_left_probability<false>(
|
||||
kg, P, N, 0, has_transmission, left_index, right_index, left_prob))
|
||||
if (!get_left_probability<in_volume_segment>(
|
||||
kg, P, N, dt, has_transmission, left_index, right_index, left_prob))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
@ -896,4 +888,27 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
/* If the function is called in volume, retrieve the previous point in volume segment, and compute
|
||||
* pdf from there. Otherwise compute from the current shading point. */
|
||||
ccl_device_inline float light_tree_pdf(KernelGlobals kg,
|
||||
float3 P,
|
||||
float3 N,
|
||||
const float dt,
|
||||
const int path_flag,
|
||||
const int emitter_object,
|
||||
const uint emitter_id,
|
||||
const int object_receiver)
|
||||
{
|
||||
if (path_flag & PATH_RAY_VOLUME_SCATTER) {
|
||||
const float3 D_times_t = N;
|
||||
const float3 D = normalize(D_times_t);
|
||||
P = P - D_times_t;
|
||||
return light_tree_pdf<true>(
|
||||
kg, P, D, dt, path_flag, emitter_object, emitter_id, object_receiver);
|
||||
}
|
||||
|
||||
return light_tree_pdf<false>(
|
||||
kg, P, N, 0.0f, path_flag, emitter_object, emitter_id, object_receiver);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -269,6 +269,26 @@ ccl_device_forceinline bool triangle_light_sample(KernelGlobals kg,
|
|||
return (ls->pdf > 0.0f);
|
||||
}
|
||||
|
||||
/* Find the ray segment lit by the triangle light. */
|
||||
ccl_device_inline bool triangle_light_valid_ray_segment(KernelGlobals kg,
|
||||
const float3 P,
|
||||
const float3 D,
|
||||
ccl_private float2 *t_range,
|
||||
const ccl_private LightSample *ls)
|
||||
{
|
||||
const int shader_flag = kernel_data_fetch(shaders, ls->shader & SHADER_MASK).flags;
|
||||
const int SD_MIS_BOTH = SD_MIS_BACK | SD_MIS_FRONT;
|
||||
if ((shader_flag & SD_MIS_BOTH) == SD_MIS_BOTH) {
|
||||
/* Both sides are sampled, the complete ray segment is visible. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Only one side is sampled, intersect the ray and the triangle light plane to find the visible
|
||||
* ray segment. Flip normal if Emission Sampling is set to back. */
|
||||
const float3 N = ls->Ng;
|
||||
return ray_plane_intersect((shader_flag & SD_MIS_BACK) ? -N : N, P, D, t_range);
|
||||
}
|
||||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_forceinline bool triangle_light_tree_parameters(
|
||||
KernelGlobals kg,
|
||||
|
@ -281,13 +301,11 @@ ccl_device_forceinline bool triangle_light_tree_parameters(
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
if (!in_volume_segment) {
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it
|
||||
* worth the overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
}
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it worth the
|
||||
* overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
|
||||
cos_theta_u = FLT_MAX;
|
||||
|
||||
|
@ -307,9 +325,8 @@ ccl_device_forceinline bool triangle_light_tree_parameters(
|
|||
}
|
||||
|
||||
const bool front_facing = bcone.theta_o != 0.0f || dot(bcone.axis, point_to_centroid) < 0;
|
||||
const bool in_volume = is_zero(N);
|
||||
|
||||
return (front_facing && shape_above_surface) || in_volume;
|
||||
return front_facing && shape_above_surface;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -7,76 +7,82 @@
|
|||
|
||||
#define vector3 point
|
||||
|
||||
float safe_noise(float p)
|
||||
float safe_noise(float co)
|
||||
{
|
||||
float f = noise("noise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
float p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", p);
|
||||
}
|
||||
|
||||
float safe_noise(vector2 p)
|
||||
float safe_noise(vector2 co)
|
||||
{
|
||||
float f = noise("noise", p.x, p.y);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector2 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", p.x, p.y);
|
||||
}
|
||||
|
||||
float safe_noise(vector3 p)
|
||||
float safe_noise(vector3 co)
|
||||
{
|
||||
float f = noise("noise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector3 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", p);
|
||||
}
|
||||
|
||||
float safe_noise(vector4 p)
|
||||
float safe_noise(vector4 co)
|
||||
{
|
||||
float f = noise("noise", vector3(p.x, p.y, p.z), p.w);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector4 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", vector3(p.x, p.y, p.z), p.w);
|
||||
}
|
||||
|
||||
float safe_snoise(float p)
|
||||
float safe_snoise(float co)
|
||||
{
|
||||
float f = noise("snoise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
float p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", p);
|
||||
}
|
||||
|
||||
float safe_snoise(vector2 p)
|
||||
float safe_snoise(vector2 co)
|
||||
{
|
||||
float f = noise("snoise", p.x, p.y);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector2 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", p.x, p.y);
|
||||
}
|
||||
|
||||
float safe_snoise(vector3 p)
|
||||
float safe_snoise(vector3 co)
|
||||
{
|
||||
float f = noise("snoise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector3 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", p);
|
||||
}
|
||||
|
||||
float safe_snoise(vector4 p)
|
||||
float safe_snoise(vector4 co)
|
||||
{
|
||||
float f = noise("snoise", vector3(p.x, p.y, p.z), p.w);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector4 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", vector3(p.x, p.y, p.z), p.w);
|
||||
}
|
||||
|
||||
#define NOISE_FBM(T) \
|
||||
|
|
|
@ -684,7 +684,12 @@ ccl_device_inline float noise_scale4(float result)
|
|||
|
||||
ccl_device_inline float snoise_1d(float p)
|
||||
{
|
||||
return noise_scale1(ensure_finite(perlin_1d(p)));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
/* The 1D variant of fmod is called fmodf. */
|
||||
p = fmodf(p, 100000.0f);
|
||||
|
||||
return noise_scale1(perlin_1d(p));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_1d(float p)
|
||||
|
@ -694,7 +699,12 @@ ccl_device_inline float noise_1d(float p)
|
|||
|
||||
ccl_device_inline float snoise_2d(float2 p)
|
||||
{
|
||||
return noise_scale2(ensure_finite(perlin_2d(p.x, p.y)));
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
p = fmod(p, 100000.0f);
|
||||
|
||||
return noise_scale2(perlin_2d(p.x, p.y));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_2d(float2 p)
|
||||
|
@ -704,7 +714,12 @@ ccl_device_inline float noise_2d(float2 p)
|
|||
|
||||
ccl_device_inline float snoise_3d(float3 p)
|
||||
{
|
||||
return noise_scale3(ensure_finite(perlin_3d(p.x, p.y, p.z)));
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
p = fmod(p, 100000.0f);
|
||||
|
||||
return noise_scale3(perlin_3d(p.x, p.y, p.z));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_3d(float3 p)
|
||||
|
@ -714,7 +729,12 @@ ccl_device_inline float noise_3d(float3 p)
|
|||
|
||||
ccl_device_inline float snoise_4d(float4 p)
|
||||
{
|
||||
return noise_scale4(ensure_finite(perlin_4d(p.x, p.y, p.z, p.w)));
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
p = fmod(p, 100000.0f);
|
||||
|
||||
return noise_scale4(perlin_4d(p.x, p.y, p.z, p.w));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_4d(float4 p)
|
||||
|
|
|
@ -45,6 +45,7 @@ CCL_NAMESPACE_BEGIN
|
|||
#define OBJECT_NONE (~0)
|
||||
#define PRIM_NONE (~0)
|
||||
#define LAMP_NONE (~0)
|
||||
#define EMITTER_NONE (~0)
|
||||
#define ID_NONE (0.0f)
|
||||
#define PASS_UNUSED (~0)
|
||||
#define LIGHTGROUP_NONE (~0)
|
||||
|
@ -1376,6 +1377,8 @@ typedef struct KernelSpotLight {
|
|||
int is_sphere;
|
||||
/* For non-uniform object scaling, the actual spread might be different. */
|
||||
float cos_half_larger_spread;
|
||||
/* Distance from the apex of the smallest enclosing cone of the light spread to light center. */
|
||||
float ray_segment_dp;
|
||||
} KernelSpotLight;
|
||||
|
||||
/* PointLight is SpotLight with only radius and invarea being used. */
|
||||
|
|
|
@ -107,6 +107,7 @@ endif()
|
|||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB
|
||||
cycles_kernel_osl
|
||||
${OSL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -903,14 +903,14 @@ static void background_cdf(
|
|||
for (int i = start; i < end; i++) {
|
||||
float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
|
||||
float3 env_color = (*pixels)[i * res_x];
|
||||
float ave_luminance = average(env_color);
|
||||
float ave_luminance = average(fabs(env_color));
|
||||
|
||||
cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
|
||||
cond_cdf[i * cdf_width].y = 0.0f;
|
||||
|
||||
for (int j = 1; j < res_x; j++) {
|
||||
env_color = (*pixels)[i * res_x + j];
|
||||
ave_luminance = average(env_color);
|
||||
ave_luminance = average(fabs(env_color));
|
||||
|
||||
cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
|
||||
cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y +
|
||||
|
@ -1362,6 +1362,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
/* Choose the angle which spans a larger cone. */
|
||||
klights[light_index].spot.cos_half_larger_spread = inversesqrtf(
|
||||
1.0f + tan_sq * fmaxf(len_u_sq, len_v_sq) / len_w_sq);
|
||||
/* radius / sin(half_angle_small) */
|
||||
klights[light_index].spot.ray_segment_dp =
|
||||
light->size * sqrtf(1.0f + len_w_sq / (tan_sq * fminf(len_u_sq, len_v_sq)));
|
||||
}
|
||||
|
||||
klights[light_index].shader_id = shader_id;
|
||||
|
|
|
@ -39,7 +39,7 @@ static std::atomic<uint64_t> g_instance_index = 0;
|
|||
/* Construct names of EXR channels which will ensure order of all channels to match exact offsets
|
||||
* in render buffers corresponding to the given passes.
|
||||
*
|
||||
* Returns `std` datatypes so that it can be assigned directly to the OIIO's `ImageSpec`. */
|
||||
* Returns `std` data-types so that it can be assigned directly to the OIIO's `ImageSpec`. */
|
||||
static std::vector<std::string> exr_channel_names_for_passes(const BufferParams &buffer_params)
|
||||
{
|
||||
static const char *component_suffixes[] = {"R", "G", "B", "A"};
|
||||
|
|
|
@ -275,8 +275,8 @@ ccl_device_inline float4 improve_5throot_solution_sse2(const float4 &old_result,
|
|||
/* Calculate powf(x, 2.4). Working domain: 1e-10 < x < 1e+10 */
|
||||
ccl_device_inline float4 fastpow24_sse2(const float4 &arg)
|
||||
{
|
||||
/* max, avg and |avg| errors were calculated in gcc without FMA instructions
|
||||
* The final precision should be better than powf in glibc */
|
||||
/* `max`, `avg` and |avg| errors were calculated in GCC without FMA instructions.
|
||||
* The final precision should be better than `powf` in GLIBC. */
|
||||
|
||||
/* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize avg error */
|
||||
/* 0x3F4CCCCD = 4/5 */
|
||||
|
|
|
@ -1030,6 +1030,46 @@ ccl_device_inline uint32_t reverse_integer_bits(uint32_t x)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Check if intervals (first->x, first->y) and (second.x, second.y) intersect, and replace the
|
||||
* first interval with their intersection. */
|
||||
ccl_device_inline bool intervals_intersect(ccl_private float2 *first, const float2 second)
|
||||
{
|
||||
first->x = fmaxf(first->x, second.x);
|
||||
first->y = fminf(first->y, second.y);
|
||||
|
||||
return first->x < first->y;
|
||||
}
|
||||
|
||||
/* Solve quadratic equation a*x^2 + b*x + c = 0, adapted from Mitsuba 3
|
||||
* The solution is ordered so that x1 <= x2.
|
||||
* Returns true if at least one solution is found. */
|
||||
ccl_device_inline bool solve_quadratic(
|
||||
const float a, const float b, const float c, ccl_private float &x1, ccl_private float &x2)
|
||||
{
|
||||
/* If the equation is linear, the solution is -c/b, but b has to be non-zero. */
|
||||
const bool valid_linear = (a == 0.0f) && (b != 0.0f);
|
||||
x1 = x2 = -c / b;
|
||||
|
||||
const float discriminant = sqr(b) - 4.0f * a * c;
|
||||
/* Allow slightly negative discriminant in case of numerical precision issues. */
|
||||
const bool valid_quadratic = (a != 0.0f) && (discriminant > -1e-5f);
|
||||
|
||||
if (valid_quadratic) {
|
||||
/* Numerically stable version of (-b ± sqrt(discriminant)) / (2 * a), avoiding catastrophic
|
||||
* cancellation when `b` is very close to `sqrt(discriminant)`, by finding the solution of
|
||||
* greater magnitude which does not suffer from loss of precision, then using the identity
|
||||
* x1 * x2 = c / a. */
|
||||
const float temp = -0.5f * (b + copysignf(safe_sqrtf(discriminant), b));
|
||||
const float r1 = temp / a;
|
||||
const float r2 = c / temp;
|
||||
|
||||
x1 = fminf(r1, r2);
|
||||
x2 = fmaxf(r1, r2);
|
||||
}
|
||||
|
||||
return (valid_linear || valid_quadratic);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __UTIL_MATH_H__ */
|
||||
|
|
|
@ -198,6 +198,11 @@ ccl_device_inline float2 clamp(const float2 a, const float2 mn, const float2 mx)
|
|||
return min(max(a, mn), mx);
|
||||
}
|
||||
|
||||
ccl_device_inline float2 fmod(const float2 a, const float b)
|
||||
{
|
||||
return make_float2(fmodf(a.x, b), fmodf(a.y, b));
|
||||
}
|
||||
|
||||
ccl_device_inline float2 fabs(const float2 a)
|
||||
{
|
||||
return make_float2(fabsf(a.x), fabsf(a.y));
|
||||
|
|
|
@ -309,6 +309,11 @@ ccl_device_inline float3 fabs(const float3 a)
|
|||
# endif
|
||||
}
|
||||
|
||||
ccl_device_inline float3 fmod(const float3 a, const float b)
|
||||
{
|
||||
return make_float3(fmodf(a.x, b), fmodf(a.y, b), fmodf(a.z, b));
|
||||
}
|
||||
|
||||
ccl_device_inline float3 sqrt(const float3 a)
|
||||
{
|
||||
# ifdef __KERNEL_SSE__
|
||||
|
|
|
@ -465,6 +465,11 @@ ccl_device_inline float4 fabs(const float4 a)
|
|||
# endif
|
||||
}
|
||||
|
||||
ccl_device_inline float4 fmod(const float4 a, const float b)
|
||||
{
|
||||
return make_float4(fmodf(a.x, b), fmodf(a.y, b), fmodf(a.z, b), fmodf(a.w, b));
|
||||
}
|
||||
|
||||
ccl_device_inline float4 floor(const float4 a)
|
||||
{
|
||||
# ifdef __KERNEL_SSE__
|
||||
|
|
|
@ -302,6 +302,140 @@ ccl_device bool ray_quad_intersect(float3 ray_P,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Find the ray segment that lies in the same side as the normal `N` of the plane.
|
||||
* `P` is the vector pointing from any point on the plane to the ray origin. */
|
||||
ccl_device bool ray_plane_intersect(const float3 N,
|
||||
const float3 P,
|
||||
const float3 ray_D,
|
||||
ccl_private float2 *t_range)
|
||||
{
|
||||
const float DN = dot(ray_D, N);
|
||||
|
||||
/* Distance from P to the plane. */
|
||||
const float t = -dot(P, N) / DN;
|
||||
|
||||
/* Limit the range to the positive side. */
|
||||
if (DN > 0.0f) {
|
||||
t_range->x = fmaxf(t_range->x, t);
|
||||
}
|
||||
else {
|
||||
t_range->y = fminf(t_range->y, t);
|
||||
}
|
||||
|
||||
return t_range->x < t_range->y;
|
||||
}
|
||||
|
||||
/* Find the ray segment inside an axis-aligned bounding box. */
|
||||
ccl_device bool ray_aabb_intersect(const float3 bbox_min,
|
||||
const float3 bbox_max,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
ccl_private float2 *t_range)
|
||||
{
|
||||
const float3 inv_ray_D = rcp(ray_D);
|
||||
|
||||
/* Absolute distances to lower and upper box coordinates; */
|
||||
const float3 t_lower = (bbox_min - ray_P) * inv_ray_D;
|
||||
const float3 t_upper = (bbox_max - ray_P) * inv_ray_D;
|
||||
|
||||
/* The four t-intervals (for x-/y-/z-slabs, and ray p(t)). */
|
||||
const float4 tmins = float3_to_float4(min(t_lower, t_upper), t_range->x);
|
||||
const float4 tmaxes = float3_to_float4(max(t_lower, t_upper), t_range->y);
|
||||
|
||||
/* Max of mins and min of maxes. */
|
||||
const float tmin = reduce_max(tmins);
|
||||
const float tmax = reduce_min(tmaxes);
|
||||
|
||||
*t_range = make_float2(tmin, tmax);
|
||||
|
||||
return tmin < tmax;
|
||||
}
|
||||
|
||||
/* Find the segment of a ray defined by P + D * t that lies inside a cylinder defined by
|
||||
* (x / len_u)^2 + (y / len_v)^2 = 1. */
|
||||
ccl_device_inline bool ray_infinite_cylinder_intersect(const float3 P,
|
||||
const float3 D,
|
||||
const float len_u,
|
||||
const float len_v,
|
||||
ccl_private float2 *t_range)
|
||||
{
|
||||
/* Convert to a 2D problem. */
|
||||
const float2 inv_len = 1.0f / make_float2(len_u, len_v);
|
||||
float2 P_proj = float3_to_float2(P) * inv_len;
|
||||
const float2 D_proj = float3_to_float2(D) * inv_len;
|
||||
|
||||
/* Solve quadratic equation a*t^2 + 2b*t + c = 0. */
|
||||
const float a = dot(D_proj, D_proj);
|
||||
float b = dot(P_proj, D_proj);
|
||||
|
||||
/* Move ray origin closer to the cylinder to prevent precision issue when the ray is far away. */
|
||||
const float t_mid = -b / a;
|
||||
P_proj += D_proj * t_mid;
|
||||
|
||||
/* Recompute b from the shifted origin. */
|
||||
b = dot(P_proj, D_proj);
|
||||
const float c = dot(P_proj, P_proj) - 1.0f;
|
||||
|
||||
float tmin, tmax;
|
||||
const bool valid = solve_quadratic(a, 2.0f * b, c, tmin, tmax);
|
||||
|
||||
return valid && intervals_intersect(t_range, make_float2(tmin, tmax) + t_mid);
|
||||
}
|
||||
|
||||
/* *
|
||||
* Find the ray segment inside a single-sided cone.
|
||||
*
|
||||
* \param axis: a unit-length direction around which the cone has a circular symmetry
|
||||
* \param P: the vector pointing from the cone apex to the ray origin
|
||||
* \param D: the direction of the ray, does not need to have unit-length
|
||||
* \param cos_angle_sq: `sqr(cos(half_aperture_of_the_cone))`
|
||||
* \param t_range: the lower and upper bounds between which the ray lies inside the cone
|
||||
* \return whether the intersection exists and is in the provided range
|
||||
*
|
||||
* See https://www.geometrictools.com/Documentation/IntersectionLineCone.pdf for illustration
|
||||
*/
|
||||
ccl_device_inline bool ray_cone_intersect(const float3 axis,
|
||||
const float3 P,
|
||||
float3 D,
|
||||
const float cos_angle_sq,
|
||||
ccl_private float2 *t_range)
|
||||
{
|
||||
if (cos_angle_sq < 1e-4f) {
|
||||
/* The cone is nearly a plane. */
|
||||
return ray_plane_intersect(axis, P, D, t_range);
|
||||
}
|
||||
|
||||
const float inv_len = inversesqrtf(len_squared(D));
|
||||
D *= inv_len;
|
||||
|
||||
const float AD = dot(axis, D);
|
||||
const float AP = dot(axis, P);
|
||||
|
||||
const float a = sqr(AD) - cos_angle_sq;
|
||||
const float b = 2.0f * (AD * AP - cos_angle_sq * dot(D, P));
|
||||
const float c = sqr(AP) - cos_angle_sq * dot(P, P);
|
||||
|
||||
float tmin = 0.0f, tmax = FLT_MAX;
|
||||
bool valid = solve_quadratic(a, b, c, tmin, tmax);
|
||||
|
||||
/* Check if the intersections are in the same hemisphere as the cone. */
|
||||
const bool tmin_valid = AP + tmin * AD > 0.0f;
|
||||
const bool tmax_valid = AP + tmax * AD > 0.0f;
|
||||
|
||||
valid &= (tmin_valid || tmax_valid);
|
||||
|
||||
if (!tmax_valid) {
|
||||
tmax = tmin;
|
||||
tmin = 0.0f;
|
||||
}
|
||||
else if (!tmin_valid) {
|
||||
tmin = tmax;
|
||||
tmax = FLT_MAX;
|
||||
}
|
||||
|
||||
return valid && intervals_intersect(t_range, make_float2(tmin, tmax) * inv_len);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __UTIL_MATH_INTERSECT_H__ */
|
||||
|
|
|
@ -14,7 +14,7 @@ CCL_NAMESPACE_BEGIN
|
|||
thread::thread(function<void()> run_cb) : run_cb_(run_cb), joined_(false)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(__linux__) && !defined(__GLIBC__)
|
||||
/* Set the stack size to 2MB to match glibc. The default 512KB on macOS is
|
||||
/* Set the stack size to 2MB to match GLIBC. The default 512KB on macOS is
|
||||
* too small for Embree, and consistent stack size also makes things more
|
||||
* predictable in general. */
|
||||
pthread_attr_t attribute;
|
||||
|
|
|
@ -161,6 +161,17 @@ ccl_device_inline Transform make_transform(float a,
|
|||
return t;
|
||||
}
|
||||
|
||||
ccl_device_inline Transform make_transform(const float3 x, const float3 y, const float3 z)
|
||||
{
|
||||
Transform t;
|
||||
|
||||
t.x = float3_to_float4(x, 0.0f);
|
||||
t.y = float3_to_float4(y, 0.0f);
|
||||
t.z = float3_to_float4(z, 0.0f);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
ccl_device_inline Transform euler_to_transform(const float3 euler)
|
||||
{
|
||||
float cx = cosf(euler.x);
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
GHOST_DECLARE_HANDLE(GHOST_SystemPathsHandle);
|
||||
|
||||
/**
|
||||
|
@ -63,7 +59,3 @@ extern const char *GHOST_getBinaryDir();
|
|||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
extern void GHOST_addToSystemRecentFiles(const char *filepath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -427,7 +427,7 @@ struct GWL_Cursor {
|
|||
|
||||
/**
|
||||
* The name of the theme (set by an environment variable).
|
||||
* When disabled, leave as an empty string and the default theme will be used.
|
||||
* When disabled, leave as an empty string and pass in nullptr to use the default theme.
|
||||
*/
|
||||
std::string theme_name;
|
||||
/**
|
||||
|
@ -2507,7 +2507,9 @@ static const wl_cursor *gwl_seat_cursor_find_from_shape(GWL_Seat *seat,
|
|||
if (!cursor->wl.theme) {
|
||||
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
|
||||
cursor->wl.theme = wl_cursor_theme_load(
|
||||
cursor->theme_name.c_str(), cursor->theme_size, seat->system->wl_shm_get());
|
||||
(cursor->theme_name.empty() ? nullptr : cursor->theme_name.c_str()),
|
||||
cursor->theme_size,
|
||||
seat->system->wl_shm_get());
|
||||
}
|
||||
|
||||
if (cursor->wl.theme) {
|
||||
|
@ -3521,7 +3523,9 @@ static bool update_cursor_scale(GWL_Cursor &cursor,
|
|||
}
|
||||
wl_cursor_theme_destroy(cursor.wl.theme);
|
||||
cursor.wl.theme = wl_cursor_theme_load(
|
||||
cursor.theme_name.c_str(), scale * cursor.theme_size, shm);
|
||||
(cursor.theme_name.empty() ? nullptr : cursor.theme_name.c_str()),
|
||||
scale * cursor.theme_size,
|
||||
shm);
|
||||
if (cursor.wl.theme_cursor) {
|
||||
cursor.wl.theme_cursor = wl_cursor_theme_get_cursor(cursor.wl.theme,
|
||||
cursor.wl.theme_cursor_name);
|
||||
|
|
|
@ -8,15 +8,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
# undef wl_array_for_each
|
||||
#undef wl_array_for_each
|
||||
/**
|
||||
* This macro causes a warning for C++ code, define our own.
|
||||
* See: https://gitlab.freedesktop.org/wayland/wayland/-/issues/34
|
||||
*/
|
||||
# define WL_ARRAY_FOR_EACH(pos, array) \
|
||||
for (pos = (decltype(pos))((array)->data); \
|
||||
reinterpret_cast<const char *>(pos) < \
|
||||
(reinterpret_cast<const char *>((array)->data) + (array)->size); \
|
||||
(pos)++)
|
||||
#endif
|
||||
#define WL_ARRAY_FOR_EACH(pos, array) \
|
||||
for (pos = (decltype(pos))((array)->data); \
|
||||
reinterpret_cast<const char *>(pos) < \
|
||||
(reinterpret_cast<const char *>((array)->data) + (array)->size); \
|
||||
(pos)++)
|
||||
|
|
|
@ -1879,6 +1879,23 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
|
||||
xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
|
||||
gwl_window_state_set_for_xdg(toplevel, state, gwl_window_state_get(window_));
|
||||
|
||||
/* NOTE(@ideasman42): Round trips are necessary with LIBDECOR on GNOME
|
||||
* because resizing later on and redrawing does *not* update as it should, see #119871.
|
||||
*
|
||||
* Without the round-trip here:
|
||||
* - The window will be created and this function will return using the requested buffer size,
|
||||
* instead of the window size which ends up being used (causing a visible flicker).
|
||||
* This has the down side that Blender's internal window state has the outdated size
|
||||
* which then gets immediately resized, causing a noticeable glitch.
|
||||
* - The window decorations will be displayed at the wrong size before refreshing
|
||||
* at the new size.
|
||||
* - On GNOME-Shell 46 shows the previous buffer-size under some conditions.
|
||||
*
|
||||
* In principle this could be used with XDG too however it causes problems with KDE
|
||||
* and some WLROOTS based compositors.
|
||||
*/
|
||||
wl_display_roundtrip(system_->wl_display_get());
|
||||
}
|
||||
else
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
|
|
@ -40,9 +40,9 @@
|
|||
#include "WindowData.h"
|
||||
|
||||
/* GPU API. */
|
||||
#include "GPU_context.h"
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_init_exit.h"
|
||||
#include "GPU_context.hh"
|
||||
#include "GPU_immediate.hh"
|
||||
#include "GPU_init_exit.hh"
|
||||
|
||||
extern int datatoc_bfont_ttf_size;
|
||||
extern char const datatoc_bfont_ttf[];
|
||||
|
|
|
@ -115,10 +115,10 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
|
|||
{
|
||||
void *newp = NULL;
|
||||
if (vmemh) {
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
const MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
const size_t prev_size = MEM_lockfree_allocN_len(vmemh);
|
||||
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
const MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
newp = MEM_lockfree_mallocN_aligned(
|
||||
prev_size, (size_t)memh_aligned->alignment, "dupli_malloc");
|
||||
}
|
||||
|
@ -135,14 +135,14 @@ void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
|
|||
void *newp = NULL;
|
||||
|
||||
if (vmemh) {
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
size_t old_len = MEM_lockfree_allocN_len(vmemh);
|
||||
const MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
const size_t old_len = MEM_lockfree_allocN_len(vmemh);
|
||||
|
||||
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
|
||||
newp = MEM_lockfree_mallocN(len, "realloc");
|
||||
}
|
||||
else {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
const MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "realloc");
|
||||
}
|
||||
|
||||
|
@ -171,14 +171,14 @@ void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
|
|||
void *newp = NULL;
|
||||
|
||||
if (vmemh) {
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
size_t old_len = MEM_lockfree_allocN_len(vmemh);
|
||||
const MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
const size_t old_len = MEM_lockfree_allocN_len(vmemh);
|
||||
|
||||
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
|
||||
newp = MEM_lockfree_mallocN(len, "recalloc");
|
||||
}
|
||||
else {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
const MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "recalloc");
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_immediate.hh"
|
||||
#include "GPU_shader.hh"
|
||||
#include "GPU_uniform_buffer.hh"
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
@ -512,8 +512,8 @@ static void updateGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
|
|||
curvemap.cache_id = curve_mapping_settings->cache_id;
|
||||
|
||||
/* Update texture. */
|
||||
int offset[3] = {0, 0, 0};
|
||||
int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
|
||||
const int offset[3] = {0, 0, 0};
|
||||
const int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
|
||||
const float *pixels = curve_mapping_settings->lut;
|
||||
GPU_texture_update_sub(
|
||||
curvemap.texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
# include "GPU_shader_shared_utils.h"
|
||||
# include "GPU_shader_shared_utils.hh"
|
||||
#endif
|
||||
|
||||
struct OCIO_GPUCurveMappingParameters {
|
||||
|
|
|
@ -60,17 +60,17 @@ TEST(MeshTopology, TrivialFaceTopology)
|
|||
EXPECT_EQ(mesh_topology.getNumFaceVertices(2), 5);
|
||||
|
||||
{
|
||||
int vertex_indices[] = {0, 1, 2, 3};
|
||||
const int vertex_indices[] = {0, 1, 2, 3};
|
||||
mesh_topology.setFaceVertexIndices(0, 4, vertex_indices);
|
||||
}
|
||||
|
||||
{
|
||||
int vertex_indices[] = {4, 5, 6};
|
||||
const int vertex_indices[] = {4, 5, 6};
|
||||
mesh_topology.setFaceVertexIndices(1, 3, vertex_indices);
|
||||
}
|
||||
|
||||
{
|
||||
int vertex_indices[] = {7, 8, 9, 10, 11};
|
||||
const int vertex_indices[] = {7, 8, 9, 10, 11};
|
||||
mesh_topology.setFaceVertexIndices(2, 5, vertex_indices);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
|||
* Currently, this API is optimized for Bullet RigidBodies, and doesn't
|
||||
* take into account other Physics Engines. Some tweaking may be necessary
|
||||
* to allow other systems to be used, in particular there may be references
|
||||
* to datatypes that aren't used here...
|
||||
* to data-types that aren't used here...
|
||||
*
|
||||
* -- Joshua Leung (22 June 2010)
|
||||
*/
|
||||
|
@ -210,7 +210,7 @@ rbCollisionShape *RB_shape_new_cylinder(float radius, float height);
|
|||
/* Setup (Convex Hull) ------------ */
|
||||
|
||||
rbCollisionShape *RB_shape_new_convex_hull(
|
||||
float *verts, int stride, int count, float margin, bool *can_embed);
|
||||
const float *verts, int stride, int count, float margin, bool *can_embed);
|
||||
|
||||
/* Setup (Triangle Mesh) ---------- */
|
||||
|
||||
|
@ -244,7 +244,7 @@ float RB_shape_get_margin(rbCollisionShape *shape);
|
|||
void RB_shape_set_margin(rbCollisionShape *shape, float value);
|
||||
|
||||
void RB_shape_trimesh_update(rbCollisionShape *shape,
|
||||
float *vertices,
|
||||
const float *vertices,
|
||||
int num_verts,
|
||||
int vert_stride,
|
||||
const float min[3],
|
||||
|
|
|
@ -712,7 +712,7 @@ rbCollisionShape *RB_shape_new_cylinder(float radius, float height)
|
|||
/* Setup (Convex Hull) ------------ */
|
||||
|
||||
rbCollisionShape *RB_shape_new_convex_hull(
|
||||
float *verts, int stride, int count, float margin, bool *can_embed)
|
||||
const float *verts, int stride, int count, float margin, bool *can_embed)
|
||||
{
|
||||
btConvexHullComputer hull_computer = btConvexHullComputer();
|
||||
|
||||
|
@ -800,7 +800,7 @@ rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
|
|||
}
|
||||
|
||||
void RB_shape_trimesh_update(rbCollisionShape *shape,
|
||||
float *vertices,
|
||||
const float *vertices,
|
||||
int num_verts,
|
||||
int vert_stride,
|
||||
const float min[3],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"\"POT-Creation-Date: 2019-02-25 20:41:30\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2016-04-23 22:41+0300\n"
|
||||
|
@ -2023,18 +2023,6 @@ msgid "Vertex Color"
|
|||
msgstr "ﺔﻄﻘﻨﻟﺍ ﻥﻮﻟ"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "ﻩﺎﺠﺗﺇ"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "ﺓﺎﺷﺮﻔﻟﺍ ﺮﺛﺆﻣ ﻒﺿﺍ"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "ﺓﺎﺷﺮﻔﻟﺍ ﺮﻴﺛﺄﺗ ﺡﺮﻃﺍ"
|
||||
|
||||
|
||||
msgid "Dissolve"
|
||||
msgstr "ﻞﻠﺤﺘﻟﺍ"
|
||||
|
||||
|
@ -2043,6 +2031,10 @@ msgid "Stroke"
|
|||
msgstr "ﺔﺒﻄﺷ"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "ﻩﺎﺠﺗﺇ"
|
||||
|
||||
|
||||
msgid "Normal"
|
||||
msgstr "ﻢﻇﺎﻧ"
|
||||
|
||||
|
@ -9276,6 +9268,14 @@ msgid "Editable falloff curve"
|
|||
msgstr "ﺮﻳﺮﺤﺘﻠﻟ ﻞﺑﺎﻗ ﻁﻮﻘﺳ ﻰﻨﺤﻨﻣ"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "ﺓﺎﺷﺮﻔﻟﺍ ﺮﺛﺆﻣ ﻒﺿﺍ"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "ﺓﺎﺷﺮﻔﻟﺍ ﺮﻴﺛﺄﺗ ﺡﺮﻃﺍ"
|
||||
|
||||
|
||||
msgid "Fill Threshold"
|
||||
msgstr "ﺔﺌﺒﻌﺘﻟﺍ ﺔﺒﺘﻋ"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-02-23 23:56+0000\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-09-26 10:37+0000\n"
|
||||
|
|
115
locale/po/ca.po
115
locale/po/ca.po
|
@ -1,10 +1,10 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-03-12 05:27+0000\n"
|
||||
"PO-Revision-Date: 2024-03-24 20:56+0000\n"
|
||||
"Last-Translator: Joan Pujolar <joan.pujolar@gmail.com>\n"
|
||||
"Language-Team: Catalan <https://translate.blender.org/projects/blender-ui/ui/ca/>\n"
|
||||
"Language: ca\n"
|
||||
|
@ -403,6 +403,10 @@ msgid "Displays glTF UI to manage material variants"
|
|||
msgstr "Mostra la IU de glTF per gestionar variants de materials"
|
||||
|
||||
|
||||
msgid "Allow glTF Embedded format"
|
||||
msgstr "Permetre format incrustat gITF"
|
||||
|
||||
|
||||
msgid "Display glTF UI to manage animations"
|
||||
msgstr "Mostrar la IU de glTF per gestionar animacions"
|
||||
|
||||
|
@ -4464,18 +4468,6 @@ msgid "Number of pixels to expand or contract fill area"
|
|||
msgstr "[Dilate/Contract]: Nombre de píxels per expandir o contraure l'àrea d'emplenament"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Direcció"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Sumar efecte de pinzell"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Restar efecte de pinzell"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "Mode esborrar"
|
||||
|
||||
|
@ -4524,6 +4516,10 @@ msgid "Strokes end extension for closing gaps, use zero to disable"
|
|||
msgstr "[Closure Size]: Extensió final dels traços per a tancar buits, posar zero per a desactivar"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Direcció"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "Direcció de l'emplenat"
|
||||
|
||||
|
@ -20581,6 +20577,14 @@ msgid "Amount of random elements that are going to be affected by the brush"
|
|||
msgstr "Quantitat d'elements aleatoris que es veuran afectats pel pinzell"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Sumar efecte de pinzell"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Restar efecte de pinzell"
|
||||
|
||||
|
||||
msgid "Max Element Distance"
|
||||
msgstr "Distància màxima d'element"
|
||||
|
||||
|
@ -21921,7 +21925,7 @@ msgstr "Usar pressió per a mescla d'impregnació"
|
|||
|
||||
|
||||
msgid "Use pressure to modulate wet mix"
|
||||
msgstr "[Use Pressure for Wet Mix]: Utilitza la pressió per a modular la mescla humida"
|
||||
msgstr "[Use Pressure for Wet Mix]: Utilitza la pressió per a modular la mescla d'impregnació"
|
||||
|
||||
|
||||
msgid "Use Pressure for Wet Persistence"
|
||||
|
@ -33889,7 +33893,7 @@ msgstr "[Keying set paths]: Col·lecció de camins de jocs d'atributs de fites"
|
|||
|
||||
|
||||
msgid "Active Keying Set"
|
||||
msgstr "Jocs de fitoatributs actiu"
|
||||
msgstr "Joc de fitoatributs actiu"
|
||||
|
||||
|
||||
msgid "Active Keying Set used to insert/delete keyframes"
|
||||
|
@ -35481,7 +35485,7 @@ msgstr "Especials de rastreig de translació"
|
|||
|
||||
|
||||
msgid "Rotation Track Specials"
|
||||
msgstr "Especials de rastreig de rotacació"
|
||||
msgstr "Especials de rastreig de rotació"
|
||||
|
||||
|
||||
msgid "Track"
|
||||
|
@ -53481,7 +53485,7 @@ msgstr "Aplica escala de solució"
|
|||
|
||||
|
||||
msgid "Apply scale on solution itself to make distance between selected tracks equals to desired"
|
||||
msgstr "[Apply Solution Scale]: Aplica l'escala sobre la solució mateixa per fer que la distància entre les rastres seleccionats sigui igual a la desitjada"
|
||||
msgstr "[Apply Solution Scale]: Aplica l'escala sobre la solució mateixa per fer que la distància entre els rastres seleccionats sigui igual a la desitjada"
|
||||
|
||||
|
||||
msgid "Distance between selected tracks"
|
||||
|
@ -57346,7 +57350,7 @@ msgstr "Restablir morfofites entre accions"
|
|||
|
||||
|
||||
msgid "Reset shape keys between each action exported. This is needed when some SK channels are not keyed on some animations"
|
||||
msgstr "Reestableix la morfofites entre cada acció exportada. Es fa necessari quan alguns canals SK no tenen fites en algunes animacions"
|
||||
msgstr "Reestableix la morfofites entre cada acció exportada. Es fa necessari quan alguns canals de MF no tinguin fites en algunes animacions"
|
||||
|
||||
|
||||
msgid "Shape Key Tangents"
|
||||
|
@ -90670,6 +90674,10 @@ msgid "Temporary Directory"
|
|||
msgstr "Directori temporal"
|
||||
|
||||
|
||||
msgid "The directory for storing temporary save files. The path must reference an existing directory or it will be ignored"
|
||||
msgstr "Directori per emmagatzamar documents guardats temporals. La ruta ha de referir-se a un directori concret o s'ignorarà"
|
||||
|
||||
|
||||
msgid ""
|
||||
"Command to launch the text editor, either a full path or a command in $PATH.\n"
|
||||
"Use the internal editor when left blank"
|
||||
|
@ -106021,7 +106029,7 @@ msgstr "Ganxo USD"
|
|||
|
||||
|
||||
msgid "Defines callback functions to extend USD IO"
|
||||
msgstr "Defineix les funcions de reinvocació per estendre a E/E d'USD"
|
||||
msgstr "Defineix les funcions de reinvocació per estendre a IE d'USD"
|
||||
|
||||
|
||||
msgid "A short description of the USD hook"
|
||||
|
@ -111250,6 +111258,11 @@ msgid "Mesh Filter Modal Map"
|
|||
msgstr "Mapa modal de filtre de malla"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "DEM data (.hgt) as Mesh and/or Image"
|
||||
msgstr "Dades DEM (.hgt) as com a malla i/o imatge"
|
||||
|
||||
|
||||
msgid "You have been logged out"
|
||||
msgstr "Ha expirat la teva sessió d'usuari"
|
||||
|
||||
|
@ -111842,6 +111855,10 @@ msgid "Path to gltfpack"
|
|||
msgstr "Ruta a gltfpack"
|
||||
|
||||
|
||||
msgid "This is the least efficient of the available forms, and should only be used when required."
|
||||
msgstr "Aquesta és la forma menys eficient de les disponibles, i només s'hauria d'emprar quan cal."
|
||||
|
||||
|
||||
msgid "Export only deformation bones is not possible when not sampling animation"
|
||||
msgstr "Exportar només ossos de deformació no és possible quan no es mostreja l'animació"
|
||||
|
||||
|
@ -114606,14 +114623,6 @@ msgid "Caps Type"
|
|||
msgstr "Tipus d'extrems"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "SAH"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "SH"
|
||||
|
||||
|
||||
msgid "Invert to Fill"
|
||||
msgstr "Invertir per emplenar"
|
||||
|
||||
|
@ -120848,6 +120857,18 @@ msgid "armatures"
|
|||
msgstr "esquelets"
|
||||
|
||||
|
||||
msgid "Unable to create builtin attribute in edit mode"
|
||||
msgstr "No s'ha pogut crear atribut de fàbrica en mode edició"
|
||||
|
||||
|
||||
msgid "Domain unsupported for \"id\" attribute"
|
||||
msgstr "Domini no admès com a atribut \"id\""
|
||||
|
||||
|
||||
msgid "Type unsupported for \"id\" attribute"
|
||||
msgstr "Tipus no admès per a atribut \"id\""
|
||||
|
||||
|
||||
msgid "Attribute name cannot be empty"
|
||||
msgstr "El nom de l'atribut no pot quedar buit"
|
||||
|
||||
|
@ -121362,18 +121383,6 @@ msgid "Auto Smooth"
|
|||
msgstr "Autosuavitzar"
|
||||
|
||||
|
||||
msgid "Socket_1"
|
||||
msgstr "Born_1"
|
||||
|
||||
|
||||
msgid "Input_1_use_attribute"
|
||||
msgstr "Input_1_use_attribute"
|
||||
|
||||
|
||||
msgid "Input_1_attribute_name"
|
||||
msgstr "Input_1_attribute_name"
|
||||
|
||||
|
||||
msgid "Tangent space can only be computed for tris/quads, aborting"
|
||||
msgstr "L'espai tangencial només es pot calcular per a tris/quads, avortant"
|
||||
|
||||
|
@ -122455,6 +122464,10 @@ msgid "Cannot create the Animation Context"
|
|||
msgstr "No es pot crear el Context d'animació"
|
||||
|
||||
|
||||
msgid "One or more F-Curves are not visible due to filter settings"
|
||||
msgstr "Una o més corbes-F no són visibles degut al filtre"
|
||||
|
||||
|
||||
msgid "F-Curves have no valid size"
|
||||
msgstr "Les corbes-F no tenen una dimensió vàlida"
|
||||
|
||||
|
@ -122793,10 +122806,6 @@ msgid "No object found to operate on"
|
|||
msgstr "No s'ha trobat cap objecte amb què operar"
|
||||
|
||||
|
||||
msgid "Bone collections can only be added to an Armature"
|
||||
msgstr "Les col·leccions d'ossos només es poden afegir a un esquelet"
|
||||
|
||||
|
||||
msgid "Cannot add bone collections to a linked Armature without an override"
|
||||
msgstr "No es poden afegir col·leccions d'ossos a una esquelet vinculat sense un sobreseïment"
|
||||
|
||||
|
@ -122805,10 +122814,6 @@ msgid "Cannot add bone collections to a linked Armature with a system override;
|
|||
msgstr "No es poden afegir col·leccions d'ossos a un esquelet enllaçat amb un sobreseïment de sistema; creeu explícitament un sobreseïment en l'esquelet"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "Les col·leccions d'ossos només es poden editar en un esquelet"
|
||||
|
||||
|
||||
msgid "Cannot update a linked Armature with a system override; explicitly create an override on the Armature"
|
||||
msgstr "No es pot actualitzar un esquelet enllaçat amb un sobreseïment de sistema; creeu explícitament un sobreseïment en l'esquelket"
|
||||
|
||||
|
@ -122821,6 +122826,10 @@ msgid "Cannot edit bone collections that are linked from another blend file"
|
|||
msgstr "No es poden editar col·leccions d'ossos vinculades a un altre document blend"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "Les col·leccions d'ossos només es poden editar en un esquelet"
|
||||
|
||||
|
||||
msgid "Cannot edit bone collections on linked Armatures without override"
|
||||
msgstr "No es poden editar les col·leccions d'ossos d'esquelets vinculats sense sobreseure"
|
||||
|
||||
|
@ -123398,6 +123407,10 @@ msgid "Data-block inputs are unsupported"
|
|||
msgstr "Ingressions de blocs de dades no compatibles"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "La primera egressió del grup de nodes ha de ser una geometria"
|
||||
|
||||
|
||||
msgid "Annotation Create Poly: LMB click to place next stroke vertex | ESC/Enter to end (or click outside this area)"
|
||||
msgstr "Anotació - Crear polígons: clicar BER per a col·locar el vèrtex següent del traç | ESC/Retorn per a finalitzar (o clicar fora de l'àrea)"
|
||||
|
||||
|
@ -133389,10 +133402,6 @@ msgid "Node group must have an output socket"
|
|||
msgstr "El grup de nodes ha de tenir un born de sortida"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "La primera egressió del grup de nodes ha de ser una geometria"
|
||||
|
||||
|
||||
msgid "NormalEdit"
|
||||
msgstr "Edició de normals (NormalEdit)"
|
||||
|
||||
|
@ -137344,7 +137353,7 @@ msgstr "Format FBX"
|
|||
|
||||
|
||||
msgid "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions"
|
||||
msgstr "Malles IO FBX, UV's, colors de vèrtex, materials, textures, càmeres, llums i accions"
|
||||
msgstr "Malles IE FBX, UV's, colors de vèrtex, materials, textures, càmeres, llums i accions"
|
||||
|
||||
|
||||
msgid "Import Images as Planes"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-12-12 02:28+0000\n"
|
||||
|
@ -2887,18 +2887,6 @@ msgid "Curve used for the strength"
|
|||
msgstr "Křivka použitá pro pevnost"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Směr"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Přidat efekt štětce"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Odečtení efektu štětce"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "Režim gumy"
|
||||
|
||||
|
@ -2923,6 +2911,10 @@ msgid "Affect Stroke Thickness"
|
|||
msgstr "Ovlivnit Tloušťku Tahu"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Směr"
|
||||
|
||||
|
||||
msgid "Normal"
|
||||
msgstr "Normála"
|
||||
|
||||
|
@ -8840,6 +8832,14 @@ msgid "Editable falloff curve"
|
|||
msgstr "Křivka útlumu"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Přidat efekt štětce"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Odečtení efektu štětce"
|
||||
|
||||
|
||||
msgid "Falloff Angle"
|
||||
msgstr "Úhel Poklesu"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-11-06 03:54+0000\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
@ -3603,18 +3603,6 @@ msgid "Curve used for the strength"
|
|||
msgstr "Kurve verwendet für die Stärke"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Richtung"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Hinzufügen-Effekt des Pinsels"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Abziehen-Effekt des Pinsels"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "Radiermodus"
|
||||
|
||||
|
@ -3659,6 +3647,10 @@ msgid "Strokes end extension for closing gaps, use zero to disable"
|
|||
msgstr "Striche Enderweiterung zum Schließen von Lücken, verwenden Sie Null zum deaktivieren"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Richtung"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "Richtung der Füllung"
|
||||
|
||||
|
@ -12965,6 +12957,14 @@ msgid "Brush deforms the mesh by deforming the constraints of a cloth simulation
|
|||
msgstr "Pinsel deformiert die Schleife indem eine Deformation, der Bedingung, einer Gewebesimulation durchgeführt wird"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Hinzufügen-Effekt des Pinsels"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Abziehen-Effekt des Pinsels"
|
||||
|
||||
|
||||
msgid "Max Element Distance"
|
||||
msgstr "Max. Elementabstand"
|
||||
|
||||
|
@ -54328,14 +54328,6 @@ msgid "Mask Value"
|
|||
msgstr "Maskiere Wert"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "CCW"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "CW"
|
||||
|
||||
|
||||
msgid "Invert to Fill"
|
||||
msgstr "Zum füllen invertieren"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2008-03-23 12:20+0200\n"
|
||||
|
|
|
@ -1,18 +1,50 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-03-25 00:51+0000\n"
|
||||
"Last-Translator: william sélifet <williamselifet@live.be>\n"
|
||||
"Language-Team: Esperanto <https://translate.blender.org/projects/blender-ui/ui/eo/>\n"
|
||||
"Language: eo\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.0.1"
|
||||
|
||||
|
||||
msgid "Name"
|
||||
msgstr "Nomo"
|
||||
|
||||
|
||||
msgid "Select"
|
||||
msgstr "Elektas"
|
||||
msgstr "Elektu"
|
||||
|
||||
|
||||
msgid "Add"
|
||||
msgstr "Aldonia"
|
||||
|
||||
|
||||
msgid "Cache Files"
|
||||
msgstr "Kaŝdosiero"
|
||||
|
||||
|
||||
msgid "Deflectors"
|
||||
msgstr "Deflekta"
|
||||
|
||||
|
||||
msgid "Angular"
|
||||
msgstr "Angula"
|
||||
|
||||
|
||||
msgid "View"
|
||||
msgstr "Rigardi"
|
||||
|
||||
|
||||
msgid "Render"
|
||||
msgstr "Por Kapitulacigi"
|
||||
msgstr "Redoni"
|
||||
|
||||
|
||||
msgid "Window"
|
||||
|
@ -23,6 +55,14 @@ msgid "Edit Mode"
|
|||
msgstr "Prilaborado Modo"
|
||||
|
||||
|
||||
msgid "F-Curves"
|
||||
msgstr "F-Kurbecoj"
|
||||
|
||||
|
||||
msgid "B-Bone"
|
||||
msgstr "B-osto"
|
||||
|
||||
|
||||
msgid "Links"
|
||||
msgstr "Ligiloj"
|
||||
|
||||
|
@ -35,6 +75,10 @@ msgid "Sculpt Mode"
|
|||
msgstr "Skulptaĵo Modo"
|
||||
|
||||
|
||||
msgid "Attribute"
|
||||
msgstr "Atributo"
|
||||
|
||||
|
||||
msgid "File"
|
||||
msgstr "Dosiero"
|
||||
|
||||
|
@ -49,7 +93,11 @@ msgstr "Nova"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Select"
|
||||
msgstr "Elektas"
|
||||
msgstr "Elektu"
|
||||
|
||||
|
||||
msgid "Handles"
|
||||
msgstr "Manpreni"
|
||||
|
||||
|
||||
msgid "View Z Axis"
|
||||
|
@ -62,7 +110,7 @@ msgstr "Montri X Axis"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Render"
|
||||
msgstr "Por Kapitulacigi"
|
||||
msgstr "Redoni"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
|
237
locale/po/es.po
237
locale/po/es.po
|
@ -1,10 +1,10 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-03-12 05:27+0000\n"
|
||||
"PO-Revision-Date: 2024-03-24 20:56+0000\n"
|
||||
"Last-Translator: Gabriel Gazzán <gabcorreo@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.blender.org/projects/blender-ui/ui/es/>\n"
|
||||
"Language: es\n"
|
||||
|
@ -403,6 +403,10 @@ msgid "Displays glTF UI to manage material variants"
|
|||
msgstr "Muestra la interfaz de glTF para administrar variantes de materiales"
|
||||
|
||||
|
||||
msgid "Allow glTF Embedded format"
|
||||
msgstr "Permitir formato glTF incorporado"
|
||||
|
||||
|
||||
msgid "Display glTF UI to manage animations"
|
||||
msgstr "Muestra la interfaz de glTF para administrar animaciones"
|
||||
|
||||
|
@ -4464,18 +4468,6 @@ msgid "Number of pixels to expand or contract fill area"
|
|||
msgstr "Cantidad de píxeles a expandir o contraer el relleno del área"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Dirección"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Adiciona el efecto del pincel"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Sustrae el efecto del pincel"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "Modo de borrar"
|
||||
|
||||
|
@ -4524,6 +4516,10 @@ msgid "Strokes end extension for closing gaps, use zero to disable"
|
|||
msgstr "Extensión del extremo de los trazos para cerrar huecos, 0 para deshabilitar"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Dirección"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "Dirección del relleno"
|
||||
|
||||
|
@ -6465,11 +6461,11 @@ msgstr "Codificación de imagen básica de AgX para un dispositivo sRGB"
|
|||
|
||||
|
||||
msgid "AgX Log"
|
||||
msgstr "AgX logarítmico"
|
||||
msgstr "AgX logarítmica"
|
||||
|
||||
|
||||
msgid "Log Encoding with Chroma inset and rotation, and with 25 Stops of Dynamic Range"
|
||||
msgstr "Codificación logarítmica con inserción y rotación de croma, con un rango dinámico de 25 paradas"
|
||||
msgstr "Codificación logarítmica con desplazamiento y rotación de croma, con un rango dinámico de 25 paradas"
|
||||
|
||||
|
||||
msgid "Display P3"
|
||||
|
@ -6621,7 +6617,7 @@ msgstr "Transformación adicional aplicada con fines artísticos, antes de la tr
|
|||
|
||||
|
||||
msgid "Do not modify image in an artistic manner"
|
||||
msgstr "No modifica las imágenes"
|
||||
msgstr "No modificará las imágenes"
|
||||
|
||||
|
||||
msgid "Use Curves"
|
||||
|
@ -19717,7 +19713,7 @@ msgstr "Rango de fotogramas de curvas"
|
|||
|
||||
|
||||
msgid "The combined frame range of all F-Curves within this action"
|
||||
msgstr "El rango combinado de fotogramas de todas las Curvas-F en esta acción"
|
||||
msgstr "El rango combinado de fotogramas de todas las curvas-f en esta acción"
|
||||
|
||||
|
||||
msgid "F-Curves"
|
||||
|
@ -20581,6 +20577,14 @@ msgid "Amount of random elements that are going to be affected by the brush"
|
|||
msgstr "Cantidad de elementos aleatorios que serán afectados por el pincel"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Adiciona el efecto del pincel"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Sustrae el efecto del pincel"
|
||||
|
||||
|
||||
msgid "Max Element Distance"
|
||||
msgstr "Distancia máx. elementos"
|
||||
|
||||
|
@ -20783,7 +20787,7 @@ msgstr "Espaciado gradiente"
|
|||
|
||||
|
||||
msgid "Spacing before brush gradient goes full circle"
|
||||
msgstr "Espacio antes de que el gradiente del pincel de la vuelta completa"
|
||||
msgstr "Espacio antes de que el gradiente del pincel de una revolución completa"
|
||||
|
||||
|
||||
msgid "Gradient Fill Mode"
|
||||
|
@ -28538,7 +28542,7 @@ msgstr "Torsionar"
|
|||
|
||||
|
||||
msgid "Number of turns around parent along the strand"
|
||||
msgstr "Cantidad de vueltas a lo largo de la hebra"
|
||||
msgstr "Cantidad de revoluciones a lo largo de la hebra"
|
||||
|
||||
|
||||
msgid "Twist Curve"
|
||||
|
@ -31381,7 +31385,7 @@ msgstr "Qué opciones de administración de color usar al guardar archivos"
|
|||
|
||||
|
||||
msgid "Follow Scene"
|
||||
msgstr "Igual que la escena"
|
||||
msgstr "De la escena"
|
||||
|
||||
|
||||
msgid "Choose BW for saving grayscale images, RGB for saving red, green and blue channels, and RGBA for saving red, green, blue and alpha channels"
|
||||
|
@ -31925,7 +31929,7 @@ msgstr "ID del elemento"
|
|||
|
||||
|
||||
msgid "Identifier of operator to call on input event"
|
||||
msgstr "Identificador del operador a invocar en un evento de entrada"
|
||||
msgstr "Identificador del operador a ser invocado por el evento de entrada"
|
||||
|
||||
|
||||
msgid "Is this keymap item user defined (doesn't just replace a builtin item)"
|
||||
|
@ -36105,7 +36109,7 @@ msgstr "Controles de puntos de referencia"
|
|||
|
||||
|
||||
msgid "Lightgroup Sync"
|
||||
msgstr "Sincronizar grupo de luces"
|
||||
msgstr "Sincronizar grupos de luces"
|
||||
|
||||
|
||||
msgid "Operator Presets"
|
||||
|
@ -39256,7 +39260,7 @@ msgstr "Invierte las coordenadas de texturizado V alrededor del punto de desplaz
|
|||
|
||||
|
||||
msgid "Mirror vertex groups (e.g. .R->.L)"
|
||||
msgstr "Simetrizar grupos de vértices (p.ej. .D -> .I)"
|
||||
msgstr "Simetrizar grupos de vértices (p.ej. .R -> .L)"
|
||||
|
||||
|
||||
msgid "Multires Modifier"
|
||||
|
@ -41585,7 +41589,7 @@ msgstr "Mostrar la previsualización usando la resolución completa o distintas
|
|||
|
||||
|
||||
msgid "None, full render"
|
||||
msgstr "No reemplazar, procesar clip original"
|
||||
msgstr "No reemplazar (clip original)"
|
||||
|
||||
|
||||
msgid "Render Undistorted"
|
||||
|
@ -42478,7 +42482,7 @@ msgstr "Interpolación de píxeles de alta calidad"
|
|||
|
||||
|
||||
msgid "Location Influence"
|
||||
msgstr "Influencia de la posición"
|
||||
msgstr "Influencia en posición"
|
||||
|
||||
|
||||
msgid "Influence of stabilization algorithm on footage location"
|
||||
|
@ -42486,7 +42490,7 @@ msgstr "Influencia del algoritmo de estabilización sobre la posición de la ima
|
|||
|
||||
|
||||
msgid "Rotation Influence"
|
||||
msgstr "Influencia rotación"
|
||||
msgstr "Influencia en rotación"
|
||||
|
||||
|
||||
msgid "Influence of stabilization algorithm on footage rotation"
|
||||
|
@ -42494,7 +42498,7 @@ msgstr "Influencia del algoritmo de estabilización sobre la rotación de la pel
|
|||
|
||||
|
||||
msgid "Scale Influence"
|
||||
msgstr "Escalar Influencia"
|
||||
msgstr "Influencia en escala"
|
||||
|
||||
|
||||
msgid "Influence of stabilization algorithm on footage scale"
|
||||
|
@ -43348,11 +43352,11 @@ msgstr "Algoritmo a usar para limitar canal"
|
|||
|
||||
|
||||
msgid "Single"
|
||||
msgstr "Único"
|
||||
msgstr "Individual"
|
||||
|
||||
|
||||
msgid "Limit by single channel"
|
||||
msgstr "Limitar en base a un solo canal"
|
||||
msgstr "Limitar en base a un único canal"
|
||||
|
||||
|
||||
msgid "Limit by maximum of other channels"
|
||||
|
@ -66400,7 +66404,7 @@ msgstr "Extruye los vértices seleccionados con una rotación en espiral alreded
|
|||
|
||||
|
||||
msgid "Turns"
|
||||
msgstr "Vueltas"
|
||||
msgstr "Revoluciones"
|
||||
|
||||
|
||||
msgid "(De)select all vertices, edges or faces"
|
||||
|
@ -68846,7 +68850,7 @@ msgstr "Qué algoritmo usar para generar el margen"
|
|||
|
||||
|
||||
msgid "Filter to combined, diffuse, glossy, transmission and subsurface passes"
|
||||
msgstr "Filtrar a las pasadas combinada, de difusión, reflectividad, transmisión y transluminiscencia"
|
||||
msgstr "Filtrar las pasadas combinada, de difusión, reflectividad, transmisión y transluminiscencia"
|
||||
|
||||
|
||||
msgid "Type of pass to bake, some of them may not be supported by the current render engine"
|
||||
|
@ -69766,11 +69770,11 @@ msgstr "Excluir a los bloqueadores seleccionados de la proyección sombras desde
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Select Light Linking Blockers"
|
||||
msgstr "Seleccionar bloqueadores vinculados"
|
||||
msgstr "Seleccionar bloqueadores de iluminación"
|
||||
|
||||
|
||||
msgid "Select all objects which block light from this emitter"
|
||||
msgstr "Selecciona todos los objetos que bloquean la iluminación de este emisor"
|
||||
msgstr "Selecciona todos los objetos que bloquean la luz de este emisor"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -69787,20 +69791,20 @@ msgstr "Estado de la vinculación de iluminación"
|
|||
|
||||
|
||||
msgid "Include selected receivers to receive light from the active emitter"
|
||||
msgstr "Incluir a los receptores seleccionados para que reciban iluminación desde el emisor activo"
|
||||
msgstr "Incluir a los receptores seleccionados para la recepción de luz desde el emisor activo"
|
||||
|
||||
|
||||
msgid "Exclude selected receivers from receiving light from the active emitter"
|
||||
msgstr "Excluir a los receptores seleccionados de la recepción de iluminación desde el emisor activo"
|
||||
msgstr "Excluir a los receptores seleccionados de la recepción de luz desde el emisor activo"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Select Light Linking Receivers"
|
||||
msgstr "Seleccionar receptores vinculados a iluminación"
|
||||
msgstr "Seleccionar receptores de iluminación"
|
||||
|
||||
|
||||
msgid "Select all objects which receive light from this emitter"
|
||||
msgstr "Seleccionar todos los objetos que reciben iluminación desde este emisor"
|
||||
msgstr "Selecciona todos los objetos que reciben luz de este emisor"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -69809,7 +69813,7 @@ msgstr "Eliminar de colección de vinculación de iluminación"
|
|||
|
||||
|
||||
msgid "Remove this object or collection from the light linking collection"
|
||||
msgstr "Eliminar este objeto o colección de la colección de vinculación de iluminación"
|
||||
msgstr "Elimina este objeto o colección de la colección de vinculación de iluminación"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -71072,7 +71076,7 @@ msgstr "Tipo de luz"
|
|||
|
||||
|
||||
msgid "Matching light types"
|
||||
msgstr "Tipos de luces coincidentes"
|
||||
msgstr "Luces del mismo tipo"
|
||||
|
||||
|
||||
msgid "Select object relative to the active object's position in the hierarchy"
|
||||
|
@ -71104,7 +71108,7 @@ msgstr "Biblioteca (datos de objeto)"
|
|||
|
||||
|
||||
msgid "Select the mirror objects of the selected object e.g. \"L.sword\" and \"R.sword\""
|
||||
msgstr "Selecciona el objeto simétrico del objeto seleccionado, p.ej: \"D.espada\" -> \"I.espada\""
|
||||
msgstr "Selecciona el objeto simétrico del objeto seleccionado, p.ej: \"L.espada\" -> \"R.espada\""
|
||||
|
||||
|
||||
msgid "Select connected parent/child objects"
|
||||
|
@ -71606,7 +71610,7 @@ msgstr "Eliminar rastreo"
|
|||
|
||||
|
||||
msgid "Clear and Keep Transformation (Clear Track)"
|
||||
msgstr "Eliminar y mantener transformaciones (Eliminar rastreo)"
|
||||
msgstr "Eliminar rastreo y mantener transformaciones"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -74913,11 +74917,11 @@ msgstr "Exporta la configuración del teclado a un script Python"
|
|||
|
||||
|
||||
msgid "All Keymaps"
|
||||
msgstr "Todos los mapas de teclado"
|
||||
msgstr "Mapa de teclado completo"
|
||||
|
||||
|
||||
msgid "Write all keymaps (not just user modified)"
|
||||
msgstr "Guarda todos los mapas de teclado (no sólo los modificados por el usuario)"
|
||||
msgstr "Guardará el mapa de teclado completo (no sólo las teclas modificadas por el usuario)"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -74926,7 +74930,7 @@ msgstr "Importar mapa de teclado..."
|
|||
|
||||
|
||||
msgid "Import key configuration from a Python script"
|
||||
msgstr "Importa la configuración del teclado desde un script Python"
|
||||
msgstr "Importará la configuración del teclado desde un script de Python"
|
||||
|
||||
|
||||
msgid "Keep Original"
|
||||
|
@ -74934,7 +74938,7 @@ msgstr "Mantener original"
|
|||
|
||||
|
||||
msgid "Keep original file after copying to configuration folder"
|
||||
msgstr "Mantiene el archivo original luego de copiar hacia la carpeta de configuración"
|
||||
msgstr "Mantendrá el archivo original luego de copiar hacia la carpeta de configuración"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -74943,7 +74947,7 @@ msgstr "Eliminar configuración de teclado"
|
|||
|
||||
|
||||
msgid "Remove key config"
|
||||
msgstr "Elimina configuración de teclado"
|
||||
msgstr "Eliminará la configuración de teclado actual"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -74952,7 +74956,7 @@ msgstr "Comprobar conflictos en teclado"
|
|||
|
||||
|
||||
msgid "Test key configuration for conflicts"
|
||||
msgstr "Comprobar conflictos en teclado"
|
||||
msgstr "Comprobará conflictos en el mapa de teclado"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -74961,7 +74965,7 @@ msgstr "Agregar elemento a mapa de teclado"
|
|||
|
||||
|
||||
msgid "Add key map item"
|
||||
msgstr "Agrega un elemento al mapa de teclado"
|
||||
msgstr "Agregará un elemento al mapa de teclado actual"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -74970,7 +74974,7 @@ msgstr "Eliminar elemento del mapa de teclado"
|
|||
|
||||
|
||||
msgid "Remove key map item"
|
||||
msgstr "Elimina un elemento del mapa de teclado"
|
||||
msgstr "Eliminará un elemento del mapa de teclado actual"
|
||||
|
||||
|
||||
msgid "Item Identifier"
|
||||
|
@ -74987,7 +74991,7 @@ msgstr "Restablecer elemento de teclado"
|
|||
|
||||
|
||||
msgid "Restore key map item"
|
||||
msgstr "Restablece un elemento del mapa de teclado"
|
||||
msgstr "Restablecerá un elemento del mapa de teclado"
|
||||
|
||||
|
||||
msgid "Identifier of the item to restore"
|
||||
|
@ -75000,11 +75004,11 @@ msgstr "Restablecer mapa de teclado"
|
|||
|
||||
|
||||
msgid "Restore key map(s)"
|
||||
msgstr "Restablece el mapa del teclado"
|
||||
msgstr "Restablecerá el mapa del teclado"
|
||||
|
||||
|
||||
msgid "Restore all keymaps to default"
|
||||
msgstr "Restablece todos los mapas de teclado a su estado predefinido"
|
||||
msgstr "Restablecerá todos los mapas de teclado a su estado predefinido"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -75994,7 +75998,7 @@ msgstr "Agregar AOV"
|
|||
|
||||
|
||||
msgid "Add a Shader AOV"
|
||||
msgstr "Agregar AOV de sombreado"
|
||||
msgstr "Agrega una AOV de sombreado"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -76003,7 +76007,7 @@ msgstr "Agregar grupo de luces"
|
|||
|
||||
|
||||
msgid "Add a Light Group"
|
||||
msgstr "Agrega un grupo de luces"
|
||||
msgstr "Agrega un nuevo grupo de luces a la capa de visualización actual"
|
||||
|
||||
|
||||
msgid "Name of newly created lightgroup"
|
||||
|
@ -76012,11 +76016,11 @@ msgstr "Nombre del grupo de luces recientemente creado"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Add Used Lightgroups"
|
||||
msgstr "Agregar grupos de luces usados"
|
||||
msgstr "Agregar grupos de luces en uso"
|
||||
|
||||
|
||||
msgid "Add all used Light Groups"
|
||||
msgstr "Agrega todos los grupos de luces usados"
|
||||
msgstr "Agrega (a la capa de visualización actual) todos los grupos de luces que se encuentren en uso en otras capas de visualización"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -76025,7 +76029,7 @@ msgstr "Eliminar capa de visualización"
|
|||
|
||||
|
||||
msgid "Remove the selected view layer"
|
||||
msgstr "Elimina la capa de visualización seleccionada"
|
||||
msgstr "Elimina la capa de visualización actual"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -76034,7 +76038,7 @@ msgstr "Eliminar AOV"
|
|||
|
||||
|
||||
msgid "Remove Active AOV"
|
||||
msgstr "Eliminar AOV activa"
|
||||
msgstr "Elimina la AOV activa"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -76043,7 +76047,7 @@ msgstr "Eliminar grupo de luces"
|
|||
|
||||
|
||||
msgid "Remove Active Lightgroup"
|
||||
msgstr "Eliminar grupo de luces activo"
|
||||
msgstr "Elimina el grupo de luces activo de la capa de visualización actual"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -76052,7 +76056,7 @@ msgstr "Eliminar grupos de luces no usados"
|
|||
|
||||
|
||||
msgid "Remove all unused Light Groups"
|
||||
msgstr "Elimina todos los grupos de luces no usados"
|
||||
msgstr "Elimina (de la capa de visualización actual) todos los grupos de luces no usados"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -84964,7 +84968,7 @@ msgstr "Abre un archivo guardado automáticamente para recuperarlo"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Recover Last Session"
|
||||
msgstr "Recuperar la última sesión"
|
||||
msgstr "Recuperar última sesión"
|
||||
|
||||
|
||||
msgid "Open the last closed file (\"quit.blend\")"
|
||||
|
@ -87768,7 +87772,7 @@ msgstr "Menús"
|
|||
|
||||
|
||||
msgid "Open on Mouse Over"
|
||||
msgstr "Abrir al posar ratón"
|
||||
msgstr "Abrir al posar el ratón"
|
||||
|
||||
|
||||
msgid "Pie Menus"
|
||||
|
@ -88074,7 +88078,7 @@ msgstr "Máscara de esténcil"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Scale Cage"
|
||||
msgstr "Escalar jaula"
|
||||
msgstr "Escalar (Jaula)"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -90670,6 +90674,10 @@ msgid "Temporary Directory"
|
|||
msgstr "Directorio temporal"
|
||||
|
||||
|
||||
msgid "The directory for storing temporary save files. The path must reference an existing directory or it will be ignored"
|
||||
msgstr "Directorio para almacenar archivos temporales. La ruta deberá referenciar a un directorio existente, de lo contrario será ignorado"
|
||||
|
||||
|
||||
msgid ""
|
||||
"Command to launch the text editor, either a full path or a command in $PATH.\n"
|
||||
"Use the internal editor when left blank"
|
||||
|
@ -92461,7 +92469,7 @@ msgstr "Verdadero cuando no sea posible establecer este valor en Ninguno"
|
|||
|
||||
|
||||
msgid "Return"
|
||||
msgstr "Devuelta"
|
||||
msgstr "Resultante"
|
||||
|
||||
|
||||
msgid "True when this property is an output value from an RNA function"
|
||||
|
@ -100306,11 +100314,11 @@ msgstr "Si existieran, los marcadores serán mostrados en una fila separada en l
|
|||
|
||||
|
||||
msgid "Show Pose Markers"
|
||||
msgstr "Mostrar marcadores de posición"
|
||||
msgstr "Mostrar marcadores de la pose"
|
||||
|
||||
|
||||
msgid "Show markers belonging to the active action instead of Scene markers (Action and Shape Key Editors only)"
|
||||
msgstr "Muestra los marcadores pertenecientes a la acción activa, en vez de los de la escena (sólo en editores de acciones y Formas clave)"
|
||||
msgstr "Mostrará los marcadores pertenecientes a la acción activa, en vez de los marcadores de la escena (sólo para el Editor de acciones y el Editor de Formas clave)"
|
||||
|
||||
|
||||
msgid "Show Sliders"
|
||||
|
@ -100334,7 +100342,7 @@ msgstr "Sincronizar marcadores"
|
|||
|
||||
|
||||
msgid "Sync Markers with keyframe edits"
|
||||
msgstr "Sincroniza los marcadores al editar fotogramas clave"
|
||||
msgstr "Sincronizar los marcadores al editar fotogramas clave"
|
||||
|
||||
|
||||
msgid "Realtime Updates"
|
||||
|
@ -104442,7 +104450,7 @@ msgstr "Estilo de control"
|
|||
|
||||
|
||||
msgid "Widget Label Style"
|
||||
msgstr "Estilo etiqueta del control"
|
||||
msgstr "Estilo Control etiqueta"
|
||||
|
||||
|
||||
msgid "Theme Text Editor"
|
||||
|
@ -104622,7 +104630,7 @@ msgstr "Colores Elementos lista"
|
|||
|
||||
|
||||
msgid "Menu Widget Colors"
|
||||
msgstr "Colores Controles menú"
|
||||
msgstr "Colores Control menú"
|
||||
|
||||
|
||||
msgid "Menu Backdrop Colors"
|
||||
|
@ -104899,7 +104907,7 @@ msgstr "Color de la estructura en modo Edición, cuando la selección de bordes
|
|||
|
||||
|
||||
msgid "Theme Widget Color Set"
|
||||
msgstr "Conjunto de colores de controles"
|
||||
msgstr "Conjunto de colores Control"
|
||||
|
||||
|
||||
msgid "Theme settings for widget color sets"
|
||||
|
@ -104931,7 +104939,7 @@ msgstr "Sombreado Arriba"
|
|||
|
||||
|
||||
msgid "Theme Widget State Color"
|
||||
msgstr "Color de estado de controles"
|
||||
msgstr "Color de estado de Control"
|
||||
|
||||
|
||||
msgid "Theme settings for widget state colors"
|
||||
|
@ -105071,7 +105079,7 @@ msgstr "Esculpido de curvas"
|
|||
|
||||
|
||||
msgid "Curve Profile Widget"
|
||||
msgstr "Control de curva de perfil"
|
||||
msgstr "Control curva de perfil"
|
||||
|
||||
|
||||
msgid "Used for defining a profile's path"
|
||||
|
@ -108131,7 +108139,7 @@ msgstr "Nombre del elemento del mapa de acción"
|
|||
|
||||
|
||||
msgid "Identifier of operator to call on action event"
|
||||
msgstr "Identificador del operador a invocar en un evento de la acción"
|
||||
msgstr "Identificador del operador a ser invocado por el evento de la acción"
|
||||
|
||||
|
||||
msgid "Operator Mode"
|
||||
|
@ -111250,6 +111258,11 @@ msgid "Mesh Filter Modal Map"
|
|||
msgstr "Mapa modal - Filtro de malla"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "DEM data (.hgt) as Mesh and/or Image"
|
||||
msgstr "Datos DEM (.hgt) como malla y/o imagen"
|
||||
|
||||
|
||||
msgid "You have been logged out"
|
||||
msgstr "Se ha cerrado la sesión"
|
||||
|
||||
|
@ -111842,6 +111855,10 @@ msgid "Path to gltfpack"
|
|||
msgstr "Ruta a gltfpack"
|
||||
|
||||
|
||||
msgid "This is the least efficient of the available forms, and should only be used when required."
|
||||
msgstr "Este es el formato menos eficiente de todos, sólo debería ser usado cuando sea necesario."
|
||||
|
||||
|
||||
msgid "Export only deformation bones is not possible when not sampling animation"
|
||||
msgstr "La exportación tan sólo de huesos deformantes no es posible cuando no se está muestreando la animación"
|
||||
|
||||
|
@ -114606,14 +114623,6 @@ msgid "Caps Type"
|
|||
msgstr "Tipo de extremos"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "Antihorario"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "Horario"
|
||||
|
||||
|
||||
msgid "Invert to Fill"
|
||||
msgstr "Invertir a Rellenar"
|
||||
|
||||
|
@ -117182,7 +117191,7 @@ msgstr "Ajustar previsualización a ventana"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Sequence Render Image"
|
||||
msgstr "Procesar fotograma"
|
||||
msgstr "Procesar imagen"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -117926,7 +117935,7 @@ msgstr "STL (.stl)"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Render Image"
|
||||
msgstr "Procesar fotograma"
|
||||
msgstr "Procesar imagen"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -118060,7 +118069,7 @@ msgstr "Nivel superior"
|
|||
|
||||
|
||||
msgid "Sub Level"
|
||||
msgstr "Sub nivel"
|
||||
msgstr "Nivel inferior"
|
||||
|
||||
|
||||
msgid "Link Materials To"
|
||||
|
@ -118230,7 +118239,7 @@ msgstr "Título del panel"
|
|||
|
||||
|
||||
msgid "Widget Label"
|
||||
msgstr "Etiqueta de control"
|
||||
msgstr "Etiqueta control"
|
||||
|
||||
|
||||
msgid "Temporary Files"
|
||||
|
@ -118481,7 +118490,7 @@ msgstr "Perspectiva / Ortogonal"
|
|||
|
||||
msgctxt "Operator"
|
||||
msgid "Viewport Render Image"
|
||||
msgstr "Procesar fotograma"
|
||||
msgstr "Procesar imagen"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
|
@ -120848,6 +120857,18 @@ msgid "armatures"
|
|||
msgstr "esqueletos"
|
||||
|
||||
|
||||
msgid "Unable to create builtin attribute in edit mode"
|
||||
msgstr "No es posible crear un atributo interno en modo Edición"
|
||||
|
||||
|
||||
msgid "Domain unsupported for \"id\" attribute"
|
||||
msgstr "Dominio no soportado para el atributo \"id\""
|
||||
|
||||
|
||||
msgid "Type unsupported for \"id\" attribute"
|
||||
msgstr "Tipo no soportado para el atributo \"id\""
|
||||
|
||||
|
||||
msgid "Attribute name cannot be empty"
|
||||
msgstr "El nombre del atributo no puede estar vacío"
|
||||
|
||||
|
@ -121315,11 +121336,11 @@ msgstr "luces"
|
|||
|
||||
|
||||
msgid "Light Linking for %s"
|
||||
msgstr "Vinculación de iluminación para %s"
|
||||
msgstr "Vinculación_iluminación %s"
|
||||
|
||||
|
||||
msgid "Shadow Linking for %s"
|
||||
msgstr "Vinculación de sombras para %s"
|
||||
msgstr "Vinculación_sombras %s"
|
||||
|
||||
|
||||
msgid "Cannot unlink unsupported '%s' from light linking collection '%s'"
|
||||
|
@ -121362,18 +121383,6 @@ msgid "Auto Smooth"
|
|||
msgstr "Suavizado automático"
|
||||
|
||||
|
||||
msgid "Socket_1"
|
||||
msgstr "Conector_1"
|
||||
|
||||
|
||||
msgid "Input_1_use_attribute"
|
||||
msgstr "Entrada_1_usar_atributo"
|
||||
|
||||
|
||||
msgid "Input_1_attribute_name"
|
||||
msgstr "Entrada_1_nombre_atributo"
|
||||
|
||||
|
||||
msgid "Tangent space can only be computed for tris/quads, aborting"
|
||||
msgstr "El espacio tangencial sólo puede ser calculado en triángulos o cuadriláteros, abortando"
|
||||
|
||||
|
@ -122455,6 +122464,10 @@ msgid "Cannot create the Animation Context"
|
|||
msgstr "No es posible crear el contexto de animación"
|
||||
|
||||
|
||||
msgid "One or more F-Curves are not visible due to filter settings"
|
||||
msgstr "Una o más curvas-f no se encuentran visibles debido a las opciones de filtrado"
|
||||
|
||||
|
||||
msgid "F-Curves have no valid size"
|
||||
msgstr "Las curvas-f tienen un tamaño inválido"
|
||||
|
||||
|
@ -122793,10 +122806,6 @@ msgid "No object found to operate on"
|
|||
msgstr "No se encontraron objetos sobre los cuales operar"
|
||||
|
||||
|
||||
msgid "Bone collections can only be added to an Armature"
|
||||
msgstr "Las colecciones de huesos sólo pueden ser agregadas a un esqueleto"
|
||||
|
||||
|
||||
msgid "Cannot add bone collections to a linked Armature without an override"
|
||||
msgstr "No es posible agregar colecciones de huesos a un esqueleto vinculado sin una redefinición"
|
||||
|
||||
|
@ -122805,10 +122814,6 @@ msgid "Cannot add bone collections to a linked Armature with a system override;
|
|||
msgstr "No es posible agregar colecciones de huesos a un esqueleto vinculado con una redefinición del sistema; crear de forma explícita una redefinición en el esqueleto"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "Las colecciones de huesos sólo pueden ser editadas en un esqueleto"
|
||||
|
||||
|
||||
msgid "Cannot update a linked Armature with a system override; explicitly create an override on the Armature"
|
||||
msgstr "No es posible actualizar un esqueleto vinculado con una redefinición del sistema; crear de forma explícita una redefinición en el esqueleto"
|
||||
|
||||
|
@ -122821,6 +122826,10 @@ msgid "Cannot edit bone collections that are linked from another blend file"
|
|||
msgstr "No es posible editar colecciones de huesos que se encuentren vinculadas desde otro archivo .blend"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "Las colecciones de huesos sólo pueden ser editadas en un esqueleto"
|
||||
|
||||
|
||||
msgid "Cannot edit bone collections on linked Armatures without override"
|
||||
msgstr "No es posible editar colecciones de huesos en esqueletos vinculados, sin una redefinición"
|
||||
|
||||
|
@ -123398,6 +123407,10 @@ msgid "Data-block inputs are unsupported"
|
|||
msgstr "Entradas del bloque de datos no soportadas"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "La primera salida del grupo de nodos debe ser una geometría"
|
||||
|
||||
|
||||
msgid "Annotation Create Poly: LMB click to place next stroke vertex | ESC/Enter to end (or click outside this area)"
|
||||
msgstr "Anotación - Línea poligonal: Clic Izq. para ubicar los puntos del trazo | Esc/Intro para finalizar (o clic fuera de este área)"
|
||||
|
||||
|
@ -127692,7 +127705,7 @@ msgstr "Y:"
|
|||
|
||||
|
||||
msgid "Pattern Area:"
|
||||
msgstr "Área patrón:"
|
||||
msgstr "Área del patrón:"
|
||||
|
||||
|
||||
msgid "Width:"
|
||||
|
@ -133389,10 +133402,6 @@ msgid "Node group must have an output socket"
|
|||
msgstr "El grupo de nodos debe contener un conector de salida"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "La primera salida del grupo de nodos debe ser una geometría"
|
||||
|
||||
|
||||
msgid "NormalEdit"
|
||||
msgstr "Editar_normales"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
|
@ -305,14 +305,14 @@ msgid "Material"
|
|||
msgstr "Materiala"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Norabidea"
|
||||
|
||||
|
||||
msgid "Stroke"
|
||||
msgstr "Trazua"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Norabidea"
|
||||
|
||||
|
||||
msgid "Normal"
|
||||
msgstr "Normala"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-11-30 20:00+0000\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
@ -2134,14 +2134,14 @@ msgid "Curve Strength"
|
|||
msgstr "Käyrän vahvuus"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Suunta"
|
||||
|
||||
|
||||
msgid "Stroke"
|
||||
msgstr "Piirto"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Suunta"
|
||||
|
||||
|
||||
msgid "Normal"
|
||||
msgstr "Normaali"
|
||||
|
||||
|
|
102
locale/po/fr.po
102
locale/po/fr.po
|
@ -1,10 +1,10 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-03-12 05:27+0000\n"
|
||||
"PO-Revision-Date: 2024-03-19 07:58+0000\n"
|
||||
"Last-Translator: Damien Picard <dam.pic@free.fr>\n"
|
||||
"Language-Team: French <https://translate.blender.org/projects/blender-ui/ui/fr/>\n"
|
||||
"Language: fr\n"
|
||||
|
@ -403,6 +403,10 @@ msgid "Displays glTF UI to manage material variants"
|
|||
msgstr "Afficher l’interface glTF pour gérer les variantes de matériaux"
|
||||
|
||||
|
||||
msgid "Allow glTF Embedded format"
|
||||
msgstr "Permettre le format gtTF embarqué"
|
||||
|
||||
|
||||
msgid "Display glTF UI to manage animations"
|
||||
msgstr "Afficher l’interface glTF pour gérer les animations"
|
||||
|
||||
|
@ -4464,18 +4468,6 @@ msgid "Number of pixels to expand or contract fill area"
|
|||
msgstr "Nombre de pixels à utiliser pour dilater ou contracter la zone remplie"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Direction"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Effet d’addition de la brosse"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Effet de soustraction de la brosse"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "Mode gomme"
|
||||
|
||||
|
@ -4524,6 +4516,10 @@ msgid "Strokes end extension for closing gaps, use zero to disable"
|
|||
msgstr "Extension de l’extrémité des traits pour fermer les interstices, 0 pour désactiver"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Direction"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "Direction du remplissage"
|
||||
|
||||
|
@ -20581,6 +20577,14 @@ msgid "Amount of random elements that are going to be affected by the brush"
|
|||
msgstr "Quantité d’éléments aléatoires qui seront affectés par la brosse"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Effet d’addition de la brosse"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Effet de soustraction de la brosse"
|
||||
|
||||
|
||||
msgid "Max Element Distance"
|
||||
msgstr "Distance max d’éléments"
|
||||
|
||||
|
@ -63164,11 +63168,11 @@ msgstr "Hauteur du plan créé"
|
|||
|
||||
|
||||
msgid "Animate Image Sequences"
|
||||
msgstr "Animer la séquence d’images"
|
||||
msgstr "Séquences d’images"
|
||||
|
||||
|
||||
msgid "Import sequentially numbered images as an animated image sequence instead of separate planes"
|
||||
msgstr "Importer les images numérotées séquentiellement en tant que séquence d’images animée, plutôt que des plans séparés"
|
||||
msgstr "Importer les images numérotées séquentiellement en tant que séquences d’images, plutôt que comme plans séparés"
|
||||
|
||||
|
||||
msgid "Offset Planes"
|
||||
|
@ -80673,7 +80677,7 @@ msgstr "Mettre à jour le dépôt de travail d’i18n (fichiers po)"
|
|||
|
||||
|
||||
msgid "Skip POT"
|
||||
msgstr "Ignorer POT"
|
||||
msgstr "Ignorer le POT"
|
||||
|
||||
|
||||
msgid "Skip POT file generation"
|
||||
|
@ -90672,6 +90676,10 @@ msgid "Temporary Directory"
|
|||
msgstr "Dossier temporaire"
|
||||
|
||||
|
||||
msgid "The directory for storing temporary save files. The path must reference an existing directory or it will be ignored"
|
||||
msgstr "Le dossier où stocker les fichiers temporaires. Le chemin doit pointer vers un dossier existant, sans quoi il sera ignoré"
|
||||
|
||||
|
||||
msgid ""
|
||||
"Command to launch the text editor, either a full path or a command in $PATH.\n"
|
||||
"Use the internal editor when left blank"
|
||||
|
@ -111844,6 +111852,10 @@ msgid "Path to gltfpack"
|
|||
msgstr "Chemin de gltfpack"
|
||||
|
||||
|
||||
msgid "This is the least efficient of the available forms, and should only be used when required."
|
||||
msgstr "Il s’agit de la moins efficace des formes disponibles, et ne devrait être utilisée que si nécessaire."
|
||||
|
||||
|
||||
msgid "Export only deformation bones is not possible when not sampling animation"
|
||||
msgstr "Impossible de n’exporter que les os de déformation si l’animation n’est pas échantillonnée"
|
||||
|
||||
|
@ -114608,14 +114620,6 @@ msgid "Caps Type"
|
|||
msgstr "Type d’extrémités"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "Antihoraire"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "Horaire"
|
||||
|
||||
|
||||
msgid "Invert to Fill"
|
||||
msgstr "Inverser pour remplir"
|
||||
|
||||
|
@ -120850,6 +120854,18 @@ msgid "armatures"
|
|||
msgstr "armatures"
|
||||
|
||||
|
||||
msgid "Unable to create builtin attribute in edit mode"
|
||||
msgstr "Impossible de créer un attribut prédéfini en mode édition"
|
||||
|
||||
|
||||
msgid "Domain unsupported for \"id\" attribute"
|
||||
msgstr "Domaine non pris en charge pour l’attribut « id »"
|
||||
|
||||
|
||||
msgid "Type unsupported for \"id\" attribute"
|
||||
msgstr "Type non pris en charge pour l’attribut « id »"
|
||||
|
||||
|
||||
msgid "Attribute name cannot be empty"
|
||||
msgstr "Le nom d’attribut ne peut pas être vide"
|
||||
|
||||
|
@ -121364,18 +121380,6 @@ msgid "Auto Smooth"
|
|||
msgstr "Lissage auto"
|
||||
|
||||
|
||||
msgid "Socket_1"
|
||||
msgstr "Prise_1"
|
||||
|
||||
|
||||
msgid "Input_1_use_attribute"
|
||||
msgstr "Entrée_1_utiliser_l_attribut"
|
||||
|
||||
|
||||
msgid "Input_1_attribute_name"
|
||||
msgstr "Entrée_1_nom_d_attribut"
|
||||
|
||||
|
||||
msgid "Tangent space can only be computed for tris/quads, aborting"
|
||||
msgstr "L’espace tangent peut seulement être calculé pour des triangles ou quadrangles, abandon"
|
||||
|
||||
|
@ -122457,6 +122461,10 @@ msgid "Cannot create the Animation Context"
|
|||
msgstr "Impossible de créer le contexte d’animation"
|
||||
|
||||
|
||||
msgid "One or more F-Curves are not visible due to filter settings"
|
||||
msgstr "Une F-courbe ou plus ne sont pas visibles à cause des réglages de filtrage"
|
||||
|
||||
|
||||
msgid "F-Curves have no valid size"
|
||||
msgstr "Les F-courbes n’ont pas de taille valide"
|
||||
|
||||
|
@ -122795,10 +122803,6 @@ msgid "No object found to operate on"
|
|||
msgstr "Aucun objet trouvé sur lequel agir"
|
||||
|
||||
|
||||
msgid "Bone collections can only be added to an Armature"
|
||||
msgstr "Les collections d’os ne peuvent être ajoutées que sur une armature"
|
||||
|
||||
|
||||
msgid "Cannot add bone collections to a linked Armature without an override"
|
||||
msgstr "Impossible d’ajouter des collections d’os à une armature liée sans redéfinition"
|
||||
|
||||
|
@ -122807,10 +122811,6 @@ msgid "Cannot add bone collections to a linked Armature with a system override;
|
|||
msgstr "Impossible d’ajouter des collections d’os à une armature liée ayant une redéfinition système ; créer une redéfinition explicite sur l’armature"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "Les collections d’os ne peuvent être éditées que sur une armature"
|
||||
|
||||
|
||||
msgid "Cannot update a linked Armature with a system override; explicitly create an override on the Armature"
|
||||
msgstr "Impossible de mettre à jour une armature liée ayant une redéfinition système ; créer une redéfinition explicite sur l’armature"
|
||||
|
||||
|
@ -122823,6 +122823,10 @@ msgid "Cannot edit bone collections that are linked from another blend file"
|
|||
msgstr "Impossible d’éditer des collections d’os liées depuis un autre fichier blend"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "Les collections d’os ne peuvent être éditées que sur une armature"
|
||||
|
||||
|
||||
msgid "Cannot edit bone collections on linked Armatures without override"
|
||||
msgstr "Impossible d’éditer des collections d’os d’une armature liée sans redéfinition"
|
||||
|
||||
|
@ -123400,6 +123404,10 @@ msgid "Data-block inputs are unsupported"
|
|||
msgstr "Les entrées blocs de données ne sont pas prises en charge"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "La première sortie du groupe de nœuds doit être une géométrie"
|
||||
|
||||
|
||||
msgid "Annotation Create Poly: LMB click to place next stroke vertex | ESC/Enter to end (or click outside this area)"
|
||||
msgstr "Création de poly d’annotation : clic gauche pour placer le prochain sommet du trait | Échap/Entrée pour finaliser (ou cliquer en dehors de cette zone)"
|
||||
|
||||
|
@ -133391,10 +133399,6 @@ msgid "Node group must have an output socket"
|
|||
msgstr "Le groupe de nœuds doit avoir une prise de sortie"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "La première sortie du groupe de nœuds doit être une géométrie"
|
||||
|
||||
|
||||
msgid "NormalEdit"
|
||||
msgstr "ÉditionNormales"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2017-12-25 14:01+0100\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-10-06 09:54+0000\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2015-03-03 16:21+0530\n"
|
||||
|
@ -655,14 +655,14 @@ msgid "Vertex Color"
|
|||
msgstr "शिरोबिन्दु रंग"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "दिशा"
|
||||
|
||||
|
||||
msgid "Dissolve"
|
||||
msgstr "भंग"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "दिशा"
|
||||
|
||||
|
||||
msgid "Radius"
|
||||
msgstr "त्रिज्या"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-01-11 03:55+0000\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-12-04 11:07+0000\n"
|
||||
|
@ -3276,18 +3276,6 @@ msgid "Curve used for the strength"
|
|||
msgstr "Kurva digunakan untuk kekuatan"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Arah"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Tambah efek kuas"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Kurangi efek kuas"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "Mode Penghapus"
|
||||
|
||||
|
@ -3332,6 +3320,10 @@ msgid "Strokes end extension for closing gaps, use zero to disable"
|
|||
msgstr "Garis luar dan ekstensi untuk menutup celah, gunakan nol untuk dinonaktifkan"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Arah"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "Arah isi"
|
||||
|
||||
|
@ -9238,6 +9230,14 @@ msgid "Cloth Simulation"
|
|||
msgstr "Simulasi Kain"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Tambah efek kuas"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Kurangi efek kuas"
|
||||
|
||||
|
||||
msgid "Projected"
|
||||
msgstr "Terproyeksi"
|
||||
|
||||
|
@ -22960,14 +22960,6 @@ msgid "Thickness Profile"
|
|||
msgstr "Profil Ketebalan"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "CCW"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "CW"
|
||||
|
||||
|
||||
msgid "Quality Steps"
|
||||
msgstr "Step Kualitas"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-03-01 16:11+0000\n"
|
||||
|
@ -3928,18 +3928,6 @@ msgid "Curve used for the strength"
|
|||
msgstr "Curva usata per la forza"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Direzione"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Aggiunge l'effetto del pennello"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Sottrae l'effetto del pennello"
|
||||
|
||||
|
||||
msgid "Dissolve"
|
||||
msgstr "Dissolvi"
|
||||
|
||||
|
@ -3968,6 +3956,10 @@ msgid "Closure Size"
|
|||
msgstr "Dimensione della Chiusura"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "Direzione"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "Direzione del riempimento"
|
||||
|
||||
|
@ -13247,6 +13239,14 @@ msgid "Color of cursor when subtracting"
|
|||
msgstr "Colore del cursore quando sottrae"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "Aggiunge l'effetto del pennello"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "Sottrae l'effetto del pennello"
|
||||
|
||||
|
||||
msgid "Falloff Angle"
|
||||
msgstr "Angolo Decadimento"
|
||||
|
||||
|
@ -54252,14 +54252,6 @@ msgid "Mask Value"
|
|||
msgstr "Valore Maschera"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "Senso Antiorario"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "Senso Orario"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Copy Active to Selected Objects"
|
||||
msgstr "Copia Attivo a Oggetti Selezionati"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: 2024-03-12 05:27+0000\n"
|
||||
|
@ -4487,18 +4487,6 @@ msgid "Number of pixels to expand or contract fill area"
|
|||
msgstr "フィルエリアを拡大,または縮小するピクセル数"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "方向"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "ブラシにエフェクトを追加"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "ブラシの効果を差し引きます"
|
||||
|
||||
|
||||
msgid "Eraser Mode"
|
||||
msgstr "消しゴムモード"
|
||||
|
||||
|
@ -4547,6 +4535,10 @@ msgid "Strokes end extension for closing gaps, use zero to disable"
|
|||
msgstr "ストロークの端を延長し,隙間を埋めます(0で無効)"
|
||||
|
||||
|
||||
msgid "Direction"
|
||||
msgstr "方向"
|
||||
|
||||
|
||||
msgid "Direction of the fill"
|
||||
msgstr "フィルの方向"
|
||||
|
||||
|
@ -20833,6 +20825,14 @@ msgid "Amount of random elements that are going to be affected by the brush"
|
|||
msgstr "このブラシにより影響を受けるランダム要素の量"
|
||||
|
||||
|
||||
msgid "Add effect of brush"
|
||||
msgstr "ブラシにエフェクトを追加"
|
||||
|
||||
|
||||
msgid "Subtract effect of brush"
|
||||
msgstr "ブラシの効果を差し引きます"
|
||||
|
||||
|
||||
msgid "Max Element Distance"
|
||||
msgstr "要素の最大距離"
|
||||
|
||||
|
@ -115570,14 +115570,6 @@ msgid "Caps Type"
|
|||
msgstr "端のタイプ"
|
||||
|
||||
|
||||
msgid "CCW"
|
||||
msgstr "反時計回り"
|
||||
|
||||
|
||||
msgid "CW"
|
||||
msgstr "時計回り"
|
||||
|
||||
|
||||
msgid "Invert to Fill"
|
||||
msgstr "反転をフィルに"
|
||||
|
||||
|
@ -122326,18 +122318,6 @@ msgid "Auto Smooth"
|
|||
msgstr "自動スムーズ"
|
||||
|
||||
|
||||
msgid "Socket_1"
|
||||
msgstr "ソケット_1"
|
||||
|
||||
|
||||
msgid "Input_1_use_attribute"
|
||||
msgstr "入力_1_属性使用"
|
||||
|
||||
|
||||
msgid "Input_1_attribute_name"
|
||||
msgstr "入力_1_属性名"
|
||||
|
||||
|
||||
msgid "Tangent space can only be computed for tris/quads, aborting"
|
||||
msgstr "タンジェント空間は三角面/四角面のみ計算可能です.中止します"
|
||||
|
||||
|
@ -123759,10 +123739,6 @@ msgid "No object found to operate on"
|
|||
msgstr "操作するオブジェクトがありません"
|
||||
|
||||
|
||||
msgid "Bone collections can only be added to an Armature"
|
||||
msgstr "ボーンコレクションはアーマチュアにのみ追加可能です"
|
||||
|
||||
|
||||
msgid "Cannot add bone collections to a linked Armature without an override"
|
||||
msgstr "オーバーライドのないリンク中のアーマチュアにはボーンコレクションを追加できません"
|
||||
|
||||
|
@ -123771,10 +123747,6 @@ msgid "Cannot add bone collections to a linked Armature with a system override;
|
|||
msgstr "システムオーバーライドのあるリンク中のアーマチュアにボーンコレクションを追加できません.アーマチュアにオーバーライドを明示的に作成してください"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "ボーンコレクションはアーマチュアでのみ編集できます"
|
||||
|
||||
|
||||
msgid "Cannot update a linked Armature with a system override; explicitly create an override on the Armature"
|
||||
msgstr "システムオーバーライドのあるリンク中アーマチュアは更新できません.アーマチュアにオーバーライドを明示的に作成してください"
|
||||
|
||||
|
@ -123787,6 +123759,10 @@ msgid "Cannot edit bone collections that are linked from another blend file"
|
|||
msgstr "他の blend ファイルからリンク中のボーンコレクションの編集はできません"
|
||||
|
||||
|
||||
msgid "Bone collections can only be edited on an Armature"
|
||||
msgstr "ボーンコレクションはアーマチュアでのみ編集できます"
|
||||
|
||||
|
||||
msgid "Cannot edit bone collections on linked Armatures without override"
|
||||
msgstr "オーバーライドのない,リンク中のアーマチュアのボーンコレクションは編集できません"
|
||||
|
||||
|
@ -124366,6 +124342,10 @@ msgid "Data-block inputs are unsupported"
|
|||
msgstr "データブロック入力は未対応です"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "ノードグループの最初の出力はジオメトリにしてください"
|
||||
|
||||
|
||||
msgid "Annotation Create Poly: LMB click to place next stroke vertex | ESC/Enter to end (or click outside this area)"
|
||||
msgstr "アノテーションポリ作成:左クリックで次のストローク頂点配置 | Esc/Enter(またはエリア外をクリック)で終了"
|
||||
|
||||
|
@ -134365,10 +134345,6 @@ msgid "Node group must have an output socket"
|
|||
msgstr "ノードグループに出力ソケットが必要です"
|
||||
|
||||
|
||||
msgid "Node group's first output must be a geometry"
|
||||
msgstr "ノードグループの最初の出力はジオメトリにしてください"
|
||||
|
||||
|
||||
msgid "NormalEdit"
|
||||
msgstr "法線編集"
|
||||
|
||||
|
|
1162
locale/po/ka.po
1162
locale/po/ka.po
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Beta (b'4b7cc5b6608a')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Release Candidate (b'64bfe491645f')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-01 00:00+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue