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
path: root/intern
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2016-07-25 16:07:17 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2016-07-25 16:07:17 +0300
commitb1532493c27b08444745cef348641f3a0e899ba8 (patch)
tree84db57081ef3e1d2a1bfbf3c4bbfe352854164f2 /intern
parent9186b9ae4806f4bbc1a14417c408e844f8e8cc1a (diff)
parente7721f5ec8b859d14c982a8a34bc269ab7eed82b (diff)
Merge branch 'master' into blender2.8
Conflicts: source/blender/blenkernel/BKE_particle.h source/blender/blenkernel/intern/library.c source/blender/blenkernel/intern/particle.c
Diffstat (limited to 'intern')
-rw-r--r--intern/atomic/intern/atomic_ops_utils.h4
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.cpp2
-rw-r--r--intern/cycles/blender/addon/properties.py2
-rw-r--r--intern/cycles/blender/addon/ui.py4
-rw-r--r--intern/cycles/blender/blender_mesh.cpp45
-rw-r--r--intern/cycles/blender/blender_object.cpp10
-rw-r--r--intern/cycles/blender/blender_sync.h4
-rw-r--r--intern/cycles/blender/blender_util.h17
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle.h6
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h2
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h24
-rw-r--r--intern/cycles/kernel/kernel_types.h17
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h2
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/constant_fold.cpp122
-rw-r--r--intern/cycles/render/constant_fold.h59
-rw-r--r--intern/cycles/render/graph.cpp56
-rw-r--r--intern/cycles/render/graph.h8
-rw-r--r--intern/cycles/render/nodes.cpp356
-rw-r--r--intern/cycles/render/nodes.h45
-rw-r--r--intern/cycles/render/scene.cpp8
-rw-r--r--intern/cycles/render/scene.h1
-rw-r--r--intern/ghost/GHOST_Types.h2
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp9
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp31
-rw-r--r--intern/libmv/intern/autotrack.cc8
-rw-r--r--intern/libmv/libmv/numeric/numeric.cc2
-rw-r--r--intern/opensubdiv/CMakeLists.txt2
-rw-r--r--intern/opensubdiv/gpu_shader_opensubd_display.glsl2
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc89
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h11
-rw-r--r--intern/opensubdiv/opensubdiv_converter.cc107
-rw-r--r--intern/opensubdiv/opensubdiv_converter_capi.h16
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc332
-rw-r--r--intern/opensubdiv/opensubdiv_topology_refiner.h41
36 files changed, 939 insertions, 511 deletions
diff --git a/intern/atomic/intern/atomic_ops_utils.h b/intern/atomic/intern/atomic_ops_utils.h
index fcbb2346243..bfec9918c16 100644
--- a/intern/atomic/intern/atomic_ops_utils.h
+++ b/intern/atomic/intern/atomic_ops_utils.h
@@ -81,7 +81,9 @@
# endif
#endif
-#ifdef UINTPTR_MAX
+#if defined(__SIZEOF_POINTER__)
+# define LG_SIZEOF_PTR __SIZEOF_POINTER__
+#elif defined(UINTPTR_MAX)
# if (UINTPTR_MAX == 0xFFFFFFFF)
# define LG_SIZEOF_PTR 4
# elif (UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF)
diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp
index 300fd55e23b..de5c0a2f463 100644
--- a/intern/audaspace/Python/AUD_PyAPI.cpp
+++ b/intern/audaspace/Python/AUD_PyAPI.cpp
@@ -861,7 +861,7 @@ Factory_filter(Factory* self, PyObject *args)
py_a_len= py_a ? PySequence_Size(py_a) : 0;
py_b_len= PySequence_Size(py_b);
- if(!py_b_len || ((py_a != NULL) && !py_b_len))
+ if(!py_b_len || ((py_a != NULL) && !py_a_len))
{
PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
return NULL;
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 04feb979165..7dc0f46fa86 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -505,7 +505,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
)
cls.debug_use_hair_bvh = BoolProperty(
name="Use Hair BVH",
- description="Use special type BVH optimized for hair. Uses more ram but renders faster",
+ description="Use special type BVH optimized for hair (uses more ram but renders faster)",
default=True,
)
cls.tile_order = EnumProperty(
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 6faec5e013b..c2538f2edd9 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -459,7 +459,9 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_z")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_normal")
- col.prop(rl, "use_pass_vector")
+ row = col.row()
+ row.prop(rl, "use_pass_vector")
+ row.active = not rd.use_motion_blur
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_object_index")
col.prop(rl, "use_pass_material_index")
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 4bd385c4200..ec11a893b5a 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -680,6 +680,43 @@ static void create_subd_mesh(Scene *scene,
/* Sync */
+static void sync_mesh_fluid_motion(BL::Object& b_ob, Scene *scene, Mesh *mesh)
+{
+ if(scene->need_motion() == Scene::MOTION_NONE)
+ return;
+
+ BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
+
+ if(!b_fluid_domain)
+ return;
+
+ /* If the mesh has modifiers following the fluid domain we can't export motion. */
+ if(b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size())
+ return;
+
+ /* Find or add attribute */
+ float3 *P = &mesh->verts[0];
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if(!attr_mP) {
+ attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+
+ /* Only export previous and next frame, we don't have any in between data. */
+ float motion_times[2] = {-1.0f, 1.0f};
+ for (int step = 0; step < 2; step++) {
+ float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
+ float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
+
+ BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi;
+ int i = 0;
+
+ for(b_fluid_domain.fluid_mesh_vertices.begin(fvi); fvi != b_fluid_domain.fluid_mesh_vertices.end(); ++fvi, ++i) {
+ mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time;
+ }
+ }
+}
+
Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
bool object_updated,
bool hide_tris)
@@ -821,6 +858,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
mesh->displacement_method = Mesh::DISPLACE_BOTH;
}
+ /* fluid motion */
+ sync_mesh_fluid_motion(b_ob, scene, mesh);
+
/* tag update */
bool rebuild = false;
@@ -910,6 +950,11 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
* would need a more extensive check to see which objects are animated */
BL::Mesh b_mesh(PointerRNA_NULL);
+ /* fluid motion is exported immediate with mesh, skip here */
+ BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
+ if (b_fluid_domain)
+ return;
+
if(ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
/* get derived mesh */
b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, false);
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 890ae76f6cc..471afa70611 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -253,11 +253,10 @@ static bool object_boundbox_clip(Scene *scene,
boundbox[3 * i + 1],
boundbox[3 * i + 2]);
p = transform_point(&tfm, p);
- p = transform_point(&worldtondc, p);
+ p = transform_perspective(&worldtondc, p);
if(p.z >= -margin) {
all_behind = false;
}
- p /= p.z;
bb_min = min(bb_min, p);
bb_max = max(bb_max, p);
}
@@ -682,12 +681,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
<< relative_time << ".";
/* fixed shutter time to get previous and next frame for motion pass */
- float shuttertime;
-
- if(scene->need_motion() == Scene::MOTION_PASS)
- shuttertime = 2.0f;
- else
- shuttertime = scene->camera->shuttertime;
+ float shuttertime = scene->motion_shutter_time();
/* compute frame and subframe time */
float time = frame_center + frame_center_delta + relative_time * shuttertime * 0.5f;
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index e7361589436..8caa8070939 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -131,7 +131,9 @@ private:
Transform& tfm,
bool *use_portal);
void sync_background_light(bool use_portal);
- void sync_mesh_motion(BL::Object& b_ob, Object *object, float motion_time);
+ void sync_mesh_motion(BL::Object& b_ob,
+ Object *object,
+ float motion_time);
void sync_camera_motion(BL::RenderSettings& b_render,
BL::Object& b_ob,
int width, int height,
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 89a53a1deca..798fe36d4fe 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -519,6 +519,23 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
return BL::SmokeDomainSettings(PointerRNA_NULL);
}
+static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
+{
+ BL::Object::modifiers_iterator b_mod;
+
+ for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if(b_mod->is_a(&RNA_FluidSimulationModifier)) {
+ BL::FluidSimulationModifier b_fmd(*b_mod);
+ BL::FluidSettings fss = b_fmd.settings();
+
+ if(fss.type() == BL::FluidSettings::type_DOMAIN)
+ return (BL::DomainFluidSettings)b_fmd.settings();
+ }
+ }
+
+ return BL::DomainFluidSettings(PointerRNA_NULL);
+}
+
/* ID Map
*
* Utility class to keep in sync with blender data.
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h
index 2fb8e219884..dabba3fb1f0 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle.h
@@ -387,6 +387,12 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
float t, u, v;
if(ray_triangle_intersect_uv(P, dir, tmax, verts[2], verts[0], verts[1], &u, &v, &t)) {
+ for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
+ if(ss_isect->hits[i].t == t) {
+ return;
+ }
+ }
+
ss_isect->num_hits++;
int hit;
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index 720ee6a1f5c..caa6c9d9a5b 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -256,7 +256,7 @@ ccl_device_inline void triangle_intersect_subsurface(
const float inv_det = 1.0f / det;
const float t = T * inv_det;
- for(int i = min(max_hits, ss_isect->num_hits); i >= 0; --i) {
+ for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
return;
}
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 5f5a3609ded..0e13b22bd2c 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -50,7 +50,7 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
else
eval->diffuse = value;
#else
- *eval = value;
+ eval->diffuse = value;
#endif
}
@@ -80,7 +80,7 @@ void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
else
eval->diffuse += value;
#else
- *eval += value;
+ eval->diffuse += value;
#endif
}
@@ -98,7 +98,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
else
return is_zero(eval->diffuse);
#else
- return is_zero(*eval);
+ return is_zero(eval->diffuse);
#endif
}
@@ -117,7 +117,7 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
else
eval->diffuse *= value;
#else
- *eval *= value;
+ eval->diffuse *= value;
#endif
}
@@ -172,7 +172,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
else
L->emission = make_float3(0.0f, 0.0f, 0.0f);
#else
- *L = make_float3(0.0f, 0.0f, 0.0f);
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
@@ -207,7 +207,7 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space
else
*throughput *= bsdf_eval->diffuse*inverse_pdf;
#else
- *throughput *= *bsdf_eval*inverse_pdf;
+ *throughput *= bsdf_eval->diffuse*inverse_pdf;
#endif
}
@@ -225,7 +225,7 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro
else
L->emission += throughput*value;
#else
- *L += throughput*value;
+ L->emission += throughput*value;
#endif
}
@@ -246,7 +246,7 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput
else
L->emission += throughput*bsdf*ao;
#else
- *L += throughput*bsdf*ao;
+ L->emission += throughput*bsdf*ao;
#endif
}
@@ -277,7 +277,7 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
else
L->emission += throughput*bsdf_eval->diffuse*shadow;
#else
- *L += throughput*(*bsdf_eval)*shadow;
+ L->emission += throughput*bsdf_eval->diffuse*shadow;
#endif
}
@@ -295,7 +295,7 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th
else
L->emission += throughput*value;
#else
- *L += throughput*value;
+ L->emission += throughput*value;
#endif
}
@@ -441,7 +441,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
else
L_sum = L->emission;
#else
- L_sum = *L;
+ L_sum = L->emission;
#endif
/* Reject invalid value */
@@ -477,7 +477,7 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
L->shadow += L_sample->shadow*fac;
L->mist += L_sample->mist*fac;
#else
- *L += *L_sample * fac;
+ L->emission += L_sample->emission * fac;
#endif
}
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 5de58ba28ed..a9be2ae717a 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -387,12 +387,13 @@ typedef enum BakePassFilterCombos {
BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE),
} BakePassFilterCombos;
-#ifdef __PASSES__
-
typedef ccl_addr_space struct PathRadiance {
+#ifdef __PASSES__
int use_light_pass;
+#endif
float3 emission;
+#ifdef __PASSES__
float3 background;
float3 ao;
@@ -426,25 +427,23 @@ typedef ccl_addr_space struct PathRadiance {
float4 shadow;
float mist;
+#endif
} PathRadiance;
typedef struct BsdfEval {
+#ifdef __PASSES__
int use_light_pass;
+#endif
float3 diffuse;
+#ifdef __PASSES__
float3 glossy;
float3 transmission;
float3 transparent;
float3 subsurface;
float3 scatter;
-} BsdfEval;
-
-#else
-
-typedef ccl_addr_space float3 PathRadiance;
-typedef float3 BsdfEval;
-
#endif
+} BsdfEval;
/* Shader Flag */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
index 962196ccbdd..ec82d4b4c22 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
@@ -109,6 +109,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
{
if(type >= SHADER_EVAL_BAKE) {
kernel_assert(output_luma == NULL);
+#ifdef __BAKING__
kernel_bake_evaluate(kg,
input,
output,
@@ -117,6 +118,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
i,
offset,
sample);
+#endif
}
else {
kernel_shader_evaluate(kg,
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index b14da3e63d0..a632ddc0598 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -22,6 +22,7 @@ set(SRC
bake.cpp
buffers.cpp
camera.cpp
+ constant_fold.cpp
film.cpp
graph.cpp
image.cpp
@@ -49,6 +50,7 @@ set(SRC_HEADERS
background.h
buffers.h
camera.h
+ constant_fold.h
film.h
graph.h
image.h
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
new file mode 100644
index 00000000000..1fee6b2c081
--- /dev/null
+++ b/intern/cycles/render/constant_fold.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "constant_fold.h"
+#include "graph.h"
+
+#include "util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output)
+: graph(graph), node(node), output(output)
+{
+}
+
+bool ConstantFolder::all_inputs_constant() const
+{
+ foreach(ShaderInput *input, node->inputs) {
+ if(input->link) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void ConstantFolder::make_constant(float value) const
+{
+ foreach(ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
+
+ graph->disconnect(output);
+}
+
+void ConstantFolder::make_constant(float3 value) const
+{
+ foreach(ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
+
+ graph->disconnect(output);
+}
+
+void ConstantFolder::make_constant_clamp(float value, bool clamp) const
+{
+ make_constant(clamp ? saturate(value) : value);
+}
+
+void ConstantFolder::make_constant_clamp(float3 value, bool clamp) const
+{
+ if (clamp) {
+ value.x = saturate(value.x);
+ value.y = saturate(value.y);
+ value.z = saturate(value.z);
+ }
+
+ make_constant(value);
+}
+
+void ConstantFolder::bypass(ShaderOutput *new_output) const
+{
+ assert(new_output);
+
+ /* Remove all outgoing links from socket and connect them to new_output instead.
+ * The graph->relink method affects node inputs, so it's not safe to use in constant
+ * folding if the node has multiple outputs and will thus be folded multiple times. */
+ vector<ShaderInput*> outputs = output->links;
+
+ graph->disconnect(output);
+
+ foreach(ShaderInput *sock, outputs) {
+ graph->connect(new_output, sock);
+ }
+}
+
+void ConstantFolder::discard() const
+{
+ assert(output->type() == SocketType::CLOSURE);
+ graph->disconnect(output);
+}
+
+void ConstantFolder::bypass_or_discard(ShaderInput *input) const
+{
+ assert(input->type() == SocketType::CLOSURE);
+
+ if (input->link) {
+ bypass(input->link);
+ }
+ else {
+ discard();
+ }
+}
+
+bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, float3 input_value, bool clamp) const
+{
+ if(!input->link) {
+ make_constant_clamp(input_value, clamp);
+ return true;
+ }
+ else if(!clamp) {
+ bypass(input->link);
+ return true;
+ }
+
+ return false;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
new file mode 100644
index 00000000000..978c8e5335a
--- /dev/null
+++ b/intern/cycles/render/constant_fold.h
@@ -0,0 +1,59 @@
+/*
+ * 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 __CONSTANT_FOLD_H__
+#define __CONSTANT_FOLD_H__
+
+#include "util_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+class ShaderGraph;
+class ShaderInput;
+class ShaderNode;
+class ShaderOutput;
+
+class ConstantFolder {
+public:
+ ShaderGraph *const graph;
+ ShaderNode *const node;
+ ShaderOutput *const output;
+
+ ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output);
+
+ bool all_inputs_constant() const;
+
+ /* Constant folding helpers, always return true for convenience. */
+ void make_constant(float value) const;
+ void make_constant(float3 value) const;
+ void make_constant_clamp(float value, bool clamp) const;
+ void make_constant_clamp(float3 value, bool clamp) const;
+
+ /* Bypass node, relinking to another output socket. */
+ void bypass(ShaderOutput *output) const;
+
+ /* For closure nodes, discard node entirely or bypass to one of its inputs. */
+ void discard() const;
+ void bypass_or_discard(ShaderInput *input) const;
+
+ /* Bypass or make constant, unless we can't due to clamp being true. */
+ bool try_bypass_or_make_constant(ShaderInput *input, float3 input_value, bool clamp) const;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __CONSTANT_FOLD_H__ */
+
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index fd48bf2631e..66601fa3502 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2016 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
#include "graph.h"
#include "nodes.h"
#include "shader.h"
+#include "constant_fold.h"
#include "util_algorithm.h"
#include "util_debug.h"
@@ -126,17 +127,6 @@ ShaderOutput *ShaderNode::output(ustring name)
return NULL;
}
-bool ShaderNode::all_inputs_constant() const
-{
- foreach(ShaderInput *input, inputs) {
- if(input->link) {
- return false;
- }
- }
-
- return true;
-}
-
void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
foreach(ShaderInput *input, inputs) {
@@ -278,6 +268,17 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
}
}
+void ShaderGraph::disconnect(ShaderOutput *from)
+{
+ assert(!finalized);
+
+ foreach(ShaderInput *sock, from->links) {
+ sock->link = NULL;
+ }
+
+ from->links.clear();
+}
+
void ShaderGraph::disconnect(ShaderInput *to)
{
assert(!finalized);
@@ -373,24 +374,12 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
ShaderNode *nnode = node->clone();
nnodemap[node] = nnode;
+ /* create new inputs and outputs to recreate links and ensure
+ * that we still point to valid SocketType if the NodeType
+ * changed in cloning, as it does for OSL nodes */
nnode->inputs.clear();
nnode->outputs.clear();
-
- foreach(ShaderInput *input, node->inputs) {
- ShaderInput *ninput = new ShaderInput(*input);
- nnode->inputs.push_back(ninput);
-
- ninput->parent = nnode;
- ninput->link = NULL;
- }
-
- foreach(ShaderOutput *output, node->outputs) {
- ShaderOutput *noutput = new ShaderOutput(*output);
- nnode->outputs.push_back(noutput);
-
- noutput->parent = nnode;
- noutput->links.clear();
- }
+ nnode->create_inputs_outputs(nnode->type);
}
/* recreate links */
@@ -525,15 +514,8 @@ void ShaderGraph::constant_fold()
}
}
/* Optimize current node. */
- if(node->constant_fold(this, output, output->links[0])) {
- /* Apply optimized value to other connected sockets and disconnect. */
- vector<ShaderInput*> links(output->links);
- for(size_t i = 0; i < links.size(); i++) {
- if(i > 0)
- links[i]->parent->copy_value(links[i]->socket_type, *links[0]->parent, links[0]->socket_type);
- disconnect(links[i]);
- }
- }
+ ConstantFolder folder(this, node, output);
+ node->constant_fold(folder);
}
}
}
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 61100cda60b..b35be48d8ca 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2016 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@ class ShaderGraph;
class SVMCompiler;
class OSLCompiler;
class OutputNode;
+class ConstantFolder;
/* Bump
*
@@ -140,9 +141,7 @@ public:
/* ** Node optimization ** */
/* Check whether the node can be replaced with single constant. */
- virtual bool constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, ShaderInput * /*optimized*/) { return false; }
-
- bool all_inputs_constant() const;
+ virtual void constant_fold(const ConstantFolder& /*folder*/) {}
/* Simplify settings used by artists to the ones which are simpler to
* evaluate in the kernel but keep the final result unchanged.
@@ -251,6 +250,7 @@ public:
OutputNode *output();
void connect(ShaderOutput *from, ShaderInput *to);
+ void disconnect(ShaderOutput *from);
void disconnect(ShaderInput *to);
void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index a8fd9da9ced..e26084c690b 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -22,6 +22,7 @@
#include "svm_color_util.h"
#include "svm_math_util.h"
#include "osl.h"
+#include "constant_fold.h"
#include "util_sky_model.h"
#include "util_foreach.h"
@@ -1576,16 +1577,11 @@ RGBToBWNode::RGBToBWNode()
{
}
-bool RGBToBWNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void RGBToBWNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(linear_rgb_to_gray(color));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(linear_rgb_to_gray(color));
}
-
- return false;
}
void RGBToBWNode::compile(SVMCompiler& compiler)
@@ -1663,40 +1659,35 @@ ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool auto
special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
}
-bool ConvertNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void ConvertNode::constant_fold(const ConstantFolder& folder)
{
/* proxy nodes should have been removed at this point */
assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
/* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
- if(all_inputs_constant()) {
+ if(folder.all_inputs_constant()) {
if(from == SocketType::FLOAT) {
if(SocketType::is_float3(to)) {
- optimized->set(make_float3(value_float, value_float, value_float));
- return true;
+ folder.make_constant(make_float3(value_float, value_float, value_float));
}
}
else if(SocketType::is_float3(from)) {
if(to == SocketType::FLOAT) {
- if(from == SocketType::COLOR)
+ if(from == SocketType::COLOR) {
/* color to float */
- optimized->set(linear_rgb_to_gray(value_color));
- else
+ folder.make_constant(linear_rgb_to_gray(value_color));
+ }
+ else {
/* vector/point/normal to float */
- optimized->set(average(value_vector));
- return true;
+ folder.make_constant(average(value_vector));
+ }
}
else if(SocketType::is_float3(to)) {
- optimized->set(value_color);
- return true;
+ folder.make_constant(value_color);
}
}
}
-
- return false;
}
void ConvertNode::compile(SVMCompiler& compiler)
@@ -2366,15 +2357,15 @@ void EmissionNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_emission");
}
-bool EmissionNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput * /*optimized*/)
+void EmissionNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
- return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength == 0.0f));
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Background Closure */
@@ -2418,15 +2409,15 @@ void BackgroundNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_background");
}
-bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput * /*optimized*/)
+void BackgroundNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
- return ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength == 0.0f));
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Holdout Closure */
@@ -3388,12 +3379,9 @@ ValueNode::ValueNode()
{
}
-bool ValueNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void ValueNode::constant_fold(const ConstantFolder& folder)
{
- optimized->set(value);
- return true;
+ folder.make_constant(value);
}
void ValueNode::compile(SVMCompiler& compiler)
@@ -3426,12 +3414,9 @@ ColorNode::ColorNode()
{
}
-bool ColorNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void ColorNode::constant_fold(const ConstantFolder& folder)
{
- optimized->set(value);
- return true;
+ folder.make_constant(value);
}
void ColorNode::compile(SVMCompiler& compiler)
@@ -3480,6 +3465,20 @@ void AddClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_add_closure");
}
+void AddClosureNode::constant_fold(const ConstantFolder& folder)
+{
+ ShaderInput *closure1_in = input("Closure1");
+ ShaderInput *closure2_in = input("Closure2");
+
+ /* remove useless add closures nodes */
+ if(!closure1_in->link) {
+ folder.bypass_or_discard(closure2_in);
+ }
+ else if(!closure2_in->link) {
+ folder.bypass_or_discard(closure1_in);
+ }
+}
+
/* Mix Closure */
NODE_DEFINE(MixClosureNode)
@@ -3511,37 +3510,28 @@ void MixClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mix_closure");
}
-bool MixClosureNode::constant_fold(ShaderGraph *graph,
- ShaderOutput * /*socket*/,
- ShaderInput * /*optimized*/)
+void MixClosureNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *closure1_in = input("Closure1");
ShaderInput *closure2_in = input("Closure2");
- ShaderOutput *closure_out = output("Closure");
/* remove useless mix closures nodes */
if(closure1_in->link == closure2_in->link) {
- graph->relink(this, closure_out, closure1_in->link);
- return true;
+ folder.bypass_or_discard(closure1_in);
}
-
- /* remove unused mix closure input when factor is 0.0 or 1.0 */
- /* check for closure links and make sure factor link is disconnected */
- if(closure1_in->link && closure2_in->link && !fac_in->link) {
+ /* remove unused mix closure input when factor is 0.0 or 1.0
+ * check for closure links and make sure factor link is disconnected */
+ else if(!fac_in->link) {
/* factor 0.0 */
- if(fac == 0.0f) {
- graph->relink(this, closure_out, closure1_in->link);
- return true;
+ if(fac <= 0.0f) {
+ folder.bypass_or_discard(closure1_in);
}
/* factor 1.0 */
- else if(fac == 1.0f) {
- graph->relink(this, closure_out, closure2_in->link);
- return true;
+ else if(fac >= 1.0f) {
+ folder.bypass_or_discard(closure2_in);
}
}
-
- return false;
}
/* Mix Closure */
@@ -3603,28 +3593,21 @@ InvertNode::InvertNode()
{
}
-bool InvertNode::constant_fold(ShaderGraph *graph,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void InvertNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *color_in = input("Color");
- ShaderOutput *color_out = output("Color");
if(!fac_in->link) {
/* evaluate fully constant node */
if(!color_in->link) {
- optimized->set(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
- return true;
+ folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
}
/* remove no-op node */
else if(fac == 0.0f) {
- graph->relink(this, color_out, color_in->link);
- return true;
+ folder.bypass(color_in->link);
}
}
-
- return false;
}
void InvertNode::compile(SVMCompiler& compiler)
@@ -3713,63 +3696,47 @@ void MixNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mix");
}
-bool MixNode::constant_fold(ShaderGraph *graph,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void MixNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *color1_in = input("Color1");
ShaderInput *color2_in = input("Color2");
- ShaderOutput *color_out = output("Color");
/* evaluate fully constant node */
- if(all_inputs_constant()) {
- float3 result = svm_mix(type, fac, color1, color2);
- optimized->set(use_clamp ? svm_mix_clamp(result) : result);
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
+ return;
}
/* remove no-op node when factor is 0.0 */
if(!fac_in->link && fac <= 0.0f) {
/* note that some of the modes will clamp out of bounds values even without use_clamp */
- if(!color1_in->link) {
- float3 result = svm_mix(type, 0.0f, color1, color1);
- optimized->set(use_clamp ? svm_mix_clamp(result) : result);
- return true;
+ if(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN) {
+ if(!color1_in->link) {
+ folder.make_constant_clamp(svm_mix(type, 0.0f, color1, color1), use_clamp);
+ return;
+ }
}
- else if(!use_clamp && type != NODE_MIX_LIGHT && type != NODE_MIX_DODGE && type != NODE_MIX_BURN) {
- graph->relink(this, color_out, color1_in->link);
- return true;
+ else if(folder.try_bypass_or_make_constant(color1_in, color1, use_clamp)) {
+ return;
}
}
- if(type != NODE_MIX_BLEND) {
- return false;
- }
-
- /* remove useless mix colors nodes */
- if(color1_in->link && color1_in->link == color2_in->link && !use_clamp) {
- graph->relink(this, color_out, color1_in->link);
- return true;
- }
- if(!color1_in->link && !color2_in->link && color1 == color2) {
- optimized->set(use_clamp ? svm_mix_clamp(color1) : color1);
- return true;
- }
-
- /* remove no-op mix color node when factor is 1.0 */
- if(!fac_in->link && fac >= 1.0f) {
- if(!color2_in->link) {
- optimized->set(use_clamp ? svm_mix_clamp(color2) : color2);
- return true;
+ if(type == NODE_MIX_BLEND) {
+ /* remove useless mix colors nodes */
+ if(color1_in->link ? (color1_in->link == color2_in->link) : (!color2_in->link && color1 == color2)) {
+ if(folder.try_bypass_or_make_constant(color1_in, color1, use_clamp)) {
+ return;
+ }
}
- else if(!use_clamp) {
- graph->relink(this, color_out, color2_in->link);
- return true;
+
+ /* remove no-op mix color node when factor is 1.0 */
+ if(!fac_in->link && fac >= 1.0f) {
+ if(folder.try_bypass_or_make_constant(color2_in, color2, use_clamp)) {
+ return;
+ }
}
}
-
- return false;
}
/* Combine RGB */
@@ -3792,16 +3759,11 @@ CombineRGBNode::CombineRGBNode()
{
}
-bool CombineRGBNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void CombineRGBNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(make_float3(r, g, b));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(r, g, b));
}
-
- return false;
}
void CombineRGBNode::compile(SVMCompiler& compiler)
@@ -3849,16 +3811,11 @@ CombineXYZNode::CombineXYZNode()
{
}
-bool CombineXYZNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void CombineXYZNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(make_float3(x, y, z));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(x, y, z));
}
-
- return false;
}
void CombineXYZNode::compile(SVMCompiler& compiler)
@@ -3906,16 +3863,11 @@ CombineHSVNode::CombineHSVNode()
{
}
-bool CombineHSVNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void CombineHSVNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(hsv_to_rgb(make_float3(h, s, v)));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
}
-
- return false;
}
void CombineHSVNode::compile(SVMCompiler& compiler)
@@ -3956,16 +3908,11 @@ GammaNode::GammaNode()
{
}
-bool GammaNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void GammaNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(svm_math_gamma_color(color, gamma));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_gamma_color(color, gamma));
}
-
- return false;
}
void GammaNode::compile(SVMCompiler& compiler)
@@ -4005,16 +3952,11 @@ BrightContrastNode::BrightContrastNode()
{
}
-bool BrightContrastNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void BrightContrastNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(svm_brightness_contrast(color, bright, contrast));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(svm_brightness_contrast(color, bright, contrast));
}
-
- return false;
}
void BrightContrastNode::compile(SVMCompiler& compiler)
@@ -4057,20 +3999,16 @@ SeparateRGBNode::SeparateRGBNode()
{
}
-bool SeparateRGBNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput *socket,
- ShaderInput *optimized)
+void SeparateRGBNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
+ if(folder.all_inputs_constant()) {
for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == socket) {
- optimized->set(color[channel]);
- return true;
+ if(outputs[channel] == folder.output) {
+ folder.make_constant(color[channel]);
+ return;
}
}
}
-
- return false;
}
void SeparateRGBNode::compile(SVMCompiler& compiler)
@@ -4118,20 +4056,16 @@ SeparateXYZNode::SeparateXYZNode()
{
}
-bool SeparateXYZNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput *socket,
- ShaderInput *optimized)
+void SeparateXYZNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
+ if(folder.all_inputs_constant()) {
for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == socket) {
- optimized->set(vector[channel]);
- return true;
+ if(outputs[channel] == folder.output) {
+ folder.make_constant(vector[channel]);
+ return;
}
}
}
-
- return false;
}
void SeparateXYZNode::compile(SVMCompiler& compiler)
@@ -4179,22 +4113,18 @@ SeparateHSVNode::SeparateHSVNode()
{
}
-bool SeparateHSVNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput *socket,
- ShaderInput *optimized)
+void SeparateHSVNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
+ if(folder.all_inputs_constant()) {
float3 hsv = rgb_to_hsv(color);
for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == socket) {
- optimized->set(hsv[channel]);
- return true;
+ if(outputs[channel] == folder.output) {
+ folder.make_constant(hsv[channel]);
+ return;
}
}
}
-
- return false;
}
void SeparateHSVNode::compile(SVMCompiler& compiler)
@@ -4580,16 +4510,11 @@ BlackbodyNode::BlackbodyNode()
{
}
-bool BlackbodyNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void BlackbodyNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- optimized->set(svm_math_blackbody_color(temperature));
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_blackbody_color(temperature));
}
-
- return false;
}
void BlackbodyNode::compile(SVMCompiler& compiler)
@@ -4691,17 +4616,11 @@ MathNode::MathNode()
{
}
-bool MathNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- ShaderInput *optimized)
+void MathNode::constant_fold(const ConstantFolder& folder)
{
- if(all_inputs_constant()) {
- float value = svm_math(type, value1, value2);
- optimized->set(use_clamp ? saturate(value) : value);
- return true;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
}
-
- return false;
}
void MathNode::compile(SVMCompiler& compiler)
@@ -4755,31 +4674,25 @@ VectorMathNode::VectorMathNode()
{
}
-bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput *socket,
- ShaderInput *optimized)
+void VectorMathNode::constant_fold(const ConstantFolder& folder)
{
float value;
float3 vector;
- if(all_inputs_constant()) {
+ if(folder.all_inputs_constant()) {
svm_vector_math(&value,
&vector,
type,
vector1,
vector2);
- if(socket == output("Value")) {
- optimized->set(value);
- return true;
+ if(folder.output == output("Value")) {
+ folder.make_constant(value);
}
- else if(socket == output("Vector")) {
- optimized->set(vector);
- return true;
+ else if(folder.output == output("Vector")) {
+ folder.make_constant(vector);
}
}
-
- return false;
}
void VectorMathNode::compile(SVMCompiler& compiler)
@@ -4913,9 +4826,7 @@ void BumpNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_bump");
}
-bool BumpNode::constant_fold(ShaderGraph *graph,
- ShaderOutput * /*socket*/,
- ShaderInput * /*optimized*/)
+void BumpNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *height_in = input("Height");
ShaderInput *normal_in = input("Normal");
@@ -4923,18 +4834,15 @@ bool BumpNode::constant_fold(ShaderGraph *graph,
if(height_in->link == NULL) {
if(normal_in->link == NULL) {
GeometryNode *geom = new GeometryNode();
- graph->add(geom);
- graph->relink(this, outputs[0], geom->output("Normal"));
+ folder.graph->add(geom);
+ folder.bypass(geom->output("Normal"));
}
else {
- graph->relink(this, outputs[0], normal_in->link);
+ folder.bypass(normal_in->link);
}
- return true;
}
/* TODO(sergey): Ignore bump with zero strength. */
-
- return false;
}
@@ -5154,12 +5062,10 @@ OSLNode::~OSLNode()
ShaderNode *OSLNode::clone() const
{
- OSLNode *node = new OSLNode(*this);
- node->type = new NodeType(*type);
- return node;
+ return OSLNode::create(this->inputs.size(), this);
}
-OSLNode* OSLNode::create(size_t num_inputs)
+OSLNode* OSLNode::create(size_t num_inputs, const OSLNode *from)
{
/* allocate space for the node itself and parameters, aligned to 16 bytes
* assuming that's the most parameter types need */
@@ -5169,7 +5075,17 @@ OSLNode* OSLNode::create(size_t num_inputs)
char *node_memory = (char*) operator new(node_size + inputs_size);
memset(node_memory, 0, node_size + inputs_size);
- return new(node_memory) OSLNode();
+ if (!from) {
+ return new(node_memory) OSLNode();
+ }
+ else {
+ /* copy input default values and node type for cloning */
+ memcpy(node_memory + node_size, (char*)from + node_size, inputs_size);
+
+ OSLNode *node = new(node_memory) OSLNode(*from);
+ node->type = new NodeType(*(from->type));
+ return node;
+ }
}
char* OSLNode::input_default_value()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 3245fdfb6d9..caad11af0f8 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -289,7 +289,7 @@ public:
class RGBToBWNode : public ShaderNode {
public:
SHADER_NODE_CLASS(RGBToBWNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
float3 color;
};
@@ -299,7 +299,7 @@ public:
ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
SHADER_NODE_BASE_CLASS(ConvertNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
SocketType::Type from, to;
@@ -436,7 +436,7 @@ public:
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual ClosureType get_closure_type() { return CLOSURE_EMISSION_ID; }
bool has_surface_emission() { return true; }
@@ -449,7 +449,7 @@ public:
class BackgroundNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BackgroundNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual ClosureType get_closure_type() { return CLOSURE_BACKGROUND_ID; }
float3 color;
@@ -605,7 +605,7 @@ class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
float value;
};
@@ -614,7 +614,7 @@ class ColorNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ColorNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
float3 value;
};
@@ -622,12 +622,13 @@ public:
class AddClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(AddClosureNode)
+ void constant_fold(const ConstantFolder& folder);
};
class MixClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
float fac;
};
@@ -643,7 +644,7 @@ public:
class InvertNode : public ShaderNode {
public:
SHADER_NODE_CLASS(InvertNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float fac;
@@ -653,7 +654,7 @@ public:
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
@@ -667,7 +668,7 @@ public:
class CombineRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineRGBNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float r, g, b;
@@ -676,7 +677,7 @@ public:
class CombineHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineHSVNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float h, s, v;
@@ -685,7 +686,7 @@ public:
class CombineXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineXYZNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float x, y, z;
@@ -694,7 +695,7 @@ public:
class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
float3 color;
@@ -704,7 +705,7 @@ public:
class BrightContrastNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BrightContrastNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
float3 color;
@@ -715,7 +716,7 @@ public:
class SeparateRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateRGBNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float3 color;
@@ -724,7 +725,7 @@ public:
class SeparateHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateHSVNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float3 color;
@@ -733,7 +734,7 @@ public:
class SeparateXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateXYZNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float3 vector;
@@ -806,7 +807,7 @@ public:
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float temperature;
@@ -816,7 +817,7 @@ class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
float value1;
float value2;
@@ -837,7 +838,7 @@ class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
float3 vector1;
float3 vector2;
@@ -859,7 +860,7 @@ public:
class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+ void constant_fold(const ConstantFolder& folder);
bool has_spatial_varying() { return true; }
virtual int get_feature() {
return NODE_FEATURE_BUMP;
@@ -920,7 +921,7 @@ public:
class OSLNode : public ShaderNode {
public:
- static OSLNode *create(size_t num_inputs);
+ static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
~OSLNode();
ShaderNode *clone() const;
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index e8367e1eb36..b341837b7e8 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -263,6 +263,14 @@ Scene::MotionType Scene::need_motion(bool advanced_shading)
return MOTION_NONE;
}
+float Scene::motion_shutter_time()
+{
+ if(need_motion() == Scene::MOTION_PASS)
+ return 2.0f;
+ else
+ return camera->shuttertime;
+}
+
bool Scene::need_global_attribute(AttributeStandard std)
{
if(std == ATTR_STD_UV)
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 5abcbfcdaad..05e807ff60c 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -213,6 +213,7 @@ public:
enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
MotionType need_motion(bool advanced_shading = true);
+ float motion_shutter_time();
bool need_update();
bool need_reset();
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 7e77ba3a41f..0dd5d15b011 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -530,7 +530,7 @@ typedef struct {
#ifdef _WIN32
-typedef long GHOST_TEmbedderWindowID;
+typedef void* GHOST_TEmbedderWindowID;
#endif // _WIN32
#ifndef _WIN32
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
index eeb6a2469ee..abce3ea6588 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -707,6 +707,7 @@ int GHOST_ContextWGL::choose_pixel_format(
PIXELFORMATDESCRIPTOR preferredPFD = {
sizeof(PIXELFORMATDESCRIPTOR), /* size */
1, /* version */
+ (DWORD) (
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_SWAP_COPY | /* support swap copy */
@@ -717,16 +718,16 @@ int GHOST_ContextWGL::choose_pixel_format(
needAlpha ? PFD_SUPPORT_COMPOSITION : /* support composition for transparent background */
#endif
0
- ),
+ )),
PFD_TYPE_RGBA, /* color type */
- (needAlpha ? 32 : 24), /* preferred color depth */
+ (BYTE) (needAlpha ? 32 : 24), /* preferred color depth */
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
- needAlpha ? 8 : 0, /* alpha buffer */
+ (BYTE) (needAlpha ? 8 : 0), /* alpha buffer */
0, /* alpha shift (ignored) */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits (ignored) */
24, /* depth buffer */
- needStencil ? 8 : 0, /* stencil buffer */
+ (BYTE) (needStencil ? 8 : 0), /* stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
index af5a2ed7097..96bd12faef8 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.cpp
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -64,7 +64,7 @@ bool GHOST_ImeWin32::SetInputLanguage()
* while composing a text.
*/
HKL keyboard_layout = ::GetKeyboardLayout(0);
- input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout);
+ input_language_id_ = LOWORD(keyboard_layout);
ime_status_ = ::ImmIsIME(keyboard_layout);
return ime_status_;
}
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index c9bcb38ab68..6a27d7aadf9 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -95,31 +95,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_parentWindowHwnd(parentwindowhwnd),
m_debug_context(is_debug)
{
- OSVERSIONINFOEX versionInfo;
- bool hasMinVersionForTaskbar = false;
-
- ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
-
- versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
- versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
- if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
- (versionInfo.dwMajorVersion >= 7))
- {
- hasMinVersionForTaskbar = true;
- }
- }
- }
- else {
- if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
- (versionInfo.dwMajorVersion >= 7))
- {
- hasMinVersionForTaskbar = true;
- }
- }
-
if (state != GHOST_kWindowStateFullScreen) {
RECT rect;
MONITORINFO monitor;
@@ -341,11 +316,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
}
}
-
- if (hasMinVersionForTaskbar)
- CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList, (LPVOID *)&m_Bar);
- else
- m_Bar = NULL;
+ CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}
diff --git a/intern/libmv/intern/autotrack.cc b/intern/libmv/intern/autotrack.cc
index f0cbc68f11e..3b7c9c5a010 100644
--- a/intern/libmv/intern/autotrack.cc
+++ b/intern/libmv/intern/autotrack.cc
@@ -67,12 +67,12 @@ int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
libmv_apiMarkerToMarker(*libmv_tracked_marker, &tracked_marker);
libmv_configureTrackRegionOptions(*libmv_options,
&options);
- (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
- &result,
- &options));
+ bool ok = (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
+ &result,
+ &options));
libmv_markerToApiMarker(tracked_marker, libmv_tracked_marker);
libmv_regionTrackergetResult(result, libmv_result);
- return result.is_usable();
+ return ok && result.is_usable();
}
void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,
diff --git a/intern/libmv/libmv/numeric/numeric.cc b/intern/libmv/libmv/numeric/numeric.cc
index 9007663c8e2..3fc1e3b2bfd 100644
--- a/intern/libmv/libmv/numeric/numeric.cc
+++ b/intern/libmv/libmv/numeric/numeric.cc
@@ -109,7 +109,7 @@ void MeanAndVarianceAlongRows(const Mat &A,
}
void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked) {
- assert(left.rows() == left.rows());
+ assert(left.rows() == right.rows());
int n = left.rows();
int m1 = left.cols();
int m2 = right.cols();
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index 311b89b97cf..f8e80de7f8f 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SRC
opensubdiv_device_context_cuda.h
opensubdiv_device_context_opencl.h
opensubdiv_intern.h
+ opensubdiv_topology_refiner.h
)
macro(OPENSUBDIV_DEFINE_COMPONENT component)
@@ -69,6 +70,7 @@ add_definitions(-DGLEW_STATIC)
if(WIN32)
add_definitions(-DNOMINMAX)
+ add_definitions(-D_USE_MATH_DEFINES)
endif()
# TODO(sergey): Put CUEW back when CUDA is officially supported by OSD.
diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index a17dcef81c7..cc9e05a11c8 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -99,6 +99,7 @@ in block {
}
uniform samplerBuffer FVarDataBuffer;
+uniform isamplerBuffer FVarDataOffsetBuffer;
out block {
VertexData v;
@@ -208,6 +209,7 @@ struct LightSource {
float spotCutoff;
float spotExponent;
float spotCosCutoff;
+ float pad, pad2;
#endif
};
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 9b9f4baa39e..ab904953c70 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -67,8 +67,10 @@
#include <opensubdiv/osd/glPatchTable.h>
#include <opensubdiv/far/stencilTable.h>
+#include <opensubdiv/far/primvarRefiner.h>
#include "opensubdiv_intern.h"
+#include "opensubdiv_topology_refiner.h"
#include "MEM_guardedalloc.h"
@@ -142,11 +144,73 @@ typedef Mesh<GLVertexBuffer,
GLPatchTable> OsdGLSLComputeMesh;
#endif
+namespace {
+
+struct FVarVertex {
+ float u, v;
+ void Clear() {
+ u = v = 0.0f;
+ }
+ void AddWithWeight(FVarVertex const & src, float weight) {
+ u += weight * src.u;
+ v += weight * src.v;
+ }
+};
+
+static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
+ const std::vector<float> uvs,
+ std::vector<float> &fvar_data) {
+ /* TODO(sergey): Make it somehow more generic way. */
+ const int fvar_width = 2;
+ const int max_level = refiner.GetMaxLevel();
+ size_t fvar_data_offset = 0, values_offset = 0;
+ for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
+ const int num_values = refiner.GetLevel(0).GetNumFVarValues(0) * 2,
+ num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
+ num_values_total = refiner.GetNumFVarValuesTotal(channel);
+ if (num_values_total <= 0) {
+ continue;
+ }
+ OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
+ if (refiner.IsUniform()) {
+ /* For uniform we only keep the highest level of refinement. */
+ fvar_data.resize(fvar_data.size() + num_values_max * fvar_width);
+ std::vector<FVarVertex> buffer(num_values_total - num_values_max);
+ FVarVertex *src = &buffer[0];
+ memcpy(src, &uvs[values_offset], num_values * sizeof(float));
+ /* Defer the last level to treat separately with its alternate
+ * destination.
+ */
+ for (int level = 1; level < max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
+ primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ /* For adaptive we keep all levels. */
+ fvar_data.resize(fvar_data.size() + num_values_total * fvar_width);
+ FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
+ memcpy(src, &uvs[values_offset], num_values * sizeof(float));
+ for (int level = 1; level <= max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ fvar_data_offset += num_values_total * fvar_width;
+ }
+ values_offset += num_values;
+ }
+}
+
+} // namespace
+
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int /*subdivide_uvs*/)
+ int level)
{
using OpenSubdiv::Far::TopologyRefiner;
@@ -164,7 +228,7 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
const int num_varying_elements = 3;
GLMeshInterface *mesh = NULL;
- TopologyRefiner *refiner = (TopologyRefiner*)topology_refiner;
+ TopologyRefiner *refiner = topology_refiner->osd_refiner;
switch(evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
@@ -210,13 +274,23 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
(OpenSubdiv_GLMesh *) OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
gl_mesh->evaluator_type = evaluator_type;
gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
- gl_mesh->topology_refiner = (OpenSubdiv_TopologyRefinerDescr*)refiner;
+ gl_mesh->topology_refiner = topology_refiner;
+
+ if (refiner->GetNumFVarChannels() > 0) {
+ std::vector<float> fvar_data;
+ interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
+ openSubdiv_osdGLAllocFVar(topology_refiner, gl_mesh, &fvar_data[0]);
+ }
+ else {
+ gl_mesh->fvar_data = NULL;
+ }
return gl_mesh;
}
void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
{
+ openSubdiv_osdGLDestroyFVar(gl_mesh);
switch (gl_mesh->evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
case OPENSUBDIV_EVALUATOR_ ## type: \
@@ -249,6 +323,8 @@ void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
#undef CHECK_EVALUATOR_TYPE
}
+ /* NOTE: OSD refiner was owned by gl_mesh, no need to free it here. */
+ OBJECT_GUARDED_DELETE(gl_mesh->topology_refiner, OpenSubdiv_TopologyRefinerDescr);
OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
}
@@ -299,6 +375,9 @@ int openSubdiv_supportGPUDisplay(void)
return openSubdiv_gpu_legacy_support() &&
(GLEW_VERSION_3_2 ||
(GLEW_VERSION_3_1 && GLEW_EXT_geometry_shader4) ||
- (GLEW_VERSION_3_0 && GLEW_EXT_geometry_shader4 && GLEW_ARB_uniform_buffer_object && (GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
+ (GLEW_VERSION_3_0 &&
+ GLEW_EXT_geometry_shader4 &&
+ GLEW_ARB_uniform_buffer_object &&
+ (GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
/* also ARB_explicit_attrib_location? */
}
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index b40505b197d..c3a194813e6 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -32,16 +32,19 @@ extern "C" {
// Types declaration.
struct OpenSubdiv_GLMesh;
+struct OpenSubdiv_GLMeshFVarData;
struct OpenSubdiv_TopologyRefinerDescr;
typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
#ifdef __cplusplus
struct OpenSubdiv_GLMeshDescr;
+
typedef struct OpenSubdiv_GLMesh {
int evaluator_type;
OpenSubdiv_GLMeshDescr *descriptor;
OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ OpenSubdiv_GLMeshFVarData *fvar_data;
} OpenSubdiv_GLMesh;
#endif
@@ -66,8 +69,7 @@ enum {
OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int subdivide_uvs);
+ int level);
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
@@ -138,6 +140,11 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
int start_patch,
int num_patches);
+void openSubdiv_osdGLAllocFVar(struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data);
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
+
/* ** Utility functions ** */
int openSubdiv_supportGPUDisplay(void);
int openSubdiv_getAvailableEvaluators(void);
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
index 0ad72c88a12..ea41a56768f 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -32,8 +32,12 @@
#include <opensubdiv/far/topologyRefinerFactory.h>
+#include "MEM_guardedalloc.h"
+
#include "opensubdiv_converter_capi.h"
#include "opensubdiv_intern.h"
+#include "opensubdiv_topology_refiner.h"
+
#include <stack>
@@ -49,6 +53,11 @@ inline void reverse_face_verts(int *face_verts, int num_verts)
face_verts[0] = last_vert;
}
+struct TopologyRefinerData {
+ const OpenSubdiv_Converter& conv;
+ std::vector<float> *uvs;
+};
+
} /* namespace */
#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
@@ -137,10 +146,11 @@ inline void check_oriented_vert_connectivity(const int num_vert_edges,
} /* namespace */
template <>
-inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopology(
+inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
TopologyRefiner& refiner,
- const OpenSubdiv_Converter& conv)
+ const TopologyRefinerData& cb_data)
{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
/* Faces and face-verts */
const int num_faces = conv.get_num_faces(&conv);
setNumBaseFaces(refiner, num_faces);
@@ -168,10 +178,11 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopolog
}
template <>
-inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopology(
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
TopologyRefiner& refiner,
- const OpenSubdiv_Converter& conv)
+ const TopologyRefinerData &cb_data)
{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
using Far::IndexArray;
/* Face relations. */
const int num_faces = conv.get_num_faces(&conv);
@@ -426,10 +437,11 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog
};
template <>
-inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
TopologyRefiner& refiner,
- const OpenSubdiv_Converter& conv)
+ const TopologyRefinerData& cb_data)
{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
typedef OpenSubdiv::Sdc::Crease Crease;
int num_edges = conv.get_num_edges(&conv);
@@ -476,14 +488,52 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
}
template <>
-inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
+inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
TopologyError /*errCode*/,
const char *msg,
- const OpenSubdiv_Converter& /*mesh*/)
+ const TopologyRefinerData& /*mesh*/)
{
printf("OpenSubdiv Error: %s\n", msg);
}
+template <>
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
+ TopologyRefiner& refiner,
+ const TopologyRefinerData& cb_data)
+{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
+ const int num_layers = conv.get_num_uv_layers(&conv);
+ if (num_layers <= 0) {
+ /* No UV maps, we can skip any face-varying data. */
+ return true;
+ }
+ const int num_faces = getNumBaseFaces(refiner);
+ size_t uvs_offset = 0;
+ for (int layer = 0; layer < num_layers; ++layer) {
+ conv.precalc_uv_layer(&conv, layer);
+ const int num_uvs = conv.get_num_uvs(&conv);
+ /* Fill in UV coordinates. */
+ cb_data.uvs->resize(cb_data.uvs->size() + num_uvs * 2);
+ conv.get_uvs(&conv, &cb_data.uvs->at(uvs_offset));
+ uvs_offset += num_uvs * 2;
+ /* Fill in per-corner index of the UV. */
+ const int channel = createBaseFVarChannel(refiner, num_uvs);
+ for (int face = 0; face < num_faces; ++face) {
+ Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
+ face,
+ channel);
+ for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
+ const int uv_index = conv.get_face_corner_uv_index(&conv,
+ face,
+ corner);
+ dst_face_uvs[corner] = uv_index;
+ }
+ }
+ conv.finish_uv_layer(&conv);
+ }
+ return true;
+}
+
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@@ -517,33 +567,43 @@ struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
Options options;
options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
options.SetCreasingMethod(Options::CREASE_UNIFORM);
- options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
+ if (converter->get_subdiv_uvs(converter)) {
+ options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_CORNERS_ONLY);
+ }
+ else {
+ options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
+ }
- TopologyRefinerFactory<OpenSubdiv_Converter>::Options
+ TopologyRefinerFactory<TopologyRefinerData>::Options
topology_options(scheme_type, options);
#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
topology_options.validateFullTopology = true;
#endif
+ OpenSubdiv_TopologyRefinerDescr *result = OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefinerDescr);
+ TopologyRefinerData cb_data = {*converter, &result->uvs};
/* We don't use guarded allocation here so we can re-use the refiner
* for GL mesh creation directly.
*/
- return (struct OpenSubdiv_TopologyRefinerDescr*)
- TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
- *converter,
+ result->osd_refiner =
+ TopologyRefinerFactory<TopologyRefinerData>::Create(
+ cb_data,
topology_options);
+
+ return result;
}
void openSubdiv_deleteTopologyRefinerDescr(
OpenSubdiv_TopologyRefinerDescr *topology_refiner)
{
- delete (OpenSubdiv::Far::TopologyRefiner *)topology_refiner;
+ delete topology_refiner->osd_refiner;
+ OBJECT_GUARDED_DELETE(topology_refiner, OpenSubdiv_TopologyRefinerDescr);
}
int openSubdiv_topologyRefinerGetSubdivLevel(
const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
{
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
return refiner->GetMaxLevel();
}
@@ -552,7 +612,7 @@ int openSubdiv_topologyRefinerGetNumVerts(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumVertices();
}
@@ -562,7 +622,7 @@ int openSubdiv_topologyRefinerGetNumEdges(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumEdges();
}
@@ -572,7 +632,7 @@ int openSubdiv_topologyRefinerGetNumFaces(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumFaces();
}
@@ -583,7 +643,7 @@ int openSubdiv_topologyRefinerGetNumFaceVerts(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetFaceVertices(face).size();
}
@@ -592,10 +652,11 @@ int openSubdiv_topologyRefnerCompareConverter(
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
OpenSubdiv_Converter *converter)
{
+ typedef OpenSubdiv::Sdc::Options Options;
using OpenSubdiv::Far::ConstIndexArray;
using OpenSubdiv::Far::TopologyRefiner;
using OpenSubdiv::Far::TopologyLevel;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
const int num_verts = base_level.GetNumVertices();
const int num_edges = base_level.GetNumEdges();
@@ -606,6 +667,12 @@ int openSubdiv_topologyRefnerCompareConverter(
if (scheme_type != refiner->GetSchemeType()) {
return false;
}
+ const Options options = refiner->GetSchemeOptions();
+ Options::FVarLinearInterpolation interp = options.GetFVarLinearInterpolation();
+ const bool subdiv_uvs = (interp != Options::FVAR_LINEAR_ALL);
+ if (converter->get_subdiv_uvs(converter) != subdiv_uvs) {
+ return false;
+ }
if (converter->get_num_verts(converter) != num_verts ||
converter->get_num_edges(converter) != num_edges ||
converter->get_num_faces(converter) != num_faces)
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index 1f09fa074d8..6eda6ae5d8a 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -47,6 +47,8 @@ typedef struct OpenSubdiv_Converter {
OpenSubdiv_SchemeType (*get_type)(const OpenSubdiv_Converter *converter);
+ bool (*get_subdiv_uvs)(const OpenSubdiv_Converter *converter);
+
int (*get_num_faces)(const OpenSubdiv_Converter *converter);
int (*get_num_edges)(const OpenSubdiv_Converter *converter);
int (*get_num_verts)(const OpenSubdiv_Converter *converter);
@@ -83,6 +85,20 @@ typedef struct OpenSubdiv_Converter {
int vert,
int *vert_faces);
+ /* Face-varying data. */
+
+ int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
+
+ void (*precalc_uv_layer)(const OpenSubdiv_Converter *converter, int layer);
+ void (*finish_uv_layer)(const OpenSubdiv_Converter *converter);
+
+ int (*get_num_uvs)(const OpenSubdiv_Converter *converter);
+ void (*get_uvs)(const OpenSubdiv_Converter *converter, float *uvs);
+
+ int (*get_face_corner_uv_index)(const OpenSubdiv_Converter *converter,
+ int face,
+ int corner);
+
void (*free_user_data)(const OpenSubdiv_Converter *converter);
void *user_data;
} OpenSubdiv_Converter;
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 698fdfee00f..752dce7744c 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -42,11 +42,29 @@
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
#include <opensubdiv/osd/cpuEvaluator.h>
+#include "MEM_guardedalloc.h"
+
+#include "opensubdiv_capi.h"
+#include "opensubdiv_topology_refiner.h"
+
using OpenSubdiv::Osd::GLMeshInterface;
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
+/* TODO(sergey): This is bit of bad level calls :S */
+extern "C" {
+void copy_m3_m3(float m1[3][3], float m2[3][3]);
+void copy_m3_m4(float m1[3][3], float m2[4][4]);
+void adjoint_m3_m3(float m1[3][3], float m[3][3]);
+float determinant_m3_array(float m[3][3]);
+bool invert_m3_m3(float m1[3][3], float m2[3][3]);
+bool invert_m3(float m[3][3]);
+void transpose_m3(float mat[3][3]);
+}
+
#define MAX_LIGHTS 8
+#define SUPPORT_COLOR_MATERIAL
+
typedef struct Light {
float position[4];
float ambient[4];
@@ -60,6 +78,7 @@ typedef struct Light {
float spot_cutoff;
float spot_exponent;
float spot_cos_cutoff;
+ float pad, pad2;
#endif
} Light;
@@ -75,7 +94,7 @@ typedef struct Transform {
} Transform;
static bool g_use_osd_glsl = false;
-static int g_active_uv_index = -1;
+static int g_active_uv_index = 0;
static GLuint g_flat_fill_solid_program = 0;
static GLuint g_flat_fill_texture2d_program = 0;
@@ -87,102 +106,98 @@ static GLuint g_lighting_ub = 0;
static Lighting g_lighting_data;
static Transform g_transform;
-/* TODO(sergey): This is actually duplicated code from BLI. */
-namespace {
-void copy_m3_m3(float m1[3][3], float m2[3][3])
-{
- /* destination comes first: */
- memcpy(&m1[0], &m2[0], 9 * sizeof(float));
-}
-
-void copy_m3_m4(float m1[3][3], float m2[4][4])
-{
- m1[0][0] = m2[0][0];
- m1[0][1] = m2[0][1];
- m1[0][2] = m2[0][2];
-
- m1[1][0] = m2[1][0];
- m1[1][1] = m2[1][1];
- m1[1][2] = m2[1][2];
-
- m1[2][0] = m2[2][0];
- m1[2][1] = m2[2][1];
- m1[2][2] = m2[2][2];
-}
-
-void adjoint_m3_m3(float m1[3][3], float m[3][3])
-{
- m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
- m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
- m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
-
- m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
- m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
- m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
-
- m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
- m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
- m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
-}
-
-float determinant_m3_array(float m[3][3])
+struct OpenSubdiv_GLMeshFVarData
{
- return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
- m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
- m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
-}
-
-bool invert_m3_m3(float m1[3][3], float m2[3][3])
-{
- float det;
- int a, b;
- bool success;
-
- /* calc adjoint */
- adjoint_m3_m3(m1, m2);
+ OpenSubdiv_GLMeshFVarData() :
+ texture_buffer(0) {
+ }
- /* then determinant old matrix! */
- det = determinant_m3_array(m2);
+ ~OpenSubdiv_GLMeshFVarData()
+ {
+ Release();
+ }
- success = (det != 0.0f);
+ void Release()
+ {
+ if (texture_buffer) {
+ glDeleteTextures(1, &texture_buffer);
+ }
+ if (offset_buffer) {
+ glDeleteTextures(1, &offset_buffer);
+ }
+ texture_buffer = 0;
+ offset_buffer = 0;
+ fvar_width = 0;
+ channel_offsets.clear();
+ }
- if (det != 0.0f) {
- det = 1.0f / det;
- for (a = 0; a < 3; a++) {
- for (b = 0; b < 3; b++) {
- m1[a][b] *= det;
+ void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
+ const OpenSubdiv::Far::PatchTable *patch_table,
+ int fvar_width,
+ const float *fvar_src_data)
+ {
+ Release();
+
+ this->fvar_width = fvar_width;
+
+ /* Expand fvar data to per-patch array */
+ const int max_level = refiner->GetMaxLevel();
+ const int num_channels = patch_table->GetNumFVarChannels();
+ std::vector<float> data;
+ int fvar_data_offset = 0;
+ channel_offsets.resize(num_channels);
+ for (int channel = 0; channel < num_channels; ++channel) {
+ OpenSubdiv::Far::ConstIndexArray indices =
+ patch_table->GetFVarValues(channel);
+
+ channel_offsets[channel] = data.size();
+ data.reserve(data.size() + indices.size() * fvar_width);
+
+ for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
+ int index = indices[fvert] * fvar_width;
+ for (int i = 0; i < fvar_width; ++i) {
+ data.push_back(fvar_src_data[fvar_data_offset + index++]);
+ }
+ }
+ if (refiner->IsUniform()) {
+ const int num_values_max = refiner->GetLevel(max_level).GetNumFVarValues(channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ const int num_values_total = refiner->GetNumFVarValuesTotal(channel);
+ fvar_data_offset += num_values_total * fvar_width;
}
}
- }
- return success;
-}
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
+ &data[0], GL_STATIC_DRAW);
-bool invert_m3(float m[3][3])
-{
- float tmp[3][3];
- bool success;
+ glGenTextures(1, &texture_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
- success = invert_m3_m3(tmp, m);
- copy_m3_m3(m, tmp);
+ glDeleteBuffers(1, &buffer);
- return success;
-}
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, channel_offsets.size()*sizeof(int),
+ &channel_offsets[0], GL_STATIC_DRAW);
-void transpose_m3(float mat[3][3])
-{
- float t;
-
- t = mat[0][1];
- mat[0][1] = mat[1][0];
- mat[1][0] = t;
- t = mat[0][2];
- mat[0][2] = mat[2][0];
- mat[2][0] = t;
- t = mat[1][2];
- mat[1][2] = mat[2][1];
- mat[2][1] = t;
-}
+ glGenTextures(1, &offset_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ GLuint texture_buffer;
+ GLuint offset_buffer;
+ std::vector<int> channel_offsets;
+ int fvar_width;
+};
+
+namespace {
GLuint compileShader(GLenum shaderType,
const char *section,
@@ -196,11 +211,14 @@ GLuint compileShader(GLenum shaderType,
version,
define,
sdefine,
+#ifdef SUPPORT_COLOR_MATERIAL
+ "#define SUPPORT_COLOR_MATERIAL\n",
+#endif
datatoc_gpu_shader_opensubd_display_glsl
};
GLuint shader = glCreateShader(shaderType);
- glShaderSource(shader, 4, sources, NULL);
+ glShaderSource(shader, 5, sources, NULL);
glCompileShader(shader);
GLint status;
@@ -295,14 +313,17 @@ GLuint linkProgram(const char *version, const char *define)
0); /* GL_TEXTURE0 */
glProgramUniform1i(program,
+ glGetUniformLocation(program, "FVarDataOffsetBuffer"),
+ 30); /* GL_TEXTURE30 */
+
+ glProgramUniform1i(program,
glGetUniformLocation(program, "FVarDataBuffer"),
31); /* GL_TEXTURE31 */
return program;
}
-void bindProgram(GLMeshInterface * /*mesh*/,
- int program)
+void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
{
glUseProgram(program);
@@ -346,23 +367,34 @@ void bindProgram(GLMeshInterface * /*mesh*/,
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
}
- /* TODO(sergey): Bring face varying back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
- glActiveTexture(GL_TEXTURE0);
- }
-#endif
+ if (gl_mesh->fvar_data != NULL) {
+ if (gl_mesh->fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
- /* TODO(sergey): Bring face varying back. */
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
- 0/* * mesh->GetFVarCount()*/);
+ if (gl_mesh->fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
- g_active_uv_index * 2);
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
+ gl_mesh->fvar_data->fvar_width);
+ if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
+ g_active_uv_index >= 0)
+ {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
+ gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
}
} /* namespace */
@@ -390,11 +422,27 @@ bool openSubdiv_osdGLDisplayInit(void)
/* minimum supported for OpenSubdiv */
}
- g_flat_fill_solid_program = linkProgram(version, "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
- g_smooth_fill_solid_program = linkProgram(version, "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
- g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
+ g_flat_fill_solid_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+ g_wireframe_program = linkProgram(
+ version,
+ "#define WIREFRAME\n");
glGenBuffers(1, &g_lighting_ub);
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
@@ -436,8 +484,8 @@ void openSubdiv_osdGLDisplayDeinit(void)
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
int active_uv_index)
{
- g_use_osd_glsl = use_osd_glsl != 0;
g_active_uv_index = active_uv_index;
+ g_use_osd_glsl = (use_osd_glsl != 0);
/* Update transformation matrices. */
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
@@ -494,7 +542,7 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
}
}
-static GLuint prepare_patchDraw(GLMeshInterface *mesh,
+static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
bool fill_quads)
{
GLint program = 0;
@@ -509,28 +557,42 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
glUniform1i(location, model == GL_FLAT);
}
- /* TODO(sergey): Bring this back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
- glActiveTexture(GL_TEXTURE0);
+ if (gl_mesh->fvar_data != NULL) {
+ if (gl_mesh->fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ gl_mesh->fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ if (gl_mesh->fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ gl_mesh->fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
GLint location = glGetUniformLocation(program, "osd_fvar_count");
if (location != -1) {
- glUniform1i(location, mesh->GetFVarCount());
+ glUniform1i(location, gl_mesh->fvar_data->fvar_width);
}
location = glGetUniformLocation(program, "osd_active_uv_offset");
if (location != -1) {
- glUniform1i(location,
- g_active_uv_index * 2);
+ if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
+ g_active_uv_index >= 0)
+ {
+ glUniform1i(location,
+ gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(location, 0);
+ }
}
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
-#endif
-
}
return program;
}
@@ -562,7 +624,7 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
program = g_wireframe_program;
}
- bindProgram(mesh, program);
+ bindProgram(gl_mesh, program);
return program;
}
@@ -623,7 +685,7 @@ static void draw_partition_patches_range(GLMeshInterface *mesh,
const int num_draw_patches = std::min(num_remained_patches,
num_block_patches - start_draw_patch);
perform_drawElements(program,
- i,
+ i + start_draw_patch,
num_draw_patches * num_control_verts,
patch.GetIndexBase() + start_draw_patch * num_control_verts);
num_remained_patches -= num_draw_patches;
@@ -669,7 +731,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
}
/* Setup GLSL/OpenGL to draw patches in current context. */
- GLuint program = prepare_patchDraw(mesh, fill_quads != 0);
+ GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
if (start_patch != -1) {
draw_partition_patches_range(mesh,
@@ -684,3 +746,23 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
/* Finish patch drawing by restoring all changes to the OpenGL context. */
finish_patchDraw(fill_quads != 0);
}
+
+void openSubdiv_osdGLAllocFVar(OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data)
+{
+ GLMeshInterface *mesh =
+ (GLMeshInterface *)(gl_mesh->descriptor);
+ gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
+ gl_mesh->fvar_data->Create(topology_refiner->osd_refiner,
+ mesh->GetFarPatchTable(),
+ 2,
+ fvar_data);
+}
+
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
+{
+ if (gl_mesh->fvar_data != NULL) {
+ OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
+ }
+}
diff --git a/intern/opensubdiv/opensubdiv_topology_refiner.h b/intern/opensubdiv/opensubdiv_topology_refiner.h
new file mode 100644
index 00000000000..b00f6a54201
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_topology_refiner.h
@@ -0,0 +1,41 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENSUBDIV_TOPOLOGY_REFINER_H__
+#define __OPENSUBDIV_TOPOLOGY_REFINER_H__
+
+#include <opensubdiv/far/topologyRefiner.h>
+
+typedef struct OpenSubdiv_TopologyRefinerDescr {
+ OpenSubdiv::Far::TopologyRefiner *osd_refiner;
+
+ /* TODO(sergey): For now only, need to find better place
+ * after revisiting whole OSD drawing pipeline and Blender
+ * integration.
+ */
+ std::vector<float> uvs;
+} OpenSubdiv_TopologyRefinerDescr;
+
+#endif /* __OPENSUBDIV_TOPOLOGY_REFINER_H__ */