Merge branch 'master' into blender2.8

This commit is contained in:
Brecht Van Lommel 2018-02-23 19:02:49 +01:00
commit a44b08a6c4
40 changed files with 688 additions and 692 deletions

View File

@ -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"

View File

@ -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)

View File

@ -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")

View File

@ -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);
}

View File

@ -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",

View File

@ -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);

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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();
}
}
}
}

View File

@ -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__

View File

@ -794,7 +794,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
}
}
ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag)
ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type)
{
#ifdef __VOLUME__
/* Only sum extinction for volumes, variable is shared with surface transparency. */
@ -802,19 +802,20 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
return;
}
uint type, param1_offset, param2_offset;
uint type, density_offset, anisotropy_offset;
uint mix_weight_offset;
decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
decode_node_uchar4(node.y, &type, &density_offset, &anisotropy_offset, &mix_weight_offset);
float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
if(mix_weight == 0.0f)
if(mix_weight == 0.0f) {
return;
}
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(node.z);
density = mix_weight * fmaxf(density, 0.0f);
/* Compute scattering coefficient. */
float density = mix_weight * fmaxf(param1, 0.0f);
float3 weight = sd->svm_closure_weight;
if(type == CLOSURE_VOLUME_ABSORPTION_ID) {
@ -825,11 +826,11 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
/* Add closure for volume scattering. */
if(type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
if(volume) {
volume->g = param2; /* g */
float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(node.w);
volume->g = anisotropy; /* g */
sd->flag |= volume_henyey_greenstein_setup(volume);
}
}
@ -839,6 +840,106 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
#endif
}
ccl_device void svm_node_principled_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag, int *offset)
{
#ifdef __VOLUME__
uint4 value_node = read_node(kg, offset);
uint4 attr_node = read_node(kg, offset);
/* Only sum extinction for volumes, variable is shared with surface transparency. */
if(shader_type != SHADER_TYPE_VOLUME) {
return;
}
uint density_offset, anisotropy_offset, absorption_color_offset, mix_weight_offset;
decode_node_uchar4(node.y, &density_offset, &anisotropy_offset, &absorption_color_offset, &mix_weight_offset);
float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
if(mix_weight == 0.0f) {
return;
}
/* Compute density. */
float primitive_density = 1.0f;
float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(value_node.x);
density = mix_weight * fmaxf(density, 0.0f);
if(density > CLOSURE_WEIGHT_CUTOFF) {
/* Density and color attribute lookup if available. */
const AttributeDescriptor attr_density = find_attribute(kg, sd, attr_node.x);
if(attr_density.offset != ATTR_STD_NOT_FOUND) {
primitive_density = primitive_attribute_float(kg, sd, attr_density, NULL, NULL);
density = fmaxf(density * primitive_density, 0.0f);
}
}
if(density > CLOSURE_WEIGHT_CUTOFF) {
/* Compute scattering color. */
float3 color = sd->svm_closure_weight;
const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y);
if(attr_color.offset != ATTR_STD_NOT_FOUND) {
color *= primitive_attribute_float3(kg, sd, attr_color, NULL, NULL);
}
/* Add closure for volume scattering. */
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), color * density);
if(volume) {
float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(value_node.y);
volume->g = anisotropy;
sd->flag |= volume_henyey_greenstein_setup(volume);
}
/* Add extinction weight. */
float3 zero = make_float3(0.0f, 0.0f, 0.0f);
float3 one = make_float3(1.0f, 1.0f, 1.0f);
float3 absorption_color = stack_load_float3(stack, absorption_color_offset);
float3 absorption = max(one - color, zero) * max(one - absorption_color, zero);
volume_extinction_setup(sd, (color + absorption) * density);
}
/* Compute emission. */
if(path_flag & PATH_RAY_SHADOW) {
/* Don't need emission for shadows. */
return;
}
uint emission_offset, emission_color_offset, blackbody_offset, temperature_offset;
decode_node_uchar4(node.z, &emission_offset, &emission_color_offset, &blackbody_offset, &temperature_offset);
float emission = (stack_valid(emission_offset))? stack_load_float(stack, emission_offset): __uint_as_float(value_node.z);
float blackbody = (stack_valid(blackbody_offset))? stack_load_float(stack, blackbody_offset): __uint_as_float(value_node.w);
if(emission > CLOSURE_WEIGHT_CUTOFF) {
float3 emission_color = stack_load_float3(stack, emission_color_offset);
emission_setup(sd, emission * emission_color);
}
if(blackbody > CLOSURE_WEIGHT_CUTOFF) {
float T = stack_load_float(stack, temperature_offset);
/* Add flame temperature from attribute if available. */
const AttributeDescriptor attr_temperature = find_attribute(kg, sd, attr_node.z);
if(attr_temperature.offset != ATTR_STD_NOT_FOUND) {
float temperature = primitive_attribute_float(kg, sd, attr_temperature, NULL, NULL);
T *= fmaxf(temperature, 0.0f);
}
T = fmaxf(T, 0.0f);
/* Stefan-Boltzmann law. */
float T4 = sqr(sqr(T));
float sigma = 5.670373e-8f * 1e-6f / M_PI_F;
float intensity = sigma * mix(1.0f, T4, blackbody);
if(intensity > CLOSURE_WEIGHT_CUTOFF) {
float3 blackbody_tint = stack_load_float3(stack, node.w);
float3 bb = blackbody_tint * intensity * svm_math_blackbody_color(T);
emission_setup(sd, bb);
}
}
#endif
}
ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
{
uint mix_weight_offset = node.y;

View File

@ -135,6 +135,7 @@ typedef enum ShaderNodeType {
NODE_BEVEL,
NODE_DISPLACEMENT,
NODE_VECTOR_DISPLACEMENT,
NODE_PRINCIPLED_VOLUME,
} ShaderNodeType;
typedef enum NodeAttributeType {

View File

@ -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)

View File

@ -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);

View File

@ -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; }

View File

@ -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"));
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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) {

View File

@ -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 */

View File

@ -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 */

View File

@ -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; }

View File

@ -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:

View File

@ -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=[

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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");

View File

@ -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

View File

@ -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);

View File

@ -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", "" )

View File

@ -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);
}

View File

@ -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, "" }
};