Merge branch 'master' into blender2.8
This commit is contained in:
commit
a44b08a6c4
|
@ -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"
|
|
@ -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)
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -135,6 +135,7 @@ typedef enum ShaderNodeType {
|
|||
NODE_BEVEL,
|
||||
NODE_DISPLACEMENT,
|
||||
NODE_VECTOR_DISPLACEMENT,
|
||||
NODE_PRINCIPLED_VOLUME,
|
||||
} ShaderNodeType;
|
||||
|
||||
typedef enum NodeAttributeType {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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=[
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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", "" )
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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, "" }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue