diff options
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, ¶m1_offset, ¶m2_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, "" } }; |