Merge branch 'blender2.8' into soc-2018-bevel
This commit is contained in:
@@ -624,10 +624,12 @@ endif()
|
||||
|
||||
if(NOT WITH_AUDASPACE)
|
||||
if(WITH_OPENAL)
|
||||
message(FATAL_ERROR "WITH_OPENAL requires WITH_AUDASPACE")
|
||||
message(WARNING "WITH_OPENAL requires WITH_AUDASPACE which is disabled")
|
||||
set(WITH_OPENAL OFF)
|
||||
endif()
|
||||
if(WITH_JACK)
|
||||
message(FATAL_ERROR "WITH_JACK requires WITH_AUDASPACE")
|
||||
message(WARNING "WITH_JACK requires WITH_AUDASPACE which is disabled")
|
||||
set(WITH_JACK OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -236,8 +236,12 @@ help: .FORCE
|
||||
@echo " * check_descriptions - check for duplicate/invalid descriptions"
|
||||
@echo ""
|
||||
@echo "Utilities (not associated with building blender)"
|
||||
@echo " * icons - updates PNG icons from SVG files."
|
||||
@echo " * icons_geom - updates Geometry icons from BLEND file."
|
||||
@echo " * icons - Updates PNG icons from SVG files."
|
||||
@echo " Set environment variables 'BLENDER_BIN' and 'INKSCAPE_BIN'"
|
||||
@echo " to define your own commands."
|
||||
@echo " * icons_geom - Updates Geometry icons from BLEND file."
|
||||
@echo " Set environment variable 'BLENDER_BIN'"
|
||||
@echo " to define your own command."
|
||||
@echo " * tgz - create a compressed archive of the source code."
|
||||
@echo " * update - updates git and all submodules"
|
||||
@echo ""
|
||||
|
||||
@@ -77,7 +77,13 @@ if 'cmake' in builder:
|
||||
# cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/nvcc')
|
||||
|
||||
elif builder.startswith('win'):
|
||||
if builder.endswith('_vc2015'):
|
||||
if builder.endswith('_vs2017'):
|
||||
if builder.startswith('win64'):
|
||||
cmake_options.extend(['-G', 'Visual Studio 15 2017 Win64'])
|
||||
elif builder.startswith('win32'):
|
||||
bits = 32
|
||||
cmake_options.extend(['-G', 'Visual Studio 15 2017'])
|
||||
elif builder.endswith('_vc2015'):
|
||||
if builder.startswith('win64'):
|
||||
cmake_options.extend(['-G', 'Visual Studio 14 2015 Win64'])
|
||||
elif builder.startswith('win32'):
|
||||
|
||||
@@ -600,7 +600,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_editor_curve
|
||||
bf_editor_gpencil
|
||||
bf_editor_interface
|
||||
bf_editor_manipulator_library
|
||||
bf_editor_gizmo_library
|
||||
bf_editor_mesh
|
||||
bf_editor_metaball
|
||||
bf_editor_object
|
||||
@@ -621,7 +621,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_python
|
||||
bf_python_ext
|
||||
bf_python_mathutils
|
||||
bf_python_gawain
|
||||
bf_python_gpu
|
||||
bf_python_bmesh
|
||||
bf_freestyle
|
||||
bf_ikplugin
|
||||
@@ -635,7 +635,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_physics
|
||||
bf_nodes
|
||||
bf_rna
|
||||
bf_editor_manipulator_library # rna -> manipulator bad-level calls
|
||||
bf_editor_gizmo_library # rna -> gizmo bad-level calls
|
||||
bf_python
|
||||
bf_imbuf
|
||||
bf_blenlib
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
echo No explicit msvc version requested, autodetecting version.
|
||||
|
||||
call "%~dp0\detect_msvc2013.cmd"
|
||||
call "%~dp0\detect_msvc2017.cmd"
|
||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||
|
||||
call "%~dp0\detect_msvc2015.cmd"
|
||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||
|
||||
call "%~dp0\detect_msvc2017.cmd"
|
||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||
|
||||
echo Compiler Detection failed. Use verbose switch for more information.
|
||||
exit /b 1
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
if "%BUILD_VS_YEAR%"=="2013" set BUILD_VS_LIBDIRPOST=vc12
|
||||
if "%BUILD_VS_YEAR%"=="2015" set BUILD_VS_LIBDIRPOST=vc14
|
||||
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc14
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
set BUILD_VS_VER=12
|
||||
set BUILD_VS_YEAR=2013
|
||||
call "%~dp0\detect_msvc_classic.cmd"
|
||||
@@ -59,8 +59,6 @@ if NOT "%1" == "" (
|
||||
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
|
||||
) else if "%1" == "2015" (
|
||||
set BUILD_VS_YEAR=2015
|
||||
) else if "%1" == "2013" (
|
||||
set BUILD_VS_YEAR=2013
|
||||
) else if "%1" == "packagename" (
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
|
||||
shift /1
|
||||
|
||||
@@ -22,13 +22,13 @@ echo - packagename [newname] ^(override default cpack package name^)
|
||||
echo - buildir [newdir] ^(override default build folder^)
|
||||
echo - x86 ^(override host auto-detect and build 32 bit code^)
|
||||
echo - x64 ^(override host auto-detect and build 64 bit code^)
|
||||
echo - 2013 ^(build with visual studio 2013^)
|
||||
echo.
|
||||
echo Experimental options
|
||||
echo - 2015 ^(build with visual studio 2015^)
|
||||
echo - 2017 ^(build with visual studio 2017^)
|
||||
echo - 2017pre ^(build with visual studio 2017 pre-release^)
|
||||
echo - 2017b ^(build with visual studio 2017 Build Tools^)
|
||||
|
||||
echo.
|
||||
echo Experimental options
|
||||
echo - 2015 ^(build with visual studio 2015^)
|
||||
echo - clang ^(enable building with clang^)
|
||||
echo - asan ^(enable asan when building with clang^)
|
||||
echo - ninja ^(enable building with ninja instead of msbuild^)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# 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,
|
||||
# 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.
|
||||
@@ -22,21 +22,21 @@
|
||||
#
|
||||
# Name:
|
||||
# dna.py
|
||||
#
|
||||
#
|
||||
# Description:
|
||||
# Creates a browsable DNA output to HTML.
|
||||
#
|
||||
#
|
||||
# Author:
|
||||
# Jeroen Bakker
|
||||
#
|
||||
#
|
||||
# Version:
|
||||
# v0.1 (12-05-2009) - migration of original source code to python.
|
||||
# Added code to support blender 2.5 branch
|
||||
# v0.2 (25-05-2009) - integrated with BlendFileReader.py
|
||||
#
|
||||
#
|
||||
# Input:
|
||||
# blender build executable
|
||||
#
|
||||
#
|
||||
# Output:
|
||||
# dna.html
|
||||
# dna.css (will only be created when not existing)
|
||||
@@ -76,12 +76,12 @@ class DNACatalogHTML:
|
||||
DNACatalog is a catalog of all information in the DNA1 file-block
|
||||
'''
|
||||
|
||||
def __init__(self, catalog, bpy_module = None):
|
||||
def __init__(self, catalog, bpy_module=None):
|
||||
self.Catalog = catalog
|
||||
self.bpy = bpy_module
|
||||
|
||||
|
||||
def WriteToHTML(self, handle):
|
||||
|
||||
|
||||
dna_html_template = """
|
||||
<!DOCTYPE html PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd>
|
||||
<html>
|
||||
@@ -105,10 +105,10 @@ class DNACatalogHTML:
|
||||
${structs_content}
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
|
||||
header = self.Catalog.Header
|
||||
bpy = self.bpy
|
||||
|
||||
|
||||
# ${version} and ${revision}
|
||||
if bpy:
|
||||
version = '.'.join(map(str, bpy.app.version))
|
||||
@@ -116,7 +116,7 @@ class DNACatalogHTML:
|
||||
else:
|
||||
version = str(header.Version)
|
||||
revision = 'Unknown'
|
||||
|
||||
|
||||
# ${bitness}
|
||||
if header.PointerSize == 8:
|
||||
bitness = '64 bit'
|
||||
@@ -125,10 +125,10 @@ class DNACatalogHTML:
|
||||
|
||||
# ${endianness}
|
||||
if header.LittleEndianness:
|
||||
endianess= 'Little endianness'
|
||||
endianess = 'Little endianness'
|
||||
else:
|
||||
endianess= 'Big endianness'
|
||||
|
||||
endianess = 'Big endianness'
|
||||
|
||||
# ${structs_list}
|
||||
log.debug("Creating structs index")
|
||||
structs_list = ''
|
||||
@@ -136,7 +136,7 @@ class DNACatalogHTML:
|
||||
structureIndex = 0
|
||||
for structure in self.Catalog.Structs:
|
||||
structs_list += list_item.format(structureIndex, structure.Type.Name)
|
||||
structureIndex+=1
|
||||
structureIndex += 1
|
||||
|
||||
# ${structs_content}
|
||||
log.debug("Creating structs content")
|
||||
@@ -144,20 +144,20 @@ class DNACatalogHTML:
|
||||
for structure in self.Catalog.Structs:
|
||||
log.debug(structure.Type.Name)
|
||||
structs_content += self.Structure(structure)
|
||||
|
||||
|
||||
d = dict(
|
||||
version = version,
|
||||
revision = revision,
|
||||
bitness = bitness,
|
||||
endianness = endianess,
|
||||
structs_list = structs_list,
|
||||
structs_content = structs_content
|
||||
version=version,
|
||||
revision=revision,
|
||||
bitness=bitness,
|
||||
endianness=endianess,
|
||||
structs_list=structs_list,
|
||||
structs_content=structs_content
|
||||
)
|
||||
|
||||
dna_html = Template(dna_html_template).substitute(d)
|
||||
dna_html = self.format(dna_html)
|
||||
handle.write(dna_html)
|
||||
|
||||
|
||||
def Structure(self, structure):
|
||||
struct_table_template = """
|
||||
<table><a name="${struct_name}"></a>
|
||||
@@ -178,23 +178,23 @@ class DNACatalogHTML:
|
||||
</table>
|
||||
<label>Total size: ${size} bytes</label><br/>
|
||||
<label>(<a href="#top">top</a>)</label><br/>"""
|
||||
|
||||
|
||||
d = dict(
|
||||
struct_name = structure.Type.Name,
|
||||
fields = self.StructureFields(structure, None, 0),
|
||||
size = str(structure.Type.Size)
|
||||
struct_name=structure.Type.Name,
|
||||
fields=self.StructureFields(structure, None, 0),
|
||||
size=str(structure.Type.Size)
|
||||
)
|
||||
|
||||
|
||||
struct_table = Template(struct_table_template).substitute(d)
|
||||
return struct_table
|
||||
|
||||
|
||||
def StructureFields(self, structure, parentReference, offset):
|
||||
fields = ''
|
||||
for field in structure.Fields:
|
||||
fields += self.StructureField(field, structure, parentReference, offset)
|
||||
offset += field.Size(self.Catalog.Header)
|
||||
return fields
|
||||
|
||||
|
||||
def StructureField(self, field, structure, parentReference, offset):
|
||||
structure_field_template = """
|
||||
<tr>
|
||||
@@ -205,7 +205,7 @@ class DNACatalogHTML:
|
||||
<td>${offset}</td>
|
||||
<td>${size}</td>
|
||||
</tr>"""
|
||||
|
||||
|
||||
if field.Type.Structure is None or field.Name.IsPointer():
|
||||
|
||||
# ${reference}
|
||||
@@ -216,37 +216,37 @@ class DNACatalogHTML:
|
||||
struct = '<a href="#{0}">{0}</a>'.format(structure.Type.Name)
|
||||
else:
|
||||
struct = structure.Type.Name
|
||||
|
||||
|
||||
# ${type}
|
||||
type = field.Type.Name
|
||||
|
||||
|
||||
# ${name}
|
||||
name = field.Name.Name
|
||||
|
||||
|
||||
# ${offset}
|
||||
# offset already set
|
||||
|
||||
|
||||
# ${size}
|
||||
size = field.Size(self.Catalog.Header)
|
||||
|
||||
|
||||
d = dict(
|
||||
reference = reference,
|
||||
struct = struct,
|
||||
type = type,
|
||||
name = name,
|
||||
offset = offset,
|
||||
size = size
|
||||
reference=reference,
|
||||
struct=struct,
|
||||
type=type,
|
||||
name=name,
|
||||
offset=offset,
|
||||
size=size
|
||||
)
|
||||
|
||||
|
||||
structure_field = Template(structure_field_template).substitute(d)
|
||||
|
||||
|
||||
elif field.Type.Structure is not None:
|
||||
reference = field.Name.AsReference(parentReference)
|
||||
structure_field = self.StructureFields(field.Type.Structure, reference, offset)
|
||||
structure_field = self.StructureFields(field.Type.Structure, reference, offset)
|
||||
|
||||
return structure_field
|
||||
|
||||
def indent(self, input, dent, startswith = ''):
|
||||
def indent(self, input, dent, startswith=''):
|
||||
output = ''
|
||||
if dent < 0:
|
||||
for line in input.split('\n'):
|
||||
@@ -257,19 +257,19 @@ class DNACatalogHTML:
|
||||
output += line.lstrip() + '\n' # remove indentation completely
|
||||
elif dent > 0:
|
||||
for line in input.split('\n'):
|
||||
output += ' '* dent + line + '\n'
|
||||
output += ' ' * dent + line + '\n'
|
||||
return output
|
||||
|
||||
|
||||
def format(self, input):
|
||||
diff = {
|
||||
'\n<!DOCTYPE':'<!DOCTYPE',
|
||||
'\n</ul>' :'</ul>',
|
||||
'<a name' :'\n<a name',
|
||||
'<tr>\n' :'<tr>',
|
||||
'<tr>' :' <tr>',
|
||||
'</th>\n' :'</th>',
|
||||
'</td>\n' :'</td>',
|
||||
'<tbody>\n' :'<tbody>'
|
||||
'\n<!DOCTYPE': '<!DOCTYPE',
|
||||
'\n</ul>': '</ul>',
|
||||
'<a name': '\n<a name',
|
||||
'<tr>\n': '<tr>',
|
||||
'<tr>': ' <tr>',
|
||||
'</th>\n': '</th>',
|
||||
'</td>\n': '</td>',
|
||||
'<tbody>\n': '<tbody>'
|
||||
}
|
||||
output = self.indent(input, 0)
|
||||
for key, value in diff.items():
|
||||
@@ -283,17 +283,17 @@ class DNACatalogHTML:
|
||||
'''
|
||||
css = """
|
||||
@CHARSET "ISO-8859-1";
|
||||
|
||||
|
||||
body {
|
||||
font-family: verdana;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
|
||||
div.title {
|
||||
font-size: large;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
page-break-before: always;
|
||||
}
|
||||
@@ -304,7 +304,7 @@ class DNACatalogHTML:
|
||||
margin-right: 3%;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
|
||||
h1:hover{
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
@@ -312,7 +312,7 @@ class DNACatalogHTML:
|
||||
h3 {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
|
||||
table {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
@@ -321,21 +321,21 @@ class DNACatalogHTML:
|
||||
width: 94%;
|
||||
margin: 20px 3% 10px;
|
||||
}
|
||||
|
||||
|
||||
caption {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
|
||||
th {
|
||||
background-color: #000000;
|
||||
color:#ffffff;
|
||||
padding-left:5px;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
|
||||
tr {
|
||||
}
|
||||
|
||||
|
||||
td {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
@@ -343,12 +343,12 @@ class DNACatalogHTML:
|
||||
padding-left:5px;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
|
||||
label {
|
||||
float:right;
|
||||
margin-right: 3%;
|
||||
}
|
||||
|
||||
|
||||
ul.multicolumn {
|
||||
list-style:none;
|
||||
float:left;
|
||||
@@ -361,18 +361,18 @@ class DNACatalogHTML:
|
||||
width:200px;
|
||||
margin-right:0px;
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
color:#a000a0;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
|
||||
a:hover {
|
||||
color:#a000a0;
|
||||
text-decoration:underline;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
css = self.indent(css, 0)
|
||||
|
||||
handle.write(css)
|
||||
@@ -389,13 +389,13 @@ def usage():
|
||||
print("\tdefault: % blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py")
|
||||
print("\twith options: % blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug\n")
|
||||
|
||||
|
||||
|
||||
######################################################
|
||||
# Main
|
||||
######################################################
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
import os, os.path
|
||||
|
||||
try:
|
||||
@@ -408,37 +408,37 @@ def main():
|
||||
else:
|
||||
filename = 'dna'
|
||||
dir = os.path.dirname(__file__)
|
||||
Path_Blend = os.path.join(dir, filename + '.blend') # temporary blend file
|
||||
Path_HTML = os.path.join(dir, filename + '.html') # output html file
|
||||
Path_CSS = os.path.join(dir, 'dna.css') # output css file
|
||||
Path_Blend = os.path.join(dir, filename + '.blend') # temporary blend file
|
||||
Path_HTML = os.path.join(dir, filename + '.html') # output html file
|
||||
Path_CSS = os.path.join(dir, 'dna.css') # output css file
|
||||
|
||||
# create a blend file for dna parsing
|
||||
if not os.path.exists(Path_Blend):
|
||||
log.info("1: write temp blend file with SDNA info")
|
||||
log.info(" saving to: " + Path_Blend)
|
||||
try:
|
||||
bpy.ops.wm.save_as_mainfile(filepath = Path_Blend, copy = True, compress = False)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=Path_Blend, copy=True, compress=False)
|
||||
except:
|
||||
log.error("Filename {0} does not exist and can't be created... quitting".format(Path_Blend))
|
||||
return
|
||||
else:
|
||||
log.info("1: found blend file with SDNA info")
|
||||
log.info(" " + Path_Blend)
|
||||
|
||||
|
||||
# read blend header from blend file
|
||||
log.info("2: read file:")
|
||||
|
||||
|
||||
if not dir in sys.path:
|
||||
sys.path.append(dir)
|
||||
import BlendFileReader
|
||||
|
||||
|
||||
handle = BlendFileReader.openBlendFile(Path_Blend)
|
||||
blendfile = BlendFileReader.BlendFile(handle)
|
||||
catalog = DNACatalogHTML(blendfile.Catalog, bpy)
|
||||
|
||||
# close temp file
|
||||
handle.close()
|
||||
|
||||
|
||||
# deleting or not?
|
||||
if '--dna-keep-blend' in sys.argv:
|
||||
# keep the blend, useful for studying hexdumps
|
||||
@@ -449,7 +449,7 @@ def main():
|
||||
log.info("5: close and delete temp blend:")
|
||||
log.info(" {0}".format(Path_Blend))
|
||||
os.remove(Path_Blend)
|
||||
|
||||
|
||||
# export dna to xhtml
|
||||
log.info("6: export sdna to xhtml file: %r" % Path_HTML)
|
||||
handleHTML = open(Path_HTML, "w")
|
||||
@@ -466,12 +466,12 @@ def main():
|
||||
if not bpy.app.background:
|
||||
log.info("7: quit blender")
|
||||
bpy.ops.wm.exit_blender()
|
||||
|
||||
|
||||
except ImportError:
|
||||
log.warning(" skipping, not running in Blender")
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# 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,
|
||||
# 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.
|
||||
@@ -34,6 +34,7 @@ log = logging.getLogger("BlendFileReader")
|
||||
# module global routines
|
||||
######################################################
|
||||
|
||||
|
||||
def ReadString(handle, length):
|
||||
'''
|
||||
ReadString reads a String of given length or a zero terminating String
|
||||
@@ -45,7 +46,7 @@ def ReadString(handle, length):
|
||||
# length == 0 means we want a zero terminating string
|
||||
result = ""
|
||||
s = ReadString(handle, 1)
|
||||
while s!="\0":
|
||||
while s != "\0":
|
||||
result += s
|
||||
s = ReadString(handle, 1)
|
||||
return result
|
||||
@@ -57,7 +58,7 @@ def Read(type, handle, fileheader):
|
||||
'''
|
||||
def unpacked_bytes(type_char, size):
|
||||
return struct.unpack(fileheader.StructPre + type_char, handle.read(size))[0]
|
||||
|
||||
|
||||
if type == 'ushort':
|
||||
return unpacked_bytes("H", 2) # unsigned short
|
||||
elif type == 'short':
|
||||
@@ -94,10 +95,10 @@ def openBlendFile(filename):
|
||||
log.debug("decompressing started")
|
||||
fs = gzip.open(filename, "rb")
|
||||
handle = tempfile.TemporaryFile()
|
||||
data = fs.read(1024*1024)
|
||||
while data:
|
||||
handle.write(data)
|
||||
data = fs.read(1024*1024)
|
||||
data = fs.read(1024 * 1024)
|
||||
while data:
|
||||
handle.write(data)
|
||||
data = fs.read(1024 * 1024)
|
||||
log.debug("decompressing finished")
|
||||
fs.close()
|
||||
log.debug("resetting decompressed file")
|
||||
@@ -112,7 +113,7 @@ def Align(handle):
|
||||
offset = handle.tell()
|
||||
trim = offset % 4
|
||||
if trim != 0:
|
||||
handle.seek(4-trim, os.SEEK_CUR)
|
||||
handle.seek(4 - trim, os.SEEK_CUR)
|
||||
|
||||
|
||||
######################################################
|
||||
@@ -121,14 +122,14 @@ def Align(handle):
|
||||
|
||||
class BlendFile:
|
||||
'''
|
||||
Reads a blendfile and store the header, all the fileblocks, and catalogue
|
||||
Reads a blendfile and store the header, all the fileblocks, and catalogue
|
||||
structs foound in the DNA fileblock
|
||||
|
||||
|
||||
- BlendFile.Header (BlendFileHeader instance)
|
||||
- BlendFile.Blocks (list of BlendFileBlock instances)
|
||||
- BlendFile.Catalog (DNACatalog instance)
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, handle):
|
||||
log.debug("initializing reading blend-file")
|
||||
self.Header = BlendFileHeader(handle)
|
||||
@@ -141,13 +142,13 @@ class BlendFile:
|
||||
found_dna_block = True
|
||||
else:
|
||||
fileblock.Header.skip(handle)
|
||||
|
||||
|
||||
self.Blocks.append(fileblock)
|
||||
fileblock = BlendFileBlock(handle, self)
|
||||
|
||||
|
||||
# appending last fileblock, "ENDB"
|
||||
self.Blocks.append(fileblock)
|
||||
|
||||
|
||||
# seems unused?
|
||||
"""
|
||||
def FindBlendFileBlocksWithCode(self, code):
|
||||
@@ -164,27 +165,27 @@ class BlendFileHeader:
|
||||
BlendFileHeader allocates the first 12 bytes of a blend file.
|
||||
It contains information about the hardware architecture.
|
||||
Header example: BLENDER_v254
|
||||
|
||||
|
||||
BlendFileHeader.Magic (str)
|
||||
BlendFileHeader.PointerSize (int)
|
||||
BlendFileHeader.LittleEndianness (bool)
|
||||
BlendFileHeader.StructPre (str) see http://docs.python.org/py3k/library/struct.html#byte-order-size-and-alignment
|
||||
BlendFileHeader.Version (int)
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, handle):
|
||||
log.debug("reading blend-file-header")
|
||||
|
||||
|
||||
self.Magic = ReadString(handle, 7)
|
||||
log.debug(self.Magic)
|
||||
|
||||
|
||||
pointersize = ReadString(handle, 1)
|
||||
log.debug(pointersize)
|
||||
if pointersize == "-":
|
||||
self.PointerSize = 8
|
||||
if pointersize == "_":
|
||||
self.PointerSize = 4
|
||||
|
||||
|
||||
endianness = ReadString(handle, 1)
|
||||
log.debug(endianness)
|
||||
if endianness == "v":
|
||||
@@ -193,11 +194,11 @@ class BlendFileHeader:
|
||||
if endianness == "V":
|
||||
self.LittleEndianness = False
|
||||
self.StructPre = ">"
|
||||
|
||||
|
||||
version = ReadString(handle, 3)
|
||||
log.debug(version)
|
||||
self.Version = int(version)
|
||||
|
||||
|
||||
log.debug("{0} {1} {2} {3}".format(self.Magic, self.PointerSize, self.LittleEndianness, version))
|
||||
|
||||
|
||||
@@ -206,11 +207,11 @@ class BlendFileBlock:
|
||||
BlendFileBlock.File (BlendFile)
|
||||
BlendFileBlock.Header (FileBlockHeader)
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, handle, blendfile):
|
||||
self.File = blendfile
|
||||
self.Header = FileBlockHeader(handle, blendfile.Header)
|
||||
|
||||
|
||||
def Get(self, handle, path):
|
||||
log.debug("find dna structure")
|
||||
dnaIndex = self.Header.SDNAIndex
|
||||
@@ -232,7 +233,7 @@ class FileBlockHeader:
|
||||
Count (int)
|
||||
FileOffset (= file pointer of datablock)
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, handle, fileheader):
|
||||
self.Code = ReadString(handle, 4).strip()
|
||||
if self.Code != "ENDB":
|
||||
@@ -257,28 +258,28 @@ class FileBlockHeader:
|
||||
class DNACatalog:
|
||||
'''
|
||||
DNACatalog is a catalog of all information in the DNA1 file-block
|
||||
|
||||
|
||||
Header = None
|
||||
Names = None
|
||||
Types = None
|
||||
Structs = None
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, fileheader, handle):
|
||||
log.debug("building DNA catalog")
|
||||
self.Names=[]
|
||||
self.Types=[]
|
||||
self.Structs=[]
|
||||
self.Names = []
|
||||
self.Types = []
|
||||
self.Structs = []
|
||||
self.Header = fileheader
|
||||
|
||||
|
||||
SDNA = ReadString(handle, 4)
|
||||
|
||||
|
||||
# names
|
||||
NAME = ReadString(handle, 4)
|
||||
numberOfNames = Read('uint', handle, fileheader)
|
||||
log.debug("building #{0} names".format(numberOfNames))
|
||||
for i in range(numberOfNames):
|
||||
name = ReadString(handle,0)
|
||||
name = ReadString(handle, 0)
|
||||
self.Names.append(DNAName(name))
|
||||
Align(handle)
|
||||
|
||||
@@ -287,7 +288,7 @@ class DNACatalog:
|
||||
numberOfTypes = Read('uint', handle, fileheader)
|
||||
log.debug("building #{0} types".format(numberOfTypes))
|
||||
for i in range(numberOfTypes):
|
||||
type = ReadString(handle,0)
|
||||
type = ReadString(handle, 0)
|
||||
self.Types.append(DNAType(type))
|
||||
Align(handle)
|
||||
|
||||
@@ -321,24 +322,24 @@ class DNACatalog:
|
||||
class DNAName:
|
||||
'''
|
||||
DNAName is a C-type name stored in the DNA.
|
||||
|
||||
|
||||
Name = str
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, name):
|
||||
self.Name = name
|
||||
|
||||
|
||||
def AsReference(self, parent):
|
||||
if parent is None:
|
||||
result = ""
|
||||
else:
|
||||
result = parent+"."
|
||||
|
||||
result = parent + "."
|
||||
|
||||
result = result + self.ShortName()
|
||||
return result
|
||||
|
||||
def ShortName(self):
|
||||
result = self.Name;
|
||||
result = self.Name
|
||||
result = result.replace("*", "")
|
||||
result = result.replace("(", "")
|
||||
result = result.replace(")", "")
|
||||
@@ -346,12 +347,12 @@ class DNAName:
|
||||
if Index != -1:
|
||||
result = result[0:Index]
|
||||
return result
|
||||
|
||||
|
||||
def IsPointer(self):
|
||||
return self.Name.find("*")>-1
|
||||
return self.Name.find("*") > -1
|
||||
|
||||
def IsMethodPointer(self):
|
||||
return self.Name.find("(*")>-1
|
||||
return self.Name.find("(*") > -1
|
||||
|
||||
def ArraySize(self):
|
||||
result = 1
|
||||
@@ -360,10 +361,10 @@ class DNAName:
|
||||
|
||||
while Index != -1:
|
||||
Index2 = Temp.find("]")
|
||||
result*=int(Temp[Index+1:Index2])
|
||||
Temp = Temp[Index2+1:]
|
||||
result *= int(Temp[Index + 1:Index2])
|
||||
Temp = Temp[Index2 + 1:]
|
||||
Index = Temp.find("[")
|
||||
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -375,46 +376,46 @@ class DNAType:
|
||||
Size = int
|
||||
Structure = DNAStructure
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, aName):
|
||||
self.Name = aName
|
||||
self.Structure=None
|
||||
self.Structure = None
|
||||
|
||||
|
||||
class DNAStructure:
|
||||
'''
|
||||
DNAType is a C-type structure stored in the DNA
|
||||
|
||||
|
||||
Type = DNAType
|
||||
Fields = [DNAField]
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, aType):
|
||||
self.Type = aType
|
||||
self.Type.Structure = self
|
||||
self.Fields=[]
|
||||
|
||||
self.Fields = []
|
||||
|
||||
def GetField(self, header, handle, path):
|
||||
splitted = path.partition(".")
|
||||
name = splitted[0]
|
||||
rest = splitted[2]
|
||||
offset = 0;
|
||||
offset = 0
|
||||
for field in self.Fields:
|
||||
if field.Name.ShortName() == name:
|
||||
log.debug("found "+name+"@"+str(offset))
|
||||
log.debug("found " + name + "@" + str(offset))
|
||||
handle.seek(offset, os.SEEK_CUR)
|
||||
return field.DecodeField(header, handle, rest)
|
||||
else:
|
||||
offset += field.Size(header)
|
||||
|
||||
log.debug("error did not find "+path)
|
||||
log.debug("error did not find " + path)
|
||||
return None
|
||||
|
||||
|
||||
class DNAField:
|
||||
'''
|
||||
DNAField is a coupled DNAType and DNAName.
|
||||
|
||||
|
||||
Type = DNAType
|
||||
Name = DNAName
|
||||
'''
|
||||
@@ -422,25 +423,24 @@ class DNAField:
|
||||
def __init__(self, aType, aName):
|
||||
self.Type = aType
|
||||
self.Name = aName
|
||||
|
||||
|
||||
def Size(self, header):
|
||||
if self.Name.IsPointer() or self.Name.IsMethodPointer():
|
||||
return header.PointerSize*self.Name.ArraySize()
|
||||
return header.PointerSize * self.Name.ArraySize()
|
||||
else:
|
||||
return self.Type.Size*self.Name.ArraySize()
|
||||
return self.Type.Size * self.Name.ArraySize()
|
||||
|
||||
def DecodeField(self, header, handle, path):
|
||||
if path == "":
|
||||
if self.Name.IsPointer():
|
||||
return Read('pointer', handle, header)
|
||||
if self.Type.Name=="int":
|
||||
if self.Type.Name == "int":
|
||||
return Read('int', handle, header)
|
||||
if self.Type.Name=="short":
|
||||
if self.Type.Name == "short":
|
||||
return Read('short', handle, header)
|
||||
if self.Type.Name=="float":
|
||||
if self.Type.Name == "float":
|
||||
return Read('float', handle, header)
|
||||
if self.Type.Name=="char":
|
||||
if self.Type.Name == "char":
|
||||
return ReadString(handle, self.Name.ArraySize())
|
||||
else:
|
||||
return self.Type.Structure.GetField(header, handle, path)
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ def man_format(data):
|
||||
data = data.replace("\t", " ")
|
||||
return data
|
||||
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
import getopt
|
||||
raise getopt.GetoptError("Usage: %s <path-to-blender> <output-filename>" % sys.argv[0])
|
||||
|
||||
@@ -73,6 +73,8 @@ def rna_info_BuildRNAInfo_cache():
|
||||
if rna_info_BuildRNAInfo_cache.ret is None:
|
||||
rna_info_BuildRNAInfo_cache.ret = rna_info.BuildRNAInfo()
|
||||
return rna_info_BuildRNAInfo_cache.ret
|
||||
|
||||
|
||||
rna_info_BuildRNAInfo_cache.ret = None
|
||||
# --- end rna_info cache
|
||||
|
||||
@@ -332,9 +334,9 @@ except ImportError:
|
||||
# to avoid having to match Blender's source tree.
|
||||
EXTRA_SOURCE_FILES = (
|
||||
"../../../release/scripts/templates_py/bmesh_simple.py",
|
||||
"../../../release/scripts/templates_py/manipulator_operator.py",
|
||||
"../../../release/scripts/templates_py/manipulator_operator_target.py",
|
||||
"../../../release/scripts/templates_py/manipulator_simple.py",
|
||||
"../../../release/scripts/templates_py/gizmo_operator.py",
|
||||
"../../../release/scripts/templates_py/gizmo_operator_target.py",
|
||||
"../../../release/scripts/templates_py/gizmo_simple.py",
|
||||
"../../../release/scripts/templates_py/operator_simple.py",
|
||||
"../../../release/scripts/templates_py/ui_panel_simple.py",
|
||||
"../../../release/scripts/templates_py/ui_previews_custom_icon.py",
|
||||
@@ -434,7 +436,7 @@ else:
|
||||
BLENDER_VERSION_DOTS = ".".join(blender_version_strings)
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# '2.62a SHA1' (release) or '2.62.1 SHA1' (non-release)
|
||||
BLENDER_VERSION_DOTS += " " + BLENDER_REVISION
|
||||
BLENDER_VERSION_DOTS += " " + BLENDER_REVISION
|
||||
|
||||
if is_release:
|
||||
# '2_62a_release'
|
||||
@@ -516,6 +518,8 @@ def escape_rst(text):
|
||||
""" Escape plain text which may contain characters used by RST.
|
||||
"""
|
||||
return text.translate(escape_rst.trans)
|
||||
|
||||
|
||||
escape_rst.trans = str.maketrans({
|
||||
"`": "\\`",
|
||||
"|": "\\|",
|
||||
@@ -1018,6 +1022,7 @@ def pymodule2sphinx(basepath, module_name, module, title):
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
# Changes in Blender will force errors here
|
||||
context_type_map = {
|
||||
"active_base": ("ObjectBase", False),
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# <pep8 compliant>
|
||||
|
||||
bpy_types_Operator_bl_property__doc__ = (
|
||||
"""
|
||||
"""
|
||||
The name of a property to use as this operators primary property.
|
||||
Currently this is only used to select the default property when
|
||||
expanding an operator into a menu.
|
||||
|
||||
@@ -29,7 +29,7 @@ You'll need to specify your user login and password, obviously.
|
||||
|
||||
Example usage:
|
||||
|
||||
./sphinx_doc_update.py --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo
|
||||
./sphinx_doc_update.py --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo
|
||||
|
||||
"""
|
||||
|
||||
@@ -107,14 +107,16 @@ def main():
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
# II) Generate doc source in temp dir.
|
||||
doc_gen_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
|
||||
"--python", "%s/doc/python_api/sphinx_doc_gen.py" % args.source_dir, "--",
|
||||
"--output", tmp_dir)
|
||||
doc_gen_cmd = (
|
||||
args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
|
||||
"--python", "%s/doc/python_api/sphinx_doc_gen.py" % args.source_dir, "--",
|
||||
"--output", tmp_dir
|
||||
)
|
||||
subprocess.run(doc_gen_cmd)
|
||||
|
||||
# III) Get Blender version info.
|
||||
getver_file = os.path.join(tmp_dir, "blendver.txt")
|
||||
getver_script = (""
|
||||
getver_script = (
|
||||
"import sys, bpy\n"
|
||||
"with open(sys.argv[-1], 'w') as f:\n"
|
||||
" is_release = bpy.app.version_cycle in {'rc', 'release'}\n"
|
||||
@@ -124,7 +126,8 @@ def main():
|
||||
" f.write('%d.%d%s\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
|
||||
" if is_release else '%s\\n' % branch)\n"
|
||||
" f.write('%d_%d%s_release' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
|
||||
" if is_release else '%d_%d_%d' % bpy.app.version)\n")
|
||||
" if is_release else '%d_%d_%d' % bpy.app.version)\n"
|
||||
)
|
||||
get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
|
||||
"--python-expr", getver_script, "--", getver_file)
|
||||
subprocess.run(get_ver_cmd)
|
||||
|
||||
@@ -34,7 +34,6 @@ add_subdirectory(opencolorio)
|
||||
add_subdirectory(mikktspace)
|
||||
add_subdirectory(glew-mx)
|
||||
add_subdirectory(eigen)
|
||||
add_subdirectory(gawain)
|
||||
|
||||
if(WITH_AUDASPACE)
|
||||
add_subdirectory(audaspace)
|
||||
|
||||
@@ -60,6 +60,10 @@ link_directories(${OPENIMAGEIO_LIBPATH}
|
||||
${TIFF_LIBPATH}
|
||||
${OPENEXR_LIBPATH})
|
||||
|
||||
if(WITH_OPENCOLORIO)
|
||||
link_directories(${OPENCOLORIO_LIBPATH})
|
||||
endif()
|
||||
|
||||
add_definitions(${GL_DEFINITIONS})
|
||||
|
||||
include_directories(${INC})
|
||||
@@ -81,7 +85,6 @@ macro(cycles_target_link_libraries target)
|
||||
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENCOLORIO)
|
||||
link_directories(${OPENCOLORIO_LIBPATH})
|
||||
target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
|
||||
endif()
|
||||
target_link_libraries(
|
||||
|
||||
@@ -164,7 +164,7 @@ bool link_ptxas(CompilationSettings &settings)
|
||||
ptx += " --verbose";
|
||||
printf("%s\n", ptx.c_str());
|
||||
}
|
||||
|
||||
|
||||
int pxresult = system(ptx.c_str());
|
||||
if(pxresult) {
|
||||
fprintf(stderr, "Error: ptxas failed (%x)\n\n", pxresult);
|
||||
|
||||
@@ -112,4 +112,3 @@ int main(int argc, const char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -524,4 +524,3 @@ int main(int argc, const char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ static bool xml_equal_string(xml_node node, const char *name, const char *value)
|
||||
|
||||
if(attr)
|
||||
return string_iequals(attr.value(), value);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -697,4 +697,3 @@ void xml_read_file(Scene *scene, const char *filepath)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ def write(node, fname):
|
||||
|
||||
f = open(fname, "w")
|
||||
f.write(s)
|
||||
|
||||
|
||||
class CyclesXMLSettings(bpy.types.PropertyGroup):
|
||||
@classmethod
|
||||
def register(cls):
|
||||
@@ -53,11 +53,11 @@ class CyclesXMLSettings(bpy.types.PropertyGroup):
|
||||
maxlen=256,
|
||||
default='',
|
||||
subtype='FILE_PATH')
|
||||
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
del bpy.types.Scene.cycles_xml
|
||||
|
||||
|
||||
# User Interface Drawing Code
|
||||
class RenderButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
@@ -74,13 +74,13 @@ class PHYSICS_PT_fluid_export(RenderButtonsPanel, bpy.types.Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
||||
cycles = context.scene.cycles_xml
|
||||
|
||||
|
||||
#layout.prop(cycles, "filepath")
|
||||
layout.operator("export_mesh.cycles_xml")
|
||||
|
||||
|
||||
|
||||
# Export Operator
|
||||
class ExportCyclesXML(bpy.types.Operator, ExportHelper):
|
||||
bl_idname = "export_mesh.cycles_xml"
|
||||
@@ -117,23 +117,23 @@ class ExportCyclesXML(bpy.types.Operator, ExportHelper):
|
||||
P += "%f %f %f " % (v.co[0], v.co[1], v.co[2])
|
||||
|
||||
verts_and_uvs = zip(mesh.tessfaces, mesh.tessface_uv_textures.active.data)
|
||||
|
||||
|
||||
for f, uvf in verts_and_uvs:
|
||||
vcount = len(f.vertices)
|
||||
nverts += str(vcount) + " "
|
||||
|
||||
for v in f.vertices:
|
||||
verts += str(v) + " "
|
||||
|
||||
|
||||
uvs += str(uvf.uv1[0]) + " " + str(uvf.uv1[1]) + " "
|
||||
uvs += str(uvf.uv2[0]) + " " + str(uvf.uv2[1]) + " "
|
||||
uvs += str(uvf.uv3[0]) + " " + str(uvf.uv3[1]) + " "
|
||||
if vcount==4:
|
||||
uvs += " " + str(uvf.uv4[0]) + " " + str(uvf.uv4[1]) + " "
|
||||
|
||||
|
||||
|
||||
node = etree.Element('mesh', attrib={'nverts': nverts.strip(), 'verts': verts.strip(), 'P': P, 'UV' : uvs.strip()})
|
||||
|
||||
|
||||
# write to file
|
||||
write(node, filepath)
|
||||
|
||||
@@ -147,5 +147,3 @@ def unregister():
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
|
||||
|
||||
@@ -45,9 +45,9 @@ if "bpy" in locals():
|
||||
import bpy
|
||||
|
||||
from . import (
|
||||
engine,
|
||||
version_update,
|
||||
)
|
||||
engine,
|
||||
version_update,
|
||||
)
|
||||
|
||||
|
||||
class CyclesRender(bpy.types.RenderEngine):
|
||||
|
||||
@@ -82,15 +82,17 @@ def _parse_command_line():
|
||||
if args.cycles_resumable_current_chunk is not None:
|
||||
import _cycles
|
||||
_cycles.set_resumable_chunk(
|
||||
int(args.cycles_resumable_num_chunks),
|
||||
int(args.cycles_resumable_current_chunk))
|
||||
int(args.cycles_resumable_num_chunks),
|
||||
int(args.cycles_resumable_current_chunk),
|
||||
)
|
||||
elif args.cycles_resumable_start_chunk is not None and \
|
||||
args.cycles_resumable_end_chunk:
|
||||
args.cycles_resumable_end_chunk:
|
||||
import _cycles
|
||||
_cycles.set_resumable_chunk_range(
|
||||
int(args.cycles_resumable_num_chunks),
|
||||
int(args.cycles_resumable_start_chunk),
|
||||
int(args.cycles_resumable_end_chunk))
|
||||
int(args.cycles_resumable_num_chunks),
|
||||
int(args.cycles_resumable_start_chunk),
|
||||
int(args.cycles_resumable_end_chunk),
|
||||
)
|
||||
|
||||
|
||||
def init():
|
||||
@@ -209,6 +211,7 @@ def system_info():
|
||||
import _cycles
|
||||
return _cycles.system_info()
|
||||
|
||||
|
||||
def register_passes(engine, scene, srl):
|
||||
engine.register_pass(scene, srl, "Combined", 4, "RGBA", 'COLOR')
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy_extras.node_utils import find_node_input, find_output_node
|
||||
from bpy_extras.node_utils import find_node_input
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
from bpy.types import (
|
||||
@@ -1008,7 +1008,7 @@ class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel):
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return (CyclesButtonsPanel.poll(context) and
|
||||
ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
|
||||
ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or
|
||||
(ob.dupli_type == 'COLLECTION' and ob.dupli_group)))
|
||||
|
||||
def draw(self, context):
|
||||
@@ -1029,7 +1029,7 @@ class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel):
|
||||
flow.prop(visibility, "transmission")
|
||||
flow.prop(visibility, "scatter")
|
||||
|
||||
if ob.type != 'LAMP':
|
||||
if ob.type != 'LIGHT':
|
||||
flow.prop(visibility, "shadow")
|
||||
|
||||
row = layout.row()
|
||||
@@ -1049,34 +1049,34 @@ class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel):
|
||||
|
||||
|
||||
class CYCLES_OT_use_shading_nodes(Operator):
|
||||
"""Enable nodes on a material, world or lamp"""
|
||||
"""Enable nodes on a material, world or light"""
|
||||
bl_idname = "cycles.use_shading_nodes"
|
||||
bl_label = "Use Nodes"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (getattr(context, "material", False) or getattr(context, "world", False) or
|
||||
getattr(context, "lamp", False))
|
||||
getattr(context, "light", False))
|
||||
|
||||
def execute(self, context):
|
||||
if context.material:
|
||||
context.material.use_nodes = True
|
||||
elif context.world:
|
||||
context.world.use_nodes = True
|
||||
elif context.lamp:
|
||||
context.lamp.use_nodes = True
|
||||
elif context.light:
|
||||
context.light.use_nodes = True
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def panel_node_draw(layout, id_data, output_types, input_name):
|
||||
def panel_node_draw(layout, id_data, output_type, input_name):
|
||||
if not id_data.use_nodes:
|
||||
layout.operator("cycles.use_shading_nodes", icon='NODETREE')
|
||||
return False
|
||||
|
||||
ntree = id_data.node_tree
|
||||
|
||||
node = find_output_node(ntree, output_types)
|
||||
node = ntree.get_output_node('CYCLES')
|
||||
if node:
|
||||
input = find_node_input(node, input_name)
|
||||
if input:
|
||||
@@ -1089,7 +1089,7 @@ def panel_node_draw(layout, id_data, output_types, input_name):
|
||||
return True
|
||||
|
||||
|
||||
class CYCLES_LAMP_PT_preview(CyclesButtonsPanel, Panel):
|
||||
class CYCLES_LIGHT_PT_preview(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Preview"
|
||||
bl_context = "data"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -1097,52 +1097,52 @@ class CYCLES_LAMP_PT_preview(CyclesButtonsPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (
|
||||
context.lamp and
|
||||
context.light and
|
||||
not (
|
||||
context.lamp.type == 'AREA' and
|
||||
context.lamp.cycles.is_portal
|
||||
context.light.type == 'AREA' and
|
||||
context.light.cycles.is_portal
|
||||
) and
|
||||
CyclesButtonsPanel.poll(context)
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.template_preview(context.lamp)
|
||||
self.layout.template_preview(context.light)
|
||||
|
||||
|
||||
class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Lamp"
|
||||
class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Light"
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.lamp and CyclesButtonsPanel.poll(context)
|
||||
return context.light and CyclesButtonsPanel.poll(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
lamp = context.lamp
|
||||
clamp = lamp.cycles
|
||||
light = context.light
|
||||
clamp = light.cycles
|
||||
# cscene = context.scene.cycles
|
||||
|
||||
layout.prop(lamp, "type", expand=True)
|
||||
layout.prop(light, "type", expand=True)
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
|
||||
if lamp.type in {'POINT', 'SUN', 'SPOT'}:
|
||||
col.prop(lamp, "shadow_soft_size", text="Size")
|
||||
elif lamp.type == 'AREA':
|
||||
col.prop(lamp, "shape", text="Shape")
|
||||
if light.type in {'POINT', 'SUN', 'SPOT'}:
|
||||
col.prop(light, "shadow_soft_size", text="Size")
|
||||
elif light.type == 'AREA':
|
||||
col.prop(light, "shape", text="Shape")
|
||||
sub = col.column(align=True)
|
||||
|
||||
if lamp.shape in {'SQUARE', 'DISK'}:
|
||||
sub.prop(lamp, "size")
|
||||
elif lamp.shape in {'RECTANGLE', 'ELLIPSE'}:
|
||||
sub.prop(lamp, "size", text="Size X")
|
||||
sub.prop(lamp, "size_y", text="Y")
|
||||
if light.shape in {'SQUARE', 'DISK'}:
|
||||
sub.prop(light, "size")
|
||||
elif light.shape in {'RECTANGLE', 'ELLIPSE'}:
|
||||
sub.prop(light, "size", text="Size X")
|
||||
sub.prop(light, "size_y", text="Y")
|
||||
|
||||
if not (lamp.type == 'AREA' and clamp.is_portal):
|
||||
if not (light.type == 'AREA' and clamp.is_portal):
|
||||
sub = col.column()
|
||||
if use_branched_path(context):
|
||||
subsub = sub.row(align=True)
|
||||
@@ -1151,53 +1151,53 @@ class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel):
|
||||
sub.prop(clamp, "max_bounces")
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
|
||||
sub.active = not (light.type == 'AREA' and clamp.is_portal)
|
||||
sub.prop(clamp, "cast_shadow")
|
||||
sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
|
||||
|
||||
if lamp.type == 'AREA':
|
||||
if light.type == 'AREA':
|
||||
col.prop(clamp, "is_portal", text="Portal")
|
||||
|
||||
if lamp.type == 'HEMI':
|
||||
layout.label(text="Not supported, interpreted as sun lamp")
|
||||
if light.type == 'HEMI':
|
||||
layout.label(text="Not supported, interpreted as sun light")
|
||||
|
||||
|
||||
class CYCLES_LAMP_PT_nodes(CyclesButtonsPanel, Panel):
|
||||
class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Nodes"
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.lamp and not (context.lamp.type == 'AREA' and
|
||||
context.lamp.cycles.is_portal) and \
|
||||
return context.light and not (context.light.type == 'AREA' and
|
||||
context.light.cycles.is_portal) and \
|
||||
CyclesButtonsPanel.poll(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
lamp = context.lamp
|
||||
if not panel_node_draw(layout, lamp, ('OUTPUT_LAMP',), 'Surface'):
|
||||
layout.prop(lamp, "color")
|
||||
light = context.light
|
||||
if not panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface'):
|
||||
layout.prop(light, "color")
|
||||
|
||||
|
||||
class CYCLES_LAMP_PT_spot(CyclesButtonsPanel, Panel):
|
||||
class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Spot Shape"
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
lamp = context.lamp
|
||||
return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
|
||||
light = context.light
|
||||
return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
lamp = context.lamp
|
||||
light = context.light
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
col.prop(lamp, "spot_size", text="Size")
|
||||
col.prop(lamp, "spot_blend", text="Blend", slider=True)
|
||||
col.prop(lamp, "show_cone")
|
||||
col.prop(light, "spot_size", text="Size")
|
||||
col.prop(light, "spot_blend", text="Blend", slider=True)
|
||||
col.prop(light, "show_cone")
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
|
||||
@@ -1226,8 +1226,8 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
|
||||
|
||||
world = context.world
|
||||
|
||||
if not panel_node_draw(layout, world, ('OUTPUT_WORLD',), 'Surface'):
|
||||
layout.prop(world, "horizon_color", text="Color")
|
||||
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
|
||||
layout.prop(world, "color")
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
|
||||
@@ -1244,7 +1244,7 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
|
||||
layout = self.layout
|
||||
|
||||
world = context.world
|
||||
panel_node_draw(layout, world, ('OUTPUT_WORLD',), 'Volume')
|
||||
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
|
||||
@@ -1344,6 +1344,7 @@ class CYCLES_WORLD_PT_settings(CyclesButtonsPanel, Panel):
|
||||
|
||||
col = layout.column()
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Surface"
|
||||
bl_parent_id = "CYCLES_WORLD_PT_settings"
|
||||
@@ -1425,7 +1426,7 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
|
||||
layout = self.layout
|
||||
|
||||
mat = context.material
|
||||
if not panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Surface'):
|
||||
if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
|
||||
layout.prop(mat, "diffuse_color")
|
||||
|
||||
|
||||
@@ -1445,7 +1446,7 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
|
||||
mat = context.material
|
||||
# cmat = mat.cycles
|
||||
|
||||
panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Volume')
|
||||
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
|
||||
|
||||
|
||||
class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
|
||||
@@ -1461,7 +1462,7 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
|
||||
layout = self.layout
|
||||
|
||||
mat = context.material
|
||||
panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Displacement')
|
||||
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
|
||||
|
||||
|
||||
class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel):
|
||||
@@ -1528,8 +1529,6 @@ class CYCLES_MATERIAL_PT_settings_volume(CyclesButtonsPanel, Panel):
|
||||
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
|
||||
|
||||
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Bake"
|
||||
bl_context = "render"
|
||||
@@ -1789,7 +1788,7 @@ def get_panels():
|
||||
'DATA_PT_area',
|
||||
'DATA_PT_camera_dof',
|
||||
'DATA_PT_falloff_curve',
|
||||
'DATA_PT_lamp',
|
||||
'DATA_PT_light',
|
||||
'DATA_PT_preview',
|
||||
'DATA_PT_spot',
|
||||
'MATERIAL_PT_context_material',
|
||||
@@ -1843,10 +1842,10 @@ classes = (
|
||||
CYCLES_OBJECT_PT_motion_blur,
|
||||
CYCLES_OBJECT_PT_cycles_settings,
|
||||
CYCLES_OT_use_shading_nodes,
|
||||
CYCLES_LAMP_PT_preview,
|
||||
CYCLES_LAMP_PT_lamp,
|
||||
CYCLES_LAMP_PT_nodes,
|
||||
CYCLES_LAMP_PT_spot,
|
||||
CYCLES_LIGHT_PT_preview,
|
||||
CYCLES_LIGHT_PT_light,
|
||||
CYCLES_LIGHT_PT_nodes,
|
||||
CYCLES_LIGHT_PT_spot,
|
||||
CYCLES_WORLD_PT_preview,
|
||||
CYCLES_WORLD_PT_surface,
|
||||
CYCLES_WORLD_PT_volume,
|
||||
|
||||
@@ -22,45 +22,6 @@ import math
|
||||
from bpy.app.handlers import persistent
|
||||
|
||||
|
||||
def check_is_new_shading_ntree(node_tree):
|
||||
for node in node_tree.nodes:
|
||||
# If material has any node with ONLY new shading system
|
||||
# compatibility then it's considered a Cycles material
|
||||
# and versioning code would need to perform on it.
|
||||
#
|
||||
# We can not check for whether NEW_SHADING in compatibility
|
||||
# because some nodes could have compatibility with both old
|
||||
# and new shading system and they can't be used for any
|
||||
# decision here.
|
||||
if node.shading_compatibility == {'NEW_SHADING'}:
|
||||
return True
|
||||
|
||||
# If node is only compatible with old shading system
|
||||
# then material can not be Cycles material and we
|
||||
# can stopiterating nodes now.
|
||||
if node.shading_compatibility == {'OLD_SHADING'}:
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def check_is_new_shading_material(material):
|
||||
if not material.node_tree:
|
||||
return False
|
||||
return check_is_new_shading_ntree(material.node_tree)
|
||||
|
||||
|
||||
def check_is_new_shading_world(world):
|
||||
if not world.node_tree:
|
||||
return False
|
||||
return check_is_new_shading_ntree(world.node_tree)
|
||||
|
||||
|
||||
def check_is_new_shading_lamp(lamp):
|
||||
if not lamp.node_tree:
|
||||
return False
|
||||
return check_is_new_shading_ntree(lamp.node_tree)
|
||||
|
||||
|
||||
def foreach_notree_node(nodetree, callback, traversed):
|
||||
if nodetree in traversed:
|
||||
return
|
||||
@@ -74,20 +35,26 @@ def foreach_notree_node(nodetree, callback, traversed):
|
||||
def foreach_cycles_node(callback):
|
||||
traversed = set()
|
||||
for material in bpy.data.materials:
|
||||
if check_is_new_shading_material(material):
|
||||
foreach_notree_node(material.node_tree,
|
||||
callback,
|
||||
traversed)
|
||||
if material.node_tree:
|
||||
foreach_notree_node(
|
||||
material.node_tree,
|
||||
callback,
|
||||
traversed,
|
||||
)
|
||||
for world in bpy.data.worlds:
|
||||
if check_is_new_shading_world(world):
|
||||
foreach_notree_node(world.node_tree,
|
||||
callback,
|
||||
traversed)
|
||||
for lamp in bpy.data.lamps:
|
||||
if check_is_new_shading_world(lamp):
|
||||
foreach_notree_node(lamp.node_tree,
|
||||
callback,
|
||||
traversed)
|
||||
if world.node_tree:
|
||||
foreach_notree_node(
|
||||
world.node_tree,
|
||||
callback,
|
||||
traversed,
|
||||
)
|
||||
for light in bpy.data.lights:
|
||||
if light.node_tree:
|
||||
foreach_notree_node(
|
||||
light.node_tree,
|
||||
callback,
|
||||
traversed,
|
||||
)
|
||||
|
||||
|
||||
def displacement_node_insert(material, nodetree, traversed):
|
||||
@@ -102,10 +69,12 @@ def displacement_node_insert(material, nodetree, traversed):
|
||||
# Gather links to replace
|
||||
displacement_links = []
|
||||
for link in nodetree.links:
|
||||
if link.to_node.bl_idname == 'ShaderNodeOutputMaterial' and \
|
||||
link.from_node.bl_idname != 'ShaderNodeDisplacement' and \
|
||||
link.to_socket.identifier == 'Displacement':
|
||||
displacement_links.append(link)
|
||||
if (
|
||||
link.to_node.bl_idname == 'ShaderNodeOutputMaterial' and
|
||||
link.from_node.bl_idname != 'ShaderNodeDisplacement' and
|
||||
link.to_socket.identifier == 'Displacement'
|
||||
):
|
||||
displacement_links.append(link)
|
||||
|
||||
# Replace links with displacement node
|
||||
for link in displacement_links:
|
||||
@@ -117,20 +86,22 @@ def displacement_node_insert(material, nodetree, traversed):
|
||||
nodetree.links.remove(link)
|
||||
|
||||
node = nodetree.nodes.new(type='ShaderNodeDisplacement')
|
||||
node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0]);
|
||||
node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1]);
|
||||
node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0])
|
||||
node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1])
|
||||
node.inputs['Scale'].default_value = 0.1
|
||||
node.inputs['Midlevel'].default_value = 0.0
|
||||
|
||||
nodetree.links.new(from_socket, node.inputs['Height'])
|
||||
nodetree.links.new(node.outputs['Displacement'], to_socket)
|
||||
|
||||
|
||||
def displacement_nodes_insert():
|
||||
traversed = set()
|
||||
for material in bpy.data.materials:
|
||||
if check_is_new_shading_material(material):
|
||||
if material.node_tree:
|
||||
displacement_node_insert(material, material.node_tree, traversed)
|
||||
|
||||
|
||||
def displacement_principled_nodes(node):
|
||||
if node.bl_idname == 'ShaderNodeDisplacement':
|
||||
if node.space != 'WORLD':
|
||||
@@ -139,6 +110,7 @@ def displacement_principled_nodes(node):
|
||||
if node.subsurface_method != 'RANDOM_WALK':
|
||||
node.subsurface_method = 'BURLEY'
|
||||
|
||||
|
||||
def square_roughness_node_insert(material, nodetree, traversed):
|
||||
if nodetree in traversed:
|
||||
return
|
||||
@@ -163,7 +135,7 @@ def square_roughness_node_insert(material, nodetree, traversed):
|
||||
for link in nodetree.links:
|
||||
if link.to_node.bl_idname in roughness_node_types and \
|
||||
link.to_socket.identifier == 'Roughness':
|
||||
roughness_links.append(link)
|
||||
roughness_links.append(link)
|
||||
|
||||
# Replace links with sqrt node
|
||||
for link in roughness_links:
|
||||
@@ -176,17 +148,18 @@ def square_roughness_node_insert(material, nodetree, traversed):
|
||||
|
||||
node = nodetree.nodes.new(type='ShaderNodeMath')
|
||||
node.operation = 'POWER'
|
||||
node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0]);
|
||||
node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1]);
|
||||
node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0])
|
||||
node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1])
|
||||
|
||||
nodetree.links.new(from_socket, node.inputs[0])
|
||||
node.inputs[1].default_value = 0.5
|
||||
nodetree.links.new(node.outputs['Value'], to_socket)
|
||||
|
||||
|
||||
def square_roughness_nodes_insert():
|
||||
traversed = set()
|
||||
for material in bpy.data.materials:
|
||||
if check_is_new_shading_material(material):
|
||||
if material.node_tree:
|
||||
square_roughness_node_insert(material, material.node_tree, traversed)
|
||||
|
||||
|
||||
@@ -288,7 +261,7 @@ def ambient_occlusion_node_relink(material, nodetree, traversed):
|
||||
ao_links = []
|
||||
for link in nodetree.links:
|
||||
if link.from_node.bl_idname == 'ShaderNodeAmbientOcclusion':
|
||||
ao_links.append(link)
|
||||
ao_links.append(link)
|
||||
|
||||
# Replace links
|
||||
for link in ao_links:
|
||||
@@ -298,10 +271,11 @@ def ambient_occlusion_node_relink(material, nodetree, traversed):
|
||||
nodetree.links.remove(link)
|
||||
nodetree.links.new(from_node.outputs['Color'], to_socket)
|
||||
|
||||
|
||||
def ambient_occlusion_nodes_relink():
|
||||
traversed = set()
|
||||
for material in bpy.data.materials:
|
||||
if check_is_new_shading_material(material):
|
||||
if material.node_tree:
|
||||
ambient_occlusion_node_relink(material, material.node_tree, traversed)
|
||||
|
||||
|
||||
@@ -337,7 +311,7 @@ def do_versions(self):
|
||||
sample_clamp = cscene.get("sample_clamp", False)
|
||||
if (sample_clamp and
|
||||
not cscene.is_property_set("sample_clamp_direct") and
|
||||
not cscene.is_property_set("sample_clamp_indirect")):
|
||||
not cscene.is_property_set("sample_clamp_indirect")):
|
||||
|
||||
cscene.sample_clamp_direct = sample_clamp
|
||||
cscene.sample_clamp_indirect = sample_clamp
|
||||
@@ -355,7 +329,7 @@ def do_versions(self):
|
||||
cscene = scene.cycles
|
||||
if (cscene.get("no_caustics", False) and
|
||||
not cscene.is_property_set("caustics_reflective") and
|
||||
not cscene.is_property_set("caustics_refractive")):
|
||||
not cscene.is_property_set("caustics_refractive")):
|
||||
|
||||
cscene.caustics_reflective = False
|
||||
cscene.caustics_refractive = False
|
||||
@@ -393,12 +367,12 @@ def do_versions(self):
|
||||
if not cscene.is_property_set("tile_order"):
|
||||
cscene.tile_order = 'CENTER'
|
||||
|
||||
for lamp in bpy.data.lamps:
|
||||
clamp = lamp.cycles
|
||||
for light in bpy.data.lights:
|
||||
clight = light.cycles
|
||||
|
||||
# MIS
|
||||
if not clamp.is_property_set("use_multiple_importance_sampling"):
|
||||
clamp.use_multiple_importance_sampling = False
|
||||
if not clight.is_property_set("use_multiple_importance_sampling"):
|
||||
clight.use_multiple_importance_sampling = False
|
||||
|
||||
for mat in bpy.data.materials:
|
||||
cmat = mat.cycles
|
||||
|
||||
@@ -124,7 +124,7 @@ static float blender_camera_focal_distance(BL::RenderEngine& b_engine,
|
||||
|
||||
if(!b_dof_object)
|
||||
return b_camera.dof_distance();
|
||||
|
||||
|
||||
/* for dof object, return distance along camera Z direction */
|
||||
BL::Array<float, 16> b_ob_matrix;
|
||||
b_engine.camera_model_matrix(b_ob, bcam->use_spherical_stereo, b_ob_matrix);
|
||||
@@ -232,7 +232,7 @@ static void blender_camera_from_object(BlenderCamera *bcam,
|
||||
bcam->motion_steps = object_motion_steps(b_ob, b_ob);
|
||||
}
|
||||
else {
|
||||
/* from lamp not implemented yet */
|
||||
/* from light not implemented yet */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,7 +726,7 @@ static void blender_camera_view_subset(BL::RenderEngine& b_engine,
|
||||
|
||||
blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height,
|
||||
&cam, &cam_aspect, &sensor_size);
|
||||
|
||||
|
||||
/* return */
|
||||
*view_box = view * (1.0f/view_aspect);
|
||||
*cam_box = cam * (1.0f/cam_aspect);
|
||||
@@ -895,4 +895,3 @@ BufferParams BlenderSync::get_buffer_params(BL::RenderSettings& b_render,
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -1077,14 +1077,6 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
|
||||
bool object_updated,
|
||||
bool hide_tris)
|
||||
{
|
||||
/* When viewport display is not needed during render we can force some
|
||||
* caches to be releases from blender side in order to reduce peak memory
|
||||
* footprint during synchronization process.
|
||||
*/
|
||||
const bool is_interface_locked = b_engine.render() &&
|
||||
b_engine.render().use_lock_interface();
|
||||
const bool can_free_caches = BlenderSession::headless || is_interface_locked;
|
||||
|
||||
/* test if we can instance or if the object is modified */
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob_instance: b_ob_data;
|
||||
@@ -1209,10 +1201,6 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
|
||||
if(view_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
|
||||
sync_curves(mesh, b_mesh, b_ob, false);
|
||||
|
||||
if(can_free_caches) {
|
||||
b_ob.cache_release();
|
||||
}
|
||||
|
||||
/* free derived mesh */
|
||||
b_data.meshes.remove(b_mesh, false, true, false);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ bool BlenderSync::object_is_light(BL::Object& b_ob)
|
||||
{
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
|
||||
return (b_ob_data && b_ob_data.is_a(&RNA_Lamp));
|
||||
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
|
||||
}
|
||||
|
||||
static uint object_ray_visibility(BL::Object& b_ob)
|
||||
@@ -126,57 +126,57 @@ void BlenderSync::sync_light(BL::Object& b_parent,
|
||||
*use_portal = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BL::Lamp b_lamp(b_ob.data());
|
||||
|
||||
BL::Light b_light(b_ob.data());
|
||||
|
||||
/* type */
|
||||
switch(b_lamp.type()) {
|
||||
case BL::Lamp::type_POINT: {
|
||||
BL::PointLamp b_point_lamp(b_lamp);
|
||||
light->size = b_point_lamp.shadow_soft_size();
|
||||
switch(b_light.type()) {
|
||||
case BL::Light::type_POINT: {
|
||||
BL::PointLight b_point_light(b_light);
|
||||
light->size = b_point_light.shadow_soft_size();
|
||||
light->type = LIGHT_POINT;
|
||||
break;
|
||||
}
|
||||
case BL::Lamp::type_SPOT: {
|
||||
BL::SpotLamp b_spot_lamp(b_lamp);
|
||||
light->size = b_spot_lamp.shadow_soft_size();
|
||||
case BL::Light::type_SPOT: {
|
||||
BL::SpotLight b_spot_light(b_light);
|
||||
light->size = b_spot_light.shadow_soft_size();
|
||||
light->type = LIGHT_SPOT;
|
||||
light->spot_angle = b_spot_lamp.spot_size();
|
||||
light->spot_smooth = b_spot_lamp.spot_blend();
|
||||
light->spot_angle = b_spot_light.spot_size();
|
||||
light->spot_smooth = b_spot_light.spot_blend();
|
||||
break;
|
||||
}
|
||||
case BL::Lamp::type_HEMI: {
|
||||
case BL::Light::type_HEMI: {
|
||||
light->type = LIGHT_DISTANT;
|
||||
light->size = 0.0f;
|
||||
break;
|
||||
}
|
||||
case BL::Lamp::type_SUN: {
|
||||
BL::SunLamp b_sun_lamp(b_lamp);
|
||||
light->size = b_sun_lamp.shadow_soft_size();
|
||||
case BL::Light::type_SUN: {
|
||||
BL::SunLight b_sun_light(b_light);
|
||||
light->size = b_sun_light.shadow_soft_size();
|
||||
light->type = LIGHT_DISTANT;
|
||||
break;
|
||||
}
|
||||
case BL::Lamp::type_AREA: {
|
||||
BL::AreaLamp b_area_lamp(b_lamp);
|
||||
case BL::Light::type_AREA: {
|
||||
BL::AreaLight b_area_light(b_light);
|
||||
light->size = 1.0f;
|
||||
light->axisu = transform_get_column(&tfm, 0);
|
||||
light->axisv = transform_get_column(&tfm, 1);
|
||||
light->sizeu = b_area_lamp.size();
|
||||
switch(b_area_lamp.shape()) {
|
||||
case BL::AreaLamp::shape_SQUARE:
|
||||
light->sizeu = b_area_light.size();
|
||||
switch(b_area_light.shape()) {
|
||||
case BL::AreaLight::shape_SQUARE:
|
||||
light->sizev = light->sizeu;
|
||||
light->round = false;
|
||||
break;
|
||||
case BL::AreaLamp::shape_RECTANGLE:
|
||||
light->sizev = b_area_lamp.size_y();
|
||||
case BL::AreaLight::shape_RECTANGLE:
|
||||
light->sizev = b_area_light.size_y();
|
||||
light->round = false;
|
||||
break;
|
||||
case BL::AreaLamp::shape_DISK:
|
||||
case BL::AreaLight::shape_DISK:
|
||||
light->sizev = light->sizeu;
|
||||
light->round = true;
|
||||
break;
|
||||
case BL::AreaLamp::shape_ELLIPSE:
|
||||
light->sizev = b_area_lamp.size_y();
|
||||
case BL::AreaLight::shape_ELLIPSE:
|
||||
light->sizev = b_area_light.size_y();
|
||||
light->round = true;
|
||||
break;
|
||||
}
|
||||
@@ -192,22 +192,22 @@ void BlenderSync::sync_light(BL::Object& b_parent,
|
||||
|
||||
/* shader */
|
||||
vector<Shader*> used_shaders;
|
||||
find_shader(b_lamp, used_shaders, scene->default_light);
|
||||
find_shader(b_light, used_shaders, scene->default_light);
|
||||
light->shader = used_shaders[0];
|
||||
|
||||
/* shadow */
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
|
||||
light->cast_shadow = get_boolean(clamp, "cast_shadow");
|
||||
light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling");
|
||||
|
||||
int samples = get_int(clamp, "samples");
|
||||
PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
|
||||
light->cast_shadow = get_boolean(clight, "cast_shadow");
|
||||
light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
|
||||
|
||||
int samples = get_int(clight, "samples");
|
||||
if(get_boolean(cscene, "use_square_samples"))
|
||||
light->samples = samples * samples;
|
||||
else
|
||||
light->samples = samples;
|
||||
|
||||
light->max_bounces = get_int(clamp, "max_bounces");
|
||||
light->max_bounces = get_int(clight, "max_bounces");
|
||||
|
||||
if(b_ob != b_ob_instance) {
|
||||
light->random_id = random_id;
|
||||
@@ -217,7 +217,7 @@ void BlenderSync::sync_light(BL::Object& b_parent,
|
||||
}
|
||||
|
||||
if(light->type == LIGHT_AREA)
|
||||
light->is_portal = get_boolean(clamp, "is_portal");
|
||||
light->is_portal = get_boolean(clight, "is_portal");
|
||||
else
|
||||
light->is_portal = false;
|
||||
|
||||
@@ -315,7 +315,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
|
||||
|
||||
/* light is handled separately */
|
||||
if(object_is_light(b_ob)) {
|
||||
/* don't use lamps for excluded layers used as mask layer */
|
||||
/* don't use lights for excluded layers used as mask layer */
|
||||
if(!motion && !((layer_flag & view_layer.holdout_layer) &&
|
||||
(layer_flag & view_layer.exclude_layer)))
|
||||
{
|
||||
@@ -394,7 +394,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
|
||||
|
||||
if(object_map.sync(&object, b_ob, b_parent, key))
|
||||
object_updated = true;
|
||||
|
||||
|
||||
/* mesh sync */
|
||||
object->mesh = sync_mesh(b_depsgraph, b_ob, b_ob_instance, object_updated, hide_tris);
|
||||
|
||||
@@ -543,7 +543,7 @@ static bool object_render_hide(BL::Object& b_ob,
|
||||
}
|
||||
parent = parent.parent();
|
||||
}
|
||||
|
||||
|
||||
hide_triangles = hide_emitter;
|
||||
|
||||
if(show_emitter) {
|
||||
@@ -563,7 +563,7 @@ void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time)
|
||||
{
|
||||
/* layer data */
|
||||
bool motion = motion_time != 0.0f;
|
||||
|
||||
|
||||
if(!motion) {
|
||||
/* prepare for sync */
|
||||
light_map.pre_sync();
|
||||
@@ -729,4 +729,3 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -146,4 +146,3 @@ bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8])
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
|
||||
/* add particle */
|
||||
BL::Particle b_pa = b_psys.particles[persistent_id[0]];
|
||||
Particle pa;
|
||||
|
||||
|
||||
pa.index = persistent_id[0];
|
||||
pa.age = b_scene.frame_current() - b_pa.birth_time();
|
||||
pa.lifetime = b_pa.lifetime();
|
||||
|
||||
@@ -326,7 +326,7 @@ static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
if(!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d))
|
||||
return NULL;
|
||||
|
||||
|
||||
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
|
||||
|
||||
if(PyLong_AsVoidPtr(pyrv3d)) {
|
||||
@@ -594,7 +594,7 @@ static PyObject *osl_compile_func(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
|
||||
return NULL;
|
||||
|
||||
|
||||
/* return */
|
||||
if(!OSLShaderManager::osl_compile(inputfile, outputfile))
|
||||
Py_RETURN_FALSE;
|
||||
|
||||
@@ -154,7 +154,7 @@ static SocketType::Type convert_socket_type(BL::NodeSocket& b_socket)
|
||||
return SocketType::STRING;
|
||||
case BL::NodeSocket::type_SHADER:
|
||||
return SocketType::CLOSURE;
|
||||
|
||||
|
||||
default:
|
||||
return SocketType::UNDEFINED;
|
||||
}
|
||||
@@ -436,7 +436,7 @@ static ShaderNode *add_node(Scene *scene,
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
|
||||
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
|
||||
GlossyBsdfNode *glossy = new GlossyBsdfNode();
|
||||
|
||||
|
||||
switch(b_glossy_node.distribution()) {
|
||||
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
|
||||
glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
|
||||
@@ -517,6 +517,12 @@ static ShaderNode *add_node(Scene *scene,
|
||||
}
|
||||
node = hair;
|
||||
}
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
|
||||
BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
|
||||
PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
|
||||
principled_hair->parametrization = (NodePrincipledHairParametrization) get_enum(b_principled_hair_node.ptr, "parametrization", NODE_PRINCIPLED_HAIR_NUM, NODE_PRINCIPLED_HAIR_REFLECTANCE);
|
||||
node = principled_hair;
|
||||
}
|
||||
else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
|
||||
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
|
||||
PrincipledBsdfNode *principled = new PrincipledBsdfNode();
|
||||
@@ -747,6 +753,8 @@ static ShaderNode *add_node(Scene *scene,
|
||||
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
|
||||
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
|
||||
voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
|
||||
voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
|
||||
voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
|
||||
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
|
||||
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
|
||||
node = voronoi;
|
||||
@@ -940,7 +948,7 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node,
|
||||
BL::NodeSocket& b_socket)
|
||||
{
|
||||
string name = b_socket.name();
|
||||
|
||||
|
||||
if(node_use_modified_socket_name(node)) {
|
||||
BL::Node::inputs_iterator b_input;
|
||||
bool found = false;
|
||||
@@ -1001,31 +1009,6 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node,
|
||||
return node->output(name.c_str());
|
||||
}
|
||||
|
||||
static BL::ShaderNode find_output_node(BL::ShaderNodeTree& b_ntree)
|
||||
{
|
||||
BL::ShaderNodeTree::nodes_iterator b_node;
|
||||
BL::ShaderNode output_node(PointerRNA_NULL);
|
||||
|
||||
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
||||
BL::ShaderNodeOutputMaterial b_output_node(*b_node);
|
||||
|
||||
if (b_output_node.is_a(&RNA_ShaderNodeOutputMaterial) ||
|
||||
b_output_node.is_a(&RNA_ShaderNodeOutputWorld) ||
|
||||
b_output_node.is_a(&RNA_ShaderNodeOutputLamp)) {
|
||||
/* regular Cycles output node */
|
||||
if(b_output_node.is_active_output()) {
|
||||
output_node = b_output_node;
|
||||
break;
|
||||
}
|
||||
else if(!output_node.ptr.data) {
|
||||
output_node = b_output_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_node;
|
||||
}
|
||||
|
||||
static void add_nodes(Scene *scene,
|
||||
BL::RenderEngine& b_engine,
|
||||
BL::BlendData& b_data,
|
||||
@@ -1045,7 +1028,7 @@ static void add_nodes(Scene *scene,
|
||||
BL::Node::outputs_iterator b_output;
|
||||
|
||||
/* find the node to use for output if there are multiple */
|
||||
BL::ShaderNode output_node = find_output_node(b_ntree);
|
||||
BL::ShaderNode output_node = b_ntree.get_output_node(BL::ShaderNodeOutputMaterial::target_CYCLES);
|
||||
|
||||
/* add nodes */
|
||||
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
||||
@@ -1068,7 +1051,7 @@ static void add_nodes(Scene *scene,
|
||||
}
|
||||
}
|
||||
else if(b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) {
|
||||
|
||||
|
||||
BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
|
||||
if(b_node->is_a(&RNA_ShaderNodeGroup))
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
|
||||
@@ -1110,7 +1093,7 @@ static void add_nodes(Scene *scene,
|
||||
|
||||
output_map[b_output->ptr.data] = proxy->outputs[0];
|
||||
}
|
||||
|
||||
|
||||
if(b_group_ntree) {
|
||||
add_nodes(scene,
|
||||
b_engine,
|
||||
@@ -1353,7 +1336,7 @@ void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
}
|
||||
else if(b_world) {
|
||||
BackgroundNode *background = new BackgroundNode();
|
||||
background->color = get_float3(b_world.horizon_color());
|
||||
background->color = get_float3(b_world.color());
|
||||
graph->add(background);
|
||||
|
||||
ShaderNode *out = graph->output();
|
||||
@@ -1418,45 +1401,45 @@ void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
background->tag_update(scene);
|
||||
}
|
||||
|
||||
/* Sync Lamps */
|
||||
/* Sync Lights */
|
||||
|
||||
void BlenderSync::sync_lamps(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
void BlenderSync::sync_lights(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
{
|
||||
shader_map.set_default(scene->default_light);
|
||||
|
||||
BL::Depsgraph::ids_iterator b_id;
|
||||
for(b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
|
||||
if (!b_id->is_a(&RNA_Lamp)) {
|
||||
if (!b_id->is_a(&RNA_Light)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BL::Lamp b_lamp(*b_id);
|
||||
BL::Light b_light(*b_id);
|
||||
Shader *shader;
|
||||
|
||||
/* test if we need to sync */
|
||||
if(shader_map.sync(&shader, b_lamp) || update_all) {
|
||||
if(shader_map.sync(&shader, b_light) || update_all) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
/* create nodes */
|
||||
if(b_lamp.use_nodes() && b_lamp.node_tree()) {
|
||||
shader->name = b_lamp.name().c_str();
|
||||
if(b_light.use_nodes() && b_light.node_tree()) {
|
||||
shader->name = b_light.name().c_str();
|
||||
|
||||
BL::ShaderNodeTree b_ntree(b_lamp.node_tree());
|
||||
BL::ShaderNodeTree b_ntree(b_light.node_tree());
|
||||
|
||||
add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
|
||||
}
|
||||
else {
|
||||
float strength = 1.0f;
|
||||
|
||||
if(b_lamp.type() == BL::Lamp::type_POINT ||
|
||||
b_lamp.type() == BL::Lamp::type_SPOT ||
|
||||
b_lamp.type() == BL::Lamp::type_AREA)
|
||||
if(b_light.type() == BL::Light::type_POINT ||
|
||||
b_light.type() == BL::Light::type_SPOT ||
|
||||
b_light.type() == BL::Light::type_AREA)
|
||||
{
|
||||
strength = 100.0f;
|
||||
}
|
||||
|
||||
EmissionNode *emission = new EmissionNode();
|
||||
emission->color = get_float3(b_lamp.color());
|
||||
emission->color = get_float3(b_light.color());
|
||||
emission->strength = strength;
|
||||
graph->add(emission);
|
||||
|
||||
@@ -1484,7 +1467,7 @@ void BlenderSync::sync_shaders(BL::Depsgraph& b_depsgraph)
|
||||
shader_map.pre_sync();
|
||||
|
||||
sync_world(b_depsgraph, auto_refresh_update);
|
||||
sync_lamps(b_depsgraph, auto_refresh_update);
|
||||
sync_lights(b_depsgraph, auto_refresh_update);
|
||||
sync_materials(b_depsgraph, auto_refresh_update);
|
||||
|
||||
/* false = don't delete unused shaders, not supported */
|
||||
@@ -1492,4 +1475,3 @@ void BlenderSync::sync_shaders(BL::Depsgraph& b_depsgraph)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -113,17 +113,17 @@ void BlenderSync::sync_recalc(BL::Depsgraph& b_depsgraph)
|
||||
BL::Material b_mat(b_id);
|
||||
shader_map.set_recalc(b_mat);
|
||||
}
|
||||
/* Lamp */
|
||||
else if (b_id.is_a(&RNA_Lamp)) {
|
||||
BL::Lamp b_lamp(b_id);
|
||||
shader_map.set_recalc(b_lamp);
|
||||
/* Light */
|
||||
else if (b_id.is_a(&RNA_Light)) {
|
||||
BL::Light b_light(b_id);
|
||||
shader_map.set_recalc(b_light);
|
||||
}
|
||||
/* Object */
|
||||
else if (b_id.is_a(&RNA_Object)) {
|
||||
BL::Object b_ob(b_id);
|
||||
const bool updated_geometry = b_update->updated_geometry();
|
||||
const bool updated_geometry = !b_update->is_dirty_geometry();
|
||||
|
||||
if (b_update->updated_transform()) {
|
||||
if (!b_update->is_dirty_transform()) {
|
||||
object_map.set_recalc(b_ob);
|
||||
light_map.set_recalc(b_ob);
|
||||
}
|
||||
@@ -207,6 +207,8 @@ void BlenderSync::sync_data(BL::RenderSettings& b_render,
|
||||
python_thread_state);
|
||||
|
||||
mesh_synced.clear();
|
||||
|
||||
free_data_after_sync(b_depsgraph);
|
||||
}
|
||||
|
||||
/* Integrator */
|
||||
@@ -292,7 +294,7 @@ void BlenderSync::sync_integrator()
|
||||
integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
|
||||
integrator->subsurface_samples = subsurface_samples * subsurface_samples;
|
||||
integrator->volume_samples = volume_samples * volume_samples;
|
||||
}
|
||||
}
|
||||
else {
|
||||
integrator->diffuse_samples = diffuse_samples;
|
||||
integrator->glossy_samples = glossy_samples;
|
||||
@@ -327,7 +329,7 @@ void BlenderSync::sync_film()
|
||||
|
||||
Film *film = scene->film;
|
||||
Film prevfilm = *film;
|
||||
|
||||
|
||||
film->exposure = get_float(cscene, "film_exposure");
|
||||
film->filter_type = (FilterType)get_enum(cscene,
|
||||
"pixel_filter_type",
|
||||
@@ -566,6 +568,30 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
|
||||
return passes;
|
||||
}
|
||||
|
||||
void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph)
|
||||
{
|
||||
/* When viewport display is not needed during render we can force some
|
||||
* caches to be releases from blender side in order to reduce peak memory
|
||||
* footprint during synchronization process.
|
||||
*/
|
||||
const bool is_interface_locked = b_engine.render() &&
|
||||
b_engine.render().use_lock_interface();
|
||||
const bool can_free_caches = BlenderSession::headless || is_interface_locked;
|
||||
if (!can_free_caches) {
|
||||
return;
|
||||
}
|
||||
/* TODO(sergey): We can actually remove the whole dependency graph,
|
||||
* but that will need some API support first.
|
||||
*/
|
||||
BL::Depsgraph::objects_iterator b_ob;
|
||||
for(b_depsgraph.objects.begin(b_ob);
|
||||
b_ob != b_depsgraph.objects.end();
|
||||
++b_ob)
|
||||
{
|
||||
b_ob->cache_release();
|
||||
}
|
||||
}
|
||||
|
||||
/* Scene Parameters */
|
||||
|
||||
SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
|
||||
@@ -580,7 +606,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
|
||||
params.shadingsystem = SHADINGSYSTEM_SVM;
|
||||
else if(shadingsystem == 1)
|
||||
params.shadingsystem = SHADINGSYSTEM_OSL;
|
||||
|
||||
|
||||
if(background || DebugFlags().viewport_static_bvh)
|
||||
params.bvh_type = SceneParams::BVH_STATIC;
|
||||
else
|
||||
@@ -645,7 +671,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
||||
|
||||
/* device type */
|
||||
vector<DeviceInfo>& devices = Device::available_devices();
|
||||
|
||||
|
||||
/* device default CPU */
|
||||
foreach(DeviceInfo& device, devices) {
|
||||
if(device.type == DEVICE_CPU) {
|
||||
@@ -720,7 +746,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
||||
int aa_samples = get_int(cscene, "aa_samples");
|
||||
int preview_samples = get_int(cscene, "preview_samples");
|
||||
int preview_aa_samples = get_int(cscene, "preview_aa_samples");
|
||||
|
||||
|
||||
if(get_boolean(cscene, "use_square_samples")) {
|
||||
aa_samples = aa_samples * aa_samples;
|
||||
preview_aa_samples = preview_aa_samples * preview_aa_samples;
|
||||
@@ -817,7 +843,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
||||
params.shadingsystem = SHADINGSYSTEM_SVM;
|
||||
else if(shadingsystem == 1)
|
||||
params.shadingsystem = SHADINGSYSTEM_OSL;
|
||||
|
||||
|
||||
/* color managagement */
|
||||
params.display_buffer_linear = GLEW_ARB_half_float_pixel &&
|
||||
b_engine.support_display_space_shader(b_scene);
|
||||
@@ -833,4 +859,3 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
|
||||
private:
|
||||
/* sync */
|
||||
void sync_lamps(BL::Depsgraph& b_depsgraph, bool update_all);
|
||||
void sync_lights(BL::Depsgraph& b_depsgraph, bool update_all);
|
||||
void sync_materials(BL::Depsgraph& b_depsgraph, bool update_all);
|
||||
void sync_objects(BL::Depsgraph& b_depsgraph, float motion_time = 0.0f);
|
||||
void sync_motion(BL::RenderSettings& b_render,
|
||||
@@ -157,6 +157,9 @@ private:
|
||||
/* Images. */
|
||||
void sync_images();
|
||||
|
||||
/* Early data free. */
|
||||
void free_data_after_sync(BL::Depsgraph& b_depsgraph);
|
||||
|
||||
/* util */
|
||||
void find_shader(BL::ID& id, vector<Shader*>& used_shaders, Shader *default_shader);
|
||||
bool BKE_object_is_modified(BL::Object& b_ob);
|
||||
@@ -218,4 +221,3 @@ private:
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BLENDER_SYNC_H__ */
|
||||
|
||||
|
||||
@@ -251,4 +251,3 @@ void BVHObjectBinning::split(BVHReference* prims,
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ void InnerNode::print(int depth) const
|
||||
{
|
||||
for(int i = 0; i < depth; i++)
|
||||
printf(" ");
|
||||
|
||||
|
||||
printf("inner node %p\n", (void*)this);
|
||||
|
||||
if(children[0])
|
||||
@@ -219,9 +219,8 @@ void LeafNode::print(int depth) const
|
||||
{
|
||||
for(int i = 0; i < depth; i++)
|
||||
printf(" ");
|
||||
|
||||
|
||||
printf("leaf node %d to %d\n", lo, hi);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -201,4 +201,3 @@ void bvh_reference_sort(int start,
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
|
||||
/* Use OpenSubdiv patch evaluation */
|
||||
bool use_patch_evaluation;
|
||||
|
||||
|
||||
/* Use Transparent shadows */
|
||||
bool use_transparent;
|
||||
|
||||
@@ -307,7 +307,7 @@ public:
|
||||
/* open shading language, only for CPU device */
|
||||
virtual void *osl_memory() { return NULL; }
|
||||
|
||||
/* load/compile kernels, must be called before adding tasks */
|
||||
/* load/compile kernels, must be called before adding tasks */
|
||||
virtual bool load_kernels(
|
||||
const DeviceRequestedFeatures& /*requested_features*/)
|
||||
{ return true; }
|
||||
@@ -317,7 +317,7 @@ public:
|
||||
virtual void task_add(DeviceTask& task) = 0;
|
||||
virtual void task_wait() = 0;
|
||||
virtual void task_cancel() = 0;
|
||||
|
||||
|
||||
/* opengl drawing */
|
||||
virtual void draw_pixels(device_memory& mem, int y,
|
||||
int w, int h, int width, int height,
|
||||
@@ -376,4 +376,3 @@ private:
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICE_H__ */
|
||||
|
||||
|
||||
@@ -179,8 +179,8 @@ public:
|
||||
KernelFunctions<void(*)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int)> convert_to_byte_kernel;
|
||||
KernelFunctions<void(*)(KernelGlobals *, uint4 *, float4 *, int, int, int, int, int)> shader_kernel;
|
||||
|
||||
KernelFunctions<void(*)(int, TilesInfo*, int, int, float*, float*, float*, float*, float*, int*, int, int)> filter_divide_shadow_kernel;
|
||||
KernelFunctions<void(*)(int, TilesInfo*, int, int, int, int, float*, float*, int*, int, int)> filter_get_feature_kernel;
|
||||
KernelFunctions<void(*)(int, TileInfo*, int, int, float*, float*, float*, float*, float*, int*, int, int)> filter_divide_shadow_kernel;
|
||||
KernelFunctions<void(*)(int, TileInfo*, int, int, int, int, float*, float*, int*, int, int)> filter_get_feature_kernel;
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int)> filter_detect_outliers_kernel;
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int)> filter_combine_halves_kernel;
|
||||
|
||||
@@ -459,18 +459,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool denoising_set_tiles(device_ptr *buffers, DenoisingTask *task)
|
||||
{
|
||||
TilesInfo *tiles = (TilesInfo*) task->tiles_mem.host_pointer;
|
||||
for(int i = 0; i < 9; i++) {
|
||||
tiles->buffers[i] = buffers[i];
|
||||
}
|
||||
|
||||
task->tiles_mem.copy_to_device();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool denoising_non_local_means(device_ptr image_ptr, device_ptr guide_ptr, device_ptr variance_ptr, device_ptr out_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
@@ -626,7 +614,7 @@ public:
|
||||
for(int y = task->rect.y; y < task->rect.w; y++) {
|
||||
for(int x = task->rect.x; x < task->rect.z; x++) {
|
||||
filter_divide_shadow_kernel()(task->render_buffer.samples,
|
||||
task->tiles,
|
||||
task->tile_info,
|
||||
x, y,
|
||||
(float*) a_ptr,
|
||||
(float*) b_ptr,
|
||||
@@ -635,7 +623,7 @@ public:
|
||||
(float*) buffer_variance_ptr,
|
||||
&task->rect.x,
|
||||
task->render_buffer.pass_stride,
|
||||
task->render_buffer.denoising_data_offset);
|
||||
task->render_buffer.offset);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -650,7 +638,7 @@ public:
|
||||
for(int y = task->rect.y; y < task->rect.w; y++) {
|
||||
for(int x = task->rect.x; x < task->rect.z; x++) {
|
||||
filter_get_feature_kernel()(task->render_buffer.samples,
|
||||
task->tiles,
|
||||
task->tile_info,
|
||||
mean_offset,
|
||||
variance_offset,
|
||||
x, y,
|
||||
@@ -658,7 +646,7 @@ public:
|
||||
(float*) variance_ptr,
|
||||
&task->rect.x,
|
||||
task->render_buffer.pass_stride,
|
||||
task->render_buffer.denoising_data_offset);
|
||||
task->render_buffer.offset);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -711,7 +699,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void denoise(DeviceTask &task, DenoisingTask& denoising, RenderTile &tile)
|
||||
void denoise(DenoisingTask& denoising, RenderTile &tile)
|
||||
{
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
@@ -722,23 +710,11 @@ public:
|
||||
denoising.functions.combine_halves = function_bind(&CPUDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
|
||||
denoising.functions.get_feature = function_bind(&CPUDevice::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.detect_outliers = function_bind(&CPUDevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.set_tiles = function_bind(&CPUDevice::denoising_set_tiles, this, _1, &denoising);
|
||||
|
||||
denoising.filter_area = make_int4(tile.x, tile.y, tile.w, tile.h);
|
||||
denoising.render_buffer.samples = tile.sample;
|
||||
|
||||
RenderTile rtiles[9];
|
||||
rtiles[4] = tile;
|
||||
task.map_neighbor_tiles(rtiles, this);
|
||||
denoising.tiles_from_rendertiles(rtiles);
|
||||
|
||||
denoising.init_from_devicetask(task);
|
||||
|
||||
denoising.run_denoising();
|
||||
|
||||
task.unmap_neighbor_tiles(rtiles, this);
|
||||
|
||||
task.update_progress(&tile, tile.w*tile.h);
|
||||
denoising.run_denoising(&tile);
|
||||
}
|
||||
|
||||
void thread_render(DeviceTask& task)
|
||||
@@ -766,7 +742,7 @@ public:
|
||||
}
|
||||
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
DenoisingTask denoising(this, task);
|
||||
|
||||
while(task.acquire_tile(this, tile)) {
|
||||
if(tile.task == RenderTile::PATH_TRACE) {
|
||||
@@ -779,7 +755,9 @@ public:
|
||||
}
|
||||
}
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
denoise(task, denoising, tile);
|
||||
denoise(denoising, tile);
|
||||
|
||||
task.update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
||||
task.release_tile(tile);
|
||||
|
||||
@@ -1072,6 +1072,7 @@ public:
|
||||
CUarray_format_enum format;
|
||||
switch(mem.data_type) {
|
||||
case TYPE_UCHAR: format = CU_AD_FORMAT_UNSIGNED_INT8; break;
|
||||
case TYPE_UINT16: format = CU_AD_FORMAT_UNSIGNED_INT16; break;
|
||||
case TYPE_UINT: format = CU_AD_FORMAT_UNSIGNED_INT32; break;
|
||||
case TYPE_INT: format = CU_AD_FORMAT_SIGNED_INT32; break;
|
||||
case TYPE_FLOAT: format = CU_AD_FORMAT_FLOAT; break;
|
||||
@@ -1251,18 +1252,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool denoising_set_tiles(device_ptr *buffers, DenoisingTask *task)
|
||||
{
|
||||
TilesInfo *tiles = (TilesInfo*) task->tiles_mem.host_pointer;
|
||||
for(int i = 0; i < 9; i++) {
|
||||
tiles->buffers[i] = buffers[i];
|
||||
}
|
||||
|
||||
task->tiles_mem.copy_to_device();
|
||||
|
||||
return !have_error();
|
||||
}
|
||||
|
||||
#define CUDA_GET_BLOCKSIZE(func, w, h) \
|
||||
int threads_per_block; \
|
||||
cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func)); \
|
||||
@@ -1534,7 +1523,7 @@ public:
|
||||
task->rect.w-task->rect.y);
|
||||
|
||||
void *args[] = {&task->render_buffer.samples,
|
||||
&task->tiles_mem.device_pointer,
|
||||
&task->tile_info_mem.device_pointer,
|
||||
&a_ptr,
|
||||
&b_ptr,
|
||||
&sample_variance_ptr,
|
||||
@@ -1542,7 +1531,7 @@ public:
|
||||
&buffer_variance_ptr,
|
||||
&task->rect,
|
||||
&task->render_buffer.pass_stride,
|
||||
&task->render_buffer.denoising_data_offset};
|
||||
&task->render_buffer.offset};
|
||||
CUDA_LAUNCH_KERNEL(cuFilterDivideShadow, args);
|
||||
cuda_assert(cuCtxSynchronize());
|
||||
|
||||
@@ -1568,14 +1557,14 @@ public:
|
||||
task->rect.w-task->rect.y);
|
||||
|
||||
void *args[] = {&task->render_buffer.samples,
|
||||
&task->tiles_mem.device_pointer,
|
||||
&task->tile_info_mem.device_pointer,
|
||||
&mean_offset,
|
||||
&variance_offset,
|
||||
&mean_ptr,
|
||||
&variance_ptr,
|
||||
&task->rect,
|
||||
&task->render_buffer.pass_stride,
|
||||
&task->render_buffer.denoising_data_offset};
|
||||
&task->render_buffer.offset};
|
||||
CUDA_LAUNCH_KERNEL(cuFilterGetFeature, args);
|
||||
cuda_assert(cuCtxSynchronize());
|
||||
|
||||
@@ -1613,7 +1602,7 @@ public:
|
||||
return !have_error();
|
||||
}
|
||||
|
||||
void denoise(RenderTile &rtile, DenoisingTask& denoising, const DeviceTask &task)
|
||||
void denoise(RenderTile &rtile, DenoisingTask& denoising)
|
||||
{
|
||||
denoising.functions.construct_transform = function_bind(&CUDADevice::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
@@ -1622,21 +1611,11 @@ public:
|
||||
denoising.functions.combine_halves = function_bind(&CUDADevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
|
||||
denoising.functions.get_feature = function_bind(&CUDADevice::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.detect_outliers = function_bind(&CUDADevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.set_tiles = function_bind(&CUDADevice::denoising_set_tiles, this, _1, &denoising);
|
||||
|
||||
denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
|
||||
denoising.render_buffer.samples = rtile.sample;
|
||||
|
||||
RenderTile rtiles[9];
|
||||
rtiles[4] = rtile;
|
||||
task.map_neighbor_tiles(rtiles, this);
|
||||
denoising.tiles_from_rendertiles(rtiles);
|
||||
|
||||
denoising.init_from_devicetask(task);
|
||||
|
||||
denoising.run_denoising();
|
||||
|
||||
task.unmap_neighbor_tiles(rtiles, this);
|
||||
denoising.run_denoising(&rtile);
|
||||
}
|
||||
|
||||
void path_trace(DeviceTask& task, RenderTile& rtile, device_vector<WorkTile>& work_tiles)
|
||||
@@ -2092,7 +2071,7 @@ public:
|
||||
|
||||
/* keep rendering tiles until done */
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
DenoisingTask denoising(this, *task);
|
||||
|
||||
while(task->acquire_tile(this, tile)) {
|
||||
if(tile.task == RenderTile::PATH_TRACE) {
|
||||
@@ -2107,7 +2086,7 @@ public:
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
denoise(tile, denoising, *task);
|
||||
denoise(tile, denoising);
|
||||
|
||||
task->update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
||||
@@ -20,12 +20,29 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DenoisingTask::DenoisingTask(Device *device)
|
||||
: tiles_mem(device, "denoising tiles_mem", MEM_READ_WRITE),
|
||||
DenoisingTask::DenoisingTask(Device *device, const DeviceTask &task)
|
||||
: tile_info_mem(device, "denoising tile info mem", MEM_READ_WRITE),
|
||||
storage(device),
|
||||
buffer(device),
|
||||
device(device)
|
||||
{
|
||||
radius = task.denoising_radius;
|
||||
nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising_strength));
|
||||
if(task.denoising_relative_pca) {
|
||||
pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising_feature_strength));
|
||||
}
|
||||
else {
|
||||
pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising_feature_strength));
|
||||
}
|
||||
|
||||
render_buffer.pass_stride = task.pass_stride;
|
||||
render_buffer.offset = task.pass_denoising_data;
|
||||
|
||||
target_buffer.pass_stride = task.pass_stride;
|
||||
target_buffer.denoising_clean_offset = task.pass_denoising_clean;
|
||||
|
||||
functions.map_neighbor_tiles = function_bind(task.map_neighbor_tiles, _1, device);
|
||||
functions.unmap_neighbor_tiles = function_bind(task.unmap_neighbor_tiles, _1, device);
|
||||
}
|
||||
|
||||
DenoisingTask::~DenoisingTask()
|
||||
@@ -38,170 +55,170 @@ DenoisingTask::~DenoisingTask()
|
||||
storage.temporary_2.free();
|
||||
storage.temporary_color.free();
|
||||
buffer.mem.free();
|
||||
tiles_mem.free();
|
||||
tile_info_mem.free();
|
||||
}
|
||||
|
||||
void DenoisingTask::init_from_devicetask(const DeviceTask &task)
|
||||
void DenoisingTask::set_render_buffer(RenderTile *rtiles)
|
||||
{
|
||||
radius = task.denoising_radius;
|
||||
nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising_strength));
|
||||
if(task.denoising_relative_pca) {
|
||||
pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising_feature_strength));
|
||||
}
|
||||
else {
|
||||
pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising_feature_strength));
|
||||
}
|
||||
tile_info = (TileInfo*) tile_info_mem.alloc(sizeof(TileInfo)/sizeof(int));
|
||||
|
||||
render_buffer.pass_stride = task.pass_stride;
|
||||
render_buffer.denoising_data_offset = task.pass_denoising_data;
|
||||
render_buffer.denoising_clean_offset = task.pass_denoising_clean;
|
||||
for(int i = 0; i < 9; i++) {
|
||||
tile_info->offsets[i] = rtiles[i].offset;
|
||||
tile_info->strides[i] = rtiles[i].stride;
|
||||
tile_info->buffers[i] = rtiles[i].buffer;
|
||||
}
|
||||
tile_info->x[0] = rtiles[3].x;
|
||||
tile_info->x[1] = rtiles[4].x;
|
||||
tile_info->x[2] = rtiles[5].x;
|
||||
tile_info->x[3] = rtiles[5].x + rtiles[5].w;
|
||||
tile_info->y[0] = rtiles[1].y;
|
||||
tile_info->y[1] = rtiles[4].y;
|
||||
tile_info->y[2] = rtiles[7].y;
|
||||
tile_info->y[3] = rtiles[7].y + rtiles[7].h;
|
||||
|
||||
target_buffer.offset = rtiles[9].offset;
|
||||
target_buffer.stride = rtiles[9].stride;
|
||||
target_buffer.ptr = rtiles[9].buffer;
|
||||
|
||||
tile_info_mem.copy_to_device();
|
||||
}
|
||||
|
||||
void DenoisingTask::setup_denoising_buffer()
|
||||
{
|
||||
/* Expand filter_area by radius pixels and clamp the result to the extent of the neighboring tiles */
|
||||
rect = rect_from_shape(filter_area.x, filter_area.y, filter_area.z, filter_area.w);
|
||||
rect = rect_expand(rect, radius);
|
||||
rect = rect_clip(rect, make_int4(tiles->x[0], tiles->y[0], tiles->x[3], tiles->y[3]));
|
||||
}
|
||||
rect = rect_clip(rect, make_int4(tile_info->x[0], tile_info->y[0], tile_info->x[3], tile_info->y[3]));
|
||||
|
||||
void DenoisingTask::tiles_from_rendertiles(RenderTile *rtiles)
|
||||
{
|
||||
tiles = (TilesInfo*) tiles_mem.alloc(sizeof(TilesInfo)/sizeof(int));
|
||||
|
||||
device_ptr buffers[9];
|
||||
for(int i = 0; i < 9; i++) {
|
||||
buffers[i] = rtiles[i].buffer;
|
||||
tiles->offsets[i] = rtiles[i].offset;
|
||||
tiles->strides[i] = rtiles[i].stride;
|
||||
}
|
||||
tiles->x[0] = rtiles[3].x;
|
||||
tiles->x[1] = rtiles[4].x;
|
||||
tiles->x[2] = rtiles[5].x;
|
||||
tiles->x[3] = rtiles[5].x + rtiles[5].w;
|
||||
tiles->y[0] = rtiles[1].y;
|
||||
tiles->y[1] = rtiles[4].y;
|
||||
tiles->y[2] = rtiles[7].y;
|
||||
tiles->y[3] = rtiles[7].y + rtiles[7].h;
|
||||
|
||||
render_buffer.offset = rtiles[4].offset;
|
||||
render_buffer.stride = rtiles[4].stride;
|
||||
render_buffer.ptr = rtiles[4].buffer;
|
||||
|
||||
functions.set_tiles(buffers);
|
||||
}
|
||||
|
||||
bool DenoisingTask::run_denoising()
|
||||
{
|
||||
/* Allocate denoising buffer. */
|
||||
buffer.passes = 14;
|
||||
buffer.width = rect.z - rect.x;
|
||||
buffer.stride = align_up(buffer.width, 4);
|
||||
buffer.h = rect.w - rect.y;
|
||||
buffer.pass_stride = align_up(buffer.stride * buffer.h, divide_up(device->mem_sub_ptr_alignment(), sizeof(float)));
|
||||
buffer.mem.alloc_to_device(buffer.pass_stride * buffer.passes, false);
|
||||
int alignment_floats = divide_up(device->mem_sub_ptr_alignment(), sizeof(float));
|
||||
buffer.pass_stride = align_up(buffer.stride * buffer.h, alignment_floats);
|
||||
/* Pad the total size by four floats since the SIMD kernels might go a bit over the end. */
|
||||
int mem_size = align_up(buffer.pass_stride * buffer.passes + 4, alignment_floats);
|
||||
buffer.mem.alloc_to_device(mem_size, false);
|
||||
}
|
||||
|
||||
void DenoisingTask::prefilter_shadowing()
|
||||
{
|
||||
device_ptr null_ptr = (device_ptr) 0;
|
||||
|
||||
/* Prefilter shadow feature. */
|
||||
{
|
||||
device_sub_ptr unfiltered_a (buffer.mem, 0, buffer.pass_stride);
|
||||
device_sub_ptr unfiltered_b (buffer.mem, 1*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr sample_var (buffer.mem, 2*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr sample_var_var (buffer.mem, 3*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr buffer_var (buffer.mem, 5*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr filtered_var (buffer.mem, 6*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_1(buffer.mem, 7*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_2(buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_3(buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr unfiltered_a (buffer.mem, 0, buffer.pass_stride);
|
||||
device_sub_ptr unfiltered_b (buffer.mem, 1*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr sample_var (buffer.mem, 2*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr sample_var_var (buffer.mem, 3*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr buffer_var (buffer.mem, 5*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr filtered_var (buffer.mem, 6*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_1(buffer.mem, 7*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_2(buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_3(buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
|
||||
|
||||
nlm_state.temporary_1_ptr = *nlm_temporary_1;
|
||||
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||
nlm_state.temporary_1_ptr = *nlm_temporary_1;
|
||||
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||
|
||||
/* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
|
||||
functions.divide_shadow(*unfiltered_a, *unfiltered_b, *sample_var, *sample_var_var, *buffer_var);
|
||||
/* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
|
||||
functions.divide_shadow(*unfiltered_a, *unfiltered_b, *sample_var, *sample_var_var, *buffer_var);
|
||||
|
||||
/* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
|
||||
nlm_state.set_parameters(6, 3, 4.0f, 1.0f);
|
||||
functions.non_local_means(*buffer_var, *sample_var, *sample_var_var, *filtered_var);
|
||||
/* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
|
||||
nlm_state.set_parameters(6, 3, 4.0f, 1.0f);
|
||||
functions.non_local_means(*buffer_var, *sample_var, *sample_var_var, *filtered_var);
|
||||
|
||||
/* Reuse memory, the previous data isn't needed anymore. */
|
||||
device_ptr filtered_a = *buffer_var,
|
||||
filtered_b = *sample_var;
|
||||
/* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
|
||||
nlm_state.set_parameters(5, 3, 1.0f, 0.25f);
|
||||
functions.non_local_means(*unfiltered_a, *unfiltered_b, *filtered_var, filtered_a);
|
||||
functions.non_local_means(*unfiltered_b, *unfiltered_a, *filtered_var, filtered_b);
|
||||
/* Reuse memory, the previous data isn't needed anymore. */
|
||||
device_ptr filtered_a = *buffer_var,
|
||||
filtered_b = *sample_var;
|
||||
/* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
|
||||
nlm_state.set_parameters(5, 3, 1.0f, 0.25f);
|
||||
functions.non_local_means(*unfiltered_a, *unfiltered_b, *filtered_var, filtered_a);
|
||||
functions.non_local_means(*unfiltered_b, *unfiltered_a, *filtered_var, filtered_b);
|
||||
|
||||
device_ptr residual_var = *sample_var_var;
|
||||
/* Estimate the residual variance between the two filtered halves. */
|
||||
functions.combine_halves(filtered_a, filtered_b, null_ptr, residual_var, 2, rect);
|
||||
device_ptr residual_var = *sample_var_var;
|
||||
/* Estimate the residual variance between the two filtered halves. */
|
||||
functions.combine_halves(filtered_a, filtered_b, null_ptr, residual_var, 2, rect);
|
||||
|
||||
device_ptr final_a = *unfiltered_a,
|
||||
final_b = *unfiltered_b;
|
||||
/* Use the residual variance for a second filter pass. */
|
||||
nlm_state.set_parameters(4, 2, 1.0f, 0.5f);
|
||||
functions.non_local_means(filtered_a, filtered_b, residual_var, final_a);
|
||||
functions.non_local_means(filtered_b, filtered_a, residual_var, final_b);
|
||||
device_ptr final_a = *unfiltered_a,
|
||||
final_b = *unfiltered_b;
|
||||
/* Use the residual variance for a second filter pass. */
|
||||
nlm_state.set_parameters(4, 2, 1.0f, 0.5f);
|
||||
functions.non_local_means(filtered_a, filtered_b, residual_var, final_a);
|
||||
functions.non_local_means(filtered_b, filtered_a, residual_var, final_b);
|
||||
|
||||
/* Combine the two double-filtered halves to a final shadow feature. */
|
||||
device_sub_ptr shadow_pass(buffer.mem, 4*buffer.pass_stride, buffer.pass_stride);
|
||||
functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
|
||||
/* Combine the two double-filtered halves to a final shadow feature. */
|
||||
device_sub_ptr shadow_pass(buffer.mem, 4*buffer.pass_stride, buffer.pass_stride);
|
||||
functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
|
||||
}
|
||||
|
||||
void DenoisingTask::prefilter_features()
|
||||
{
|
||||
device_sub_ptr unfiltered (buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr variance (buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_1(buffer.mem, 10*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_2(buffer.mem, 11*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_3(buffer.mem, 12*buffer.pass_stride, buffer.pass_stride);
|
||||
|
||||
nlm_state.temporary_1_ptr = *nlm_temporary_1;
|
||||
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||
|
||||
int mean_from[] = { 0, 1, 2, 12, 6, 7, 8 };
|
||||
int variance_from[] = { 3, 4, 5, 13, 9, 10, 11};
|
||||
int pass_to[] = { 1, 2, 3, 0, 5, 6, 7};
|
||||
for(int pass = 0; pass < 7; pass++) {
|
||||
device_sub_ptr feature_pass(buffer.mem, pass_to[pass]*buffer.pass_stride, buffer.pass_stride);
|
||||
/* Get the unfiltered pass and its variance from the RenderBuffers. */
|
||||
functions.get_feature(mean_from[pass], variance_from[pass], *unfiltered, *variance);
|
||||
/* Smooth the pass and store the result in the denoising buffers. */
|
||||
nlm_state.set_parameters(2, 2, 1.0f, 0.25f);
|
||||
functions.non_local_means(*unfiltered, *unfiltered, *variance, *feature_pass);
|
||||
}
|
||||
}
|
||||
|
||||
void DenoisingTask::prefilter_color()
|
||||
{
|
||||
int mean_from[] = {20, 21, 22};
|
||||
int variance_from[] = {23, 24, 25};
|
||||
int mean_to[] = { 8, 9, 10};
|
||||
int variance_to[] = {11, 12, 13};
|
||||
int num_color_passes = 3;
|
||||
|
||||
storage.temporary_color.alloc_to_device(3*buffer.pass_stride, false);
|
||||
device_sub_ptr nlm_temporary_1(storage.temporary_color, 0*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_2(storage.temporary_color, 1*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_3(storage.temporary_color, 2*buffer.pass_stride, buffer.pass_stride);
|
||||
|
||||
nlm_state.temporary_1_ptr = *nlm_temporary_1;
|
||||
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||
|
||||
for(int pass = 0; pass < num_color_passes; pass++) {
|
||||
device_sub_ptr color_pass(storage.temporary_color, pass*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr color_var_pass(buffer.mem, variance_to[pass]*buffer.pass_stride, buffer.pass_stride);
|
||||
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
|
||||
}
|
||||
|
||||
/* Prefilter general features. */
|
||||
{
|
||||
device_sub_ptr unfiltered (buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr variance (buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_1(buffer.mem, 10*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_2(buffer.mem, 11*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr nlm_temporary_3(buffer.mem, 12*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr depth_pass (buffer.mem, 0, buffer.pass_stride);
|
||||
device_sub_ptr color_var_pass(buffer.mem, variance_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
device_sub_ptr output_pass (buffer.mem, mean_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
functions.detect_outliers(storage.temporary_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
|
||||
|
||||
nlm_state.temporary_1_ptr = *nlm_temporary_1;
|
||||
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||
|
||||
int mean_from[] = { 0, 1, 2, 12, 6, 7, 8 };
|
||||
int variance_from[] = { 3, 4, 5, 13, 9, 10, 11};
|
||||
int pass_to[] = { 1, 2, 3, 0, 5, 6, 7};
|
||||
for(int pass = 0; pass < 7; pass++) {
|
||||
device_sub_ptr feature_pass(buffer.mem, pass_to[pass]*buffer.pass_stride, buffer.pass_stride);
|
||||
/* Get the unfiltered pass and its variance from the RenderBuffers. */
|
||||
functions.get_feature(mean_from[pass], variance_from[pass], *unfiltered, *variance);
|
||||
/* Smooth the pass and store the result in the denoising buffers. */
|
||||
nlm_state.set_parameters(2, 2, 1.0f, 0.25f);
|
||||
functions.non_local_means(*unfiltered, *unfiltered, *variance, *feature_pass);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy color passes. */
|
||||
{
|
||||
int mean_from[] = {20, 21, 22};
|
||||
int variance_from[] = {23, 24, 25};
|
||||
int mean_to[] = { 8, 9, 10};
|
||||
int variance_to[] = {11, 12, 13};
|
||||
int num_color_passes = 3;
|
||||
|
||||
storage.temporary_color.alloc_to_device(3*buffer.pass_stride, false);
|
||||
|
||||
for(int pass = 0; pass < num_color_passes; pass++) {
|
||||
device_sub_ptr color_pass(storage.temporary_color, pass*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr color_var_pass(buffer.mem, variance_to[pass]*buffer.pass_stride, buffer.pass_stride);
|
||||
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
|
||||
}
|
||||
|
||||
{
|
||||
device_sub_ptr depth_pass (buffer.mem, 0, buffer.pass_stride);
|
||||
device_sub_ptr color_var_pass(buffer.mem, variance_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
device_sub_ptr output_pass (buffer.mem, mean_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
functions.detect_outliers(storage.temporary_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
|
||||
}
|
||||
}
|
||||
storage.temporary_color.free();
|
||||
}
|
||||
|
||||
void DenoisingTask::construct_transform()
|
||||
{
|
||||
storage.w = filter_area.z;
|
||||
storage.h = filter_area.w;
|
||||
|
||||
storage.transform.alloc_to_device(storage.w*storage.h*TRANSFORM_SIZE, false);
|
||||
storage.rank.alloc_to_device(storage.w*storage.h, false);
|
||||
|
||||
functions.construct_transform();
|
||||
}
|
||||
|
||||
void DenoisingTask::reconstruct()
|
||||
{
|
||||
|
||||
device_only_memory<float> temporary_1(device, "Denoising NLM temporary 1");
|
||||
device_only_memory<float> temporary_2(device, "Denoising NLM temporary 2");
|
||||
@@ -214,21 +231,36 @@ bool DenoisingTask::run_denoising()
|
||||
storage.XtWY.alloc_to_device(storage.w*storage.h*XTWY_SIZE, false);
|
||||
|
||||
reconstruction_state.filter_window = rect_from_shape(filter_area.x-rect.x, filter_area.y-rect.y, storage.w, storage.h);
|
||||
int tile_coordinate_offset = filter_area.y*render_buffer.stride + filter_area.x;
|
||||
reconstruction_state.buffer_params = make_int4(render_buffer.offset + tile_coordinate_offset,
|
||||
render_buffer.stride,
|
||||
render_buffer.pass_stride,
|
||||
render_buffer.denoising_clean_offset);
|
||||
int tile_coordinate_offset = filter_area.y*target_buffer.stride + filter_area.x;
|
||||
reconstruction_state.buffer_params = make_int4(target_buffer.offset + tile_coordinate_offset,
|
||||
target_buffer.stride,
|
||||
target_buffer.pass_stride,
|
||||
target_buffer.denoising_clean_offset);
|
||||
reconstruction_state.source_w = rect.z-rect.x;
|
||||
reconstruction_state.source_h = rect.w-rect.y;
|
||||
|
||||
{
|
||||
device_sub_ptr color_ptr (buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
device_sub_ptr color_var_ptr(buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
functions.reconstruct(*color_ptr, *color_var_ptr, render_buffer.ptr);
|
||||
}
|
||||
device_sub_ptr color_ptr (buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
device_sub_ptr color_var_ptr(buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
functions.reconstruct(*color_ptr, *color_var_ptr, target_buffer.ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
void DenoisingTask::run_denoising(RenderTile *tile)
|
||||
{
|
||||
RenderTile rtiles[10];
|
||||
rtiles[4] = *tile;
|
||||
functions.map_neighbor_tiles(rtiles);
|
||||
set_render_buffer(rtiles);
|
||||
|
||||
setup_denoising_buffer();
|
||||
|
||||
prefilter_shadowing();
|
||||
prefilter_features();
|
||||
prefilter_color();
|
||||
|
||||
construct_transform();
|
||||
reconstruct();
|
||||
|
||||
functions.unmap_neighbor_tiles(rtiles);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -32,20 +32,24 @@ public:
|
||||
float nlm_k_2;
|
||||
float pca_threshold;
|
||||
|
||||
/* Pointer and parameters of the RenderBuffers. */
|
||||
/* Parameters of the RenderBuffers. */
|
||||
struct RenderBuffers {
|
||||
int denoising_data_offset;
|
||||
int denoising_clean_offset;
|
||||
int pass_stride;
|
||||
int offset;
|
||||
int stride;
|
||||
device_ptr ptr;
|
||||
int pass_stride;
|
||||
int samples;
|
||||
} render_buffer;
|
||||
|
||||
TilesInfo *tiles;
|
||||
device_vector<int> tiles_mem;
|
||||
void tiles_from_rendertiles(RenderTile *rtiles);
|
||||
/* Pointer and parameters of the target buffer. */
|
||||
struct TargetBuffer {
|
||||
int offset;
|
||||
int stride;
|
||||
int pass_stride;
|
||||
int denoising_clean_offset;
|
||||
device_ptr ptr;
|
||||
} target_buffer;
|
||||
|
||||
TileInfo *tile_info;
|
||||
device_vector<int> tile_info_mem;
|
||||
|
||||
int4 rect;
|
||||
int4 filter_area;
|
||||
@@ -85,7 +89,8 @@ public:
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr
|
||||
)> detect_outliers;
|
||||
function<bool(device_ptr*)> set_tiles;
|
||||
function<void(RenderTile *rtiles)> map_neighbor_tiles;
|
||||
function<void(RenderTile *rtiles)> unmap_neighbor_tiles;
|
||||
} functions;
|
||||
|
||||
/* Stores state of the current Reconstruction operation,
|
||||
@@ -138,12 +143,10 @@ public:
|
||||
{}
|
||||
} storage;
|
||||
|
||||
DenoisingTask(Device *device);
|
||||
DenoisingTask(Device *device, const DeviceTask &task);
|
||||
~DenoisingTask();
|
||||
|
||||
void init_from_devicetask(const DeviceTask &task);
|
||||
|
||||
bool run_denoising();
|
||||
void run_denoising(RenderTile *tile);
|
||||
|
||||
struct DenoiseBuffers {
|
||||
int pass_stride;
|
||||
@@ -160,6 +163,14 @@ public:
|
||||
|
||||
protected:
|
||||
Device *device;
|
||||
|
||||
void set_render_buffer(RenderTile *rtiles);
|
||||
void setup_denoising_buffer();
|
||||
void prefilter_shadowing();
|
||||
void prefilter_features();
|
||||
void prefilter_color();
|
||||
void construct_transform();
|
||||
void reconstruct();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -41,4 +41,3 @@ string device_cuda_capabilities(void);
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICE_INTERN_H__ */
|
||||
|
||||
|
||||
@@ -104,6 +104,26 @@ void device_memory::device_zero()
|
||||
}
|
||||
}
|
||||
|
||||
void device_memory::swap_device(Device *new_device,
|
||||
size_t new_device_size,
|
||||
device_ptr new_device_ptr)
|
||||
{
|
||||
original_device = device;
|
||||
original_device_size = device_size;
|
||||
original_device_ptr = device_pointer;
|
||||
|
||||
device = new_device;
|
||||
device_size = new_device_size;
|
||||
device_pointer = new_device_ptr;
|
||||
}
|
||||
|
||||
void device_memory::restore_device()
|
||||
{
|
||||
device = original_device;
|
||||
device_size = original_device_size;
|
||||
device_pointer = original_device_ptr;
|
||||
}
|
||||
|
||||
/* Device Sub Ptr */
|
||||
|
||||
device_sub_ptr::device_sub_ptr(device_memory& mem, int offset, int size)
|
||||
@@ -118,4 +138,3 @@ device_sub_ptr::~device_sub_ptr()
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ enum MemoryType {
|
||||
enum DataType {
|
||||
TYPE_UNKNOWN,
|
||||
TYPE_UCHAR,
|
||||
TYPE_UINT16,
|
||||
TYPE_UINT,
|
||||
TYPE_INT,
|
||||
TYPE_FLOAT,
|
||||
@@ -50,13 +51,14 @@ enum DataType {
|
||||
TYPE_UINT64,
|
||||
};
|
||||
|
||||
static inline size_t datatype_size(DataType datatype)
|
||||
static inline size_t datatype_size(DataType datatype)
|
||||
{
|
||||
switch(datatype) {
|
||||
case TYPE_UNKNOWN: return 1;
|
||||
case TYPE_UCHAR: return sizeof(uchar);
|
||||
case TYPE_FLOAT: return sizeof(float);
|
||||
case TYPE_UINT: return sizeof(uint);
|
||||
case TYPE_UINT16: return sizeof(uint16_t);
|
||||
case TYPE_INT: return sizeof(int);
|
||||
case TYPE_HALF: return sizeof(half);
|
||||
case TYPE_UINT64: return sizeof(uint64_t);
|
||||
@@ -156,6 +158,16 @@ template<> struct device_type_traits<half> {
|
||||
static const int num_elements = 1;
|
||||
};
|
||||
|
||||
template<> struct device_type_traits<ushort4> {
|
||||
static const DataType data_type = TYPE_UINT16;
|
||||
static const int num_elements = 4;
|
||||
};
|
||||
|
||||
template<> struct device_type_traits<uint16_t> {
|
||||
static const DataType data_type = TYPE_UINT16;
|
||||
static const int num_elements = 1;
|
||||
};
|
||||
|
||||
template<> struct device_type_traits<half4> {
|
||||
static const DataType data_type = TYPE_HALF;
|
||||
static const int num_elements = 4;
|
||||
@@ -200,6 +212,9 @@ public:
|
||||
|
||||
virtual ~device_memory();
|
||||
|
||||
void swap_device(Device *new_device, size_t new_device_size, device_ptr new_device_ptr);
|
||||
void restore_device();
|
||||
|
||||
protected:
|
||||
friend class CUDADevice;
|
||||
|
||||
@@ -222,6 +237,10 @@ protected:
|
||||
void device_copy_to();
|
||||
void device_copy_from(int y, int w, int h, int elem);
|
||||
void device_zero();
|
||||
|
||||
device_ptr original_device_ptr;
|
||||
size_t original_device_size;
|
||||
Device *original_device;
|
||||
};
|
||||
|
||||
/* Device Only Memory
|
||||
@@ -478,4 +497,3 @@ protected:
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICE_MEMORY_H__ */
|
||||
|
||||
|
||||
@@ -285,26 +285,27 @@ public:
|
||||
mem.copy_from_device(0, mem.data_size, 1);
|
||||
}
|
||||
|
||||
Device *original_device = mem.device;
|
||||
device_ptr original_ptr = mem.device_pointer;
|
||||
size_t original_size = mem.device_size;
|
||||
|
||||
mem.device = sub_device;
|
||||
mem.device_pointer = 0;
|
||||
mem.device_size = 0;
|
||||
mem.swap_device(sub_device, 0, 0);
|
||||
|
||||
mem.copy_to_device();
|
||||
tiles[i].buffer = mem.device_pointer;
|
||||
tiles[i].device_size = mem.device_size;
|
||||
|
||||
mem.device = original_device;
|
||||
mem.device_pointer = original_ptr;
|
||||
mem.device_size = original_size;
|
||||
mem.restore_device();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unmap_neighbor_tiles(Device * sub_device, RenderTile * tiles)
|
||||
{
|
||||
/* Copy denoised result back to the host. */
|
||||
device_vector<float> &mem = tiles[9].buffers->buffer;
|
||||
mem.swap_device(sub_device, tiles[9].device_size, tiles[9].buffer);
|
||||
mem.copy_from_device(0, mem.data_size, 1);
|
||||
mem.restore_device();
|
||||
/* Copy denoised result to the original device. */
|
||||
mem.copy_to_device();
|
||||
|
||||
for(int i = 0; i < 9; i++) {
|
||||
if(!tiles[i].buffers) {
|
||||
continue;
|
||||
@@ -312,28 +313,9 @@ public:
|
||||
|
||||
device_vector<float> &mem = tiles[i].buffers->buffer;
|
||||
if(mem.device != sub_device) {
|
||||
Device *original_device = mem.device;
|
||||
device_ptr original_ptr = mem.device_pointer;
|
||||
size_t original_size = mem.device_size;
|
||||
|
||||
mem.device = sub_device;
|
||||
mem.device_pointer = tiles[i].buffer;
|
||||
|
||||
/* Copy denoised tile to the host. */
|
||||
if(i == 4) {
|
||||
mem.copy_from_device(0, mem.data_size, 1);
|
||||
}
|
||||
|
||||
mem.swap_device(sub_device, tiles[i].device_size, tiles[i].buffer);
|
||||
sub_device->mem_free(mem);
|
||||
|
||||
mem.device = original_device;
|
||||
mem.device_pointer = original_ptr;
|
||||
mem.device_size = original_size;
|
||||
|
||||
/* Copy denoised tile to the original device. */
|
||||
if(i == 4) {
|
||||
mem.copy_to_device();
|
||||
}
|
||||
mem.restore_device();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,4 +379,3 @@ Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -797,5 +797,3 @@ void Device::server_run()
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ public:
|
||||
boost::asio::write(socket,
|
||||
boost::asio::buffer(archive_str),
|
||||
boost::asio::transfer_all(), error);
|
||||
|
||||
|
||||
if(error.value())
|
||||
error_func->network_error(error.message());
|
||||
|
||||
@@ -193,7 +193,7 @@ public:
|
||||
boost::asio::write(socket,
|
||||
boost::asio::buffer(buffer, size),
|
||||
boost::asio::transfer_all(), error);
|
||||
|
||||
|
||||
if(error.value())
|
||||
error_func->network_error(error.message());
|
||||
}
|
||||
@@ -467,7 +467,7 @@ private:
|
||||
/* buffer and endpoint for receiving messages */
|
||||
char receive_buffer[256];
|
||||
boost::asio::ip::udp::endpoint receive_endpoint;
|
||||
|
||||
|
||||
// os, version, devices, status, host name, group name, ip as far as fields go
|
||||
struct ServerInfo {
|
||||
string cycles_version;
|
||||
@@ -489,4 +489,3 @@ CCL_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
#endif /* __DEVICE_NETWORK_H__ */
|
||||
|
||||
|
||||
@@ -137,6 +137,10 @@ void device_opencl_info(vector<DeviceInfo>& devices)
|
||||
info.has_volume_decoupled = false;
|
||||
info.bvh_layout_mask = BVH_LAYOUT_BVH2;
|
||||
info.id = id;
|
||||
|
||||
/* Check OpenCL extensions */
|
||||
info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
|
||||
|
||||
devices.push_back(info);
|
||||
num_devices++;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
|
||||
ENQUEUE_SPLIT_KERNEL(buffer_update, global_size, local_size);
|
||||
|
||||
if(task->get_cancel() && cancel_time == DBL_MAX) {
|
||||
/* Wait up to twice as many seconds for current samples to finish
|
||||
/* Wait up to twice as many seconds for current samples to finish
|
||||
* to avoid artifacts in render result from ending too soon.
|
||||
*/
|
||||
cancel_time = time_dt() + 2.0 * time_multiplier;
|
||||
@@ -322,5 +322,3 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
|
||||
@@ -131,6 +131,3 @@ public:
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICE_SPLIT_KERNEL_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -126,4 +126,3 @@ void DeviceTask::update_progress(RenderTile *rtile, int pixel_samples)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -86,4 +86,3 @@ protected:
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICE_TASK_H__ */
|
||||
|
||||
|
||||
@@ -254,4 +254,3 @@ void MemoryManager::set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg)
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* WITH_OPENCL */
|
||||
|
||||
|
||||
@@ -104,4 +104,3 @@ public:
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -59,19 +59,22 @@ struct OpenCLPlatformDevice {
|
||||
cl_device_id device_id,
|
||||
cl_device_type device_type,
|
||||
const string& device_name,
|
||||
const string& hardware_id)
|
||||
const string& hardware_id,
|
||||
const string& device_extensions)
|
||||
: platform_id(platform_id),
|
||||
platform_name(platform_name),
|
||||
device_id(device_id),
|
||||
device_type(device_type),
|
||||
device_name(device_name),
|
||||
hardware_id(hardware_id) {}
|
||||
hardware_id(hardware_id),
|
||||
device_extensions(device_extensions) {}
|
||||
cl_platform_id platform_id;
|
||||
string platform_name;
|
||||
cl_device_id device_id;
|
||||
cl_device_type device_type;
|
||||
string device_name;
|
||||
string hardware_id;
|
||||
string device_extensions;
|
||||
};
|
||||
|
||||
/* Contains all static OpenCL helper functions. */
|
||||
@@ -130,6 +133,12 @@ public:
|
||||
|
||||
static string get_device_name(cl_device_id device_id);
|
||||
|
||||
static bool get_device_extensions(cl_device_id device_id,
|
||||
string *device_extensions,
|
||||
cl_int* error = NULL);
|
||||
|
||||
static string get_device_extensions(cl_device_id device_id);
|
||||
|
||||
static bool get_device_type(cl_device_id device_id,
|
||||
cl_device_type *device_type,
|
||||
cl_int* error = NULL);
|
||||
@@ -362,7 +371,7 @@ public:
|
||||
void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half);
|
||||
void shader(DeviceTask& task);
|
||||
|
||||
void denoise(RenderTile& tile, DenoisingTask& denoising, const DeviceTask& task);
|
||||
void denoise(RenderTile& tile, DenoisingTask& denoising);
|
||||
|
||||
class OpenCLDeviceTask : public DeviceTask {
|
||||
public:
|
||||
@@ -436,8 +445,6 @@ protected:
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task);
|
||||
bool denoising_set_tiles(device_ptr *buffers,
|
||||
DenoisingTask *task);
|
||||
|
||||
device_ptr mem_alloc_sub_ptr(device_memory& mem, int offset, int size);
|
||||
void mem_free_sub_ptr(device_ptr ptr);
|
||||
|
||||
@@ -246,7 +246,6 @@ bool OpenCLDeviceBase::load_kernels(const DeviceRequestedFeatures& requested_fea
|
||||
denoising_program.add_kernel(ustring("filter_nlm_normalize"));
|
||||
denoising_program.add_kernel(ustring("filter_nlm_construct_gramian"));
|
||||
denoising_program.add_kernel(ustring("filter_finalize"));
|
||||
denoising_program.add_kernel(ustring("filter_set_tiles"));
|
||||
|
||||
vector<OpenCLProgram*> programs;
|
||||
programs.push_back(&base_program);
|
||||
@@ -977,13 +976,20 @@ bool OpenCLDeviceBase::denoising_divide_shadow(device_ptr a_ptr,
|
||||
cl_mem sv_variance_mem = CL_MEM_PTR(sv_variance_ptr);
|
||||
cl_mem buffer_variance_mem = CL_MEM_PTR(buffer_variance_ptr);
|
||||
|
||||
cl_mem tiles_mem = CL_MEM_PTR(task->tiles_mem.device_pointer);
|
||||
cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
|
||||
|
||||
cl_kernel ckFilterDivideShadow = denoising_program(ustring("filter_divide_shadow"));
|
||||
|
||||
kernel_set_args(ckFilterDivideShadow, 0,
|
||||
task->render_buffer.samples,
|
||||
tiles_mem,
|
||||
int arg_ofs = kernel_set_args(ckFilterDivideShadow, 0,
|
||||
task->render_buffer.samples,
|
||||
tile_info_mem);
|
||||
cl_mem buffers[9];
|
||||
for(int i = 0; i < 9; i++) {
|
||||
buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
|
||||
arg_ofs += kernel_set_args(ckFilterDivideShadow, arg_ofs,
|
||||
buffers[i]);
|
||||
}
|
||||
kernel_set_args(ckFilterDivideShadow, arg_ofs,
|
||||
a_mem,
|
||||
b_mem,
|
||||
sample_variance_mem,
|
||||
@@ -991,7 +997,7 @@ bool OpenCLDeviceBase::denoising_divide_shadow(device_ptr a_ptr,
|
||||
buffer_variance_mem,
|
||||
task->rect,
|
||||
task->render_buffer.pass_stride,
|
||||
task->render_buffer.denoising_data_offset);
|
||||
task->render_buffer.offset);
|
||||
enqueue_kernel(ckFilterDivideShadow,
|
||||
task->rect.z-task->rect.x,
|
||||
task->rect.w-task->rect.y);
|
||||
@@ -1008,20 +1014,27 @@ bool OpenCLDeviceBase::denoising_get_feature(int mean_offset,
|
||||
cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
|
||||
cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
|
||||
|
||||
cl_mem tiles_mem = CL_MEM_PTR(task->tiles_mem.device_pointer);
|
||||
cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
|
||||
|
||||
cl_kernel ckFilterGetFeature = denoising_program(ustring("filter_get_feature"));
|
||||
|
||||
kernel_set_args(ckFilterGetFeature, 0,
|
||||
task->render_buffer.samples,
|
||||
tiles_mem,
|
||||
int arg_ofs = kernel_set_args(ckFilterGetFeature, 0,
|
||||
task->render_buffer.samples,
|
||||
tile_info_mem);
|
||||
cl_mem buffers[9];
|
||||
for(int i = 0; i < 9; i++) {
|
||||
buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
|
||||
arg_ofs += kernel_set_args(ckFilterGetFeature, arg_ofs,
|
||||
buffers[i]);
|
||||
}
|
||||
kernel_set_args(ckFilterGetFeature, arg_ofs,
|
||||
mean_offset,
|
||||
variance_offset,
|
||||
mean_mem,
|
||||
variance_mem,
|
||||
task->rect,
|
||||
task->render_buffer.pass_stride,
|
||||
task->render_buffer.denoising_data_offset);
|
||||
task->render_buffer.offset);
|
||||
enqueue_kernel(ckFilterGetFeature,
|
||||
task->rect.z-task->rect.x,
|
||||
task->rect.w-task->rect.y);
|
||||
@@ -1056,29 +1069,8 @@ bool OpenCLDeviceBase::denoising_detect_outliers(device_ptr image_ptr,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenCLDeviceBase::denoising_set_tiles(device_ptr *buffers,
|
||||
DenoisingTask *task)
|
||||
void OpenCLDeviceBase::denoise(RenderTile &rtile, DenoisingTask& denoising)
|
||||
{
|
||||
task->tiles_mem.copy_to_device();
|
||||
|
||||
cl_mem tiles_mem = CL_MEM_PTR(task->tiles_mem.device_pointer);
|
||||
|
||||
cl_kernel ckFilterSetTiles = denoising_program(ustring("filter_set_tiles"));
|
||||
|
||||
kernel_set_args(ckFilterSetTiles, 0, tiles_mem);
|
||||
for(int i = 0; i < 9; i++) {
|
||||
cl_mem buffer_mem = CL_MEM_PTR(buffers[i]);
|
||||
kernel_set_args(ckFilterSetTiles, i+1, buffer_mem);
|
||||
}
|
||||
|
||||
enqueue_kernel(ckFilterSetTiles, 1, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenCLDeviceBase::denoise(RenderTile &rtile, DenoisingTask& denoising, const DeviceTask &task)
|
||||
{
|
||||
denoising.functions.set_tiles = function_bind(&OpenCLDeviceBase::denoising_set_tiles, this, _1, &denoising);
|
||||
denoising.functions.construct_transform = function_bind(&OpenCLDeviceBase::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
denoising.functions.divide_shadow = function_bind(&OpenCLDeviceBase::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
|
||||
@@ -1090,16 +1082,7 @@ void OpenCLDeviceBase::denoise(RenderTile &rtile, DenoisingTask& denoising, cons
|
||||
denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
|
||||
denoising.render_buffer.samples = rtile.sample;
|
||||
|
||||
RenderTile rtiles[9];
|
||||
rtiles[4] = rtile;
|
||||
task.map_neighbor_tiles(rtiles, this);
|
||||
denoising.tiles_from_rendertiles(rtiles);
|
||||
|
||||
denoising.init_from_devicetask(task);
|
||||
|
||||
denoising.run_denoising();
|
||||
|
||||
task.unmap_neighbor_tiles(rtiles, this);
|
||||
denoising.run_denoising(&rtile);
|
||||
}
|
||||
|
||||
void OpenCLDeviceBase::shader(DeviceTask& task)
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
}
|
||||
else if(task->type == DeviceTask::RENDER) {
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
DenoisingTask denoising(this, *task);
|
||||
|
||||
/* Keep rendering tiles until done. */
|
||||
while(task->acquire_tile(this, tile)) {
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
}
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
denoise(tile, denoising, *task);
|
||||
denoise(tile, denoising);
|
||||
task->update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
}
|
||||
else if(task->type == DeviceTask::RENDER) {
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
DenoisingTask denoising(this, *task);
|
||||
|
||||
/* Allocate buffer for kernel globals */
|
||||
device_only_memory<KernelGlobalsDummy> kgbuffer(this, "kernel_globals");
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
}
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
denoise(tile, denoising, *task);
|
||||
denoise(tile, denoising);
|
||||
task->update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
||||
|
||||
@@ -831,13 +831,15 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
|
||||
FIRST_VLOG(2) << "Adding new device "
|
||||
<< readable_device_name << ".";
|
||||
string hardware_id = get_hardware_id(platform_name, device_id);
|
||||
string device_extensions = get_device_extensions(device_id);
|
||||
usable_devices->push_back(OpenCLPlatformDevice(
|
||||
platform_id,
|
||||
platform_name,
|
||||
device_id,
|
||||
device_type,
|
||||
readable_device_name,
|
||||
hardware_id));
|
||||
hardware_id,
|
||||
device_extensions));
|
||||
}
|
||||
else {
|
||||
FIRST_VLOG(2) << "Ignoring device " << device_name
|
||||
@@ -1047,6 +1049,40 @@ string OpenCLInfo::get_device_name(cl_device_id device_id)
|
||||
return device_name;
|
||||
}
|
||||
|
||||
bool OpenCLInfo::get_device_extensions(cl_device_id device_id,
|
||||
string *device_extensions,
|
||||
cl_int* error)
|
||||
{
|
||||
char buffer[1024];
|
||||
cl_int err;
|
||||
if((err = clGetDeviceInfo(device_id,
|
||||
CL_DEVICE_EXTENSIONS,
|
||||
sizeof(buffer),
|
||||
&buffer,
|
||||
NULL)) != CL_SUCCESS)
|
||||
{
|
||||
if(error != NULL) {
|
||||
*error = err;
|
||||
}
|
||||
*device_extensions = "";
|
||||
return false;
|
||||
}
|
||||
if(error != NULL) {
|
||||
*error = CL_SUCCESS;
|
||||
}
|
||||
*device_extensions = buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
string OpenCLInfo::get_device_extensions(cl_device_id device_id)
|
||||
{
|
||||
string device_extensions;
|
||||
if(!get_device_extensions(device_id, &device_extensions)) {
|
||||
return "";
|
||||
}
|
||||
return device_extensions;
|
||||
}
|
||||
|
||||
bool OpenCLInfo::get_device_type(cl_device_id device_id,
|
||||
cl_device_type *device_type,
|
||||
cl_int* error)
|
||||
|
||||
@@ -200,4 +200,3 @@
|
||||
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.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ met:
|
||||
distribution.
|
||||
* Neither the name of Industrial Light & Magic nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
@@ -26,4 +26,3 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
@@ -33,4 +33,3 @@ 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.
|
||||
|
||||
|
||||
@@ -25,4 +25,3 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
@@ -26,4 +26,3 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
@@ -13,4 +13,3 @@ MIT license
|
||||
|
||||
Boost License
|
||||
* Boost and OpenCL dynamic loading
|
||||
|
||||
|
||||
@@ -496,4 +496,3 @@ void Node::hash(MD5Hash& md5)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -97,4 +97,3 @@ struct Node
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -45,4 +45,3 @@ private:
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -217,4 +217,3 @@ const NodeType *NodeType::find(ustring name)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -263,4 +263,3 @@ const NodeType *structname::register_type()
|
||||
{ type->register_output(ustring(#name), ustring(ui_name), SocketType::ENUM); }
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -458,4 +458,3 @@ xml_node xml_write_node(Node *node, xml_node xml_root)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -32,4 +32,3 @@ void xml_read_node(XMLReader& reader, Node *node, xml_node xml_node);
|
||||
xml_node xml_write_node(Node *node, xml_node xml_root);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ set(SRC_CLOSURE_HEADERS
|
||||
closure/volume.h
|
||||
closure/bsdf_principled_diffuse.h
|
||||
closure/bsdf_principled_sheen.h
|
||||
closure/bsdf_hair_principled.h
|
||||
)
|
||||
|
||||
set(SRC_SVM_HEADERS
|
||||
@@ -287,6 +288,7 @@ set(SRC_UTIL_HEADERS
|
||||
../util/util_types_uint3_impl.h
|
||||
../util/util_types_uint4.h
|
||||
../util/util_types_uint4_impl.h
|
||||
../util/util_types_ushort4.h
|
||||
../util/util_types_vector3.h
|
||||
../util/util_types_vector3_impl.h
|
||||
)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
|
||||
#include "kernel/closure/bsdf_toon.h"
|
||||
#include "kernel/closure/bsdf_hair.h"
|
||||
#include "kernel/closure/bsdf_hair_principled.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_sheen.h"
|
||||
#include "kernel/closure/bssrdf.h"
|
||||
@@ -171,6 +172,10 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
|
||||
label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
label = bsdf_principled_hair_sample(kg, sc, sd, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
#ifdef __PRINCIPLED__
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
|
||||
@@ -284,6 +289,9 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
@@ -366,6 +374,9 @@ float3 bsdf_eval(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
@@ -424,6 +435,9 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
|
||||
bsdf_ashikhmin_shirley_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
bsdf_principled_hair_blur(sc, roughness);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -486,4 +500,3 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ ccl_device_forceinline float3 bsdf_ashikhmin_shirley_eval_reflect(
|
||||
lobe = 1.0f;
|
||||
}
|
||||
float norm = sqrtf((n_x + 1.0f)*(n_y + 1.0f)) / (8.0f * M_PI_F);
|
||||
|
||||
|
||||
out = NdotO * norm * lobe * pump;
|
||||
*pdf = norm * lobe / HdotI;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Modifications Copyright 2011, Blender Foundation.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
@@ -46,7 +46,7 @@ ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)
|
||||
{
|
||||
float sigma = fmaxf(bsdf->sigma, 0.01f);
|
||||
bsdf->invsigma2 = 1.0f/(sigma * sigma);
|
||||
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
@@ -159,4 +159,3 @@ ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng,
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_ASHIKHMIN_VELVET_H__ */
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I,
|
||||
}
|
||||
else
|
||||
*pdf = 0.0f;
|
||||
|
||||
|
||||
return LABEL_REFLECT|LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
@@ -140,4 +140,3 @@ ccl_device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_DIFFUSE_H__ */
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ typedef ccl_addr_space struct DiffuseRampBsdf {
|
||||
ccl_device float3 bsdf_diffuse_ramp_get_color(const float3 colors[8], float pos)
|
||||
{
|
||||
int MAXCOLORS = 8;
|
||||
|
||||
|
||||
float npos = pos * (float)(MAXCOLORS - 1);
|
||||
int ipos = float_to_int(npos);
|
||||
if(ipos < 0)
|
||||
@@ -99,7 +99,7 @@ ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, float3 Ng, floa
|
||||
}
|
||||
else
|
||||
*pdf = 0.0f;
|
||||
|
||||
|
||||
return LABEL_REFLECT|LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,4 +278,3 @@ ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng,
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_HAIR_H__ */
|
||||
|
||||
|
||||
502
intern/cycles/kernel/closure/bsdf_hair_principled.h
Normal file
502
intern/cycles/kernel/closure/bsdf_hair_principled.h
Normal file
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL_CPU__
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
|
||||
#include "kernel/kernel_color.h"
|
||||
|
||||
#ifndef __BSDF_HAIR_PRINCIPLED_H__
|
||||
#define __BSDF_HAIR_PRINCIPLED_H__
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef ccl_addr_space struct PrincipledHairExtra {
|
||||
/* Geometry data. */
|
||||
float4 geom;
|
||||
} PrincipledHairExtra;
|
||||
|
||||
typedef ccl_addr_space struct PrincipledHairBSDF {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
/* Absorption coefficient. */
|
||||
float3 sigma;
|
||||
/* Variance of the underlying logistic distribution. */
|
||||
float v;
|
||||
/* Scale factor of the underlying logistic distribution. */
|
||||
float s;
|
||||
/* Cuticle tilt angle. */
|
||||
float alpha;
|
||||
/* IOR. */
|
||||
float eta;
|
||||
/* Effective variance for the diffuse bounce only. */
|
||||
float m0_roughness;
|
||||
|
||||
/* Extra closure. */
|
||||
PrincipledHairExtra *extra;
|
||||
} PrincipledHairBSDF;
|
||||
|
||||
static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF), "PrincipledHairBSDF is too large!");
|
||||
static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra), "PrincipledHairExtra is too large!");
|
||||
|
||||
ccl_device_inline float cos_from_sin(const float s)
|
||||
{
|
||||
return safe_sqrtf(1.0f - s*s);
|
||||
}
|
||||
|
||||
/* Gives the change in direction in the normal plane for the given angles and p-th-order scattering. */
|
||||
ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
|
||||
{
|
||||
return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
|
||||
}
|
||||
|
||||
/* Remaps the given angle to [-pi, pi]. */
|
||||
ccl_device_inline float wrap_angle(float a)
|
||||
{
|
||||
while(a > M_PI_F) {
|
||||
a -= M_2PI_F;
|
||||
}
|
||||
while(a < -M_PI_F) {
|
||||
a += M_2PI_F;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Logistic distribution function. */
|
||||
ccl_device_inline float logistic(float x, float s)
|
||||
{
|
||||
float v = expf(-fabsf(x)/s);
|
||||
return v / (s * sqr(1.0f + v));
|
||||
}
|
||||
|
||||
/* Logistic cumulative density function. */
|
||||
ccl_device_inline float logistic_cdf(float x, float s)
|
||||
{
|
||||
float arg = -x/s;
|
||||
/* expf() overflows if arg >= 89.0. */
|
||||
if(arg > 88.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
else {
|
||||
return 1.0f / (1.0f + expf(arg));
|
||||
}
|
||||
}
|
||||
|
||||
/* Numerical approximation to the Bessel function of the first kind. */
|
||||
ccl_device_inline float bessel_I0(float x)
|
||||
{
|
||||
x = sqr(x);
|
||||
float val = 1.0f + 0.25f*x;
|
||||
float pow_x_2i = sqr(x);
|
||||
uint64_t i_fac_2 = 1;
|
||||
int pow_4_i = 16;
|
||||
for(int i = 2; i < 10; i++) {
|
||||
i_fac_2 *= i*i;
|
||||
float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
|
||||
if(val == newval) {
|
||||
return val;
|
||||
}
|
||||
val = newval;
|
||||
pow_x_2i *= x;
|
||||
pow_4_i *= 4;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Logarithm of the Bessel function of the first kind. */
|
||||
ccl_device_inline float log_bessel_I0(float x)
|
||||
{
|
||||
if (x > 12.0f) {
|
||||
/* log(1/x) == -log(x) iff x > 0.
|
||||
* This is only used with positive cosines */
|
||||
return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
|
||||
}
|
||||
else {
|
||||
return logf(bessel_I0(x));
|
||||
}
|
||||
}
|
||||
|
||||
/* Logistic distribution limited to the interval [-pi, pi]. */
|
||||
ccl_device_inline float trimmed_logistic(float x, float s)
|
||||
{
|
||||
/* The logistic distribution is symmetric and centered around zero,
|
||||
* so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
|
||||
* Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
|
||||
float scaling_fac = 1.0f - 2.0f*logistic_cdf(-M_PI_F, s);
|
||||
float val = logistic(x, s);
|
||||
return safe_divide(val, scaling_fac);
|
||||
}
|
||||
|
||||
/* Sampling function for the trimmed logistic function. */
|
||||
ccl_device_inline float sample_trimmed_logistic(float u, float s)
|
||||
{
|
||||
float cdf_minuspi = logistic_cdf(-M_PI_F, s);
|
||||
float x = -s*logf(1.0f / (u*(1.0f - 2.0f*cdf_minuspi) + cdf_minuspi) - 1.0f);
|
||||
return clamp(x, -M_PI_F, M_PI_F);
|
||||
}
|
||||
|
||||
/* Azimuthal scattering function Np. */
|
||||
ccl_device_inline float azimuthal_scattering(float phi,
|
||||
int p,
|
||||
float s,
|
||||
float gamma_o,
|
||||
float gamma_t)
|
||||
{
|
||||
float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
|
||||
float val = trimmed_logistic(phi_o, s);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Longitudinal scattering function Mp. */
|
||||
ccl_device_inline float longitudinal_scattering(float sin_theta_i,
|
||||
float cos_theta_i,
|
||||
float sin_theta_o,
|
||||
float cos_theta_o,
|
||||
float v)
|
||||
{
|
||||
float inv_v = 1.0f/v;
|
||||
float cos_arg = cos_theta_i * cos_theta_o * inv_v;
|
||||
float sin_arg = sin_theta_i * sin_theta_o * inv_v;
|
||||
if(v <= 0.1f) {
|
||||
float i0 = log_bessel_I0(cos_arg);
|
||||
float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f*inv_v));
|
||||
return val;
|
||||
}
|
||||
else {
|
||||
float i0 = bessel_I0(cos_arg);
|
||||
float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine the three values using their luminances. */
|
||||
ccl_device_inline float4 combine_with_energy(KernelGlobals *kg, float3 c)
|
||||
{
|
||||
return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
|
||||
}
|
||||
|
||||
#ifdef __HAIR__
|
||||
/* Set up the hair closure. */
|
||||
ccl_device int bsdf_principled_hair_setup(ShaderData *sd, PrincipledHairBSDF *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
|
||||
bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
|
||||
bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
|
||||
/* Apply Primary Reflection Roughness modifier. */
|
||||
bsdf->m0_roughness = clamp(bsdf->m0_roughness*bsdf->v, 0.001f, 1.0f);
|
||||
|
||||
/* Map from roughness_u and roughness_v to variance and scale factor. */
|
||||
bsdf->v = sqr(0.726f*bsdf->v + 0.812f*sqr(bsdf->v) + 3.700f*pow20(bsdf->v));
|
||||
bsdf->s = (0.265f*bsdf->s + 1.194f*sqr(bsdf->s) + 5.372f*pow22(bsdf->s))*M_SQRT_PI_8_F;
|
||||
bsdf->m0_roughness = sqr(0.726f*bsdf->m0_roughness + 0.812f*sqr(bsdf->m0_roughness) + 3.700f*pow20(bsdf->m0_roughness));
|
||||
|
||||
/* Compute local frame, aligned to curve tangent and ray direction. */
|
||||
float3 X = safe_normalize(sd->dPdu);
|
||||
float3 Y = safe_normalize(cross(X, sd->I));
|
||||
float3 Z = safe_normalize(cross(X, Y));
|
||||
/* TODO: the solution below works where sd->Ng is the normal
|
||||
* pointing from the center of the curve to the shading point.
|
||||
* It doesn't work for triangles, see https://developer.blender.org/T43625 */
|
||||
|
||||
/* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
|
||||
* the center, to grazing the other edge. This is the sine of the angle
|
||||
* between sd->Ng and Z, as seen from the tangent X. */
|
||||
|
||||
/* TODO: we convert this value to a cosine later and discard the sign, so
|
||||
* we could probably save some operations. */
|
||||
float h = dot(cross(sd->Ng, X), Z);
|
||||
|
||||
kernel_assert(fabsf(h) < 1.0f + 1e-4f);
|
||||
kernel_assert(isfinite3_safe(Y));
|
||||
kernel_assert(isfinite_safe(h));
|
||||
|
||||
bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
#endif /* __HAIR__ */
|
||||
|
||||
/* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */
|
||||
ccl_device_inline void hair_attenuation(KernelGlobals *kg,
|
||||
float f,
|
||||
float3 T,
|
||||
float4 *Ap)
|
||||
{
|
||||
/* Primary specular (R). */
|
||||
Ap[0] = make_float4(f, f, f, f);
|
||||
|
||||
/* Transmission (TT). */
|
||||
float3 col = sqr(1.0f - f) * T;
|
||||
Ap[1] = combine_with_energy(kg, col);
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
col *= T*f;
|
||||
Ap[2] = combine_with_energy(kg, col);
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
col *= safe_divide_color(T*f, make_float3(1.0f, 1.0f, 1.0f) - T*f);
|
||||
Ap[3] = combine_with_energy(kg, col);
|
||||
|
||||
/* Normalize sampling weights. */
|
||||
float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
|
||||
float fac = safe_divide(1.0f, totweight);
|
||||
|
||||
Ap[0].w *= fac;
|
||||
Ap[1].w *= fac;
|
||||
Ap[2].w *= fac;
|
||||
Ap[3].w *= fac;
|
||||
}
|
||||
|
||||
/* Given the tilt angle, generate the rotated theta_i for the different bounces. */
|
||||
ccl_device_inline void hair_alpha_angles(float sin_theta_i,
|
||||
float cos_theta_i,
|
||||
float alpha,
|
||||
float *angles)
|
||||
{
|
||||
float sin_1alpha = sinf(alpha);
|
||||
float cos_1alpha = cos_from_sin(sin_1alpha);
|
||||
float sin_2alpha = 2.0f*sin_1alpha*cos_1alpha;
|
||||
float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
|
||||
float sin_4alpha = 2.0f*sin_2alpha*cos_2alpha;
|
||||
float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
|
||||
|
||||
angles[0] = sin_theta_i*cos_2alpha + cos_theta_i*sin_2alpha;
|
||||
angles[1] = fabsf(cos_theta_i*cos_2alpha - sin_theta_i*sin_2alpha);
|
||||
angles[2] = sin_theta_i*cos_1alpha - cos_theta_i*sin_1alpha;
|
||||
angles[3] = fabsf(cos_theta_i*cos_1alpha + sin_theta_i*sin_1alpha);
|
||||
angles[4] = sin_theta_i*cos_4alpha - cos_theta_i*sin_4alpha;
|
||||
angles[5] = fabsf(cos_theta_i*cos_4alpha + sin_theta_i*sin_4alpha);
|
||||
}
|
||||
|
||||
/* Evaluation function for our shader. */
|
||||
ccl_device float3 bsdf_principled_hair_eval(KernelGlobals *kg,
|
||||
const ShaderData *sd,
|
||||
const ShaderClosure *sc,
|
||||
const float3 omega_in,
|
||||
float *pdf)
|
||||
{
|
||||
kernel_assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
|
||||
|
||||
const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF*) sc;
|
||||
float3 Y = float4_to_float3(bsdf->extra->geom);
|
||||
|
||||
float3 X = safe_normalize(sd->dPdu);
|
||||
kernel_assert(fabsf(dot(X, Y)) < 1e-4f);
|
||||
float3 Z = safe_normalize(cross(X, Y));
|
||||
|
||||
float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
|
||||
float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
|
||||
float sin_theta_o = wo.x;
|
||||
float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||
float phi_o = atan2f(wo.z, wo.y);
|
||||
|
||||
float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||
float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||
|
||||
float sin_gamma_o = bsdf->extra->geom.w;
|
||||
float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||
float gamma_o = safe_asinf(sin_gamma_o);
|
||||
|
||||
float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
|
||||
float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
float gamma_t = safe_asinf(sin_gamma_t);
|
||||
|
||||
float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
float4 Ap[4];
|
||||
hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
|
||||
|
||||
float sin_theta_i = wi.x;
|
||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||
float phi_i = atan2f(wi.z, wi.y);
|
||||
|
||||
float phi = phi_i - phi_o;
|
||||
|
||||
float angles[6];
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||
|
||||
float4 F;
|
||||
float Mp, Np;
|
||||
|
||||
/* Primary specular (R). */
|
||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
||||
F = Ap[0] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
/* Transmission (TT). */
|
||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[1] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[2] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
|
||||
Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
*pdf = F.w;
|
||||
return float4_to_float3(F);
|
||||
}
|
||||
|
||||
/* Sampling function for the hair shader. */
|
||||
ccl_device int bsdf_principled_hair_sample(KernelGlobals *kg,
|
||||
const ShaderClosure *sc,
|
||||
ShaderData *sd,
|
||||
float randu,
|
||||
float randv,
|
||||
float3 *eval,
|
||||
float3 *omega_in,
|
||||
float3 *domega_in_dx,
|
||||
float3 *domega_in_dy,
|
||||
float *pdf)
|
||||
{
|
||||
PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*) sc;
|
||||
|
||||
float3 Y = float4_to_float3(bsdf->extra->geom);
|
||||
|
||||
float3 X = safe_normalize(sd->dPdu);
|
||||
kernel_assert(fabsf(dot(X, Y)) < 1e-4f);
|
||||
float3 Z = safe_normalize(cross(X, Y));
|
||||
|
||||
float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
|
||||
|
||||
float2 u[2];
|
||||
u[0] = make_float2(randu, randv);
|
||||
u[1].x = lcg_step_float_addrspace(&sd->lcg_state);
|
||||
u[1].y = lcg_step_float_addrspace(&sd->lcg_state);
|
||||
|
||||
float sin_theta_o = wo.x;
|
||||
float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||
float phi_o = atan2f(wo.z, wo.y);
|
||||
|
||||
float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||
float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||
|
||||
float sin_gamma_o = bsdf->extra->geom.w;
|
||||
float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||
float gamma_o = safe_asinf(sin_gamma_o);
|
||||
|
||||
float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
|
||||
float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
float gamma_t = safe_asinf(sin_gamma_t);
|
||||
|
||||
float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
float4 Ap[4];
|
||||
hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
|
||||
|
||||
int p = 0;
|
||||
for(; p < 3; p++) {
|
||||
if(u[0].x < Ap[p].w) {
|
||||
break;
|
||||
}
|
||||
u[0].x -= Ap[p].w;
|
||||
}
|
||||
|
||||
float v = bsdf->v;
|
||||
if(p == 1) {
|
||||
v *= 0.25f;
|
||||
}
|
||||
if(p >= 2) {
|
||||
v *= 4.0f;
|
||||
}
|
||||
|
||||
u[1].x = max(u[1].x, 1e-5f);
|
||||
float fac = 1.0f + v*logf(u[1].x + (1.0f - u[1].x)*expf(-2.0f/v));
|
||||
float sin_theta_i = -fac * sin_theta_o + cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
|
||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||
|
||||
float angles[6];
|
||||
if(p < 3) {
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
|
||||
sin_theta_i = angles[2*p];
|
||||
cos_theta_i = angles[2*p+1];
|
||||
}
|
||||
|
||||
float phi;
|
||||
if(p < 3) {
|
||||
phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
|
||||
}
|
||||
else {
|
||||
phi = M_2PI_F*u[0].y;
|
||||
}
|
||||
float phi_i = phi_o + phi;
|
||||
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||
|
||||
float4 F;
|
||||
float Mp, Np;
|
||||
|
||||
/* Primary specular (R). */
|
||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
||||
F = Ap[0] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
/* Transmission (TT). */
|
||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[1] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[2] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
|
||||
Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
kernel_assert(isfinite3_safe(float4_to_float3(F)));
|
||||
|
||||
*eval = float4_to_float3(F);
|
||||
*pdf = F.w;
|
||||
|
||||
*omega_in = X*sin_theta_i + Y*cos_theta_i*cosf(phi_i) + Z*cos_theta_i*sinf(phi_i);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 N = safe_normalize(sd->I + *omega_in);
|
||||
*domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
|
||||
*domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
|
||||
#endif
|
||||
|
||||
return LABEL_GLOSSY|((p == 0)? LABEL_REFLECT : LABEL_TRANSMIT);
|
||||
}
|
||||
|
||||
/* Implements Filter Glossy by capping the effective roughness. */
|
||||
ccl_device void bsdf_principled_hair_blur(ShaderClosure *sc, float roughness)
|
||||
{
|
||||
PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)sc;
|
||||
|
||||
bsdf->v = fmaxf(roughness, bsdf->v);
|
||||
bsdf->s = fmaxf(roughness, bsdf->s);
|
||||
bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_HAIR_PRINCIPLED_H__ */
|
||||
@@ -231,7 +231,7 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
|
||||
|
||||
/* 5. compute normal */
|
||||
return normalize(make_float3(-slope_x, -slope_y, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the reflection color
|
||||
*
|
||||
@@ -434,7 +434,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
|
||||
|
||||
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
@@ -535,7 +535,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
|
||||
|
||||
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
|
||||
float G = G1o * G1i;
|
||||
|
||||
@@ -706,7 +706,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
|
||||
#endif
|
||||
&inside);
|
||||
|
||||
|
||||
if(!inside && fresnel != 1.0f) {
|
||||
|
||||
*omega_in = T;
|
||||
@@ -733,7 +733,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
|
||||
float cosNI = dot(N, *omega_in);
|
||||
|
||||
/* eq. 34: now calculate G1(i,m) */
|
||||
float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
|
||||
/* eq. 21 */
|
||||
float cosHI = dot(m, *omega_in);
|
||||
@@ -1125,4 +1125,3 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_MICROFACET_H__ */
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef ccl_addr_space struct PhongRampBsdf {
|
||||
ccl_device float3 bsdf_phong_ramp_get_color(const float3 colors[8], float pos)
|
||||
{
|
||||
int MAXCOLORS = 8;
|
||||
|
||||
|
||||
float npos = pos * (float)(MAXCOLORS - 1);
|
||||
int ipos = float_to_int(npos);
|
||||
if(ipos < 0)
|
||||
@@ -71,7 +71,7 @@ ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const fl
|
||||
float m_exponent = bsdf->exponent;
|
||||
float cosNI = dot(bsdf->N, omega_in);
|
||||
float cosNO = dot(bsdf->N, I);
|
||||
|
||||
|
||||
if(cosNI > 0 && cosNO > 0) {
|
||||
// reflect the view vector
|
||||
float3 R = (2 * cosNO) * bsdf->N - I;
|
||||
@@ -84,7 +84,7 @@ ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const fl
|
||||
return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, float3 Ng, float3
|
||||
const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
|
||||
float cosNO = dot(bsdf->N, I);
|
||||
float m_exponent = bsdf->exponent;
|
||||
|
||||
|
||||
if(cosNO > 0) {
|
||||
// reflect the view vector
|
||||
float3 R = (2 * cosNO) * bsdf->N - I;
|
||||
@@ -107,7 +107,7 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, float3 Ng, float3
|
||||
*domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
|
||||
*domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
|
||||
#endif
|
||||
|
||||
|
||||
float3 T, B;
|
||||
make_orthonormals (R, &T, &B);
|
||||
float phi = M_2PI_F * randu;
|
||||
|
||||
@@ -123,5 +123,3 @@ ccl_device int bsdf_principled_diffuse_sample(const ShaderClosure *sc,
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_PRINCIPLED_DIFFUSE_H__ */
|
||||
|
||||
|
||||
|
||||
@@ -109,5 +109,3 @@ ccl_device int bsdf_principled_sheen_sample(const ShaderClosure *sc,
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_PRINCIPLED_SHEEN_H__ */
|
||||
|
||||
|
||||
|
||||
@@ -78,4 +78,3 @@ ccl_device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_REFLECTION_H__ */
|
||||
|
||||
|
||||
@@ -87,4 +87,3 @@ ccl_device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, float3
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_REFRACTION_H__ */
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float a
|
||||
is = (1.0f - (angle - max_angle)/smooth);
|
||||
else
|
||||
is = 0.0f;
|
||||
|
||||
|
||||
return make_float3(is, is, is);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const
|
||||
float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
|
||||
|
||||
float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
|
||||
|
||||
if(eval.x > 0.0f) {
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
@@ -152,7 +152,7 @@ ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc, const f
|
||||
float smooth = bsdf->smooth*M_PI_2_F;
|
||||
float cosNI = dot(bsdf->N, omega_in);
|
||||
float cosNO = dot(bsdf->N, I);
|
||||
|
||||
|
||||
if(cosNI > 0 && cosNO > 0) {
|
||||
/* reflect the view vector */
|
||||
float3 R = (2 * cosNO) * bsdf->N - I;
|
||||
@@ -166,7 +166,7 @@ ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc, const f
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
return *pdf * eval;
|
||||
}
|
||||
|
||||
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, float
|
||||
float max_angle = bsdf->size*M_PI_2_F;
|
||||
float smooth = bsdf->smooth*M_PI_2_F;
|
||||
float cosNO = dot(bsdf->N, I);
|
||||
|
||||
|
||||
if(cosNO > 0) {
|
||||
/* reflect the view vector */
|
||||
float3 R = (2 * cosNO) * bsdf->N - I;
|
||||
@@ -216,4 +216,3 @@ ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, float
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_TOON_H__ */
|
||||
|
||||
|
||||
@@ -107,4 +107,3 @@ ccl_device int bsdf_transparent_sample(const ShaderClosure *sc, float3 Ng, float
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_TRANSPARENT_H__ */
|
||||
|
||||
|
||||
@@ -62,14 +62,14 @@ ccl_device float fresnel_dielectric(
|
||||
Nn = -N;
|
||||
*is_inside = true;
|
||||
}
|
||||
|
||||
|
||||
// compute reflection
|
||||
*R = (2 * cos)* Nn - I;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*dRdx = (2 * dot(Nn, dIdx)) * Nn - dIdx;
|
||||
*dRdy = (2 * dot(Nn, dIdy)) * Nn - dIdy;
|
||||
#endif
|
||||
|
||||
|
||||
float arg = 1 -(neta * neta *(1 -(cos * cos)));
|
||||
if(arg < 0) {
|
||||
*T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
@@ -159,4 +159,3 @@ ccl_device_forceinline float3 interpolate_fresnel_color(float3 L, float3 H, floa
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_UTIL_H__ */
|
||||
|
||||
|
||||
@@ -500,4 +500,3 @@ ccl_device_forceinline float bssrdf_pdf(const ShaderClosure *sc, float r)
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __KERNEL_BSSRDF_H__ */
|
||||
|
||||
|
||||
@@ -76,9 +76,8 @@ ccl_device void emissive_sample(const float3 Ng, float randu, float randv,
|
||||
ccl_device float3 emissive_simple_eval(const float3 Ng, const float3 I)
|
||||
{
|
||||
float res = emissive_pdf(Ng, I);
|
||||
|
||||
|
||||
return make_float3(res, res, res);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
|
||||
ccl_device int volume_henyey_greenstein_setup(HenyeyGreensteinVolume *volume)
|
||||
{
|
||||
volume->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
|
||||
|
||||
|
||||
/* clamp anisotropy to avoid delta function */
|
||||
volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define XTWX_SIZE (((DENOISE_FEATURES+1)*(DENOISE_FEATURES+2))/2)
|
||||
#define XTWY_SIZE (DENOISE_FEATURES+1)
|
||||
|
||||
typedef struct TilesInfo {
|
||||
typedef struct TileInfo {
|
||||
int offsets[9];
|
||||
int strides[9];
|
||||
int x[4];
|
||||
@@ -33,6 +33,39 @@ typedef struct TilesInfo {
|
||||
#else
|
||||
long long int buffers[9];
|
||||
#endif
|
||||
} TilesInfo;
|
||||
} TileInfo;
|
||||
|
||||
#ifdef __KERNEL_OPENCL__
|
||||
# define CCL_FILTER_TILE_INFO ccl_global TileInfo* tile_info, \
|
||||
ccl_global float *tile_buffer_1, \
|
||||
ccl_global float *tile_buffer_2, \
|
||||
ccl_global float *tile_buffer_3, \
|
||||
ccl_global float *tile_buffer_4, \
|
||||
ccl_global float *tile_buffer_5, \
|
||||
ccl_global float *tile_buffer_6, \
|
||||
ccl_global float *tile_buffer_7, \
|
||||
ccl_global float *tile_buffer_8, \
|
||||
ccl_global float *tile_buffer_9
|
||||
# define CCL_FILTER_TILE_INFO_ARG tile_info, \
|
||||
tile_buffer_1, tile_buffer_2, tile_buffer_3, \
|
||||
tile_buffer_4, tile_buffer_5, tile_buffer_6, \
|
||||
tile_buffer_7, tile_buffer_8, tile_buffer_9
|
||||
# define ccl_get_tile_buffer(id) (id == 0 ? tile_buffer_1 \
|
||||
: id == 1 ? tile_buffer_2 \
|
||||
: id == 2 ? tile_buffer_3 \
|
||||
: id == 3 ? tile_buffer_4 \
|
||||
: id == 4 ? tile_buffer_5 \
|
||||
: id == 5 ? tile_buffer_6 \
|
||||
: id == 6 ? tile_buffer_7 \
|
||||
: id == 7 ? tile_buffer_8 \
|
||||
: tile_buffer_9)
|
||||
#else
|
||||
# ifdef __KERNEL_CUDA__
|
||||
# define CCL_FILTER_TILE_INFO ccl_global TileInfo* tile_info
|
||||
# else
|
||||
# define CCL_FILTER_TILE_INFO TileInfo* tile_info
|
||||
# endif
|
||||
# define ccl_get_tile_buffer(id) (tile_info->buffers[id])
|
||||
#endif
|
||||
|
||||
#endif /* __FILTER_DEFINES_H__*/
|
||||
|
||||
@@ -26,7 +26,7 @@ CCL_NAMESPACE_BEGIN
|
||||
* bufferVariance: The buffer-based variance of the shadow feature. Unbiased, but quite noisy.
|
||||
*/
|
||||
ccl_device void kernel_filter_divide_shadow(int sample,
|
||||
ccl_global TilesInfo *tiles,
|
||||
CCL_FILTER_TILE_INFO,
|
||||
int x, int y,
|
||||
ccl_global float *unfilteredA,
|
||||
ccl_global float *unfilteredB,
|
||||
@@ -37,13 +37,13 @@ ccl_device void kernel_filter_divide_shadow(int sample,
|
||||
int buffer_pass_stride,
|
||||
int buffer_denoising_offset)
|
||||
{
|
||||
int xtile = (x < tiles->x[1])? 0: ((x < tiles->x[2])? 1: 2);
|
||||
int ytile = (y < tiles->y[1])? 0: ((y < tiles->y[2])? 1: 2);
|
||||
int xtile = (x < tile_info->x[1])? 0: ((x < tile_info->x[2])? 1: 2);
|
||||
int ytile = (y < tile_info->y[1])? 0: ((y < tile_info->y[2])? 1: 2);
|
||||
int tile = ytile*3+xtile;
|
||||
|
||||
int offset = tiles->offsets[tile];
|
||||
int stride = tiles->strides[tile];
|
||||
const ccl_global float *ccl_restrict center_buffer = (ccl_global float*) tiles->buffers[tile];
|
||||
int offset = tile_info->offsets[tile];
|
||||
int stride = tile_info->strides[tile];
|
||||
const ccl_global float *ccl_restrict center_buffer = (ccl_global float*) ccl_get_tile_buffer(tile);
|
||||
center_buffer += (y*stride + x + offset)*buffer_pass_stride;
|
||||
center_buffer += buffer_denoising_offset + 14;
|
||||
|
||||
@@ -79,7 +79,7 @@ ccl_device void kernel_filter_divide_shadow(int sample,
|
||||
* - rect: The prefilter area (lower pixels inclusive, upper pixels exclusive).
|
||||
*/
|
||||
ccl_device void kernel_filter_get_feature(int sample,
|
||||
ccl_global TilesInfo *tiles,
|
||||
CCL_FILTER_TILE_INFO,
|
||||
int m_offset, int v_offset,
|
||||
int x, int y,
|
||||
ccl_global float *mean,
|
||||
@@ -87,10 +87,10 @@ ccl_device void kernel_filter_get_feature(int sample,
|
||||
int4 rect, int buffer_pass_stride,
|
||||
int buffer_denoising_offset)
|
||||
{
|
||||
int xtile = (x < tiles->x[1])? 0: ((x < tiles->x[2])? 1: 2);
|
||||
int ytile = (y < tiles->y[1])? 0: ((y < tiles->y[2])? 1: 2);
|
||||
int xtile = (x < tile_info->x[1])? 0: ((x < tile_info->x[2])? 1: 2);
|
||||
int ytile = (y < tile_info->y[1])? 0: ((y < tile_info->y[2])? 1: 2);
|
||||
int tile = ytile*3+xtile;
|
||||
ccl_global float *center_buffer = ((ccl_global float*) tiles->buffers[tile]) + (tiles->offsets[tile] + y*tiles->strides[tile] + x)*buffer_pass_stride + buffer_denoising_offset;
|
||||
ccl_global float *center_buffer = ((ccl_global float*) ccl_get_tile_buffer(tile)) + (tile_info->offsets[tile] + y*tile_info->strides[tile] + x)*buffer_pass_stride + buffer_denoising_offset;
|
||||
|
||||
int buffer_w = align_up(rect.z - rect.x, 4);
|
||||
int idx = (y-rect.y)*buffer_w + (x - rect.x);
|
||||
|
||||
@@ -30,4 +30,3 @@
|
||||
#include "kernel/geom/geom_curve_intersect.h"
|
||||
#include "kernel/geom/geom_volume.h"
|
||||
#include "kernel/geom/geom_primitive.h"
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const Sh
|
||||
uint attr_offset = object_attribute_map_offset(kg, sd->object);
|
||||
attr_offset += attribute_primitive_type(kg, sd);
|
||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
|
||||
|
||||
while(attr_map.x != id) {
|
||||
if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
|
||||
return attribute_not_found();
|
||||
@@ -77,7 +77,7 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const Sh
|
||||
|
||||
AttributeDescriptor desc;
|
||||
desc.element = (AttributeElement)attr_map.y;
|
||||
|
||||
|
||||
if(sd->prim == PRIM_NONE &&
|
||||
desc.element != ATTR_ELEMENT_MESH &&
|
||||
desc.element != ATTR_ELEMENT_VOXEL &&
|
||||
@@ -108,4 +108,3 @@ ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderD
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -23,6 +23,33 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __HAIR__
|
||||
|
||||
/* Interpolation of curve geometry */
|
||||
|
||||
ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
|
||||
{
|
||||
float fc = 0.71f;
|
||||
float data[4];
|
||||
float t2 = t * t;
|
||||
data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
|
||||
data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
|
||||
data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
|
||||
data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
|
||||
return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
|
||||
{
|
||||
float data[4];
|
||||
float fc = 0.71f;
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
|
||||
data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
|
||||
data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
|
||||
data[3] = fc * t3 - fc * t2;
|
||||
return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
|
||||
}
|
||||
|
||||
/* Reading attributes on various curve elements */
|
||||
|
||||
ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user