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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2015-06-29 17:41:00 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2015-06-29 18:18:11 +0300
commitd140e70c496122915eb5c05aba83153e2e0d7998 (patch)
tree1e589247d69da64aa7b0e7802319237ec050b5d6 /intern/cycles/render
parent147bd16ed1bb3415b30408b0eab110d0854eadd2 (diff)
parent295d0c52a26730edc6d4ed1276e4051cce006be5 (diff)
Merge branch 'master' into temp-ghash-experimentstemp-ghash-experiments
Note that 'store hash' feature was removed for now - to complex to maintain (conflicts) and relatively easy to re-add if we ever really want this one day. Conflicts: source/blender/blenlib/BLI_ghash.h source/blender/blenlib/intern/BLI_ghash.c source/blender/blenlib/intern/hash_mm2a.c source/blender/bmesh/tools/bmesh_region_match.c tests/gtests/blenlib/BLI_ghash_performance_test.cc tests/gtests/blenlib/BLI_ghash_test.cc tests/gtests/blenlib/CMakeLists.txt
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/attribute.cpp2
-rw-r--r--intern/cycles/render/background.cpp2
-rw-r--r--intern/cycles/render/bake.cpp12
-rw-r--r--intern/cycles/render/bake.h1
-rw-r--r--intern/cycles/render/blackbody.cpp140
-rw-r--r--intern/cycles/render/blackbody.h28
-rw-r--r--intern/cycles/render/buffers.cpp16
-rw-r--r--intern/cycles/render/camera.cpp30
-rw-r--r--intern/cycles/render/camera.h6
-rw-r--r--intern/cycles/render/curves.cpp10
-rw-r--r--intern/cycles/render/film.cpp22
-rw-r--r--intern/cycles/render/graph.cpp110
-rw-r--r--intern/cycles/render/graph.h25
-rw-r--r--intern/cycles/render/image.cpp60
-rw-r--r--intern/cycles/render/image.h7
-rw-r--r--intern/cycles/render/integrator.cpp2
-rw-r--r--intern/cycles/render/light.cpp168
-rw-r--r--intern/cycles/render/light.h5
-rw-r--r--intern/cycles/render/mesh.cpp119
-rw-r--r--intern/cycles/render/mesh.h10
-rw-r--r--intern/cycles/render/nodes.cpp75
-rw-r--r--intern/cycles/render/nodes.h94
-rw-r--r--intern/cycles/render/object.cpp51
-rw-r--r--intern/cycles/render/object.h6
-rw-r--r--intern/cycles/render/osl.cpp50
-rw-r--r--intern/cycles/render/particles.cpp6
-rw-r--r--intern/cycles/render/scene.cpp14
-rw-r--r--intern/cycles/render/scene.h1
-rw-r--r--intern/cycles/render/session.cpp105
-rw-r--r--intern/cycles/render/session.h15
-rw-r--r--intern/cycles/render/shader.cpp81
-rw-r--r--intern/cycles/render/shader.h16
-rw-r--r--intern/cycles/render/sky_model.cpp433
-rw-r--r--intern/cycles/render/sky_model.h296
-rw-r--r--intern/cycles/render/sky_model_data.h29
-rw-r--r--intern/cycles/render/svm.cpp12
-rw-r--r--intern/cycles/render/tables.cpp3
-rw-r--r--intern/cycles/render/tile.cpp3
39 files changed, 1243 insertions, 824 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 2dc6962633d..4e8a1794813 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -18,7 +18,6 @@ set(SRC
attribute.cpp
background.cpp
bake.cpp
- blackbody.cpp
buffers.cpp
camera.cpp
film.cpp
@@ -47,7 +46,6 @@ set(SRC_HEADERS
attribute.h
bake.h
background.h
- blackbody.h
buffers.h
camera.h
film.h
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 656420f5dbc..6e94459da55 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -52,7 +52,7 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize)
{
- if (resize) {
+ if(resize) {
buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
}
else {
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index f5e51f2e159..5fd7bd8f16f 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -93,7 +93,7 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
need_update = false;
}
-void Background::device_free(Device *device, DeviceScene *dscene)
+void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 1e8c1ac8bc9..4bbac0f91d1 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -55,6 +55,11 @@ void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float d
m_dvdy[i] = dvdy;
}
+void BakeData::set_null(int i)
+{
+ m_primitive[i] = -1;
+}
+
int BakeData::object()
{
return m_object;
@@ -221,7 +226,10 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
return true;
}
-void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void BakeManager::device_update(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene * /*scene*/,
+ Progress& progress)
{
if(!need_update)
return;
@@ -231,7 +239,7 @@ void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
need_update = false;
}
-void BakeManager::device_free(Device *device, DeviceScene *dscene)
+void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 9ff10dafa0e..14d975a4b4e 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -31,6 +31,7 @@ public:
~BakeData();
void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
+ void set_null(int i);
int object();
size_t size();
uint4 data(int i);
diff --git a/intern/cycles/render/blackbody.cpp b/intern/cycles/render/blackbody.cpp
deleted file mode 100644
index 04e6eaf5373..00000000000
--- a/intern/cycles/render/blackbody.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Adapted from Open Shading Language with this license:
- *
- * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
- * All Rights Reserved.
- *
- * Modifications Copyright 2013, Blender Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Sony Pictures Imageworks nor the names of its
- * contributors may be used to endorse or promote products derived 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
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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.
- */
-
-#include "blackbody.h"
-#include "util_color.h"
-#include "util_math.h"
-
-#include "kernel_types.h"
-
-CCL_NAMESPACE_BEGIN
-
-vector<float> blackbody_table_build()
-{
- /* quoted from OSLs opcolor.cpp
- In order to speed up the blackbody computation, we have a table
- storing the precomputed BB values for a range of temperatures. Less
- than BB_DRAPER always returns 0. Greater than BB_MAX_TABLE_RANGE
- does the full computation, we think it'll be rare to inquire higher
- temperatures.
-
- Since the bb function is so nonlinear, we actually space the table
- entries nonlinearly, with the relationship between the table index i
- and the temperature T as follows:
- i = ((T-Draper)/spacing)^(1/xpower)
- T = pow(i, xpower) * spacing + Draper
- And furthermore, we store in the table the true value raised ^(1/5).
- I tuned this a bit, and with the current values we can have all
- blackbody results accurate to within 0.1% with a table size of 317
- (about 5 KB of data).
- */
-
- const float cie_colour_match[81][3] = {
- {0.0014f,0.0000f,0.0065f}, {0.0022f,0.0001f,0.0105f}, {0.0042f,0.0001f,0.0201f},
- {0.0076f,0.0002f,0.0362f}, {0.0143f,0.0004f,0.0679f}, {0.0232f,0.0006f,0.1102f},
- {0.0435f,0.0012f,0.2074f}, {0.0776f,0.0022f,0.3713f}, {0.1344f,0.0040f,0.6456f},
- {0.2148f,0.0073f,1.0391f}, {0.2839f,0.0116f,1.3856f}, {0.3285f,0.0168f,1.6230f},
- {0.3483f,0.0230f,1.7471f}, {0.3481f,0.0298f,1.7826f}, {0.3362f,0.0380f,1.7721f},
- {0.3187f,0.0480f,1.7441f}, {0.2908f,0.0600f,1.6692f}, {0.2511f,0.0739f,1.5281f},
- {0.1954f,0.0910f,1.2876f}, {0.1421f,0.1126f,1.0419f}, {0.0956f,0.1390f,0.8130f},
- {0.0580f,0.1693f,0.6162f}, {0.0320f,0.2080f,0.4652f}, {0.0147f,0.2586f,0.3533f},
- {0.0049f,0.3230f,0.2720f}, {0.0024f,0.4073f,0.2123f}, {0.0093f,0.5030f,0.1582f},
- {0.0291f,0.6082f,0.1117f}, {0.0633f,0.7100f,0.0782f}, {0.1096f,0.7932f,0.0573f},
- {0.1655f,0.8620f,0.0422f}, {0.2257f,0.9149f,0.0298f}, {0.2904f,0.9540f,0.0203f},
- {0.3597f,0.9803f,0.0134f}, {0.4334f,0.9950f,0.0087f}, {0.5121f,1.0000f,0.0057f},
- {0.5945f,0.9950f,0.0039f}, {0.6784f,0.9786f,0.0027f}, {0.7621f,0.9520f,0.0021f},
- {0.8425f,0.9154f,0.0018f}, {0.9163f,0.8700f,0.0017f}, {0.9786f,0.8163f,0.0014f},
- {1.0263f,0.7570f,0.0011f}, {1.0567f,0.6949f,0.0010f}, {1.0622f,0.6310f,0.0008f},
- {1.0456f,0.5668f,0.0006f}, {1.0026f,0.5030f,0.0003f}, {0.9384f,0.4412f,0.0002f},
- {0.8544f,0.3810f,0.0002f}, {0.7514f,0.3210f,0.0001f}, {0.6424f,0.2650f,0.0000f},
- {0.5419f,0.2170f,0.0000f}, {0.4479f,0.1750f,0.0000f}, {0.3608f,0.1382f,0.0000f},
- {0.2835f,0.1070f,0.0000f}, {0.2187f,0.0816f,0.0000f}, {0.1649f,0.0610f,0.0000f},
- {0.1212f,0.0446f,0.0000f}, {0.0874f,0.0320f,0.0000f}, {0.0636f,0.0232f,0.0000f},
- {0.0468f,0.0170f,0.0000f}, {0.0329f,0.0119f,0.0000f}, {0.0227f,0.0082f,0.0000f},
- {0.0158f,0.0057f,0.0000f}, {0.0114f,0.0041f,0.0000f}, {0.0081f,0.0029f,0.0000f},
- {0.0058f,0.0021f,0.0000f}, {0.0041f,0.0015f,0.0000f}, {0.0029f,0.0010f,0.0000f},
- {0.0020f,0.0007f,0.0000f}, {0.0014f,0.0005f,0.0000f}, {0.0010f,0.0004f,0.0000f},
- {0.0007f,0.0002f,0.0000f}, {0.0005f,0.0002f,0.0000f}, {0.0003f,0.0001f,0.0000f},
- {0.0002f,0.0001f,0.0000f}, {0.0002f,0.0001f,0.0000f}, {0.0001f,0.0000f,0.0000f},
- {0.0001f,0.0000f,0.0000f}, {0.0001f,0.0000f,0.0000f}, {0.0000f,0.0000f,0.0000f}
- };
-
- const double c1 = 3.74183e-16; // 2*pi*h*c^2, W*m^2
- const double c2 = 1.4388e-2; // h*c/k, m*K
- // h is Planck's const, k is Boltzmann's
- const float dlambda = 5.0f * 1e-9f; // in meters
-
- /* Blackbody table from 800 to 12k Kelvin (319 entries (317+2 offset) * 3) */
- vector<float> blackbody_table(956);
-
- float X, Y, Z;
-
- /* ToDo: bring this back to what OSL does with the lastTemperature limit ? */
- for (int i = 0; i <= 317; ++i) {
- double Temperature = pow((double)i, (double)BB_TABLE_XPOWER) * (double)BB_TABLE_SPACING + (double)BB_DRAPER;
- X = 0;
- Y = 0;
- Z = 0;
-
- /* from OSL "spectrum_to_XYZ" */
- for (int n = 0; n < 81; ++n) {
- float lambda = 380.0f + 5.0f * n;
- double wlm = lambda * 1e-9f; // Wavelength in meters
- // N.B. spec_intens returns result in W/m^2 but it's a differential,
- // needs to be scaled by dlambda!
- float spec_intens = float((c1 * pow(wlm, -5.0)) / (exp(c2 / (wlm * Temperature)) -1.0));
- float Me = spec_intens * dlambda;
-
- X += Me * cie_colour_match[n][0];
- Y += Me * cie_colour_match[n][1];
- Z += Me * cie_colour_match[n][2];
- }
-
- /* Convert from xyz color space */
- float3 col = xyz_to_rgb(X, Y, Z);
-
- /* Clamp to zero if values are smaller */
- col = max(col, make_float3(0.0f, 0.0f, 0.0f));
-
- col.x = powf(col.x, 1.0f / BB_TABLE_YPOWER);
- col.y = powf(col.y, 1.0f / BB_TABLE_YPOWER);
- col.z = powf(col.z, 1.0f / BB_TABLE_YPOWER);
-
- /* Store in table in RRRGGGBBB format */
- blackbody_table[i] = col.x;
- blackbody_table[i+319*1] = col.y;
- blackbody_table[i+319*2] = col.z;
- }
-
- return blackbody_table;
-}
-CCL_NAMESPACE_END
diff --git a/intern/cycles/render/blackbody.h b/intern/cycles/render/blackbody.h
deleted file mode 100644
index 6b752a227fa..00000000000
--- a/intern/cycles/render/blackbody.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __BLACKBODY_H__
-#define __BLACKBODY_H__
-
-#include "util_vector.h"
-
-CCL_NAMESPACE_BEGIN
-
-vector<float> blackbody_table_build();
-
-CCL_NAMESPACE_END
-
-#endif /* __BLACKBODY_H__ */
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 5202bf5862c..fab3f701757 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -187,7 +187,7 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
else if(type == PASS_MIST) {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
float f = *in;
- pixels[0] = clamp(f*scale_exposure, 0.0f, 1.0f);
+ pixels[0] = saturate(f*scale_exposure);
}
}
#ifdef WITH_CYCLES_DEBUG
@@ -197,6 +197,12 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
pixels[0] = f;
}
}
+ else if(type == PASS_RAY_BOUNCES) {
+ for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f;
+ }
+ }
#endif
else {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
@@ -298,7 +304,7 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
pixels[2] = f.z*scale_exposure;
/* clamp since alpha might be > 1.0 due to russian roulette */
- pixels[3] = clamp(f.w*scale, 0.0f, 1.0f);
+ pixels[3] = saturate(f.w*scale);
}
}
}
@@ -369,13 +375,9 @@ void DisplayBuffer::draw_set(int width, int height)
void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
{
if(draw_width != 0 && draw_height != 0) {
- glPushMatrix();
- glTranslatef(params.full_x, params.full_y, 0.0f);
device_memory& rgba = rgba_data();
- device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent, draw_params);
-
- glPopMatrix();
+ device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params);
}
}
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index ea9b853d454..89505221862 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -80,6 +80,7 @@ Camera::Camera()
need_update = true;
need_device_update = true;
+ need_flags_update = true;
previous_need_motion = -1;
}
@@ -162,8 +163,8 @@ void Camera::update()
transform_perspective(&rastertocamera, make_float3(0, 0, 0));
}
else {
- dx = make_float3(0, 0, 0);
- dy = make_float3(0, 0, 0);
+ dx = make_float3(0.0f, 0.0f, 0.0f);
+ dy = make_float3(0.0f, 0.0f, 0.0f);
}
dx = transform_direction(&cameratoworld, dx);
@@ -171,6 +172,7 @@ void Camera::update()
need_update = false;
need_device_update = true;
+ need_flags_update = true;
}
void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
@@ -179,7 +181,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
update();
- if (previous_need_motion != need_motion) {
+ if(previous_need_motion != need_motion) {
/* scene's motion model could have been changed since previous device
* camera update this could happen for example in case when one render
* layer has got motion pass and another not */
@@ -284,11 +286,11 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
previous_need_motion = need_motion;
}
-void Camera::device_update_volume(Device *device,
+void Camera::device_update_volume(Device * /*device*/,
DeviceScene *dscene,
Scene *scene)
{
- if(!need_device_update) {
+ if(!need_device_update && !need_flags_update) {
return;
}
KernelCamera *kcam = &dscene->data.cam;
@@ -304,9 +306,10 @@ void Camera::device_update_volume(Device *device,
}
}
need_device_update = false;
+ need_flags_update = false;
}
-void Camera::device_free(Device *device, DeviceScene *dscene)
+void Camera::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
/* nothing to free, only writing to constant memory */
}
@@ -368,7 +371,7 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
*/
P += nearclip * D / Pclip.z;
}
- else if (type == CAMERA_ORTHOGRAPHIC) {
+ else if(type == CAMERA_ORTHOGRAPHIC) {
D = make_float3(0.0f, 0.0f, 1.0f);
/* TODO(sergey): Aperture support? */
P = transform_perspective(&rastertocamera,
@@ -400,7 +403,7 @@ BoundBox Camera::viewplane_bounds_get()
bounds.grow(transform_raster_to_world((float)width, (float)height));
bounds.grow(transform_raster_to_world((float)width, 0.0f));
if(type == CAMERA_PERSPECTIVE) {
- /* Center point has the most distancei in local Z axis,
+ /* Center point has the most distance in local Z axis,
* use it to construct bounding box/
*/
bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
@@ -409,15 +412,4 @@ BoundBox Camera::viewplane_bounds_get()
return bounds;
}
-Transform Camera::transform_from_viewplane(BoundBox2D &viewplane)
-{
- return
- transform_scale(1.0f / (viewplane.right - viewplane.left),
- 1.0f / (viewplane.top - viewplane.bottom),
- 1.0f) *
- transform_translate(-viewplane.left,
- -viewplane.bottom,
- 0.0f);
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index e1faee3543d..3efbe904e2f 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -105,6 +105,7 @@ public:
/* update */
bool need_update;
bool need_device_update;
+ bool need_flags_update;
int previous_need_motion;
/* functions */
@@ -123,9 +124,12 @@ public:
bool motion_modified(const Camera& cam);
void tag_update();
+ /* Public utility functions. */
BoundBox viewplane_bounds_get();
+
+private:
+ /* Private utility functions. */
float3 transform_raster_to_world(float raster_x, float raster_y);
- Transform transform_from_viewplane(BoundBox2D &viewplane);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index 80dc6434cde..f671eb19cae 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -103,7 +103,10 @@ CurveSystemManager::~CurveSystemManager()
{
}
-void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void CurveSystemManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene * /*scene*/,
+ Progress& progress)
{
if(!need_update)
return;
@@ -144,7 +147,8 @@ void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scen
need_update = false;
}
-void CurveSystemManager::device_free(Device *device, DeviceScene *dscene)
+void CurveSystemManager::device_free(Device * /*device*/,
+ DeviceScene * /*dscene*/)
{
}
@@ -174,7 +178,7 @@ bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemMana
use_curves == CurveSystemManager.use_curves);
}
-void CurveSystemManager::tag_update(Scene *scene)
+void CurveSystemManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index c6d12928dd4..7282b04a22e 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -151,6 +151,14 @@ void Pass::add(PassType type, vector<Pass>& passes)
pass.components = 1;
pass.exposure = false;
break;
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
+ case PASS_RAY_BOUNCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
#endif
}
@@ -187,7 +195,7 @@ bool Pass::contains(const vector<Pass>& passes, PassType type)
/* Pixel Filter */
-static float filter_func_box(float v, float width)
+static float filter_func_box(float /*v*/, float /*width*/)
{
return 1.0f;
}
@@ -399,6 +407,12 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
case PASS_BVH_TRAVERSAL_STEPS:
kfilm->pass_bvh_traversal_steps = kfilm->pass_stride;
break;
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
+ break;
+ case PASS_RAY_BOUNCES:
+ kfilm->pass_ray_bounces = kfilm->pass_stride;
+ break;
#endif
case PASS_NONE:
@@ -424,7 +438,9 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
need_update = false;
}
-void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene)
+void Film::device_free(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene *scene)
{
if(filter_table_offset != TABLE_OFFSET_INVALID) {
scene->lookup_tables->remove_table(filter_table_offset);
@@ -459,7 +475,7 @@ void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
passes = passes_;
}
-void Film::tag_update(Scene *scene)
+void Film::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 9896eaba89b..e0537101247 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -33,7 +33,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp
name = name_;
type = type_;
link = NULL;
- value = make_float3(0, 0, 0);
+ value = make_float3(0.0f, 0.0f, 0.0f);
stack_offset = SVM_STACK_INVALID;
default_value = NONE;
usage = USE_ALL;
@@ -404,6 +404,36 @@ void ShaderGraph::remove_unneeded_nodes()
}
}
}
+ else if(node->special_type == SHADER_SPECIAL_TYPE_EMISSION) {
+ EmissionNode *em = static_cast<EmissionNode*>(node);
+
+ if(em->outputs[0]->links.size()) {
+ /* Black color or zero strength, remove node */
+ if((!em->inputs[0]->link && em->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!em->inputs[1]->link && em->inputs[1]->value.x == 0.0f)) {
+ vector<ShaderInput*> inputs = em->outputs[0]->links;
+
+ relink(em->inputs, inputs, NULL);
+ removed[em->id] = true;
+ any_node_removed = true;
+ }
+ }
+ }
+ else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
+ BumpNode *bump = static_cast<BumpNode*>(node);
+
+ if(bump->outputs[0]->links.size()) {
+ /* Height input not connected */
+ /* ToDo: Strength zero? */
+ if(!bump->inputs[0]->link) {
+ vector<ShaderInput*> inputs = bump->outputs[0]->links;
+
+ relink(bump->inputs, inputs, NULL);
+ removed[bump->id] = true;
+ any_node_removed = true;
+ }
+ }
+ }
else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
MixClosureNode *mix = static_cast<MixClosureNode*>(node);
@@ -545,7 +575,7 @@ void ShaderGraph::clean()
else
delete node;
}
-
+
nodes = newnodes;
}
@@ -727,10 +757,18 @@ void ShaderGraph::bump_from_displacement()
/* connect bump output to normal input nodes that aren't set yet. actually
* this will only set the normal input to the geometry node that we created
* and connected to all other normal inputs already. */
- foreach(ShaderNode *node, nodes)
- foreach(ShaderInput *input, node->inputs)
+ foreach(ShaderNode *node, nodes) {
+ /* Don't connect normal to the bump node we're coming from,
+ * otherwise it'll be a cycle in graph.
+ */
+ if(node == bump) {
+ continue;
+ }
+ foreach(ShaderInput *input, node->inputs) {
if(!input->link && input->default_value == ShaderInput::NORMAL)
connect(set_normal->output("Normal"), input);
+ }
+ }
/* for displacement bump, clear the normal input in case the above loop
* connected the setnormal out to the bump normalin */
@@ -825,6 +863,26 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
}
}
+int ShaderGraph::get_num_closures()
+{
+ int num_closures = 0;
+ foreach(ShaderNode *node, nodes) {
+ if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfNode *bsdf_node = static_cast<BsdfNode*>(node);
+ /* TODO(sergey): Make it more generic approach, maybe some utility
+ * macros like CLOSURE_IS_FOO()?
+ */
+ if(CLOSURE_IS_BSSRDF(bsdf_node->closure))
+ num_closures = num_closures + 3;
+ else if(CLOSURE_IS_GLASS(bsdf_node->closure))
+ num_closures = num_closures + 2;
+ else
+ num_closures = num_closures + 1;
+ }
+ }
+ return num_closures;
+}
+
void ShaderGraph::dump_graph(const char *filename)
{
FILE *fd = fopen(filename, "w");
@@ -836,29 +894,59 @@ void ShaderGraph::dump_graph(const char *filename)
fprintf(fd, "digraph shader_graph {\n");
fprintf(fd, "ranksep=1.5\n");
+ fprintf(fd, "rankdir=LR\n");
fprintf(fd, "splines=false\n");
foreach(ShaderNode *node, nodes) {
fprintf(fd, "// NODE: %p\n", node);
- fprintf(fd,
- "\"%p\" [shape=record,label=\"%s\"]\n",
- node,
- node->name.c_str());
+ fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
+ if(node->inputs.size()) {
+ fprintf(fd, "{");
+ foreach(ShaderInput *socket, node->inputs) {
+ if(socket != node->inputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<IN_%p>%s", socket, socket->name);
+ }
+ fprintf(fd, "}|");
+ }
+ fprintf(fd, "%s", node->name.c_str());
+ if(node->bump == SHADER_BUMP_CENTER) {
+ fprintf(fd, " (bump:center)");
+ }
+ else if(node->bump == SHADER_BUMP_DX) {
+ fprintf(fd, " (bump:dx)");
+ }
+ else if(node->bump == SHADER_BUMP_DY) {
+ fprintf(fd, " (bump:dy)");
+ }
+ if(node->outputs.size()) {
+ fprintf(fd, "|{");
+ foreach(ShaderOutput *socket, node->outputs) {
+ if(socket != node->outputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<OUT_%p>%s", socket, socket->name);
+ }
+ fprintf(fd, "}");
+ }
+ fprintf(fd, "}\"]");
}
foreach(ShaderNode *node, nodes) {
foreach(ShaderOutput *output, node->outputs) {
foreach(ShaderInput *input, output->links) {
fprintf(fd,
- "// CONNECTION: %p->%p (%s:%s)\n",
+ "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
output,
input,
output->name, input->name);
fprintf(fd,
- "\"%p\":s -> \"%p\":n [label=\"%s:%s\"]\n",
+ "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
output->parent,
+ output,
input->parent,
- output->name, input->name);
+ input);
}
}
}
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index b39b3dae324..9117fd03a95 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -81,6 +81,10 @@ enum ShaderNodeSpecialType {
SHADER_SPECIAL_TYPE_GEOMETRY,
SHADER_SPECIAL_TYPE_SCRIPT,
SHADER_SPECIAL_TYPE_BACKGROUND,
+ SHADER_SPECIAL_TYPE_IMAGE_SLOT,
+ SHADER_SPECIAL_TYPE_CLOSURE,
+ SHADER_SPECIAL_TYPE_EMISSION,
+ SHADER_SPECIAL_TYPE_BUMP,
};
/* Enum
@@ -193,7 +197,6 @@ public:
virtual bool has_surface_emission() { return false; }
virtual bool has_surface_transparent() { return false; }
virtual bool has_surface_bssrdf() { return false; }
- virtual bool has_converter_blackbody() { return false; }
virtual bool has_bssrdf_bump() { return false; }
virtual bool has_spatial_varying() { return false; }
virtual bool has_object_dependency() { return false; }
@@ -206,6 +209,24 @@ public:
ShaderBump bump; /* for bump mapping utility */
ShaderNodeSpecialType special_type; /* special node type */
+
+ /* ** Selective nodes compilation ** */
+
+ /* TODO(sergey): More explicitly mention in the function names
+ * that those functions are for selective compilation only?
+ */
+
+ /* Nodes are split into several groups, group of level 0 contains
+ * nodes which are most commonly used, further levels are extension
+ * of previous one and includes less commonly used nodes.
+ */
+ virtual int get_group() { return NODE_GROUP_LEVEL_0; }
+
+ /* Node feature are used to disable huge nodes inside the group,
+ * so it's possible to disable huge nodes inside of the required
+ * nodes group.
+ */
+ virtual int get_feature() { return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP; }
};
@@ -253,6 +274,8 @@ public:
void remove_unneeded_nodes();
void finalize(bool do_bump = false, bool do_osl = false);
+ int get_num_closures();
+
void dump_graph(const char *filename);
protected:
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 61a0a81d51d..c62afcd7719 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -407,7 +407,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
int scanlinesize = width*components*sizeof(uchar);
in->read_image(TypeDesc::UINT8,
- (uchar*)pixels + (height-1)*scanlinesize,
+ (uchar*)pixels + (((size_t)height)-1)*scanlinesize,
AutoStride,
-scanlinesize,
AutoStride);
@@ -425,9 +425,10 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
builtin_image_pixels_cb(img->filename, img->builtin_data, pixels);
}
+ size_t num_pixels = ((size_t)width) * height * depth;
if(cmyk) {
/* CMYK */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
@@ -436,7 +437,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
else if(components == 2) {
/* grayscale + alpha */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = pixels[i*2+1];
pixels[i*4+2] = pixels[i*2+0];
pixels[i*4+1] = pixels[i*2+0];
@@ -445,7 +446,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
else if(components == 3) {
/* RGB */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
pixels[i*4+2] = pixels[i*3+2];
pixels[i*4+1] = pixels[i*3+1];
@@ -454,7 +455,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
else if(components == 1) {
/* grayscale */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
pixels[i*4+2] = pixels[i];
pixels[i*4+1] = pixels[i];
@@ -463,7 +464,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
}
if(img->use_alpha == false) {
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
}
}
@@ -529,7 +530,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
vector<float> tmppixels;
if(components > 4) {
- tmppixels.resize(width*height*components);
+ tmppixels.resize(((size_t)width)*height*components);
readpixels = &tmppixels[0];
}
@@ -547,7 +548,8 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
if(components > 4) {
- for(int i = width*height-1; i >= 0; i--) {
+ size_t dimensions = ((size_t)width)*height;
+ for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
pixels[i*4+3] = tmppixels[i*components+3];
pixels[i*4+2] = tmppixels[i*components+2];
pixels[i*4+1] = tmppixels[i*components+1];
@@ -566,9 +568,10 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
}
+ size_t num_pixels = ((size_t)width) * height * depth;
if(cmyk) {
/* CMYK */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 255;
pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
@@ -577,7 +580,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
else if(components == 2) {
/* grayscale + alpha */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = pixels[i*2+1];
pixels[i*4+2] = pixels[i*2+0];
pixels[i*4+1] = pixels[i*2+0];
@@ -586,7 +589,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
else if(components == 3) {
/* RGB */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 1.0f;
pixels[i*4+2] = pixels[i*3+2];
pixels[i*4+1] = pixels[i*3+1];
@@ -595,7 +598,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
else if(components == 1) {
/* grayscale */
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 1.0f;
pixels[i*4+2] = pixels[i];
pixels[i*4+1] = pixels[i];
@@ -604,7 +607,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
}
if(img->use_alpha == false) {
- for(int i = width*height*depth-1; i >= 0; i--) {
+ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i*4+3] = 1.0f;
}
}
@@ -791,7 +794,36 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
need_update = false;
}
-void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& progess)
+void ImageManager::device_update_slot(Device *device,
+ DeviceScene *dscene,
+ int slot,
+ Progress *progress)
+{
+ Image *image;
+ if(slot >= tex_image_byte_start) {
+ int byte_slot = slot - tex_image_byte_start;
+ assert(images[byte_slot] != NULL);
+ image = images[byte_slot];
+ }
+ else {
+ assert(float_images[slot] != NULL);
+ image = float_images[slot];
+ }
+ if(image->users == 0) {
+ device_free_image(device, dscene, slot);
+ }
+ else if(image->need_load) {
+ if(!osl_texture_system || float_images[slot]->builtin_data)
+ device_load_image(device,
+ dscene,
+ slot,
+ progress);
+ }
+}
+
+void ImageManager::device_pack_images(Device *device,
+ DeviceScene *dscene,
+ Progress& /*progess*/)
{
/* for OpenCL, we pack all image textures inside a single big texture, and
* will do our own interpolation in the kernel */
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 2f5dcb6efd5..70cc4935daa 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -63,6 +63,7 @@ public:
bool is_float_image(const string& filename, void *builtin_data, bool& is_linear);
void device_update(Device *device, DeviceScene *dscene, Progress& progress);
+ void device_update_slot(Device *device, DeviceScene *dscene, int slot, Progress *progress);
void device_free(Device *device, DeviceScene *dscene);
void device_free_builtin(Device *device, DeviceScene *dscene);
@@ -73,9 +74,9 @@ public:
bool need_update;
- boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb;
- boost::function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb;
- boost::function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb;
+ function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb;
+ function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb;
+ function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb;
struct Image {
string filename;
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 17c50ca826f..465d7ea02c6 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -216,7 +216,7 @@ bool Integrator::modified(const Integrator& integrator)
sample_all_lights_indirect == integrator.sample_all_lights_indirect);
}
-void Integrator::tag_update(Scene *scene)
+void Integrator::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index b6c7b379a7e..4e962616263 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -129,6 +129,8 @@ Light::Light()
shader = 0;
samples = 1;
max_bounces = 1024;
+
+ is_portal = false;
}
void Light::tag_update(Scene *scene)
@@ -136,6 +138,17 @@ void Light::tag_update(Scene *scene)
scene->light_manager->need_update = true;
}
+bool Light::has_contribution(Scene *scene)
+{
+ if(is_portal) {
+ return false;
+ }
+ if(type == LIGHT_BACKGROUND) {
+ return true;
+ }
+ return scene->shaders[shader]->has_surface_emission;
+}
+
/* Light Manager */
LightManager::LightManager()
@@ -153,10 +166,17 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
progress.set_status("Updating Lights", "Computing distribution");
/* count */
- size_t num_lights = scene->lights.size();
+ size_t num_lights = 0;
size_t num_background_lights = 0;
size_t num_triangles = 0;
+ bool background_mis = false;
+
+ foreach(Light *light, scene->lights) {
+ if(light->has_contribution(scene))
+ num_lights++;
+ }
+
foreach(Object *object, scene->objects) {
Mesh *mesh = object->mesh;
bool have_emission = false;
@@ -287,22 +307,29 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
float trianglearea = totarea;
/* point lights */
- float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
+ float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
bool use_lamp_mis = false;
- for(int i = 0; i < scene->lights.size(); i++, offset++) {
- Light *light = scene->lights[i];
+ int light_index = 0;
+ foreach(Light *light, scene->lights) {
+ if(!light->has_contribution(scene))
+ continue;
distribution[offset].x = totarea;
- distribution[offset].y = __int_as_float(~(int)i);
+ distribution[offset].y = __int_as_float(~light_index);
distribution[offset].z = 1.0f;
distribution[offset].w = light->size;
totarea += lightarea;
if(light->size > 0.0f && light->use_mis)
use_lamp_mis = true;
- if(light->type == LIGHT_BACKGROUND)
+ if(light->type == LIGHT_BACKGROUND) {
num_background_lights++;
+ background_mis = light->use_mis;
+ }
+
+ light_index++;
+ offset++;
}
/* normalize cumulative distribution functions */
@@ -364,6 +391,18 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* CDF */
device->tex_alloc("__light_distribution", dscene->light_distribution);
+
+ /* Portals */
+ if(num_background_lights > 0 && light_index != scene->lights.size()) {
+ kintegrator->portal_offset = light_index;
+ kintegrator->num_portals = scene->lights.size() - light_index;
+ kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
+ }
+ else {
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+ }
}
else {
dscene->light_distribution.clear();
@@ -374,6 +413,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
kintegrator->pdf_lights = 0.0f;
kintegrator->inv_pdf_lights = 0.0f;
kintegrator->use_lamp_mis = false;
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+
kfilm->pass_shadow_scale = 1.0f;
}
}
@@ -389,16 +432,16 @@ static void background_cdf(int start,
for(int i = start; i < end; i++) {
float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
float3 env_color = (*pixels)[i * res];
- float ave_luminamce = average(env_color);
+ float ave_luminance = average(env_color);
- cond_cdf[i * cdf_count].x = ave_luminamce * sin_theta;
+ cond_cdf[i * cdf_count].x = ave_luminance * sin_theta;
cond_cdf[i * cdf_count].y = 0.0f;
for(int j = 1; j < res; j++) {
env_color = (*pixels)[i * res + j];
- ave_luminamce = average(env_color);
+ ave_luminance = average(env_color);
- cond_cdf[i * cdf_count + j].x = ave_luminamce * sin_theta;
+ cond_cdf[i * cdf_count + j].x = ave_luminance * sin_theta;
cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
}
@@ -513,10 +556,8 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(scene->lights.size() == 0)
return;
- float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
-
- if(!device->info.advanced_shading) {
- /* remove unsupported light */
+ /* remove background light? */
+ if(!(device->info.advanced_shading)) {
foreach(Light *light, scene->lights) {
if(light->type == LIGHT_BACKGROUND) {
scene->lights.erase(std::remove(scene->lights.begin(), scene->lights.end(), light), scene->lights.end());
@@ -525,10 +566,16 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
}
}
- for(size_t i = 0; i < scene->lights.size(); i++) {
- Light *light = scene->lights[i];
+ float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
+ int light_index = 0;
+
+ foreach(Light *light, scene->lights) {
+ if(!light->has_contribution(scene)) {
+ continue;
+ }
+
float3 co = light->co;
- int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
+ int shader_id = scene->shader_manager->get_shader_id(light->shader);
float samples = __int_as_float(light->samples);
float max_bounces = __int_as_float(light->max_bounces);
@@ -561,11 +608,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
- light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -582,11 +629,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
- light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_BACKGROUND) {
uint visibility = scene->background->visibility;
@@ -611,11 +658,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
use_light_visibility = true;
}
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_AREA) {
float3 axisu = light->axisu*(light->sizeu*light->size);
@@ -629,11 +676,11 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
- light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
- light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -649,19 +696,52 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
- light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
- light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
- light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
+
+ light_index++;
+ }
+
+ /* TODO(sergey): Consider moving portals update to their own function
+ * keeping this one more manageable.
+ */
+ foreach(Light *light, scene->lights) {
+ if(!light->is_portal)
+ continue;
+ assert(light->type == LIGHT_AREA);
+
+ float3 co = light->co;
+ float3 axisu = light->axisu*(light->sizeu*light->size);
+ float3 axisv = light->axisv*(light->sizev*light->size);
+ float area = len(axisu)*len(axisv);
+ float invarea = (area > 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+ light_data[light_index*LIGHT_SIZE + 1] = make_float4(area, axisu.x, axisu.y, axisu.z);
+ light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
+ light_data[light_index*LIGHT_SIZE + 3] = make_float4(-1, dir.x, dir.y, dir.z);
+ light_data[light_index*LIGHT_SIZE + 4] = make_float4(-1, 0.0f, 0.0f, 0.0f);
+
+ light_index++;
}
-
+
+ VLOG(1) << "Number of lights without contribution: "
+ << scene->lights.size() - light_index;
+
device->tex_alloc("__light_data", dscene->light_data);
}
void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->lights.size() << " lights.";
+
if(!need_update)
return;
@@ -699,7 +779,7 @@ void LightManager::device_free(Device *device, DeviceScene *dscene)
dscene->light_background_conditional_cdf.clear();
}
-void LightManager::tag_update(Scene *scene)
+void LightManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 1f8eac6a97f..afec3628dda 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -56,11 +56,16 @@ public:
bool use_transmission;
bool use_scatter;
+ bool is_portal;
+
int shader;
int samples;
int max_bounces;
void tag_update(Scene *scene);
+
+ /* Check whether the light has contribution the the scene. */
+ bool has_contribution(Scene *scene);
};
class LightManager {
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 9c7310d4a05..45685fe5927 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -20,9 +20,11 @@
#include "camera.h"
#include "curves.h"
#include "device.h"
+#include "graph.h"
#include "shader.h"
#include "light.h"
#include "mesh.h"
+#include "nodes.h"
#include "object.h"
#include "scene.h"
@@ -135,7 +137,7 @@ void Mesh::clear()
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
- geometry_synced = false;
+ geometry_flags = GEOMETRY_NONE;
}
int Mesh::split_vertex(int vertex)
@@ -210,11 +212,11 @@ void Mesh::compute_bounds()
bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w);
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (use_motion_blur && attr) {
+ if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow(vert_steps[i]);
}
@@ -223,7 +225,7 @@ void Mesh::compute_bounds()
size_t steps_size = curve_keys.size() * (motion_steps - 1);
float3 *key_steps = curve_attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow(key_steps[i]);
}
@@ -237,19 +239,19 @@ void Mesh::compute_bounds()
for(size_t i = 0; i < curve_keys_size; i++)
bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w);
- if (use_motion_blur && attr) {
+ if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow_safe(vert_steps[i]);
}
- if (use_motion_blur && curve_attr) {
+ if(use_motion_blur && curve_attr) {
size_t steps_size = curve_keys.size() * (motion_steps - 1);
float3 *key_steps = curve_attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
bnds.grow_safe(key_steps[i]);
}
}
@@ -653,6 +655,10 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
}
}
}
+#else
+ (void)device;
+ (void)scene;
+ (void)mesh_attributes;
#endif
}
@@ -1095,6 +1101,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size());
device->tex_alloc("__bvh_nodes", dscene->bvh_nodes);
}
+ if(pack.leaf_nodes.size()) {
+ dscene->bvh_leaf_nodes.reference((float4*)&pack.leaf_nodes[0], pack.leaf_nodes.size());
+ device->tex_alloc("__bvh_leaf_nodes", dscene->bvh_leaf_nodes);
+ }
if(pack.object_node.size()) {
dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size());
device->tex_alloc("__object_node", dscene->object_node);
@@ -1124,7 +1134,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
}
-void MeshManager::device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void MeshManager::device_update_flags(Device * /*device*/,
+ DeviceScene * /*dscene*/,
+ Scene * scene,
+ Progress& /*progress*/)
{
if(!need_update && !need_flags_update) {
return;
@@ -1141,8 +1154,59 @@ void MeshManager::device_update_flags(Device *device, DeviceScene *dscene, Scene
need_flags_update = false;
}
+void MeshManager::device_update_displacement_images(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress)
+{
+ progress.set_status("Updating Displacement Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> bump_images;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update) {
+ foreach(uint shader_index, mesh->used_shaders) {
+ Shader *shader = scene->shaders[shader_index];
+ if(shader->graph_bump == NULL) {
+ continue;
+ }
+ foreach(ShaderNode* node, shader->graph_bump->nodes) {
+ if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
+ continue;
+ }
+ if(device->info.pack_images) {
+ /* If device requires packed images we need to update all
+ * images now, even if they're not used for displacement.
+ */
+ image_manager->device_update(device,
+ dscene,
+ progress);
+ return;
+ }
+ ImageSlotNode *image_node = static_cast<ImageSlotNode*>(node);
+ int slot = image_node->slot;
+ if(slot != -1) {
+ bump_images.insert(slot);
+ }
+ }
+ }
+ }
+ }
+ foreach(int slot, bump_images) {
+ pool.push(function_bind(&ImageManager::device_update_slot,
+ image_manager,
+ device,
+ dscene,
+ slot,
+ &progress));
+ }
+ pool.wait_work();
+}
+
void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
+
if(!need_update)
return;
@@ -1161,6 +1225,28 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
}
+ /* Update images needed for true displacement. */
+ bool need_displacement_images = false;
+ bool old_need_object_flags_update = false;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update &&
+ mesh->displacement_method != Mesh::DISPLACE_BUMP)
+ {
+ need_displacement_images = true;
+ break;
+ }
+ }
+ if(need_displacement_images) {
+ VLOG(1) << "Updating images used for true displacement.";
+ device_update_displacement_images(device, dscene, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device,
+ dscene,
+ scene,
+ progress,
+ false);
+ }
+
/* device update */
device_free(device, dscene);
@@ -1208,7 +1294,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
&progress,
i,
num_bvh));
- i++;
+ if(!mesh->transform_applied) {
+ i++;
+ }
}
}
@@ -1233,11 +1321,22 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
device_update_bvh(device, dscene, scene, progress);
need_update = false;
+
+ if(need_displacement_images) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
}
void MeshManager::device_free(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->bvh_nodes);
+ device->tex_free(dscene->bvh_leaf_nodes);
device->tex_free(dscene->object_node);
device->tex_free(dscene->tri_woop);
device->tex_free(dscene->prim_type);
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 62e775e5bc9..76c186a3feb 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -71,8 +71,13 @@ public:
ustring name;
/* Mesh Data */
- bool geometry_synced; /* used to distinguish meshes with no verts
- and meshed for which geometry is not created */
+ enum GeometryFlags {
+ GEOMETRY_NONE = 0,
+ GEOMETRY_TRIANGLES = (1 << 0),
+ GEOMETRY_CURVES = (1 << 1),
+ };
+ int geometry_flags; /* used to distinguish meshes with no verts
+ and meshed for which geometry is not created */
vector<float3> verts;
vector<Triangle> triangles;
@@ -162,6 +167,7 @@ public:
void device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_displacement_images(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 7a39811cacd..69ae2078216 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -186,7 +186,7 @@ ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
ImageTextureNode::ImageTextureNode()
-: TextureNode("image_texture")
+: ImageSlotTextureNode("image_texture")
{
image_manager = NULL;
slot = -1;
@@ -227,7 +227,7 @@ void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attribute
#ifdef WITH_PTEX
/* todo: avoid loading other texture coordinates when using ptex,
* and hide texture coordinate socket in the UI */
- if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ if(shader->has_surface && string_endswith(filename, ".ptx")) {
/* ptex */
attributes->add(ATTR_STD_PTEX_FACE_ID);
attributes->add(ATTR_STD_PTEX_UV);
@@ -380,7 +380,7 @@ ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
EnvironmentTextureNode::EnvironmentTextureNode()
-: TextureNode("environment_texture")
+: ImageSlotTextureNode("environment_texture")
{
image_manager = NULL;
slot = -1;
@@ -417,7 +417,7 @@ ShaderNode *EnvironmentTextureNode::clone() const
void EnvironmentTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
#ifdef WITH_PTEX
- if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ if(shader->has_surface && string_endswith(filename, ".ptx")) {
/* ptex */
attributes->add(ATTR_STD_PTEX_FACE_ID);
attributes->add(ATTR_STD_PTEX_UV);
@@ -632,7 +632,7 @@ static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidi
sky_state = arhosek_xyz_skymodelstate_alloc_init(turbidity, ground_albedo, solarElevation);
/* Copy values from sky_state to SunSky */
- for (int i = 0; i < 9; ++i) {
+ for(int i = 0; i < 9; ++i) {
sunsky->config_x[i] = (float)sky_state->configs[0][i];
sunsky->config_y[i] = (float)sky_state->configs[1][i];
sunsky->config_z[i] = (float)sky_state->configs[2][i];
@@ -1507,11 +1507,11 @@ ProxyNode::ProxyNode(ShaderSocketType type_)
add_output("Output", type);
}
-void ProxyNode::compile(SVMCompiler& compiler)
+void ProxyNode::compile(SVMCompiler& /*compiler*/)
{
}
-void ProxyNode::compile(OSLCompiler& compiler)
+void ProxyNode::compile(OSLCompiler& /*compiler*/)
{
}
@@ -1520,6 +1520,8 @@ void ProxyNode::compile(OSLCompiler& compiler)
BsdfNode::BsdfNode(bool scattering_)
: ShaderNode("bsdf"), scattering(scattering_)
{
+ special_type = SHADER_SPECIAL_TYPE_CLOSURE;
+
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
@@ -1587,7 +1589,7 @@ void BsdfNode::compile(SVMCompiler& compiler)
compile(compiler, NULL, NULL);
}
-void BsdfNode::compile(OSLCompiler& compiler)
+void BsdfNode::compile(OSLCompiler& /*compiler*/)
{
assert(0);
}
@@ -1609,6 +1611,7 @@ ShaderEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init();
AnisotropicBsdfNode::AnisotropicBsdfNode()
{
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
distribution = ustring("GGX");
add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
@@ -1661,6 +1664,7 @@ ShaderEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init();
GlossyBsdfNode::GlossyBsdfNode()
{
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
distribution = ustring("GGX");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
@@ -1699,6 +1703,7 @@ ShaderEnum GlassBsdfNode::distribution_enum = glass_distribution_init();
GlassBsdfNode::GlassBsdfNode()
{
+ closure = CLOSURE_BSDF_SHARP_GLASS_ID;
distribution = ustring("Sharp");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
@@ -1738,6 +1743,7 @@ ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init(
RefractionBsdfNode::RefractionBsdfNode()
{
+ closure = CLOSURE_BSDF_REFRACTION_ID;
distribution = ustring("Sharp");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
@@ -1776,6 +1782,7 @@ ShaderEnum ToonBsdfNode::component_enum = toon_component_init();
ToonBsdfNode::ToonBsdfNode()
{
+ closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
component = ustring("Diffuse");
add_input("Size", SHADER_SOCKET_FLOAT, 0.5f);
@@ -1916,6 +1923,8 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump()
EmissionNode::EmissionNode()
: ShaderNode("emission")
{
+ special_type = SHADER_SPECIAL_TYPE_EMISSION;
+
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f);
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
@@ -2078,7 +2087,7 @@ void VolumeNode::compile(SVMCompiler& compiler)
compile(compiler, NULL, NULL);
}
-void VolumeNode::compile(OSLCompiler& compiler)
+void VolumeNode::compile(OSLCompiler& /*compiler*/)
{
assert(0);
}
@@ -2135,6 +2144,7 @@ ShaderEnum HairBsdfNode::component_enum = hair_component_init();
HairBsdfNode::HairBsdfNode()
{
+ closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
component = ustring("Reflection");
add_input("Offset", SHADER_SOCKET_FLOAT);
@@ -2248,10 +2258,15 @@ void GeometryNode::compile(SVMCompiler& compiler)
out = output("Pointiness");
if(!out->links.empty()) {
compiler.stack_assign(out);
- compiler.add_node(attr_node,
- ATTR_STD_POINTINESS,
- out->stack_offset,
- NODE_ATTR_FLOAT);
+ if(compiler.output_type() != SHADER_TYPE_VOLUME) {
+ compiler.add_node(attr_node,
+ ATTR_STD_POINTINESS,
+ out->stack_offset,
+ NODE_ATTR_FLOAT);
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), out->stack_offset);
+ }
}
}
@@ -2442,7 +2457,7 @@ void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
if(shader->has_surface) {
if(!from_dupli) {
if(!output("UV")->links.empty()) {
- if (attribute != "")
+ if(attribute != "")
attributes->add(attribute);
else
attributes->add(ATTR_STD_UV);
@@ -2475,7 +2490,7 @@ void UVMapNode::compile(SVMCompiler& compiler)
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, out->stack_offset);
}
else {
- if (attribute != "")
+ if(attribute != "")
attr = compiler.attribute(attribute);
else
attr = compiler.attribute(ATTR_STD_UV);
@@ -2916,7 +2931,7 @@ AddClosureNode::AddClosureNode()
add_output("Closure", SHADER_SOCKET_CLOSURE);
}
-void AddClosureNode::compile(SVMCompiler& compiler)
+void AddClosureNode::compile(SVMCompiler& /*compiler*/)
{
/* handled in the SVM compiler */
}
@@ -2939,7 +2954,7 @@ MixClosureNode::MixClosureNode()
add_output("Closure", SHADER_SOCKET_CLOSURE);
}
-void MixClosureNode::compile(SVMCompiler& compiler)
+void MixClosureNode::compile(SVMCompiler& /*compiler*/)
{
/* handled in the SVM compiler */
}
@@ -2977,7 +2992,7 @@ void MixClosureWeightNode::compile(SVMCompiler& compiler)
weight1_out->stack_offset, weight2_out->stack_offset));
}
-void MixClosureWeightNode::compile(OSLCompiler& compiler)
+void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/)
{
assert(0);
}
@@ -3647,9 +3662,17 @@ void BlackbodyNode::compile(SVMCompiler& compiler)
ShaderInput *temperature_in = input("Temperature");
ShaderOutput *color_out = output("Color");
- compiler.stack_assign(temperature_in);
compiler.stack_assign(color_out);
- compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset);
+
+ if(temperature_in->link == NULL) {
+ float3 color = svm_math_blackbody_color(temperature_in->value.x);
+ compiler.add_node(NODE_VALUE_V, color_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, color);
+ }
+ else {
+ compiler.stack_assign(temperature_in);
+ compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset);
+ }
}
void BlackbodyNode::compile(OSLCompiler& compiler)
@@ -3747,7 +3770,7 @@ void MathNode::compile(SVMCompiler& compiler)
value1_in->value.x,
value2_in->value.x);
if(use_clamp) {
- optimized_value = clamp(optimized_value, 0.0f, 1.0f);
+ optimized_value = saturate(optimized_value);
}
compiler.add_node(NODE_VALUE_F,
__float_as_int(optimized_value),
@@ -3911,6 +3934,8 @@ BumpNode::BumpNode()
{
invert = false;
+ special_type = SHADER_SPECIAL_TYPE_BUMP;
+
/* this input is used by the user, but after graph transform it is no longer
* used and moved to sampler center/x/y instead */
add_input("Height", SHADER_SOCKET_FLOAT);
@@ -3987,7 +4012,7 @@ void RGBCurvesNode::compile(OSLCompiler& compiler)
{
float ramp[RAMP_TABLE_SIZE][3];
- for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ for(int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp[i][0] = curves[i].x;
ramp[i][1] = curves[i].y;
ramp[i][2] = curves[i].z;
@@ -4025,7 +4050,7 @@ void VectorCurvesNode::compile(OSLCompiler& compiler)
{
float ramp[RAMP_TABLE_SIZE][3];
- for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ for(int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp[i][0] = curves[i].x;
ramp[i][1] = curves[i].y;
ramp[i][2] = curves[i].z;
@@ -4075,7 +4100,7 @@ void RGBRampNode::compile(OSLCompiler& compiler)
float ramp_color[RAMP_TABLE_SIZE][3];
float ramp_alpha[RAMP_TABLE_SIZE];
- for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
+ for(int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp_color[i][0] = ramp[i].x;
ramp_color[i][1] = ramp[i].y;
ramp_color[i][2] = ramp[i].z;
@@ -4122,7 +4147,7 @@ OSLScriptNode::OSLScriptNode()
special_type = SHADER_SPECIAL_TYPE_SCRIPT;
}
-void OSLScriptNode::compile(SVMCompiler& compiler)
+void OSLScriptNode::compile(SVMCompiler& /*compiler*/)
{
/* doesn't work for SVM, obviously ... */
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 0ec0fce512f..7ec20f0879b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -55,13 +55,28 @@ public:
/* Nodes */
+/* Any node which uses image manager's slot should be a subclass of this one. */
+class ImageSlotNode : public ShaderNode {
+public:
+ ImageSlotNode(const char *name_) : ShaderNode(name_) {
+ special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
+ }
+ int slot;
+};
+
class TextureNode : public ShaderNode {
public:
TextureNode(const char *name_) : ShaderNode(name_) {}
TextureMapping tex_mapping;
};
-class ImageTextureNode : public TextureNode {
+class ImageSlotTextureNode : public ImageSlotNode {
+public:
+ ImageSlotTextureNode(const char *name_) : ImageSlotNode(name_) {}
+ TextureMapping tex_mapping;
+};
+
+class ImageTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
~ImageTextureNode();
@@ -69,7 +84,6 @@ public:
void attributes(Shader *shader, AttributeRequestSet *attributes);
ImageManager *image_manager;
- int slot;
int is_float;
bool is_linear;
bool use_alpha;
@@ -85,15 +99,15 @@ public:
static ShaderEnum projection_enum;
};
-class EnvironmentTextureNode : public TextureNode {
+class EnvironmentTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
~EnvironmentTextureNode();
ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ImageManager *image_manager;
- int slot;
int is_float;
bool is_linear;
bool use_alpha;
@@ -111,6 +125,8 @@ class SkyTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(SkyTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
float3 sun_direction;
float turbidity;
float ground_albedo;
@@ -128,6 +144,8 @@ class GradientTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(GradientTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
};
@@ -141,6 +159,8 @@ class VoronoiTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(VoronoiTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring coloring;
static ShaderEnum coloring_enum;
@@ -150,6 +170,8 @@ class MusgraveTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(MusgraveTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
@@ -159,6 +181,8 @@ class WaveTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(WaveTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
};
@@ -167,12 +191,16 @@ class MagicTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(MagicTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
int depth;
};
class CheckerTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(CheckerTextureNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
class BrickTextureNode : public TextureNode {
@@ -181,11 +209,14 @@ public:
float offset, squash;
int offset_frequency, squash_frequency;
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
class MappingNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MappingNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
TextureMapping tex_mapping;
};
@@ -308,6 +339,7 @@ public:
class HoldoutNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HoldoutNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class AmbientOcclusionNode : public ShaderNode {
@@ -315,6 +347,7 @@ public:
SHADER_NODE_CLASS(AmbientOcclusionNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class VolumeNode : public ShaderNode {
@@ -322,6 +355,7 @@ public:
SHADER_NODE_CLASS(VolumeNode)
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2);
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ClosureType closure;
};
@@ -369,6 +403,7 @@ public:
SHADER_NODE_CLASS(UVMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring attribute;
bool from_dupli;
@@ -377,6 +412,7 @@ public:
class LightPathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LightPathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class LightFalloffNode : public ShaderNode {
@@ -388,12 +424,14 @@ public:
class ObjectInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ObjectInfoNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class ParticleInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ParticleInfoNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class HairInfoNode : public ShaderNode {
@@ -402,6 +440,10 @@ public:
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ virtual int get_feature() {
+ return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
+ }
};
class ValueNode : public ShaderNode {
@@ -436,12 +478,16 @@ public:
class InvertNode : public ShaderNode {
public:
SHADER_NODE_CLASS(InvertNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
bool use_clamp;
ustring type;
@@ -451,41 +497,55 @@ public:
class CombineRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineRGBNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class CombineHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineHSVNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class CombineXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineXYZNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class BrightContrastNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BrightContrastNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class SeparateRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateRGBNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class SeparateHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateHSVNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class SeparateXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateXYZNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class HSVNode : public ShaderNode {
@@ -512,18 +572,21 @@ class FresnelNode : public ShaderNode {
public:
SHADER_NODE_CLASS(FresnelNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class LayerWeightNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LayerWeightNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class WireframeNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WireframeNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
bool use_pixel_size;
};
@@ -531,18 +594,21 @@ public:
class WavelengthNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WavelengthNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
-
- bool has_converter_blackbody() { return true; }
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
bool use_clamp;
@@ -553,6 +619,7 @@ public:
class NormalNode : public ShaderNode {
public:
SHADER_NODE_CLASS(NormalNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
float3 direction;
};
@@ -560,6 +627,7 @@ public:
class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring type;
static ShaderEnum type_enum;
@@ -569,6 +637,8 @@ class VectorTransformNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorTransformNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
ustring type;
ustring convert_from;
ustring convert_to;
@@ -581,6 +651,9 @@ class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
bool has_spatial_varying() { return true; }
+ virtual int get_feature() {
+ return NODE_FEATURE_BUMP;
+ }
bool invert;
};
@@ -588,12 +661,18 @@ public:
class RGBCurvesNode : public ShaderNode {
public:
SHADER_NODE_CLASS(RGBCurvesNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
float4 curves[RAMP_TABLE_SIZE];
};
class VectorCurvesNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorCurvesNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
float4 curves[RAMP_TABLE_SIZE];
};
@@ -602,6 +681,7 @@ public:
SHADER_NODE_CLASS(RGBRampNode)
float4 ramp[RAMP_TABLE_SIZE];
bool interpolate;
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class SetNormalNode : public ShaderNode {
@@ -630,6 +710,7 @@ public:
SHADER_NODE_CLASS(NormalMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring space;
static ShaderEnum space_enum;
@@ -642,6 +723,7 @@ public:
SHADER_NODE_CLASS(TangentNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring direction_type;
static ShaderEnum direction_type_enum;
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 1225125b57e..4a57ac4dff1 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "camera.h"
#include "device.h"
#include "light.h"
#include "mesh.h"
@@ -23,6 +24,7 @@
#include "scene.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_progress.h"
#include "util_vector.h"
@@ -104,11 +106,11 @@ void Object::apply_transform(bool apply_to_motion)
if(apply_to_motion) {
Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (attr) {
+ if(attr) {
size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
float3 *vert_steps = attr->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
vert_steps[i] = transform_point(&tfm, vert_steps[i]);
}
@@ -119,7 +121,7 @@ void Object::apply_transform(bool apply_to_motion)
size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
float3 *normal_steps = attr_N->data_float3();
- for (size_t i = 0; i < steps_size; i++)
+ for(size_t i = 0; i < steps_size; i++)
normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
}
}
@@ -146,12 +148,12 @@ void Object::apply_transform(bool apply_to_motion)
if(apply_to_motion) {
Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if (curve_attr) {
+ if(curve_attr) {
/* apply transform to motion curve keys */
size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
float4 *key_steps = curve_attr->data_float4();
- for (size_t i = 0; i < steps_size; i++) {
+ for(size_t i = 0; i < steps_size; i++) {
float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
float radius = key_steps[i].w * scalar;
@@ -191,6 +193,7 @@ void Object::tag_update(Scene *scene)
}
}
+ scene->camera->need_flags_update = true;
scene->curve_system_manager->need_update = true;
scene->mesh_manager->need_update = true;
scene->object_manager->need_update = true;
@@ -377,6 +380,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->objects.size() << " objects.";
+
if(!need_update)
return;
@@ -402,8 +407,11 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
}
}
-void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene,
- Scene *scene, Progress& progress)
+void ObjectManager::device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& /*progress*/,
+ bool bounds_valid)
{
if(!need_update && !need_flags_update)
return;
@@ -418,9 +426,13 @@ void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene,
uint *object_flag = dscene->object_flag.get_data();
vector<Object *> volume_objects;
+ bool has_volume_objects = false;
foreach(Object *object, scene->objects) {
if(object->mesh->has_volume) {
- volume_objects.push_back(object);
+ if(bounds_valid) {
+ volume_objects.push_back(object);
+ }
+ has_volume_objects = true;
}
}
@@ -433,15 +445,23 @@ void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene,
object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
}
- foreach(Object *volume_object, volume_objects) {
- if(object == volume_object) {
- continue;
- }
- if(object->bounds.intersects(volume_object->bounds)) {
- object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
- break;
+ if(bounds_valid) {
+ foreach(Object *volume_object, volume_objects) {
+ if(object == volume_object) {
+ continue;
+ }
+ if(object->bounds.intersects(volume_object->bounds)) {
+ object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ break;
+ }
}
}
+ else if(has_volume_objects) {
+ /* Not really valid, but can't make more reliable in the case
+ * of bounds not being up to date.
+ */
+ object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ }
++object_index;
}
@@ -474,6 +494,7 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u
bool apply_to_motion = need_motion != Scene::MOTION_PASS;
#else
bool motion_blur = false;
+ bool apply_to_motion = false;
#endif
int i = 0;
bool have_instancing = false;
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index acc08a0e204..379d1748cdd 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -77,7 +77,11 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress);
- void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress,
+ bool bounds_valid = true);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 9d6f412d9ce..a02f91ad2cf 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -67,7 +67,7 @@ OSLShaderManager::~OSLShaderManager()
texture_system_free();
}
-void OSLShaderManager::reset(Scene *scene)
+void OSLShaderManager::reset(Scene * /*scene*/)
{
shading_system_free();
shading_system_init();
@@ -75,6 +75,8 @@ void OSLShaderManager::reset(Scene *scene)
void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+
if(!need_update)
return;
@@ -211,9 +213,9 @@ void OSLShaderManager::shading_system_init()
"__unused__",
"__unused__",
- "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
- "glossy_ancestor", /* PATH_RAY_GLOSSY_ANCESTOR */
- "bssrdf_ancestor", /* PATH_RAY_BSSRDF_ANCESTOR */
+ "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
+ "__unused__",
+ "__unused__",
"__unused__", /* PATH_RAY_SINGLE_PASS_DONE */
"volume_scatter", /* PATH_RAY_VOLUME_SCATTER */
};
@@ -414,7 +416,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
/* if output exists with the same name, add "In" suffix */
foreach(ShaderOutput *output, node->outputs) {
- if (strcmp(input->name, output->name)==0) {
+ if(strcmp(input->name, output->name)==0) {
sname += "In";
break;
}
@@ -434,7 +436,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
/* if input exists with the same name, add "Out" suffix */
foreach(ShaderInput *input, node->inputs) {
- if (strcmp(input->name, output->name)==0) {
+ if(strcmp(input->name, output->name)==0) {
sname += "Out";
break;
}
@@ -860,75 +862,75 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
#else
-void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
+void OSLCompiler::add(ShaderNode * /*node*/, const char * /*name*/, bool /*isfilepath*/)
{
}
-void OSLCompiler::parameter(const char *name, float f)
+void OSLCompiler::parameter(const char * /*name*/, float /*f*/)
{
}
-void OSLCompiler::parameter_color(const char *name, float3 f)
+void OSLCompiler::parameter_color(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter_vector(const char *name, float3 f)
+void OSLCompiler::parameter_vector(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter_point(const char *name, float3 f)
+void OSLCompiler::parameter_point(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter_normal(const char *name, float3 f)
+void OSLCompiler::parameter_normal(const char * /*name*/, float3 /*f*/)
{
}
-void OSLCompiler::parameter(const char *name, int f)
+void OSLCompiler::parameter(const char * /*name*/, int /*f*/)
{
}
-void OSLCompiler::parameter(const char *name, const char *s)
+void OSLCompiler::parameter(const char * /*name*/, const char * /*s*/)
{
}
-void OSLCompiler::parameter(const char *name, ustring s)
+void OSLCompiler::parameter(const char * /*name*/, ustring /*s*/)
{
}
-void OSLCompiler::parameter(const char *name, const Transform& tfm)
+void OSLCompiler::parameter(const char * /*name*/, const Transform& /*tfm*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const float /*f*/[], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_color_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_vector_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_normal_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen)
+void OSLCompiler::parameter_point_array(const char * /*name*/, const float /*f*/[][3], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const int /*f*/[], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const char * const /*s*/[], int /*arraylen*/)
{
}
-void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen)
+void OSLCompiler::parameter_array(const char * /*name*/, const Transform /*tfm*/[], int /*arraylen*/)
{
}
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index f2f154cdab4..8f9e8c6d639 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -19,6 +19,7 @@
#include "scene.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_map.h"
#include "util_progress.h"
#include "util_vector.h"
@@ -92,6 +93,9 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->particle_systems.size()
+ << " particle systems.";
+
if(!need_update)
return;
@@ -111,7 +115,7 @@ void ParticleSystemManager::device_free(Device *device, DeviceScene *dscene)
dscene->particles.clear();
}
-void ParticleSystemManager::tag_update(Scene *scene)
+void ParticleSystemManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 524574f096d..19d715d834b 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -160,11 +160,6 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel() || device->have_error()) return;
- progress.set_status("Updating Images");
- image_manager->device_update(device, &dscene, progress);
-
- if(progress.get_cancel() || device->have_error()) return;
-
progress.set_status("Updating Background");
background->device_update(device, &dscene, this);
@@ -185,13 +180,18 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel() || device->have_error()) return;
+ progress.set_status("Updating Meshes");
+ mesh_manager->device_update(device, &dscene, this, progress);
+
+ if(progress.get_cancel() || device->have_error()) return;
+
progress.set_status("Updating Objects Flags");
object_manager->device_update_flags(device, &dscene, this, progress);
if(progress.get_cancel() || device->have_error()) return;
- progress.set_status("Updating Meshes");
- mesh_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Images");
+ image_manager->device_update(device, &dscene, progress);
if(progress.get_cancel() || device->have_error()) return;
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 53c3a95903c..851e5ac0b72 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -62,6 +62,7 @@ class DeviceScene {
public:
/* BVH */
device_vector<float4> bvh_nodes;
+ device_vector<float4> bvh_leaf_nodes;
device_vector<uint> object_node;
device_vector<float4> tri_woop;
device_vector<uint> prim_type;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 99826aa4349..57c1500628a 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -20,7 +20,10 @@
#include "buffers.h"
#include "camera.h"
#include "device.h"
+#include "graph.h"
#include "integrator.h"
+#include "mesh.h"
+#include "object.h"
#include "scene.h"
#include "session.h"
#include "bake.h"
@@ -77,6 +80,9 @@ Session::Session(const SessionParams& params_)
gpu_need_tonemap = false;
pause = false;
kernels_loaded = false;
+
+ /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
+ max_closure_global = 1;
}
Session::~Session()
@@ -405,6 +411,11 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
if(tile_buffers.size() == 0)
tile_buffers.resize(tile_manager.state.num_tiles, NULL);
+ /* In certain circumstances number of tiles in the tile manager could
+ * be changed. This is not supported by the progressive refine feature.
+ */
+ assert(tile_buffers.size() == tile_manager.state.num_tiles);
+
tilebuffers = tile_buffers[tile.index];
if(tilebuffers == NULL) {
tilebuffers = new RenderBuffers(tile_device);
@@ -593,6 +604,42 @@ void Session::run_cpu()
update_progressive_refine(true);
}
+DeviceRequestedFeatures Session::get_requested_device_features()
+{
+ /* TODO(sergey): Consider moving this to the Scene level. */
+ DeviceRequestedFeatures requested_features;
+ requested_features.experimental = params.experimental;
+ if(!params.background) {
+ requested_features.max_closure = 64;
+ requested_features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
+ requested_features.nodes_features = NODE_FEATURE_ALL;
+ }
+ else {
+ requested_features.max_closure = get_max_closure_count();
+ scene->shader_manager->get_requested_features(
+ scene,
+ requested_features.max_nodes_group,
+ requested_features.nodes_features);
+ }
+
+ /* This features are not being tweaked as often as shaders,
+ * so could be done selective magic for the viewport as well.
+ */
+ requested_features.use_hair = false;
+ requested_features.use_object_motion = false;
+ requested_features.use_camera_motion = scene->camera->use_motion;
+ foreach(Object *object, scene->objects) {
+ Mesh *mesh = object->mesh;
+ if(mesh->curves.size() > 0) {
+ requested_features.use_hair = true;
+ }
+ requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur;
+ requested_features.use_camera_motion |= mesh->use_motion_blur;
+ }
+
+ return requested_features;
+}
+
void Session::load_kernels()
{
thread_scoped_lock scene_lock(scene->mutex);
@@ -600,7 +647,7 @@ void Session::load_kernels()
if(!kernels_loaded) {
progress.set_status("Loading render kernels (may take a few minutes the first time)");
- if(!device->load_kernels(params.experimental)) {
+ if(!device->load_kernels(get_requested_device_features())) {
string message = device->error_message();
if(message.empty())
message = "Failed loading render kernel, see console for errors";
@@ -778,13 +825,21 @@ void Session::update_status_time(bool show_pause, bool show_done)
string status, substatus;
if(!params.progressive) {
- bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL;
- bool is_multidevice = params.device.multi_devices.size() > 1;
- bool is_cpu = params.device.type == DEVICE_CPU;
+ const int progress_sample = progress.get_sample(), num_samples = tile_manager.num_samples;
+ const bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL;
+ const bool is_multidevice = params.device.multi_devices.size() > 1;
+ const bool is_cpu = params.device.type == DEVICE_CPU;
+ const bool is_last_tile = (num_samples * num_tiles - progress_sample) < num_samples;
substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles);
- if((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) {
+ if((is_gpu && !is_multidevice && !device->info.use_split_kernel) ||
+ (is_cpu && (num_tiles == 1 || is_last_tile)))
+ {
+ /* When using split-kernel (OpenCL) each thread in a tile will be working on a different
+ * sample. Can't display sample number when device uses split-kernel
+ */
+
/* when rendering on GPU multithreading happens within single tile, as in
* tiles are handling sequentially and in this case we could display
* currently rendering sample number
@@ -792,17 +847,21 @@ void Session::update_status_time(bool show_pause, bool show_done)
* also display the info on CPU, when using 1 tile only
*/
- int sample = progress.get_sample(), num_samples = tile_manager.num_samples;
-
+ int status_sample = progress_sample;
if(tile > 1) {
/* sample counter is global for all tiles, subtract samples
* from already finished tiles to get sample counter for
* current tile only
*/
- sample -= (tile - 1) * num_samples;
+ if(is_cpu && is_last_tile && num_tiles > 1) {
+ status_sample = num_samples - (num_samples * num_tiles - progress_sample);
+ }
+ else {
+ status_sample -= (tile - 1) * num_samples;
+ }
}
- substatus += string_printf(", Sample %d/%d", sample, num_samples);
+ substatus += string_printf(", Sample %d/%d", status_sample, num_samples);
}
}
else if(tile_manager.num_samples == USHRT_MAX)
@@ -852,6 +911,7 @@ void Session::path_trace()
task.update_progress_sample = function_bind(&Session::update_progress_sample, this);
task.need_finish_queue = params.progressive_refine;
task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
+ task.requested_tile_size = params.tile_size;
device->task_add(task);
}
@@ -889,9 +949,9 @@ bool Session::update_progressive_refine(bool cancel)
double current_time = time_dt();
- if (current_time - last_update_time < params.progressive_update_timeout) {
+ if(current_time - last_update_time < params.progressive_update_timeout) {
/* if last sample was processed, we need to write buffers anyway */
- if (!write)
+ if(!write && sample != 1)
return false;
}
@@ -901,10 +961,14 @@ bool Session::update_progressive_refine(bool cancel)
rtile.buffers = buffers;
rtile.sample = sample;
- if(write)
- write_render_tile_cb(rtile);
- else
- update_render_tile_cb(rtile);
+ if(write) {
+ if(write_render_tile_cb)
+ write_render_tile_cb(rtile);
+ }
+ else {
+ if(update_render_tile_cb)
+ update_render_tile_cb(rtile);
+ }
}
}
@@ -927,4 +991,15 @@ void Session::device_free()
*/
}
+int Session::get_max_closure_count()
+{
+ int max_closures = 0;
+ for(int i = 0; i < scene->shaders.size(); i++) {
+ int num_closures = scene->shaders[i]->graph->get_num_closures();
+ max_closures = max(max_closures, num_closures);
+ }
+ max_closure_global = max(max_closure_global, max_closures);
+ return max_closure_global;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index c77652d3722..c669bccd34b 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -32,6 +32,7 @@ CCL_NAMESPACE_BEGIN
class BufferParams;
class Device;
class DeviceScene;
+class DeviceRequestedFeatures;
class DisplayBuffer;
class Progress;
class RenderBuffers;
@@ -125,8 +126,8 @@ public:
TileManager tile_manager;
Stats stats;
- boost::function<void(RenderTile&)> write_render_tile_cb;
- boost::function<void(RenderTile&)> update_render_tile_cb;
+ function<void(RenderTile&)> write_render_tile_cb;
+ function<void(RenderTile&)> update_render_tile_cb;
Session(const SessionParams& params);
~Session();
@@ -204,6 +205,16 @@ protected:
bool update_progressive_refine(bool cancel);
vector<RenderBuffers *> tile_buffers;
+
+ DeviceRequestedFeatures get_requested_device_features();
+
+ /* ** Split kernel routines ** */
+
+ /* Maximumnumber of closure during session lifetime. */
+ int max_closure_global;
+
+ /* Get maximum number of closures to be used in kernel. */
+ int get_max_closure_count();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 5899c562f72..31be2a3d3f4 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -15,7 +15,7 @@
*/
#include "background.h"
-#include "blackbody.h"
+#include "camera.h"
#include "device.h"
#include "graph.h"
#include "light.h"
@@ -32,6 +32,8 @@
CCL_NAMESPACE_BEGIN
+vector<float> ShaderManager::beckmann_table;
+
/* Beckmann sampling precomputed table, see bsdf_microfacet.h */
/* 2D slope distribution (alpha = 1.0) */
@@ -146,7 +148,6 @@ Shader::Shader()
has_surface_transparent = false;
has_surface_emission = false;
has_surface_bssrdf = false;
- has_converter_blackbody = false;
has_volume = false;
has_displacement = false;
has_bssrdf_bump = false;
@@ -240,7 +241,6 @@ void Shader::tag_used(Scene *scene)
ShaderManager::ShaderManager()
{
need_update = true;
- blackbody_table_offset = TABLE_OFFSET_INVALID;
beckmann_table_offset = TABLE_OFFSET_INVALID;
}
@@ -252,6 +252,8 @@ ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
{
ShaderManager *manager;
+ (void)shadingsystem; /* Ignored when built without OSL. */
+
#ifdef WITH_OSL
if(shadingsystem == SHADINGSYSTEM_OSL)
manager = new OSLShaderManager();
@@ -321,7 +323,10 @@ void ShaderManager::device_update_shaders_used(Scene *scene)
scene->shaders[light->shader]->used = true;
}
-void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ShaderManager::device_update_common(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& /*progress*/)
{
device->tex_free(dscene->shader_flag);
dscene->shader_flag.clear();
@@ -332,7 +337,6 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
uint shader_flag_size = scene->shaders.size()*4;
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
uint i = 0;
- bool has_converter_blackbody = false;
bool has_volumes = false;
foreach(Shader *shader, scene->shaders) {
@@ -359,8 +363,6 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
flag |= SD_HETEROGENEOUS_VOLUME;
if(shader->has_bssrdf_bump)
flag |= SD_HAS_BSSRDF_BUMP;
- if(shader->has_converter_blackbody)
- has_converter_blackbody = true;
if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
flag |= SD_VOLUME_EQUIANGULAR;
if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
@@ -384,26 +386,16 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
device->tex_alloc("__shader_flag", dscene->shader_flag);
- /* blackbody lookup table */
+ /* lookup tables */
KernelTables *ktables = &dscene->data.tables;
-
- if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) {
- if(blackbody_table.size() == 0) {
- blackbody_table = blackbody_table_build();
- }
- blackbody_table_offset = scene->lookup_tables->add_table(dscene, blackbody_table);
-
- ktables->blackbody_offset = (int)blackbody_table_offset;
- }
- else if(!has_converter_blackbody && blackbody_table_offset != TABLE_OFFSET_INVALID) {
- scene->lookup_tables->remove_table(blackbody_table_offset);
- blackbody_table_offset = TABLE_OFFSET_INVALID;
- }
/* beckmann lookup table */
if(beckmann_table_offset == TABLE_OFFSET_INVALID) {
if(beckmann_table.size() == 0) {
- beckmann_table_build(beckmann_table);
+ thread_scoped_lock lock(lookup_table_mutex);
+ if(beckmann_table.size() == 0) {
+ beckmann_table_build(beckmann_table);
+ }
}
beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
ktables->beckmann_offset = (int)beckmann_table_offset;
@@ -416,11 +408,6 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(blackbody_table_offset != TABLE_OFFSET_INVALID) {
- scene->lookup_tables->remove_table(blackbody_table_offset);
- blackbody_table_offset = TABLE_OFFSET_INVALID;
- }
-
if(beckmann_table_offset != TABLE_OFFSET_INVALID) {
scene->lookup_tables->remove_table(beckmann_table_offset);
beckmann_table_offset = TABLE_OFFSET_INVALID;
@@ -494,5 +481,45 @@ void ShaderManager::add_default(Scene *scene)
}
}
+/* NOTE: Expects max_group and features to be initialized in the callee. */
+void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
+ int& max_group,
+ int& features)
+{
+ foreach(ShaderNode *node, graph->nodes) {
+ max_group = max(max_group, node->get_group());
+ features |= node->get_feature();
+ if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfNode *bsdf_node = static_cast<BsdfNode*>(node);
+ if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ features |= NODE_FEATURE_VOLUME;
+ }
+ }
+ }
+}
+
+void ShaderManager::get_requested_features(Scene *scene,
+ int& max_group,
+ int& features)
+{
+ max_group = NODE_GROUP_LEVEL_0;
+ features = 0;
+ for(int i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ /* Gather requested features from all the nodes from the graph nodes. */
+ get_requested_graph_features(shader->graph, max_group, features);
+ /* Gather requested features from the graph itself. */
+ if(shader->graph_bump) {
+ get_requested_graph_features(shader->graph_bump,
+ max_group,
+ features);
+ }
+ ShaderNode *output_node = shader->graph->output();
+ if(output_node->input("Displacement")->link != NULL) {
+ features |= NODE_FEATURE_BUMP;
+ }
+ }
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 1dee47c7731..64d45635ef1 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -36,6 +36,7 @@
#include "util_map.h"
#include "util_param.h"
#include "util_string.h"
+#include "util_thread.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN
@@ -103,7 +104,6 @@ public:
bool has_volume;
bool has_displacement;
bool has_surface_bssrdf;
- bool has_converter_blackbody;
bool has_bssrdf_bump;
bool has_heterogeneous_volume;
bool has_object_dependency;
@@ -165,17 +165,25 @@ public:
* have any shader assigned explicitly */
static void add_default(Scene *scene);
+ /* Selective nodes compilation. */
+ void get_requested_features(Scene *scene,
+ int& max_group,
+ int& features);
+
protected:
ShaderManager();
typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
AttributeIDMap unique_attribute_id;
- vector<float> blackbody_table;
- vector<float> beckmann_table;
+ thread_mutex lookup_table_mutex;
+ static vector<float> beckmann_table;
- size_t blackbody_table_offset;
size_t beckmann_table_offset;
+
+ void get_requested_graph_features(ShaderGraph *graph,
+ int& max_group,
+ int& features);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/sky_model.cpp b/intern/cycles/render/sky_model.cpp
index adb07d9e288..c8a5dbe55e0 100644
--- a/intern/cycles/render/sky_model.cpp
+++ b/intern/cycles/render/sky_model.cpp
@@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license.
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
All rights reserved.
-Redistribution and use in source and binary forms, with or without
+Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
@@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- * None of the names of the contributors may be used to endorse or promote
- products derived from this software without specific prior written
+ * None of the names of the contributors may be used to endorse or promote
+ products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
@@ -40,24 +40,24 @@ and the 2013 IEEE CG&A paper
"Adding a Solar Radiance Function to the Hosek Skylight Model"
- both by
+ both by
Lukas Hosek and Alexander Wilkie
Charles University in Prague, Czech Republic
Version: 1.4a, February 22nd, 2013
-
+
Version history:
1.4a February 22nd, 2013
- Removed unnecessary and counter-intuitive solar radius parameters
+ Removed unnecessary and counter-intuitive solar radius parameters
from the interface of the colourspace sky dome initialisation functions.
1.4 February 11th, 2013
Fixed a bug which caused the relative brightness of the solar disc
- and the sky dome to be off by a factor of about 6. The sun was too
- bright: this affected both normal and alien sun scenarios. The
+ and the sky dome to be off by a factor of about 6. The sun was too
+ bright: this affected both normal and alien sun scenarios. The
coefficients of the solar radiance function were changed to fix this.
1.3 January 21st, 2013 (not released to the public)
@@ -81,7 +81,7 @@ Version history:
the result of a simple conversion from spectral data via the CIE 2 degree
standard observer matching functions. Therefore, after multiplication
with 683 lm / W, the Y channel now corresponds to luminance in lm.
-
+
1.0 May 11th, 2012
Initial release.
@@ -110,7 +110,7 @@ CCL_NAMESPACE_BEGIN
// Some macro definitions that occur elsewhere in ART, and that have to be
// replicated to make this a stand-alone module.
-#ifndef MATH_PI
+#ifndef MATH_PI
#define MATH_PI 3.141592653589793
#endif
@@ -138,250 +138,231 @@ typedef const double *ArHosekSkyModel_Radiance_Dataset;
// internal functions
static void ArHosekSkyModel_CookConfiguration(
- ArHosekSkyModel_Dataset dataset,
- ArHosekSkyModelConfiguration config,
- double turbidity,
- double albedo,
- double solar_elevation
- )
+ ArHosekSkyModel_Dataset dataset,
+ ArHosekSkyModelConfiguration config,
+ double turbidity,
+ double albedo,
+ double solar_elevation)
{
- const double * elev_matrix;
-
- int int_turbidity = (int)turbidity;
- double turbidity_rem = turbidity - (double)int_turbidity;
-
- solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
-
- // alb 0 low turb
-
- elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1) );
-
-
- for( unsigned int i = 0; i < 9; ++i )
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] =
- (1.0-albedo) * (1.0 - turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ const double * elev_matrix;
- // alb 1 low turb
- elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1));
- for(unsigned int i = 0; i < 9; ++i)
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (albedo) * (1.0 - turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ int int_turbidity = (int)turbidity;
+ double turbidity_rem = turbidity - (double)int_turbidity;
- if(int_turbidity == 10)
- return;
-
- // alb 0 high turb
- elev_matrix = dataset + (9*6*(int_turbidity));
- for(unsigned int i = 0; i < 9; ++i)
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (1.0-albedo) * (turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
+
+ // alb 0 low turb
- // alb 1 high turb
- elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity));
- for(unsigned int i = 0; i < 9; ++i)
- {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (albedo) * (turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1));
+
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] =
+ (1.0-albedo) * (1.0 - turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
}
+
+ // alb 1 low turb
+ elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1));
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (albedo) * (1.0 - turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ }
+
+ if(int_turbidity == 10)
+ return;
+
+ // alb 0 high turb
+ elev_matrix = dataset + (9*6*(int_turbidity));
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (1.0-albedo) * (turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ }
+
+ // alb 1 high turb
+ elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity));
+ for(unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (albedo) * (turbidity_rem)
+ * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i+45]);
+ }
}
static double ArHosekSkyModel_CookRadianceConfiguration(
- ArHosekSkyModel_Radiance_Dataset dataset,
- double turbidity,
- double albedo,
- double solar_elevation
- )
+ ArHosekSkyModel_Radiance_Dataset dataset,
+ double turbidity,
+ double albedo,
+ double solar_elevation)
{
- const double* elev_matrix;
-
- int int_turbidity = (int)turbidity;
- double turbidity_rem = turbidity - (double)int_turbidity;
- double res;
- solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
-
- // alb 0 low turb
- elev_matrix = dataset + (6*(int_turbidity-1));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res = (1.0-albedo) * (1.0 - turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
-
- // alb 1 low turb
- elev_matrix = dataset + (6*10 + 6*(int_turbidity-1));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (albedo) * (1.0 - turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
- if(int_turbidity == 10)
- return res;
-
- // alb 0 high turb
- elev_matrix = dataset + (6*(int_turbidity));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (1.0-albedo) * (turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
-
- // alb 1 high turb
- elev_matrix = dataset + (6*10 + 6*(int_turbidity));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (albedo) * (turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
- return res;
+ const double* elev_matrix;
+
+ int int_turbidity = (int)turbidity;
+ double turbidity_rem = turbidity - (double)int_turbidity;
+ double res;
+ solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
+
+ // alb 0 low turb
+ elev_matrix = dataset + (6*(int_turbidity-1));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res = (1.0-albedo) * (1.0 - turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+
+ // alb 1 low turb
+ elev_matrix = dataset + (6*10 + 6*(int_turbidity-1));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (albedo) * (1.0 - turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+ if(int_turbidity == 10)
+ return res;
+
+ // alb 0 high turb
+ elev_matrix = dataset + (6*(int_turbidity));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (1.0-albedo) * (turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+
+ // alb 1 high turb
+ elev_matrix = dataset + (6*10 + 6*(int_turbidity));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (albedo) * (turbidity_rem) *
+ ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
+ 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+ return res;
}
static double ArHosekSkyModel_GetRadianceInternal(
- ArHosekSkyModelConfiguration configuration,
- double theta,
- double gamma
- )
+ ArHosekSkyModelConfiguration configuration,
+ double theta,
+ double gamma)
{
- const double expM = exp(configuration[4] * gamma);
- const double rayM = cos(gamma)*cos(gamma);
- const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5);
- const double zenith = sqrt(cos(theta));
+ const double expM = exp(configuration[4] * gamma);
+ const double rayM = cos(gamma)*cos(gamma);
+ const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5);
+ const double zenith = sqrt(cos(theta));
- return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) *
+ return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) *
(configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith);
}
-void arhosekskymodelstate_free(
- ArHosekSkyModelState * state
- )
+void arhosekskymodelstate_free(ArHosekSkyModelState * state)
{
- free(state);
+ free(state);
}
-double arhosekskymodel_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- double wavelength
- )
+double arhosekskymodel_radiance(ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength)
{
- int low_wl = (int)((wavelength - 320.0) / 40.0);
-
- if ( low_wl < 0 || low_wl >= 11 )
- return 0.0f;
-
- double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0);
-
- double val_low =
- ArHosekSkyModel_GetRadianceInternal(
- state->configs[low_wl],
- theta,
- gamma
- )
- * state->radiances[low_wl]
- * state->emission_correction_factor_sky[low_wl];
-
- if ( interp < 1e-6 )
- return val_low;
-
- double result = ( 1.0 - interp ) * val_low;
-
- if ( low_wl+1 < 11 )
- {
- result +=
- interp
- * ArHosekSkyModel_GetRadianceInternal(
- state->configs[low_wl+1],
- theta,
- gamma
- )
- * state->radiances[low_wl+1]
- * state->emission_correction_factor_sky[low_wl+1];
- }
-
- return result;
+ int low_wl = (int)((wavelength - 320.0) / 40.0);
+
+ if(low_wl < 0 || low_wl >= 11)
+ return 0.0f;
+
+ double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0);
+
+ double val_low =
+ ArHosekSkyModel_GetRadianceInternal(
+ state->configs[low_wl],
+ theta,
+ gamma)
+ * state->radiances[low_wl]
+ * state->emission_correction_factor_sky[low_wl];
+
+ if(interp < 1e-6)
+ return val_low;
+
+ double result = ( 1.0 - interp ) * val_low;
+
+ if(low_wl+1 < 11) {
+ result +=
+ interp
+ * ArHosekSkyModel_GetRadianceInternal(
+ state->configs[low_wl+1],
+ theta,
+ gamma)
+ * state->radiances[low_wl+1]
+ * state->emission_correction_factor_sky[low_wl+1];
+ }
+
+ return result;
}
// xyz and rgb versions
-ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation
- )
+ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
+ const double turbidity,
+ const double albedo,
+ const double elevation)
{
- ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState);
-
- state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
- state->turbidity = turbidity;
- state->albedo = albedo;
- state->elevation = elevation;
-
- for( unsigned int channel = 0; channel < 3; ++channel )
- {
- ArHosekSkyModel_CookConfiguration(
- datasetsXYZ[channel],
- state->configs[channel],
- turbidity,
- albedo,
- elevation
- );
-
- state->radiances[channel] =
- ArHosekSkyModel_CookRadianceConfiguration(
- datasetsXYZRad[channel],
- turbidity,
- albedo,
- elevation
- );
+ ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState);
+
+ state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
+ state->turbidity = turbidity;
+ state->albedo = albedo;
+ state->elevation = elevation;
+
+ for(unsigned int channel = 0; channel < 3; ++channel) {
+ ArHosekSkyModel_CookConfiguration(
+ datasetsXYZ[channel],
+ state->configs[channel],
+ turbidity,
+ albedo,
+ elevation);
+
+ state->radiances[channel] =
+ ArHosekSkyModel_CookRadianceConfiguration(
+ datasetsXYZRad[channel],
+ turbidity,
+ albedo,
+ elevation);
}
-
+
return state;
}
diff --git a/intern/cycles/render/sky_model.h b/intern/cycles/render/sky_model.h
index 3814543c8b6..237e4e61bf5 100644
--- a/intern/cycles/render/sky_model.h
+++ b/intern/cycles/render/sky_model.h
@@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license.
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
All rights reserved.
-Redistribution and use in source and binary forms, with or without
+Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
@@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- * None of the names of the contributors may be used to endorse or promote
- products derived from this software without specific prior written
+ * None of the names of the contributors may be used to endorse or promote
+ products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
@@ -41,24 +41,24 @@ and the 2013 IEEE CG&A paper
"Adding a Solar Radiance Function to the Hosek Skylight Model"
- both by
+ both by
Lukas Hosek and Alexander Wilkie
Charles University in Prague, Czech Republic
Version: 1.4a, February 22nd, 2013
-
+
Version history:
1.4a February 22nd, 2013
- Removed unnecessary and counter-intuitive solar radius parameters
+ Removed unnecessary and counter-intuitive solar radius parameters
from the interface of the colourspace sky dome initialisation functions.
1.4 February 11th, 2013
Fixed a bug which caused the relative brightness of the solar disc
- and the sky dome to be off by a factor of about 6. The sun was too
- bright: this affected both normal and alien sun scenarios. The
+ and the sky dome to be off by a factor of about 6. The sun was too
+ bright: this affected both normal and alien sun scenarios. The
coefficients of the solar radiance function were changed to fix this.
1.3 January 21st, 2013 (not released to the public)
@@ -82,7 +82,7 @@ Version history:
the result of a simple conversion from spectral data via the CIE 2 degree
standard observer matching functions. Therefore, after multiplication
with 683 lm / W, the Y channel now corresponds to luminance in lm.
-
+
1.0 May 11th, 2012
Initial release.
@@ -96,9 +96,9 @@ an updated version of this code has been published!
/*
This code is taken from ART, a rendering research system written in a
-mix of C99 / Objective C. Since ART is not a small system and is intended to
-be inter-operable with other libraries, and since C does not have namespaces,
-the structures and functions in ART all have to have somewhat wordy
+mix of C99 / Objective C. Since ART is not a small system and is intended to
+be inter-operable with other libraries, and since C does not have namespaces,
+the structures and functions in ART all have to have somewhat wordy
canonical names that begin with Ar.../ar..., like those seen in this example.
Usage information:
@@ -119,7 +119,7 @@ snippet, we assume that 'albedo' is defined as
double albedo[num_channels];
-with a ground albedo value between [0,1] for each channel. The solar elevation
+with a ground albedo value between [0,1] for each channel. The solar elevation
is given in radians.
for ( unsigned int i = 0; i < num_channels; i++ )
@@ -130,11 +130,11 @@ is given in radians.
solarElevation
);
-Note that starting with version 1.3, there is also a second initialisation
-function which generates skydome states for different solar emission spectra
+Note that starting with version 1.3, there is also a second initialisation
+function which generates skydome states for different solar emission spectra
and solar radii: 'arhosekskymodelstate_alienworld_alloc_init()'.
-See the notes about the "Alien World" functionality provided further down for a
+See the notes about the "Alien World" functionality provided further down for a
discussion of the usefulness and limits of that second initalisation function.
Sky model states that have been initialized with either function behave in a
completely identical fashion during use and cleanup.
@@ -155,7 +155,7 @@ on the skydome determined via the angles theta and gamma works as follows:
gamma,
channel_center[i]
);
-
+
The variable "channel_center" is assumed to hold the channel center wavelengths
for each of the num_channels samples of the spectrum we are building.
@@ -188,114 +188,114 @@ by calling arhosek_rgb_skymodelstate_alloc_init.
Solar Radiance Function
-----------------------
-For each position on the solar disc, this function returns the entire radiance
-one sees - direct emission, as well as in-scattered light in the area of the
-solar disc. The latter is important for low solar elevations - nice images of
-the setting sun would not be possible without this. This is also the reason why
-this function, just like the regular sky dome model evaluation function, needs
-access to the sky dome data structures, as these provide information on
+For each position on the solar disc, this function returns the entire radiance
+one sees - direct emission, as well as in-scattered light in the area of the
+solar disc. The latter is important for low solar elevations - nice images of
+the setting sun would not be possible without this. This is also the reason why
+this function, just like the regular sky dome model evaluation function, needs
+access to the sky dome data structures, as these provide information on
in-scattered radiance.
CAVEAT #1: in this release, this function is only provided in spectral form!
RGB/XYZ versions to follow at a later date.
-CAVEAT #2: (fixed from release 1.3 onwards)
+CAVEAT #2: (fixed from release 1.3 onwards)
CAVEAT #3: limb darkening renders the brightness of the solar disc
inhomogeneous even for high solar elevations - only taking a single
sample at the centre of the sun will yield an incorrect power
estimate for the solar disc! Always take multiple random samples
across the entire solar disc to estimate its power!
-
+
CAVEAT #4: in this version, the limb darkening calculations still use a fairly
- computationally expensive 5th order polynomial that was directly
+ computationally expensive 5th order polynomial that was directly
taken from astronomical literature. For the purposes of Computer
- Graphics, this is needlessly accurate, though, and will be replaced
+ Graphics, this is needlessly accurate, though, and will be replaced
by a cheaper approximation in a future release.
"Alien World" functionality
---------------------------
-The Hosek sky model can be used to roughly (!) predict the appearance of
-outdoor scenes on earth-like planets, i.e. planets of a similar size and
-atmospheric make-up. Since the spectral version of our model predicts sky dome
-luminance patterns and solar radiance independently for each waveband, and
-since the intensity of each waveband is solely dependent on the input radiance
-from the star that the world in question is orbiting, it is trivial to re-scale
+The Hosek sky model can be used to roughly (!) predict the appearance of
+outdoor scenes on earth-like planets, i.e. planets of a similar size and
+atmospheric make-up. Since the spectral version of our model predicts sky dome
+luminance patterns and solar radiance independently for each waveband, and
+since the intensity of each waveband is solely dependent on the input radiance
+from the star that the world in question is orbiting, it is trivial to re-scale
the wavebands to match a different star radiance.
-At least in theory, the spectral version of the model has always been capable
-of this sort of thing, and the actual sky dome and solar radiance models were
+At least in theory, the spectral version of the model has always been capable
+of this sort of thing, and the actual sky dome and solar radiance models were
actually not altered at all in this release. All we did was to add some support
-functionality for doing this more easily with the existing data and functions,
+functionality for doing this more easily with the existing data and functions,
and to add some explanations.
Just use 'arhosekskymodelstate_alienworld_alloc_init()' to initialise the sky
-model states (you will have to provide values for star temperature and solar
-intensity compared to the terrestrial sun), and do everything else as you
+model states (you will have to provide values for star temperature and solar
+intensity compared to the terrestrial sun), and do everything else as you
did before.
-CAVEAT #1: we assume the emission of the star that illuminates the alien world
- to be a perfect blackbody emission spectrum. This is never entirely
- realistic - real star emission spectra are considerably more complex
- than this, mainly due to absorption effects in the outer layers of
- stars. However, blackbody spectra are a reasonable first assumption
- in a usage scenario like this, where 100% accuracy is simply not
- necessary: for rendering purposes, there are likely no visible
- differences between a highly accurate solution based on a more
+CAVEAT #1: we assume the emission of the star that illuminates the alien world
+ to be a perfect blackbody emission spectrum. This is never entirely
+ realistic - real star emission spectra are considerably more complex
+ than this, mainly due to absorption effects in the outer layers of
+ stars. However, blackbody spectra are a reasonable first assumption
+ in a usage scenario like this, where 100% accuracy is simply not
+ necessary: for rendering purposes, there are likely no visible
+ differences between a highly accurate solution based on a more
involved simulation, and this approximation.
CAVEAT #2: we always use limb darkening data from our own sun to provide this
- "appearance feature", even for suns of strongly different
- temperature. Which is presumably not very realistic, but (as with
- the unaltered blackbody spectrum from caveat #1) probably not a bad
+ "appearance feature", even for suns of strongly different
+ temperature. Which is presumably not very realistic, but (as with
+ the unaltered blackbody spectrum from caveat #1) probably not a bad
first guess, either. If you need more accuracy than we provide here,
please make inquiries with a friendly astro-physicst of your choice.
-CAVEAT #3: you have to provide a value for the solar intensity of the star
- which illuminates the alien world. For this, please bear in mind
- that there is very likely a comparatively tight range of absolute
- solar irradiance values for which an earth-like planet with an
- atmosphere like the one we assume in our model can exist in the
+CAVEAT #3: you have to provide a value for the solar intensity of the star
+ which illuminates the alien world. For this, please bear in mind
+ that there is very likely a comparatively tight range of absolute
+ solar irradiance values for which an earth-like planet with an
+ atmosphere like the one we assume in our model can exist in the
first place!
-
- Too much irradiance, and the atmosphere probably boils off into
- space, too little, it freezes. Which means that stars of
- considerably different emission colour than our sun will have to be
- fairly different in size from it, to still provide a reasonable and
- inhabitable amount of irradiance. Red stars will need to be much
- larger than our sun, while white or blue stars will have to be
- comparatively tiny. The initialisation function handles this and
+
+ Too much irradiance, and the atmosphere probably boils off into
+ space, too little, it freezes. Which means that stars of
+ considerably different emission colour than our sun will have to be
+ fairly different in size from it, to still provide a reasonable and
+ inhabitable amount of irradiance. Red stars will need to be much
+ larger than our sun, while white or blue stars will have to be
+ comparatively tiny. The initialisation function handles this and
computes a plausible solar radius for a given emission spectrum. In
terms of absolute radiometric values, you should probably not stray
all too far from a solar intensity value of 1.0.
-CAVEAT #4: although we now support different solar radii for the actual solar
- disc, the sky dome luminance patterns are *not* parameterised by
- this value - i.e. the patterns stay exactly the same for different
- solar radii! Which is of course not correct. But in our experience,
- solar discs up to several degrees in diameter (! - our own sun is
- half a degree across) do not cause the luminance patterns on the sky
- to change perceptibly. The reason we know this is that we initially
- used unrealistically large suns in our brute force path tracer, in
- order to improve convergence speeds (which in the beginning were
- abysmal). Later, we managed to do the reference renderings much
- faster even with realistically small suns, and found that there was
- no real difference in skydome appearance anyway.
- Conclusion: changing the solar radius should not be over-done, so
- close orbits around red supergiants are a no-no. But for the
- purposes of getting a fairly credible first impression of what an
- alien world with a reasonably sized sun would look like, what we are
+CAVEAT #4: although we now support different solar radii for the actual solar
+ disc, the sky dome luminance patterns are *not* parameterised by
+ this value - i.e. the patterns stay exactly the same for different
+ solar radii! Which is of course not correct. But in our experience,
+ solar discs up to several degrees in diameter (! - our own sun is
+ half a degree across) do not cause the luminance patterns on the sky
+ to change perceptibly. The reason we know this is that we initially
+ used unrealistically large suns in our brute force path tracer, in
+ order to improve convergence speeds (which in the beginning were
+ abysmal). Later, we managed to do the reference renderings much
+ faster even with realistically small suns, and found that there was
+ no real difference in skydome appearance anyway.
+ Conclusion: changing the solar radius should not be over-done, so
+ close orbits around red supergiants are a no-no. But for the
+ purposes of getting a fairly credible first impression of what an
+ alien world with a reasonably sized sun would look like, what we are
doing here is probably still o.k.
-HINT #1: if you want to model the sky of an earth-like planet that orbits
- a binary star, just super-impose two of these models with solar
+HINT #1: if you want to model the sky of an earth-like planet that orbits
+ a binary star, just super-impose two of these models with solar
intensity of ~0.5 each, and closely spaced solar positions. Light is
additive, after all. Tattooine, here we come... :-)
P.S. according to Star Wars canon, Tattooine orbits a binary
- that is made up of a G and K class star, respectively.
- So ~5500K and ~4200K should be good first guesses for their
+ that is made up of a G and K class star, respectively.
+ So ~5500K and ~4200K should be good first guesses for their
temperature. Just in case you were wondering, after reading the
previous paragraph.
*/
@@ -316,37 +316,37 @@ typedef double ArHosekSkyModelConfiguration[9];
---------------------------
This struct holds the pre-computation data for one particular albedo value.
- Most fields are self-explanatory, but users should never directly
- manipulate any of them anyway. The only consistent way to manipulate such
- structs is via the functions 'arhosekskymodelstate_alloc_init' and
+ Most fields are self-explanatory, but users should never directly
+ manipulate any of them anyway. The only consistent way to manipulate such
+ structs is via the functions 'arhosekskymodelstate_alloc_init' and
'arhosekskymodelstate_free'.
-
+
'emission_correction_factor_sky'
'emission_correction_factor_sun'
- The original model coefficients were fitted against the emission of
+ The original model coefficients were fitted against the emission of
our local sun. If a different solar emission is desired (i.e. if the
- model is being used to predict skydome appearance for an earth-like
- planet that orbits a different star), these correction factors, which
- are determined during the alloc_init step, are applied to each waveband
- separately (they default to 1.0 in normal usage). This is the simplest
- way to retrofit this sort of capability to the existing model. The
- different factors for sky and sun are needed since the solar disc may
+ model is being used to predict skydome appearance for an earth-like
+ planet that orbits a different star), these correction factors, which
+ are determined during the alloc_init step, are applied to each waveband
+ separately (they default to 1.0 in normal usage). This is the simplest
+ way to retrofit this sort of capability to the existing model. The
+ different factors for sky and sun are needed since the solar disc may
be of a different size compared to the terrestrial sun.
---------------------------------------------------------------------------- */
typedef struct ArHosekSkyModelState
{
- ArHosekSkyModelConfiguration configs[11];
- double radiances[11];
- double turbidity;
- double solar_radius;
- double emission_correction_factor_sky[11];
- double emission_correction_factor_sun[11];
- double albedo;
- double elevation;
-}
+ ArHosekSkyModelConfiguration configs[11];
+ double radiances[11];
+ double turbidity;
+ double solar_radius;
+ double emission_correction_factor_sky[11];
+ double emission_correction_factor_sun[11];
+ double albedo;
+ double elevation;
+}
ArHosekSkyModelState;
/* ----------------------------------------------------------------------------
@@ -358,11 +358,10 @@ ArHosekSkyModelState;
---------------------------------------------------------------------------- */
-ArHosekSkyModelState * arhosekskymodelstate_alloc_init(
- const double solar_elevation,
- const double atmospheric_turbidity,
- const double ground_albedo
- );
+ArHosekSkyModelState *arhosekskymodelstate_alloc_init(
+ const double solar_elevation,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
/* ----------------------------------------------------------------------------
@@ -375,78 +374,67 @@ ArHosekSkyModelState * arhosekskymodelstate_alloc_init(
'solar_intensity' controls the overall brightness of the sky, relative
to the solar irradiance on Earth. A value of 1.0 yields a sky dome that
is, on average over the wavelenghts covered in the model (!), as bright
- as the terrestrial sky in radiometric terms.
-
- Which means that the solar radius has to be adjusted, since the
- emissivity of a solar surface with a given temperature is more or less
- fixed. So hotter suns have to be smaller to be equally bright as the
+ as the terrestrial sky in radiometric terms.
+
+ Which means that the solar radius has to be adjusted, since the
+ emissivity of a solar surface with a given temperature is more or less
+ fixed. So hotter suns have to be smaller to be equally bright as the
terrestrial sun, while cooler suns have to be larger. Note that there are
limits to the validity of the luminance patterns of the underlying model:
see the discussion above for more on this. In particular, an alien sun with
a surface temperature of only 2000 Kelvin has to be very large if it is
- to be as bright as the terrestrial sun - so large that the luminance
+ to be as bright as the terrestrial sun - so large that the luminance
patterns are no longer a really good fit in that case.
-
+
If you need information about the solar radius that the model computes
- for a given temperature (say, for light source sampling purposes), you
- have to query the 'solar_radius' variable of the sky model state returned
+ for a given temperature (say, for light source sampling purposes), you
+ have to query the 'solar_radius' variable of the sky model state returned
*after* running this function.
---------------------------------------------------------------------------- */
-ArHosekSkyModelState * arhosekskymodelstate_alienworld_alloc_init(
- const double solar_elevation,
- const double solar_intensity,
- const double solar_surface_temperature_kelvin,
- const double atmospheric_turbidity,
- const double ground_albedo
- );
-
-void arhosekskymodelstate_free(
- ArHosekSkyModelState * state
- );
-
-double arhosekskymodel_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- double wavelength
- );
+ArHosekSkyModelState* arhosekskymodelstate_alienworld_alloc_init(
+ const double solar_elevation,
+ const double solar_intensity,
+ const double solar_surface_temperature_kelvin,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
+
+void arhosekskymodelstate_free(ArHosekSkyModelState *state);
+
+double arhosekskymodel_radiance(ArHosekSkyModelState *state,
+ double theta,
+ double gamma,
+ double wavelength);
// CIE XYZ and RGB versions
ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation
- );
+ const double turbidity,
+ const double albedo,
+ const double elevation);
ArHosekSkyModelState * arhosek_rgb_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation
- );
+ const double turbidity,
+ const double albedo,
+ const double elevation);
-double arhosek_tristim_skymodel_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- int channel
- );
+double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState* state,
+ double theta,
+ double gamma,
+ int channel);
// Delivers the complete function: sky + sun, including limb darkening.
// Please read the above description before using this - there are several
// caveats!
-double arhosekskymodel_solar_radiance(
- ArHosekSkyModelState * state,
- double theta,
- double gamma,
- double wavelength
- );
+double arhosekskymodel_solar_radiance(ArHosekSkyModelState* state,
+ double theta,
+ double gamma,
+ double wavelength);
#endif // _SKY_MODEL_H_
diff --git a/intern/cycles/render/sky_model_data.h b/intern/cycles/render/sky_model_data.h
index 4171bd12756..e6f3f761532 100644
--- a/intern/cycles/render/sky_model_data.h
+++ b/intern/cycles/render/sky_model_data.h
@@ -4,7 +4,7 @@ This source is published under the following 3-clause BSD license.
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
All rights reserved.
-Redistribution and use in source and binary forms, with or without
+Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
@@ -12,8 +12,8 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- * None of the names of the contributors may be used to endorse or promote
- products derived from this software without specific prior written
+ * None of the names of the contributors may be used to endorse or promote
+ products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
@@ -41,24 +41,24 @@ and the 2013 IEEE CG&A paper
"Adding a Solar Radiance Function to the Hosek Skylight Model"
- both by
+ both by
Lukas Hosek and Alexander Wilkie
Charles University in Prague, Czech Republic
Version: 1.4a, February 22nd, 2013
-
+
Version history:
1.4a February 22nd, 2013
- Removed unnecessary and counter-intuitive solar radius parameters
+ Removed unnecessary and counter-intuitive solar radius parameters
from the interface of the colourspace sky dome initialisation functions.
1.4 February 11th, 2013
Fixed a bug which caused the relative brightness of the solar disc
- and the sky dome to be off by a factor of about 6. The sun was too
- bright: this affected both normal and alien sun scenarios. The
+ and the sky dome to be off by a factor of about 6. The sun was too
+ bright: this affected both normal and alien sun scenarios. The
coefficients of the solar radiance function were changed to fix this.
1.3 January 21st, 2013 (not released to the public)
@@ -82,7 +82,7 @@ Version history:
the result of a simple conversion from spectral data via the CIE 2 degree
standard observer matching functions. Therefore, after multiplication
with 683 lm / W, the Y channel now corresponds to luminance in lm.
-
+
1.0 May 11th, 2012
Initial release.
@@ -96,15 +96,14 @@ CCL_NAMESPACE_BEGIN
/*
-This file contains the coefficient data for the XYZ colour space version of
+This file contains the coefficient data for the XYZ colour space version of
the model.
*/
// Uses Sep 9 pattern / Aug 23 mean dataset
-static const double datasetXYZ1[] =
-{
+static const double datasetXYZ1[] = {
// albedo 0, turbidity 1
-1.117001e+000,
-1.867262e-001,
@@ -3849,15 +3848,13 @@ static const double datasetXYZRad3[] =
-static const double* datasetsXYZ[] =
-{
+static const double* datasetsXYZ[] = {
datasetXYZ1,
datasetXYZ2,
datasetXYZ3
};
-static const double* datasetsXYZRad[] =
-{
+static const double* datasetsXYZRad[] = {
datasetXYZRad1,
datasetXYZRad2,
datasetXYZRad3
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 2e3abfcffb9..d0bd34915df 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -24,6 +24,7 @@
#include "svm.h"
#include "util_debug.h"
+#include "util_logging.h"
#include "util_foreach.h"
#include "util_progress.h"
@@ -39,12 +40,14 @@ SVMShaderManager::~SVMShaderManager()
{
}
-void SVMShaderManager::reset(Scene *scene)
+void SVMShaderManager::reset(Scene * /*scene*/)
{
}
void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+
if(!need_update)
return;
@@ -354,7 +357,7 @@ uint SVMCompiler::attribute(AttributeStandard std)
return shader_manager->get_attribute_id(std);
}
-bool SVMCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
+bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
{
/* nasty exception .. */
if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump"))
@@ -390,10 +393,6 @@ void SVMCompiler::generate_node(ShaderNode *node, set<ShaderNode*>& done)
current_shader->has_heterogeneous_volume = true;
}
- /* detect if we have a blackbody converter, to prepare lookup table */
- if(node->has_converter_blackbody())
- current_shader->has_converter_blackbody = true;
-
if(node->has_object_dependency()) {
current_shader->has_object_dependency = true;
}
@@ -713,7 +712,6 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
shader->has_surface_transparent = false;
shader->has_surface_bssrdf = false;
shader->has_bssrdf_bump = false;
- shader->has_converter_blackbody = false;
shader->has_volume = false;
shader->has_displacement = false;
shader->has_heterogeneous_volume = false;
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
index faf7ea3409b..ad3f4866072 100644
--- a/intern/cycles/render/tables.cpp
+++ b/intern/cycles/render/tables.cpp
@@ -19,6 +19,7 @@
#include "tables.h"
#include "util_debug.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -36,6 +37,8 @@ LookupTables::~LookupTables()
void LookupTables::device_update(Device *device, DeviceScene *dscene)
{
+ VLOG(1) << "Total " << lookup_tables.size() << " lookup tables.";
+
if(!need_update)
return;
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index 675f49ec300..7e68ce84d94 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -28,6 +28,7 @@ TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, i
tile_size = tile_size_;
tile_order = tile_order_;
start_resolution = start_resolution_;
+ num_samples = num_samples_;
num_devices = num_devices_;
preserve_tile_device = preserve_tile_device_;
background = background_;
@@ -234,7 +235,7 @@ bool TileManager::next_tile(Tile& tile, int device)
{
list<Tile>::iterator tile_it;
- if (background)
+ if(background)
tile_it = next_background_tile(device, tile_order);
else
tile_it = next_viewport_tile(device);