Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_files/buildbot/master.cfg368
-rw-r--r--build_files/buildbot/master_unpack.py151
-rw-r--r--build_files/buildbot/slave_compile.py7
-rw-r--r--intern/cycles/blender/blender_mesh.cpp2
-rw-r--r--intern/cycles/blender/blender_session.cpp10
-rw-r--r--intern/cycles/blender/blender_shader.cpp16
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h8
-rw-r--r--intern/cycles/kernel/kernel_types.h13
-rw-r--r--intern/cycles/kernel/kernel_volume.h15
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/node_principled_volume.osl94
-rw-r--r--intern/cycles/kernel/svm/svm.h5
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h117
-rw-r--r--intern/cycles/kernel/svm/svm_types.h1
-rw-r--r--intern/cycles/render/attribute.cpp35
-rw-r--r--intern/cycles/render/attribute.h1
-rw-r--r--intern/cycles/render/graph.h1
-rw-r--r--intern/cycles/render/nodes.cpp166
-rw-r--r--intern/cycles/render/nodes.h33
-rw-r--r--intern/cycles/render/object.cpp9
-rw-r--r--intern/cycles/render/osl.cpp13
-rw-r--r--intern/cycles/render/osl.h2
-rw-r--r--intern/cycles/render/shader.cpp3
-rw-r--r--intern/cycles/render/shader.h1
-rw-r--r--intern/cycles/render/svm.cpp11
-rw-r--r--intern/cycles/render/svm.h1
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py98
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/smoke.c4
-rw-r--r--source/blender/editors/space_node/drawnode.c25
-rw-r--r--source/blender/editors/space_node/node_draw.c8
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp24
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c44
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.c85
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_scatter.c2
40 files changed, 688 insertions, 692 deletions
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
deleted file mode 100644
index e3101430e50..00000000000
--- a/build_files/buildbot/master.cfg
+++ /dev/null
@@ -1,368 +0,0 @@
-# -*- python -*-
-# ex: set syntax=python:
-
-# <pep8 compliant>
-
-# List of the branches being built automatically overnight
-NIGHT_SCHEDULE_BRANCHES = [None, "blender2.8"]
-
-# List of the branches available for force build
-FORCE_SCHEDULE_BRANCHES = ["master", "blender2.8", "experimental-build"]
-
-"""
-Stock Twisted directory lister doesn't provide any information about last file
-modification time, we hack the class a bit in order to have such functionaliity
-:)
-"""
-
-from buildbot.status.web.base import DirectoryLister
-
-
-def get_files_and_directories(self, directory):
- from twisted.web.static import (getTypeAndEncoding,
- formatFileSize)
- import urllib
- import cgi
- import time
- import os
- files = []
- dirs = []
- for path in directory:
- url = urllib.quote(path, "/")
- escapedPath = cgi.escape(path)
- lastmodified = time.ctime(os.path.getmtime(
- os.path.join(self.path, path)))
- if os.path.isdir(os.path.join(self.path, path)):
- url = url + '/'
- dirs.append({'text': escapedPath + "/", 'href': url,
- 'size': '', 'type': '[Directory]',
- 'encoding': '',
- 'lastmodified': lastmodified})
- else:
- mimetype, encoding = getTypeAndEncoding(path, self.contentTypes,
- self.contentEncodings,
- self.defaultType)
- try:
- size = os.stat(os.path.join(self.path, path)).st_size
- except OSError:
- continue
- files.append({
- 'text': escapedPath, "href": url,
- 'type': '[%s]' % mimetype,
- 'encoding': (encoding and '[%s]' % encoding or ''),
- 'size': formatFileSize(size),
- 'lastmodified': lastmodified})
- return dirs, files
-DirectoryLister._getFilesAndDirectories = get_files_and_directories
-
-# Dictionary that the buildmaster pays attention to.
-c = BuildmasterConfig = {}
-
-# BUILD SLAVES
-#
-# We load the slaves and their passwords from a separator file, so we can have
-# this one in SVN.
-
-from buildbot.buildslave import BuildSlave
-import master_private
-
-c['slaves'] = []
-
-for slave in master_private.slaves:
- c['slaves'].append(BuildSlave(slave['name'], slave['password']))
-
-# TCP port through which slaves connect
-
-c['slavePortnum'] = 9989
-
-# CHANGE SOURCES
-
-from buildbot.changes.svnpoller import SVNPoller
-from buildbot.changes.gitpoller import GitPoller
-
-c['change_source'] = GitPoller(
- 'git://git.blender.org/blender.git',
- pollinterval=1200)
-
-
-# CODEBASES
-#
-# Allow to control separately things like branches for each repo and submodules.
-
-all_repositories = {
- r'git://git.blender.org/blender.git': 'blender',
- r'git://git.blender.org/blender-translations.git': 'blender-translations',
- r'git://git.blender.org/blender-addons.git': 'blender-addons',
- r'git://git.blender.org/blender-addons-contrib.git': 'blender-addons-contrib',
- r'git://git.blender.org/blender-dev-tools.git': 'blender-dev-tools',
- r'https://svn.blender.org/svnroot/bf-blender/': 'lib svn',
-}
-
-
-def codebaseGenerator(chdict):
- return all_repositories[chdict['repository']]
-
-c['codebaseGenerator'] = codebaseGenerator
-
-
-# SCHEDULERS
-#
-# Decide how to react to incoming changes.
-
-# from buildbot.scheduler import Scheduler
-from buildbot.schedulers import timed, forcesched
-
-c['schedulers'] = []
-
-
-def schedule_force_build(name):
- c['schedulers'].append(forcesched.ForceScheduler(name='force ' + name,
- builderNames=[name],
- codebases=[forcesched.CodebaseParameter(
- codebase="blender",
- branch=forcesched.ChoiceStringParameter(
- name="branch", choices=FORCE_SCHEDULE_BRANCHES, default="master"),
- # Do not hide revision, can be handy!
- repository=forcesched.FixedParameter(name="repository", default="", hide=True),
- project=forcesched.FixedParameter(name="project", default="", hide=True)),
- # For now, hide other codebases.
- forcesched.CodebaseParameter(hide=True, codebase="blender-translations"),
- forcesched.CodebaseParameter(
- codebase="blender-addons",
- branch=forcesched.ChoiceStringParameter(
- name="branch", choices=["master", "blender2.8"], default="master"),
- repository=forcesched.FixedParameter(name="repository", default="", hide=True),
- project=forcesched.FixedParameter(name="project", default="", hide=True),
- revision=forcesched.FixedParameter(name="revision", default="", hide=True),
- ),
- forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"),
- forcesched.CodebaseParameter(hide=True, codebase="blender-dev-tools"),
- forcesched.CodebaseParameter(hide=True, codebase="lib svn")],
- properties=[]))
-
-
-def schedule_build(name, hour, minute=0):
- for current_branch in NIGHT_SCHEDULE_BRANCHES:
- scheduler_name = "nightly " + name
- if current_branch:
- scheduler_name += ' ' + current_branch
- # Use special addons submodule branch when building blender2.8 branch.
- addons_branch = "master"
- if current_branch == "blender2.8":
- addons_branch = "blender2.8"
- c['schedulers'].append(timed.Nightly(name=scheduler_name,
- codebases={
- "blender": {"repository": ""},
- "blender-translations": {"repository": "", "branch": "master"},
- "blender-addons": {"repository": "", "branch": addons_branch},
- "blender-addons-contrib": {"repository": "", "branch": "master"},
- "blender-dev-tools": {"repository": "", "branch": "master"},
- "lib svn": {"repository": "", "branch": "trunk"}},
- branch=current_branch,
- builderNames=[name],
- hour=hour,
- minute=minute))
-
-
-# BUILDERS
-#
-# The 'builders' list defines the Builders, which tell Buildbot how to
-# perform a build: what steps, and which slaves can execute them.
-# Note that any particular build will only take place on one slave.
-
-from buildbot.process.factory import BuildFactory
-from buildbot.process.properties import Interpolate
-from buildbot.steps.source import SVN
-from buildbot.steps.source import Git
-from buildbot.steps.shell import ShellCommand
-from buildbot.steps.shell import Compile
-from buildbot.steps.shell import Test
-from buildbot.steps.transfer import FileUpload
-from buildbot.steps.master import MasterShellCommand
-from buildbot.config import BuilderConfig
-
-# add builder utility
-
-c['builders'] = []
-buildernames = []
-
-
-def add_builder(c, name, libdir, factory, branch='',
- rsync=False, hour=3, minute=0):
- slavenames = []
-
- for slave in master_private.slaves:
- if name in slave['builders']:
- slavenames.append(slave['name'])
-
- if len(slavenames) > 0:
- f = factory(name, libdir, branch, rsync)
- c['builders'].append(BuilderConfig(name=name,
- slavenames=slavenames,
- factory=f,
- category='blender'))
- buildernames.append(name)
-
- schedule_build(name, hour, minute)
- schedule_force_build(name)
-
-# common steps
-
-
-def git_submodule_step(submodule):
- return Git(name=submodule + '.git',
- repourl='git://git.blender.org/' + submodule + '.git',
- mode='update',
- codebase=submodule,
- workdir=submodule + '.git')
-
-
-def git_step(branch=''):
- if branch:
- return Git(name='blender.git',
- repourl='git://git.blender.org/blender.git',
- mode='update',
- branch=branch,
- codebase='blender',
- workdir='blender.git',
- submodules=True)
- else:
- return Git(name='blender.git',
- repourl='git://git.blender.org/blender.git',
- mode='update',
- codebase='blender',
- workdir='blender.git',
- submodules=True)
-
-
-def git_submodules_update():
- command = ['git', 'submodule', 'update', '--remote']
- return ShellCommand(name='Submodules Update',
- command=command,
- description='updating',
- descriptionDone='up to date',
- workdir='blender.git')
-
-
-def lib_svn_step(dir):
- return SVN(name='lib svn',
- baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir,
- codebase='lib svn',
- mode='update',
- defaultBranch='trunk',
- workdir='lib/' + dir)
-
-
-def rsync_step(id, branch, rsync_script):
- return ShellCommand(name='rsync',
- command=['python', rsync_script, id, branch],
- description='uploading',
- descriptionDone='uploaded',
- workdir='install')
-
-# generic builder
-
-
-def generic_builder(id, libdir='', branch='', rsync=False):
- filename = 'uploaded/buildbot_upload_' + id + '.zip'
- compile_script = '../blender.git/build_files/buildbot/slave_compile.py'
- test_script = '../blender.git/build_files/buildbot/slave_test.py'
- pack_script = '../blender.git/build_files/buildbot/slave_pack.py'
- rsync_script = '../blender.git/build_files/buildbot/slave_rsync.py'
- unpack_script = 'master_unpack.py'
-
- f = BuildFactory()
- if libdir != '':
- f.addStep(lib_svn_step(libdir))
-
- for submodule in ('blender-translations',
- 'blender-addons',
- 'blender-addons-contrib',
- 'blender-dev-tools'):
- f.addStep(git_submodule_step(submodule))
-
- f.addStep(git_step(branch))
- f.addStep(git_submodules_update())
-
- f.addStep(Compile(command=['python', compile_script, id], timeout=3600))
- f.addStep(Test(command=['python', test_script, id]))
- f.addStep(ShellCommand(name='package',
- command=['python', pack_script, id, branch or Interpolate('%(src:blender:branch)s')],
- description='packaging',
- descriptionDone='packaged'))
- if rsync:
- f.addStep(rsync_step(id, branch, rsync_script))
- else:
- f.addStep(FileUpload(name='upload',
- slavesrc='buildbot_upload.zip',
- masterdest=filename,
- maxsize=180 * 1024 * 1024,
- workdir='install'))
- f.addStep(MasterShellCommand(name='unpack',
- command=['python2.7', unpack_script, filename],
- description='unpacking',
- descriptionDone='unpacked'))
- return f
-
-# Builders
-
-add_builder(c, 'mac_x86_64_10_9_cmake', 'darwin', generic_builder, hour=1)
-add_builder(c, 'linux_glibc219_i686_cmake', '', generic_builder, hour=2)
-add_builder(c, 'linux_glibc219_x86_64_cmake', '', generic_builder, hour=1)
-add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=1)
-add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=2)
-add_builder(c, 'win32_cmake_vc2015', 'windows_vc14', generic_builder, hour=3)
-add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=4)
-
-# STATUS TARGETS
-#
-# 'status' is a list of Status Targets. The results of each build will be
-# pushed to these targets. buildbot/status/*.py has a variety to choose from,
-# including web pages, email senders, and IRC bots.
-
-c['status'] = []
-
-from buildbot.status import html
-from buildbot.status.web import authz
-from buildbot.status.web import auth
-
-users = []
-for slave in master_private.slaves:
- users += [(slave['name'], slave['password'])]
-
-authz_cfg = authz.Authz(
- auth=auth.BasicAuth(users),
- # change any of these to True to enable; see the manual for more
- # options
- gracefulShutdown=False,
- forceBuild=True, # use this to test your slave once it is set up
- forceAllBuilds=False,
- pingBuilder=False,
- stopBuild=True,
- stopAllBuilds=False,
- cancelPendingBuild=True,
-)
-
-c['status'].append(html.WebStatus(http_port=8010, authz=authz_cfg))
-#c['status'].append(html.WebStatus(http_port=8010))
-
-# PROJECT IDENTITY
-
-c['projectName'] = "Blender"
-c['projectURL'] = "http://www.blender.org"
-
-# the 'buildbotURL' string should point to the location where the buildbot's
-# internal web server (usually the html.WebStatus page) is visible. This
-# typically uses the port number set in the Waterfall 'status' entry, but
-# with an externally-visible host name which the buildbot cannot figure out
-# without some help.
-
-c['buildbotURL'] = "http://builder.blender.org/"
-
-# DB URL
-#
-# This specifies what database buildbot uses to store change and scheduler
-# state. You can leave this at its default for all but the largest
-# installations.
-
-c['db_url'] = "sqlite:///state.sqlite"
diff --git a/build_files/buildbot/master_unpack.py b/build_files/buildbot/master_unpack.py
deleted file mode 100644
index 157e244e210..00000000000
--- a/build_files/buildbot/master_unpack.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# Runs on Buildbot master, to unpack incoming unload.zip into latest
-# builds directory and remove older builds.
-
-# <pep8 compliant>
-
-import os
-import shutil
-import sys
-import zipfile
-
-
-# extension stripping
-def strip_extension(filename):
- extensions = '.zip', '.tar', '.bz2', '.gz', '.tgz', '.tbz', '.exe'
-
- for ext in extensions:
- if filename.endswith(ext):
- filename = filename[:-len(ext)]
-
- return filename
-
-
-# extract platform from package name
-def get_platform(filename):
- # name is blender-version-platform.extension. we want to get the
- # platform out, but there may be some variations, so we fiddle a
- # bit to handle current and hopefully future names
- filename = strip_extension(filename)
- filename = strip_extension(filename)
-
- tokens = filename.split("-")
- platforms = ('osx', 'mac', 'bsd',
- 'win', 'linux', 'source',
- 'irix', 'solaris')
- platform_tokens = []
- found = False
-
- for i, token in enumerate(tokens):
- if not found:
- for platform in platforms:
- if platform in token.lower():
- found = True
- break
-
- if found:
- platform_tokens += [token]
-
- return '-'.join(platform_tokens)
-
-
-def get_branch(filename):
- if filename.startswith("blender-2.8"):
- return "blender2.8"
-
- tokens = filename.split("-")
- branch = ""
-
- for token in tokens:
- if token == "blender":
- return branch
-
- if branch == "":
- branch = token
- else:
- branch = branch + "-" + token
-
- return ""
-
-# get filename
-if len(sys.argv) < 2:
- sys.stderr.write("Not enough arguments, expecting file to unpack\n")
- sys.exit(1)
-
-filename = sys.argv[1]
-
-# open zip file
-if not os.path.exists(filename):
- sys.stderr.write("File %r not found.\n" % filename)
- sys.exit(1)
-
-try:
- z = zipfile.ZipFile(filename, "r")
-except Exception as ex:
- sys.stderr.write('Failed to open zip file: %s\n' % str(ex))
- sys.exit(1)
-
-if len(z.namelist()) != 1:
- sys.stderr.write("Expected one file in %r." % filename)
- sys.exit(1)
-
-package = z.namelist()[0]
-packagename = os.path.basename(package)
-
-# detect platform and branch
-platform = get_platform(packagename)
-branch = get_branch(packagename)
-
-if platform == '':
- sys.stderr.write('Failed to detect platform ' +
- 'from package: %r\n' % packagename)
- sys.exit(1)
-
-# extract
-if not branch or branch == 'master':
- directory = 'public_html/download'
-elif branch == 'experimental-build':
- directory = 'public_html/download/experimental'
-else:
- directory = 'public_html/download'
-
-try:
- filename = os.path.join(directory, packagename)
- zf = z.open(package)
- f = file(filename, "wb")
-
- shutil.copyfileobj(zf, f)
- os.chmod(filename, 0644)
-
- zf.close()
- z.close()
-except Exception as ex:
- sys.stderr.write('Failed to unzip package: %s\n' % str(ex))
- sys.exit(1)
-
-# remove other files from the same platform and branch
-try:
- for f in os.listdir(directory):
- if get_platform(f) == platform and get_branch(f) == branch:
- if f != packagename:
- os.remove(os.path.join(directory, f))
-except Exception as ex:
- sys.stderr.write('Failed to remove old packages: %s\n' % str(ex))
- sys.exit(1)
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index f2f8edc614d..ff19bcce758 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -73,8 +73,9 @@ if 'cmake' in builder:
if builder.endswith('x86_64_10_9_cmake'):
cmake_extra_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
cmake_extra_options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.9')
- cmake_extra_options.append('-DCUDA_HOST_COMPILER=/usr/local/cuda-hack/clang')
- cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/nvcc')
+ # Used to trick CUDFA to see CLang as an older version.
+ # cmake_extra_options.append('-DCUDA_HOST_COMPILER=/usr/local/cuda-hack/clang')
+ # cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/nvcc')
elif builder.startswith('win'):
if builder.endswith('_vc2015'):
@@ -116,7 +117,7 @@ if 'cmake' in builder:
# Prepare CMake options needed to configure cuda binaries compilation, 64bit only.
if bits == 64:
cuda_cmake_options.append("-DWITH_CYCLES_CUDA_BINARIES=%s" % ('ON' if build_cubins else 'OFF'))
- cuda_cmake_options.append("-DCYCLES_CUDA_BINARIES_ARCH=sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61")
+ cuda_cmake_options.append("-DCYCLES_CUDA_BINARIES_ARCH=sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61;sm_70")
if build_cubins or 'cuda' in targets:
cuda_cmake_options.append("-DCUDA_64_BIT_DEVICE_CODE=ON")
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index df1b1a4ca10..bda6306d11f 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -367,6 +367,8 @@ static void create_mesh_volume_attributes(Scene *scene,
create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame);
if(mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT))
create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame);
+ if(mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE))
+ create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame);
if(mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY))
create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 60e49161be2..a40ba0706b4 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -1071,7 +1071,8 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT))
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
channels = 1;
else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
channels = 4;
@@ -1292,6 +1293,13 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
return true;
}
}
+ else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
+ SmokeDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
+ if(length == num_pixels) {
+ SmokeDomainSettings_temperature_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
else {
fprintf(stderr,
"Cycles error: unknown volume attribute %s, skipping\n",
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 131e76d106e..7d3abe35b20 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -560,6 +560,10 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
node = new AbsorptionVolumeNode();
}
+ else if(b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
+ PrincipledVolumeNode *principled = new PrincipledVolumeNode();
+ node = principled;
+ }
else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
node = new GeometryNode();
}
@@ -1028,6 +1032,10 @@ static void add_nodes(Scene *scene,
for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
BL::NodeSocket to_socket(b_link->to_socket());
SocketType::Type to_socket_type = convert_socket_type(to_socket);
+ if (to_socket_type == SocketType::UNDEFINED) {
+ continue;
+ }
+
ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
@@ -1051,6 +1059,10 @@ static void add_nodes(Scene *scene,
*/
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
SocketType::Type input_type = convert_socket_type(*b_input);
+ if (input_type == SocketType::UNDEFINED) {
+ continue;
+ }
+
ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
graph->add(proxy);
@@ -1063,6 +1075,10 @@ static void add_nodes(Scene *scene,
}
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
SocketType::Type output_type = convert_socket_type(*b_output);
+ if (output_type == SocketType::UNDEFINED) {
+ continue;
+ }
+
ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
graph->add(proxy);
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index 6be448c4fa4..286d898992e 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -68,7 +68,13 @@ ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *s
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
- return float4_to_float3(r);
+ if(r.w != 0.0f && r.w != 1.0f) {
+ /* For RGBA colors, unpremultiply after interpolation. */
+ return float4_to_float3(r) / r.w;
+ }
+ else {
+ return float4_to_float3(r);
+ }
}
#endif
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 44e7fd46adc..d967edca75d 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -798,6 +798,7 @@ typedef enum AttributeStandard {
ATTR_STD_VOLUME_COLOR,
ATTR_STD_VOLUME_FLAME,
ATTR_STD_VOLUME_HEAT,
+ ATTR_STD_VOLUME_TEMPERATURE,
ATTR_STD_VOLUME_VELOCITY,
ATTR_STD_POINTINESS,
ATTR_STD_NUM,
@@ -924,19 +925,22 @@ enum ShaderDataFlag {
SD_HAS_DISPLACEMENT = (1 << 26),
/* Has constant emission (value stored in __shader_flag) */
SD_HAS_CONSTANT_EMISSION = (1 << 27),
+ /* Needs to access attributes */
+ SD_NEED_ATTRIBUTES = (1 << 28),
SD_SHADER_FLAGS = (SD_USE_MIS |
SD_HAS_TRANSPARENT_SHADOW |
SD_HAS_VOLUME |
SD_HAS_ONLY_VOLUME |
- SD_HETEROGENEOUS_VOLUME|
+ SD_HETEROGENEOUS_VOLUME |
SD_HAS_BSSRDF_BUMP |
SD_VOLUME_EQUIANGULAR |
SD_VOLUME_MIS |
SD_VOLUME_CUBIC |
SD_HAS_BUMP |
SD_HAS_DISPLACEMENT |
- SD_HAS_CONSTANT_EMISSION)
+ SD_HAS_CONSTANT_EMISSION |
+ SD_NEED_ATTRIBUTES)
};
/* Object flags. */
@@ -957,6 +961,8 @@ enum ShaderDataObjectFlag {
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
/* object is used to catch shadows */
SD_OBJECT_SHADOW_CATCHER = (1 << 7),
+ /* object has volume attributes */
+ SD_OBJECT_HAS_VOLUME_ATTRIBUTES = (1 << 8),
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK |
SD_OBJECT_MOTION |
@@ -964,7 +970,8 @@ enum ShaderDataObjectFlag {
SD_OBJECT_NEGATIVE_SCALE_APPLIED |
SD_OBJECT_HAS_VOLUME |
SD_OBJECT_INTERSECTS_VOLUME |
- SD_OBJECT_SHADOW_CATCHER)
+ SD_OBJECT_SHADOW_CATCHER |
+ SD_OBJECT_HAS_VOLUME_ATTRIBUTES)
};
typedef ccl_addr_space struct ShaderData {
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 3274e05f98e..058e7dccafd 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -106,8 +106,21 @@ ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE);
- if(shader_flag & SD_HETEROGENEOUS_VOLUME)
+ if(shader_flag & SD_HETEROGENEOUS_VOLUME) {
return true;
+ }
+ else if(shader_flag & SD_NEED_ATTRIBUTES) {
+ /* We want to render world or objects without any volume grids
+ * as homogenous, but can only verify this at runtime since other
+ * heterogenous volume objects may be using the same shader. */
+ int object = stack[i].object;
+ if(object != OBJECT_NONE) {
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if(object_flag & SD_OBJECT_HAS_VOLUME_ATTRIBUTES) {
+ return true;
+ }
+ }
+ }
}
return false;
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 19b7769200e..6ec651a96d8 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -36,6 +36,7 @@ set(SRC_OSL
node_hair_info.osl
node_scatter_volume.osl
node_absorption_volume.osl
+ node_principled_volume.osl
node_holdout.osl
node_hsv.osl
node_image_texture.osl
diff --git a/intern/cycles/kernel/shaders/node_principled_volume.osl b/intern/cycles/kernel/shaders/node_principled_volume.osl
new file mode 100644
index 00000000000..609fb95866d
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_principled_volume.osl
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdosl.h"
+
+shader node_principled_volume(
+ color Color = color(0.5, 0.5, 0.5),
+ float Density = 1.0,
+ float Anisotropy = 0.0,
+ color AbsorptionColor = color(0.0, 0.0, 0.0),
+ float EmissionStrength = 0.0,
+ color EmissionColor = color(1.0, 1.0, 1.0),
+ float BlackbodyIntensity = 0.0,
+ color BlackbodyTint = color(1.0, 1.0, 1.0),
+ float Temperature = 1500.0,
+ string DensityAttribute = "geom:density",
+ string ColorAttribute = "geom:color",
+ string TemperatureAttribute = "geom:temperature",
+ output closure color Volume = 0)
+{
+ /* Compute density. */
+ float primitive_density = 1.0;
+ float density = max(Density, 0.0);
+
+ if(density > 1e-5) {
+ if(getattribute(DensityAttribute, primitive_density)) {
+ density = max(density * primitive_density, 0.0);
+ }
+ }
+
+ if(density > 1e-5) {
+ /* Compute scattering color. */
+ color scatter_color = Color;
+ color primitive_color;
+ if(getattribute(ColorAttribute, primitive_color)) {
+ scatter_color *= primitive_color;
+ }
+
+ /* Add scattering and absorption closures. */
+ color scatter_coeff = scatter_color;
+ color absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - AbsorptionColor, 0.0);
+ Volume = scatter_coeff * density * henyey_greenstein(Anisotropy) +
+ absorption_coeff * density * absorption();
+ }
+
+ /* Compute emission. */
+ float emission_strength = max(EmissionStrength, 0.0);
+ float blackbody_intensity = BlackbodyIntensity;
+
+ if(emission_strength > 1e-5) {
+ Volume += emission_strength * EmissionColor * emission();
+ }
+
+ if(blackbody_intensity > 1e-3) {
+ float T = Temperature;
+
+ /* Add temperature from attribute if available. */
+ float temperature;
+ if(getattribute(TemperatureAttribute, temperature)) {
+ T *= max(temperature, 0.0);
+ }
+
+ T = max(T, 0.0);
+
+ /* Stefan-Boltzman law. */
+ float T4 = (T * T) * (T * T);
+ float sigma = 5.670373e-8 * 1e-6 / M_PI;
+ float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+
+ if(intensity > 1e-5) {
+ color bb = blackbody(T);
+ float l = luminance(bb);
+
+ if(l != 0.0) {
+ bb *= BlackbodyTint * intensity / l;
+ Volume += bb * emission();
+ }
+ }
+ }
+}
+
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index fae9f783483..39cd5da7b12 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -334,7 +334,10 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
break;
# if NODES_FEATURE(NODE_FEATURE_VOLUME)
case NODE_CLOSURE_VOLUME:
- svm_node_closure_volume(kg, sd, stack, node, type, path_flag);
+ svm_node_closure_volume(kg, sd, stack, node, type);
+ break;
+ case NODE_PRINCIPLED_VOLUME:
+ svm_node_principled_volume(kg, sd, stack, node, type, path_flag, &offset);
break;
# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
# ifdef __EXTRA_NODES__
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 24452c81fe0..819b256bde0 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -794,7 +794,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
}
}
-ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag)
+ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type)
{
#ifdef __VOLUME__
/* Only sum extinction for volumes, variable is shared with surface transparency. */
@@ -802,19 +802,20 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
return;
}
- uint type, param1_offset, param2_offset;
+ uint type, density_offset, anisotropy_offset;
uint mix_weight_offset;
- decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
+ decode_node_uchar4(node.y, &type, &density_offset, &anisotropy_offset, &mix_weight_offset);
float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
- if(mix_weight == 0.0f)
+ if(mix_weight == 0.0f) {
return;
+ }
- float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
+ float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(node.z);
+ density = mix_weight * fmaxf(density, 0.0f);
/* Compute scattering coefficient. */
- float density = mix_weight * fmaxf(param1, 0.0f);
float3 weight = sd->svm_closure_weight;
if(type == CLOSURE_VOLUME_ABSORPTION_ID) {
@@ -825,11 +826,11 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
/* Add closure for volume scattering. */
if(type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
- float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
if(volume) {
- volume->g = param2; /* g */
+ float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(node.w);
+ volume->g = anisotropy; /* g */
sd->flag |= volume_henyey_greenstein_setup(volume);
}
}
@@ -839,6 +840,106 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
#endif
}
+ccl_device void svm_node_principled_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag, int *offset)
+{
+#ifdef __VOLUME__
+ uint4 value_node = read_node(kg, offset);
+ uint4 attr_node = read_node(kg, offset);
+
+ /* Only sum extinction for volumes, variable is shared with surface transparency. */
+ if(shader_type != SHADER_TYPE_VOLUME) {
+ return;
+ }
+
+ uint density_offset, anisotropy_offset, absorption_color_offset, mix_weight_offset;
+ decode_node_uchar4(node.y, &density_offset, &anisotropy_offset, &absorption_color_offset, &mix_weight_offset);
+ float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
+
+ if(mix_weight == 0.0f) {
+ return;
+ }
+
+ /* Compute density. */
+ float primitive_density = 1.0f;
+ float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(value_node.x);
+ density = mix_weight * fmaxf(density, 0.0f);
+
+ if(density > CLOSURE_WEIGHT_CUTOFF) {
+ /* Density and color attribute lookup if available. */
+ const AttributeDescriptor attr_density = find_attribute(kg, sd, attr_node.x);
+ if(attr_density.offset != ATTR_STD_NOT_FOUND) {
+ primitive_density = primitive_attribute_float(kg, sd, attr_density, NULL, NULL);
+ density = fmaxf(density * primitive_density, 0.0f);
+ }
+ }
+
+ if(density > CLOSURE_WEIGHT_CUTOFF) {
+ /* Compute scattering color. */
+ float3 color = sd->svm_closure_weight;
+
+ const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y);
+ if(attr_color.offset != ATTR_STD_NOT_FOUND) {
+ color *= primitive_attribute_float3(kg, sd, attr_color, NULL, NULL);
+ }
+
+ /* Add closure for volume scattering. */
+ HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), color * density);
+ if(volume) {
+ float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(value_node.y);
+ volume->g = anisotropy;
+ sd->flag |= volume_henyey_greenstein_setup(volume);
+ }
+
+ /* Add extinction weight. */
+ float3 zero = make_float3(0.0f, 0.0f, 0.0f);
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 absorption_color = stack_load_float3(stack, absorption_color_offset);
+ float3 absorption = max(one - color, zero) * max(one - absorption_color, zero);
+ volume_extinction_setup(sd, (color + absorption) * density);
+ }
+
+ /* Compute emission. */
+ if(path_flag & PATH_RAY_SHADOW) {
+ /* Don't need emission for shadows. */
+ return;
+ }
+
+ uint emission_offset, emission_color_offset, blackbody_offset, temperature_offset;
+ decode_node_uchar4(node.z, &emission_offset, &emission_color_offset, &blackbody_offset, &temperature_offset);
+ float emission = (stack_valid(emission_offset))? stack_load_float(stack, emission_offset): __uint_as_float(value_node.z);
+ float blackbody = (stack_valid(blackbody_offset))? stack_load_float(stack, blackbody_offset): __uint_as_float(value_node.w);
+
+ if(emission > CLOSURE_WEIGHT_CUTOFF) {
+ float3 emission_color = stack_load_float3(stack, emission_color_offset);
+ emission_setup(sd, emission * emission_color);
+ }
+
+ if(blackbody > CLOSURE_WEIGHT_CUTOFF) {
+ float T = stack_load_float(stack, temperature_offset);
+
+ /* Add flame temperature from attribute if available. */
+ const AttributeDescriptor attr_temperature = find_attribute(kg, sd, attr_node.z);
+ if(attr_temperature.offset != ATTR_STD_NOT_FOUND) {
+ float temperature = primitive_attribute_float(kg, sd, attr_temperature, NULL, NULL);
+ T *= fmaxf(temperature, 0.0f);
+ }
+
+ T = fmaxf(T, 0.0f);
+
+ /* Stefan-Boltzmann law. */
+ float T4 = sqr(sqr(T));
+ float sigma = 5.670373e-8f * 1e-6f / M_PI_F;
+ float intensity = sigma * mix(1.0f, T4, blackbody);
+
+ if(intensity > CLOSURE_WEIGHT_CUTOFF) {
+ float3 blackbody_tint = stack_load_float3(stack, node.w);
+ float3 bb = blackbody_tint * intensity * svm_math_blackbody_color(T);
+ emission_setup(sd, bb);
+ }
+ }
+#endif
+}
+
ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
{
uint mix_weight_offset = node.y;
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 390d3255684..4c3a5975fb8 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -135,6 +135,7 @@ typedef enum ShaderNodeType {
NODE_BEVEL,
NODE_DISPLACEMENT,
NODE_VECTOR_DISPLACEMENT,
+ NODE_PRINCIPLED_VOLUME,
} ShaderNodeType;
typedef enum NodeAttributeType {
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 2c22db8189d..6816f8ca3f3 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -281,6 +281,8 @@ const char *Attribute::standard_name(AttributeStandard std)
return "flame";
case ATTR_STD_VOLUME_HEAT:
return "heat";
+ case ATTR_STD_VOLUME_TEMPERATURE:
+ return "temperature";
case ATTR_STD_VOLUME_VELOCITY:
return "velocity";
case ATTR_STD_POINTINESS:
@@ -296,9 +298,13 @@ const char *Attribute::standard_name(AttributeStandard std)
AttributeStandard Attribute::name_standard(const char *name)
{
- for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
- if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0)
- return (AttributeStandard)std;
+ if(name) {
+ for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
+ if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
+ return (AttributeStandard)std;
+ }
+ }
+ }
return ATTR_STD_NONE;
}
@@ -425,6 +431,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_VOLUME_DENSITY:
case ATTR_STD_VOLUME_FLAME:
case ATTR_STD_VOLUME_HEAT:
+ case ATTR_STD_VOLUME_TEMPERATURE:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
break;
case ATTR_STD_VOLUME_COLOR:
@@ -612,9 +619,11 @@ bool AttributeRequestSet::modified(const AttributeRequestSet& other)
void AttributeRequestSet::add(ustring name)
{
- foreach(AttributeRequest& req, requests)
- if(req.name == name)
+ foreach(AttributeRequest& req, requests) {
+ if(req.name == name) {
return;
+ }
+ }
requests.push_back(AttributeRequest(name));
}
@@ -638,6 +647,22 @@ void AttributeRequestSet::add(AttributeRequestSet& reqs)
}
}
+void AttributeRequestSet::add_standard(ustring name)
+{
+ if(!name) {
+ return;
+ }
+
+ AttributeStandard std = Attribute::name_standard(name.c_str());
+
+ if(std) {
+ add(std);
+ }
+ else {
+ add(name);
+ }
+}
+
bool AttributeRequestSet::find(ustring name)
{
foreach(AttributeRequest& req, requests)
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index d15ee401a72..9e23345675d 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -159,6 +159,7 @@ public:
void add(ustring name);
void add(AttributeStandard std);
void add(AttributeRequestSet& reqs);
+ void add_standard(ustring name);
bool find(ustring name);
bool find(AttributeStandard std);
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 7ed292b5b96..2c134932b3c 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -156,6 +156,7 @@ public:
virtual bool has_bssrdf_bump() { return false; }
virtual bool has_spatial_varying() { return false; }
virtual bool has_object_dependency() { return false; }
+ virtual bool has_attribute_dependency() { return false; }
virtual bool has_integrator_dependency() { return false; }
virtual bool has_volume_support() { return false; }
virtual bool has_raytrace() { return false; }
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 56c9e669a5c..7006fb6fe1d 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -208,7 +208,7 @@ NODE_DEFINE(ImageTextureNode)
TEXTURE_MAPPING_DEFINE(ImageTextureNode);
- SOCKET_STRING(filename, "Filename", ustring(""));
+ SOCKET_STRING(filename, "Filename", ustring());
static NodeEnum color_space_enum;
color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
@@ -419,7 +419,7 @@ NODE_DEFINE(EnvironmentTextureNode)
TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
- SOCKET_STRING(filename, "Filename", ustring(""));
+ SOCKET_STRING(filename, "Filename", ustring());
static NodeEnum color_space_enum;
color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
@@ -1348,7 +1348,7 @@ NODE_DEFINE(PointDensityTextureNode)
{
NodeType* type = NodeType::add("point_density_texture", create, NodeType::SHADER);
- SOCKET_STRING(filename, "Filename", ustring(""));
+ SOCKET_STRING(filename, "Filename", ustring());
static NodeEnum space_enum;
space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
@@ -2844,6 +2844,120 @@ void ScatterVolumeNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_scatter_volume");
}
+/* Principled Volume Closure */
+
+NODE_DEFINE(PrincipledVolumeNode)
+{
+ NodeType* type = NodeType::add("principled_volume", create, NodeType::SHADER);
+
+ SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
+ SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
+ SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
+
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
+ SOCKET_IN_COLOR(absorption_color, "Absorption Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
+ SOCKET_IN_COLOR(emission_color, "Emission Color", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
+ SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(temperature, "Temperature", 1500.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+
+ SOCKET_OUT_CLOSURE(volume, "Volume");
+
+ return type;
+}
+
+PrincipledVolumeNode::PrincipledVolumeNode()
+: VolumeNode(node_type)
+{
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+}
+
+void PrincipledVolumeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
+{
+ if(shader->has_volume) {
+ ShaderInput *density_in = input("Density");
+ ShaderInput *blackbody_in = input("Blackbody Intensity");
+
+ if(density_in->link || density > 0.0f) {
+ attributes->add_standard(density_attribute);
+ attributes->add_standard(color_attribute);
+ }
+
+ if(blackbody_in->link || blackbody_intensity > 0.0f) {
+ attributes->add_standard(temperature_attribute);
+ }
+
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PrincipledVolumeNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderInput *density_in = input("Density");
+ ShaderInput *anisotropy_in = input("Anisotropy");
+ ShaderInput *absorption_color_in = input("Absorption Color");
+ ShaderInput *emission_in = input("Emission Strength");
+ ShaderInput *emission_color_in = input("Emission Color");
+ ShaderInput *blackbody_in = input("Blackbody Intensity");
+ ShaderInput *blackbody_tint_in = input("Blackbody Tint");
+ ShaderInput *temperature_in = input("Temperature");
+
+ if(color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+
+ compiler.add_node(NODE_PRINCIPLED_VOLUME,
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(density_in),
+ compiler.stack_assign_if_linked(anisotropy_in),
+ compiler.stack_assign(absorption_color_in),
+ compiler.closure_mix_weight_offset()),
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(emission_in),
+ compiler.stack_assign(emission_color_in),
+ compiler.stack_assign_if_linked(blackbody_in),
+ compiler.stack_assign(temperature_in)),
+ compiler.stack_assign(blackbody_tint_in));
+
+ int attr_density = compiler.attribute_standard(density_attribute);
+ int attr_color = compiler.attribute_standard(color_attribute);
+ int attr_temperature = compiler.attribute_standard(temperature_attribute);
+
+ compiler.add_node(
+ __float_as_int(density),
+ __float_as_int(anisotropy),
+ __float_as_int(emission_strength),
+ __float_as_int(blackbody_intensity));
+
+ compiler.add_node(
+ attr_density,
+ attr_color,
+ attr_temperature);
+}
+
+void PrincipledVolumeNode::compile(OSLCompiler& compiler)
+{
+ if(Attribute::name_standard(density_attribute.c_str())) {
+ density_attribute = ustring("geom:" + density_attribute.string());
+ }
+ if(Attribute::name_standard(color_attribute.c_str())) {
+ color_attribute = ustring("geom:" + color_attribute.string());
+ }
+ if(Attribute::name_standard(temperature_attribute.c_str())) {
+ temperature_attribute = ustring("geom:" + temperature_attribute.string());
+ }
+
+ compiler.add(this, "node_principled_volume");
+}
+
/* Hair BSDF Closure */
NODE_DEFINE(HairBsdfNode)
@@ -3167,7 +3281,7 @@ NODE_DEFINE(UVMapNode)
{
NodeType* type = NodeType::add("uvmap", create, NodeType::SHADER);
- SOCKET_IN_STRING(attribute, "attribute", ustring(""));
+ SOCKET_STRING(attribute, "attribute", ustring());
SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
SOCKET_OUT_POINT(UV, "UV");
@@ -4465,7 +4579,7 @@ NODE_DEFINE(AttributeNode)
{
NodeType* type = NodeType::add("attribute", create, NodeType::SHADER);
- SOCKET_STRING(attribute, "Attribute", ustring(""));
+ SOCKET_STRING(attribute, "Attribute", ustring());
SOCKET_OUT_COLOR(color, "Color");
SOCKET_OUT_VECTOR(vector, "Vector");
@@ -4486,16 +4600,12 @@ void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
ShaderOutput *fac_out = output("Fac");
if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
- AttributeStandard std = Attribute::name_standard(attribute.c_str());
-
- if(std != ATTR_STD_NONE)
- attributes->add(std);
- else
- attributes->add(attribute);
+ attributes->add_standard(attribute);
}
- if(shader->has_volume)
+ if(shader->has_volume) {
attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
ShaderNode::attributes(shader, attributes);
}
@@ -4506,13 +4616,7 @@ void AttributeNode::compile(SVMCompiler& compiler)
ShaderOutput *vector_out = output("Vector");
ShaderOutput *fac_out = output("Fac");
ShaderNodeType attr_node = NODE_ATTR;
- AttributeStandard std = Attribute::name_standard(attribute.c_str());
- int attr;
-
- if(std != ATTR_STD_NONE)
- attr = compiler.attribute(std);
- else
- attr = compiler.attribute(attribute);
+ int attr = compiler.attribute_standard(attribute);;
if(bump == SHADER_BUMP_DX)
attr_node = NODE_ATTR_BUMP_DX;
@@ -5470,7 +5574,7 @@ NODE_DEFINE(NormalMapNode)
space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
SOCKET_ENUM(space, "Space", space_enum, NODE_TANGENT_RADIAL);
- SOCKET_STRING(attribute, "Attribute", ustring(""));
+ SOCKET_STRING(attribute, "Attribute", ustring());
SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
@@ -5489,7 +5593,7 @@ NormalMapNode::NormalMapNode()
void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute == ustring("")) {
+ if(attribute.empty()) {
attributes->add(ATTR_STD_UV_TANGENT);
attributes->add(ATTR_STD_UV_TANGENT_SIGN);
}
@@ -5512,7 +5616,7 @@ void NormalMapNode::compile(SVMCompiler& compiler)
int attr = 0, attr_sign = 0;
if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute == ustring("")) {
+ if(attribute.empty()) {
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
}
@@ -5534,7 +5638,7 @@ void NormalMapNode::compile(SVMCompiler& compiler)
void NormalMapNode::compile(OSLCompiler& compiler)
{
if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute == ustring("")) {
+ if(attribute.empty()) {
compiler.parameter("attr_name", ustring("geom:tangent"));
compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
}
@@ -5565,7 +5669,7 @@ NODE_DEFINE(TangentNode)
axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
- SOCKET_STRING(attribute, "Attribute", ustring(""));
+ SOCKET_STRING(attribute, "Attribute", ustring());
SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
SOCKET_OUT_NORMAL(tangent, "Tangent");
@@ -5582,7 +5686,7 @@ void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface) {
if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute == ustring(""))
+ if(attribute.empty())
attributes->add(ATTR_STD_UV_TANGENT);
else
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
@@ -5600,7 +5704,7 @@ void TangentNode::compile(SVMCompiler& compiler)
int attr;
if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute == ustring(""))
+ if(attribute.empty())
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
else
attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
@@ -5618,7 +5722,7 @@ void TangentNode::compile(SVMCompiler& compiler)
void TangentNode::compile(OSLCompiler& compiler)
{
if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute == ustring(""))
+ if(attribute.empty())
compiler.parameter("attr_name", ustring("geom:tangent"));
else
compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
@@ -5731,7 +5835,7 @@ NODE_DEFINE(VectorDisplacementNode)
space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
- SOCKET_STRING(attribute, "Attribute", ustring(""));
+ SOCKET_STRING(attribute, "Attribute", ustring());
SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
@@ -5750,7 +5854,7 @@ VectorDisplacementNode::VectorDisplacementNode()
void VectorDisplacementNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute == ustring("")) {
+ if(attribute.empty()) {
attributes->add(ATTR_STD_UV_TANGENT);
attributes->add(ATTR_STD_UV_TANGENT_SIGN);
}
@@ -5774,7 +5878,7 @@ void VectorDisplacementNode::compile(SVMCompiler& compiler)
int attr = 0, attr_sign = 0;
if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute == ustring("")) {
+ if(attribute.empty()) {
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
}
@@ -5797,7 +5901,7 @@ void VectorDisplacementNode::compile(SVMCompiler& compiler)
void VectorDisplacementNode::compile(OSLCompiler& compiler)
{
if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute == ustring("")) {
+ if(attribute.empty()) {
compiler.parameter("attr_name", ustring("geom:tangent"));
compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index f664ebf545d..33df2866341 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -82,6 +82,7 @@ public:
~ImageTextureNode();
ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
ImageManager *image_manager;
int is_float;
@@ -112,6 +113,7 @@ public:
~EnvironmentTextureNode();
ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ImageManager *image_manager;
@@ -257,6 +259,7 @@ public:
~PointDensityTextureNode();
ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
bool has_object_dependency() { return true; }
@@ -361,6 +364,7 @@ public:
ClosureType get_closure_type() { return distribution; }
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
};
class DiffuseBsdfNode : public BsdfNode {
@@ -394,6 +398,7 @@ public:
bool has_integrator_dependency();
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
};
class TranslucentBsdfNode : public BsdfNode {
@@ -556,6 +561,25 @@ public:
float anisotropy;
};
+class PrincipledVolumeNode : public VolumeNode {
+public:
+ SHADER_NODE_CLASS(PrincipledVolumeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
+
+ ustring density_attribute;
+ ustring color_attribute;
+ ustring temperature_attribute;
+
+ float anisotropy;
+ float3 absorption_color;
+ float emission_strength;
+ float3 emission_color;
+ float blackbody_intensity;
+ float3 blackbody_tint;
+ float temperature;
+};
+
class HairBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(HairBsdfNode)
@@ -572,6 +596,7 @@ class GeometryNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GeometryNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
float3 normal_osl;
@@ -581,6 +606,7 @@ class TextureCoordinateNode : public ShaderNode {
public:
SHADER_NODE_CLASS(TextureCoordinateNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
bool has_object_dependency() { return use_transform; }
@@ -594,6 +620,7 @@ class UVMapNode : public ShaderNode {
public:
SHADER_NODE_CLASS(UVMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
@@ -627,6 +654,7 @@ class ParticleInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ParticleInfoNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
@@ -635,6 +663,7 @@ public:
SHADER_NODE_CLASS(HairInfoNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
virtual int get_feature() {
@@ -796,6 +825,7 @@ class AttributeNode : public ShaderNode {
public:
SHADER_NODE_CLASS(AttributeNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
ustring attribute;
@@ -993,6 +1023,7 @@ class NormalMapNode : public ShaderNode {
public:
SHADER_NODE_CLASS(NormalMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
@@ -1007,6 +1038,7 @@ class TangentNode : public ShaderNode {
public:
SHADER_NODE_CLASS(TangentNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
@@ -1046,6 +1078,7 @@ class VectorDisplacementNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorDisplacementNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency() { return true; }
virtual int get_feature() {
return NODE_FEATURE_BUMP;
}
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index e03160954bc..b981d2b8849 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -604,9 +604,16 @@ void ObjectManager::device_update_flags(Device *,
foreach(Object *object, scene->objects) {
if(object->mesh->has_volume) {
object_flag[object_index] |= SD_OBJECT_HAS_VOLUME;
+ object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+
+ foreach(Attribute& attr, object->mesh->attributes.attributes) {
+ if(attr.element == ATTR_ELEMENT_VOXEL) {
+ object_flag[object_index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+ }
+ }
}
else {
- object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
+ object_flag[object_index] &= ~(SD_OBJECT_HAS_VOLUME|SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
}
if(object->is_shadow_catcher) {
object_flag[object_index] |= SD_OBJECT_SHADOW_CATCHER;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 4d066c89b76..9e931280691 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -744,6 +744,10 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
current_shader->has_object_dependency = true;
}
+ if(node->has_attribute_dependency()) {
+ current_shader->has_attribute_dependency = true;
+ }
+
if(node->has_integrator_dependency()) {
current_shader->has_integrator_dependency = true;
}
@@ -991,6 +995,14 @@ void OSLCompiler::parameter_color_array(const char *name, const array<float3>& f
ss->Parameter(name, type, table.data());
}
+void OSLCompiler::parameter_attribute(const char *name, ustring s)
+{
+ if(Attribute::name_standard(s.c_str()))
+ parameter(name, (string("geom:") + s.c_str()).c_str());
+ else
+ parameter(name, s.c_str());
+}
+
void OSLCompiler::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
{
ShaderNode *node = (input->link)? input->link->parent: NULL;
@@ -1124,6 +1136,7 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
shader->has_surface_spatial_varying = false;
shader->has_volume_spatial_varying = false;
shader->has_object_dependency = false;
+ shader->has_attribute_dependency = false;
shader->has_integrator_dependency = false;
/* generate surface shader */
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 2be1126fdd3..95e35dd857b 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -140,6 +140,8 @@ public:
void parameter_array(const char *name, const float f[], int arraylen);
void parameter_color_array(const char *name, const array<float3>& f);
+ void parameter_attribute(const char *name, ustring s);
+
ShaderType output_type() { return current_type; }
bool background;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index a1ebb26eba3..578c61a3e79 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -191,6 +191,7 @@ Shader::Shader()
has_surface_spatial_varying = false;
has_volume_spatial_varying = false;
has_object_dependency = false;
+ has_attribute_dependency = false;
has_integrator_dependency = false;
has_volume_connected = false;
@@ -463,6 +464,8 @@ void ShaderManager::device_update_common(Device *device,
flag |= SD_HAS_ONLY_VOLUME;
if(shader->heterogeneous_volume && shader->has_volume_spatial_varying)
flag |= SD_HETEROGENEOUS_VOLUME;
+ if(shader->has_attribute_dependency)
+ flag |= SD_NEED_ATTRIBUTES;
if(shader->has_bssrdf_bump)
flag |= SD_HAS_BSSRDF_BUMP;
if(device->info.has_volume_decoupled) {
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 4a48c1347da..abd483caabc 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -121,6 +121,7 @@ public:
bool has_surface_spatial_varying;
bool has_volume_spatial_varying;
bool has_object_dependency;
+ bool has_attribute_dependency;
bool has_integrator_dependency;
/* displacement */
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index b678277433b..c5b4060d5c3 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -399,6 +399,12 @@ uint SVMCompiler::attribute(AttributeStandard std)
return shader_manager->get_attribute_id(std);
}
+uint SVMCompiler::attribute_standard(ustring name)
+{
+ AttributeStandard std = Attribute::name_standard(name.c_str());
+ return (std)? attribute(std): attribute(name);
+}
+
bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
{
/* nasty exception .. */
@@ -447,6 +453,10 @@ void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet& done)
current_shader->has_object_dependency = true;
}
+ if(node->has_attribute_dependency()) {
+ current_shader->has_attribute_dependency = true;
+ }
+
if(node->has_integrator_dependency()) {
current_shader->has_integrator_dependency = true;
}
@@ -830,6 +840,7 @@ void SVMCompiler::compile(Scene *scene,
shader->has_surface_spatial_varying = false;
shader->has_volume_spatial_varying = false;
shader->has_object_dependency = false;
+ shader->has_attribute_dependency = false;
shader->has_integrator_dependency = false;
/* generate bump shader */
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 0e9905957c7..18be0fa9a22 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -117,6 +117,7 @@ public:
void add_node(const float4& f);
uint attribute(ustring name);
uint attribute(AttributeStandard std);
+ uint attribute_standard(ustring name);
uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
uint closure_mix_weight_offset() { return mix_weight_offset; }
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 9fa6dbf6eef..91a0120f6ac 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -388,102 +388,16 @@ class QuickSmoke(Operator):
node_out = nodes.new(type='ShaderNodeOutputMaterial')
node_out.location = grid_location(6, 1)
- # Add shader 1
- node_add_shader_1 = nodes.new(type='ShaderNodeAddShader')
- node_add_shader_1.location = grid_location(5, 1)
- links.new(node_add_shader_1.outputs["Shader"],
+ # Add Principled Volume
+ node_principled = nodes.new(type='ShaderNodeVolumePrincipled')
+ node_principled.location = grid_location(4, 1)
+ links.new(node_principled.outputs["Volume"],
node_out.inputs["Volume"])
- if self.style in {'SMOKE', 'FIRE', 'BOTH'}:
- # Smoke
-
- # Add shader 2
- node_add_shader_2 = nodes.new(type='ShaderNodeAddShader')
- node_add_shader_2.location = grid_location(4, 2)
- links.new(node_add_shader_2.outputs["Shader"],
- node_add_shader_1.inputs[0])
-
- # Volume scatter
- node_scatter = nodes.new(type='ShaderNodeVolumeScatter')
- node_scatter.location = grid_location(3, 3)
- links.new(node_scatter.outputs["Volume"],
- node_add_shader_2.inputs[0])
-
- # Volume absorption
- node_absorption = nodes.new(type='ShaderNodeVolumeAbsorption')
- node_absorption.location = grid_location(3, 2)
- links.new(node_absorption.outputs["Volume"],
- node_add_shader_2.inputs[1])
-
- # Density Multiplier
- node_densmult = nodes.new(type='ShaderNodeMath')
- node_densmult.location = grid_location(2, 2)
- node_densmult.operation = 'MULTIPLY'
- node_densmult.inputs[1].default_value = 5.0
- links.new(node_densmult.outputs["Value"],
- node_scatter.inputs["Density"])
- links.new(node_densmult.outputs["Value"],
- node_absorption.inputs["Density"])
-
- # Attribute "density"
- node_attrib_density = nodes.new(type='ShaderNodeAttribute')
- node_attrib_density.attribute_name = "density"
- node_attrib_density.location = grid_location(1, 2)
- links.new(node_attrib_density.outputs["Fac"],
- node_densmult.inputs[0])
-
- # Attribute "color"
- node_attrib_color = nodes.new(type='ShaderNodeAttribute')
- node_attrib_color.attribute_name = "color"
- node_attrib_color.location = grid_location(2, 3)
- links.new(node_attrib_color.outputs["Color"],
- node_scatter.inputs["Color"])
- links.new(node_attrib_color.outputs["Color"],
- node_absorption.inputs["Color"])
+ node_principled.inputs["Density"].default_value = 5.0
if self.style in {'FIRE', 'BOTH'}:
- # Fire
-
- # Emission
- node_emission = nodes.new(type='ShaderNodeEmission')
- node_emission.inputs["Color"].default_value = (0.8, 0.1, 0.01, 1.0)
- node_emission.location = grid_location(4, 1)
- links.new(node_emission.outputs["Emission"],
- node_add_shader_1.inputs[1])
-
- # Flame strength multiplier
- node_flame_strength_mult = nodes.new(type='ShaderNodeMath')
- node_flame_strength_mult.location = grid_location(3, 1)
- node_flame_strength_mult.operation = 'MULTIPLY'
- node_flame_strength_mult.inputs[1].default_value = 2.5
- links.new(node_flame_strength_mult.outputs["Value"],
- node_emission.inputs["Strength"])
-
- # Color ramp Flame
- node_flame_ramp = nodes.new(type='ShaderNodeValToRGB')
- node_flame_ramp.location = grid_location(1, 1)
- ramp = node_flame_ramp.color_ramp
- ramp.interpolation = 'EASE'
-
- # orange
- elem = ramp.elements.new(0.5)
- elem.color = (1.0, 0.128, 0.0, 1.0)
-
- # yellow
- elem = ramp.elements.new(0.9)
- elem.color = (0.9, 0.6, 0.1, 1.0)
-
- links.new(node_flame_ramp.outputs["Color"],
- node_emission.inputs["Color"])
-
- # Attribute "flame"
- node_attrib_flame = nodes.new(type='ShaderNodeAttribute')
- node_attrib_flame.attribute_name = "flame"
- node_attrib_flame.location = grid_location(0, 1)
- links.new(node_attrib_flame.outputs["Fac"],
- node_flame_ramp.inputs["Fac"])
- links.new(node_attrib_flame.outputs["Fac"],
- node_flame_strength_mult.inputs[0])
+ node_principled.inputs["Blackbody Intensity"].default_value = 1.0
# Blender Internal
else:
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index dc8462f1af1..bb3eb1a7856 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -272,6 +272,7 @@ shader_node_categories = [
NodeItem("ShaderNodeHoldout", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeVolumeAbsorption", poll=eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeVolumeScatter", poll=eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeVolumePrincipled"),
NodeItem("ShaderNodeEeveeSpecular", poll=object_eevee_shader_nodes_poll),
]),
ShaderNewNodeCategory("SH_NEW_TEXTURE", "Texture", items=[
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 770b2b4a185..73d3e30ee87 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -802,6 +802,7 @@ struct ShadeResult;
#define SH_NODE_BEVEL 197
#define SH_NODE_DISPLACEMENT 198
#define SH_NODE_VECTOR_DISPLACEMENT 199
+#define SH_NODE_VOLUME_PRINCIPLED 200
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 97a26b23c17..1e41c276de4 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3616,6 +3616,7 @@ static void registerShaderNodes(void)
register_node_type_sh_holdout();
register_node_type_sh_volume_absorption();
register_node_type_sh_volume_scatter();
+ register_node_type_sh_volume_principled();
register_node_type_sh_subsurface_scattering();
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 9b11b66cedd..d170459844d 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -525,8 +525,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->burning_rate = 0.75f;
smd->domain->flame_smoke = 1.0f;
smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.25f;
- smd->domain->flame_max_temp = 1.75f;
+ smd->domain->flame_ignition = 1.5f;
+ smd->domain->flame_max_temp = 3.0f;
/* color */
smd->domain->flame_smoke_color[0] = 0.7f;
smd->domain->flame_smoke_color[1] = 0.7f;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 68934ebedd6..3c00114579e 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3016,7 +3016,7 @@ static const float std_node_socket_colors[][4] = {
{0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
{0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
{0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
- {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */
+ {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */
};
/* common color callbacks for standard types */
@@ -3103,20 +3103,11 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
uiTemplateComponentMenu(layout, ptr, "default_value", text);
break;
case SOCK_RGBA:
- {
- uiLayout *row = uiLayoutRow(layout, false);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
- /* draw the socket name right of the actual button */
- uiItemR(row, ptr, "default_value", 0, "", 0);
- uiItemL(row, text, 0);
- break;
- }
case SOCK_STRING:
{
- uiLayout *row = uiLayoutRow(layout, true);
- /* draw the socket name right of the actual button */
- uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
uiItemL(row, text, 0);
+ uiItemR(row, ptr, "default_value", 0, "", 0);
break;
}
default:
@@ -3150,11 +3141,6 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
break;
}
- case SOCK_BOOLEAN:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
case SOCK_VECTOR:
{
uiLayout *row;
@@ -3164,11 +3150,8 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
break;
}
+ case SOCK_BOOLEAN:
case SOCK_RGBA:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
case SOCK_STRING:
{
uiItemR(layout, ptr, "default_value", 0, NULL, 0);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 94bd752cf81..83ea519a015 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -359,6 +359,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy -= NODE_DYS / 2;
/* output sockets */
+ bool add_output_space = false;
+
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
if (nodeSocketIsHidden(nsock))
continue;
@@ -391,6 +393,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy = buty;
if (nsock->next)
dy -= NODE_SOCKDY;
+
+ add_output_space = true;
+ }
+
+ if (add_output_space) {
+ dy -= NODE_DY / 4;
}
node->prvr.xmin = locx + NODE_DYS;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 539b9fa45b4..4cb1c13a44a 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1290,7 +1290,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
return 1;
}
- /* last token is single character channel identifier */
+ /* last token is channel identifier */
len = imb_exr_split_token(name, end, &token);
if (len == 0) {
printf("multilayer read: bad channel name: %s\n", name);
@@ -1319,10 +1319,30 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
ok = true;
}
}
+ else if (BLI_strcaseeq(token, "red")) {
+ echan->chan_id = 'R';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "green")) {
+ echan->chan_id = 'G';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "blue")) {
+ echan->chan_id = 'B';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "alpha")) {
+ echan->chan_id = 'A';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "depth")) {
+ echan->chan_id = 'Z';
+ ok = true;
+ }
if (ok == false) {
BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME));
- printf("multilayer read: channel token too long: %s\n", tokenbuf);
+ printf("multilayer read: unknown channel token: %s\n", tokenbuf);
return 0;
}
}
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 4c5c584b16b..92c0ef6fa19 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -364,6 +364,42 @@ static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values)
#endif
}
+static void rna_SmokeModifier_temperature_grid_get(PointerRNA *ptr, float *values)
+{
+#ifdef WITH_SMOKE
+ SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_SmokeModifier_grid_get_length(ptr, length);
+ float *flame;
+
+ BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
+ flame = smoke_turbulence_get_flame(sds->wt);
+ }
+ else {
+ flame = smoke_get_flame(sds->fluid);
+ }
+
+ if (flame) {
+ /* Output is such that 0..1 maps to 0..1000K */
+ float offset = sds->flame_ignition;
+ float scale = sds->flame_max_temp - sds->flame_ignition;
+
+ for (int i = 0; i < size; i++) {
+ values[i] = (flame[i] > 0.01f) ? offset + flame[i] * scale : 0.0f;
+ }
+ }
+ else {
+ memset(values, 0, size * sizeof(float));
+ }
+
+ BLI_rw_mutex_unlock(sds->fluid_mutex);
+#else
+ UNUSED_VARS(ptr, values);
+#endif
+}
+
static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value)
{
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
@@ -679,6 +715,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_SmokeModifier_heat_grid_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Heat Grid", "Smoke heat grid");
+ prop = RNA_def_property(srna, "temperature_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_SmokeModifier_temperature_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K");
+
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "cell_size", "Cell Size");
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 230918776dc..ee70fcf510f 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -212,6 +212,7 @@ set(SRC
shader/nodes/node_shader_tex_wave.c
shader/nodes/node_shader_volume_scatter.c
shader/nodes/node_shader_volume_absorption.c
+ shader/nodes/node_shader_volume_principled.c
shader/nodes/node_shader_uvAlongStroke.c
shader/nodes/node_shader_uvmap.c
shader/node_shader_tree.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index bb9f9881e33..a507fdbd787 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -114,6 +114,7 @@ void register_node_type_sh_emission(void);
void register_node_type_sh_holdout(void);
void register_node_type_sh_volume_absorption(void);
void register_node_type_sh_volume_scatter(void);
+void register_node_type_sh_volume_principled(void);
void register_node_type_sh_bsdf_hair(void);
void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 394e141647e..44713a7a000 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -93,6 +93,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BS
DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
DefNode( ShaderNode, SH_NODE_VOLUME_ABSORPTION, 0, "VOLUME_ABSORPTION", VolumeAbsorption, "Volume Absorption", "" )
DefNode( ShaderNode, SH_NODE_VOLUME_SCATTER, 0, "VOLUME_SCATTER", VolumeScatter, "Volume Scatter", "" )
+DefNode( ShaderNode, SH_NODE_VOLUME_PRINCIPLED, 0, "PRINCIPLED_VOLUME", VolumePrincipled, "Principled Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" )
DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" )
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
new file mode 100644
index 00000000000..f9a481e6c7e
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
@@ -0,0 +1,85 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_volume_principled_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
+ { SOCK_STRING, 1, N_("Color Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_STRING, 1, N_("Density Attribute"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Absorption Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Emission Strength"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1000.0f},
+ { SOCK_RGBA, 1, N_("Emission Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Blackbody Intensity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Blackbody Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Temperature"), 1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6500.0f},
+ { SOCK_STRING, 1, N_("Temperature Attribute"),0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_volume_principled_out[] = {
+ { SOCK_SHADER, 0, N_("Volume")},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Density Attribute")) {
+ strcpy(((bNodeSocketValueString *)sock->default_value)->value, "density");
+ }
+ else if (STREQ(sock->name, "Temperature Attribute")) {
+ strcpy(((bNodeSocketValueString *)sock->default_value)->value, "temperature");
+ }
+ }
+}
+
+static int node_shader_gpu_volume_principled(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+{
+ return false;
+}
+
+/* node type definition */
+void register_node_type_sh_volume_principled(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_volume_principled_in, sh_node_volume_principled_out);
+ node_type_size_preset(&ntype, NODE_SIZE_LARGE);
+ node_type_init(&ntype, node_shader_init_volume_principled);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_volume_principled);
+
+ nodeRegisterType(&ntype);
+}
+
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
index bce4695af10..dfd7154e6b8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
@@ -32,7 +32,7 @@
static bNodeSocketTemplate sh_node_volume_scatter_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
- { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
{ -1, 0, "" }
};