Cycles-Bake: displacement support (fix T40068)
authorDalai Felinto <dfelinto@gmail.com>
Wed, 7 May 2014 20:26:24 +0000 (17:26 -0300)
committerDalai Felinto <dfelinto@gmail.com>
Thu, 8 May 2014 17:38:43 +0000 (14:38 -0300)
Code with contribution from Brecht Van Lommel.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D510

intern/cycles/blender/blender_session.cpp
intern/cycles/kernel/kernel_displace.h
intern/cycles/render/bake.cpp
intern/cycles/render/bake.h

index 6f959d426801587ce660039e3f0680e47e08526a..01a5acd8982825d02afdc46a4368370d9b0ffadf 100644 (file)
@@ -487,7 +487,7 @@ static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const
 
        int i;
        for(i=0; i < num_pixels; i++) {
-               data->set(i, bp.primitive_id(), bp.uv());
+               data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
                bp = bp.next();
        }
 }
index e54a16ac118d9b866c280543a06f127fa4a7f985..4727e90a231763f62218ab8dd14f7a1b4e176946 100644 (file)
@@ -102,7 +102,9 @@ ccl_device bool is_light_pass(ShaderEvalType type)
 ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i)
 {
        ShaderData sd;
-       uint4 in = input[i];
+       uint4 in = input[i * 2];
+       uint4 diff = input[i * 2 + 1];
+
        float3 out;
 
        int object = in.x;
@@ -114,6 +116,11 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
        float u = __uint_as_float(in.z);
        float v = __uint_as_float(in.w);
 
+       float dudx = __uint_as_float(diff.x);
+       float dudy = __uint_as_float(diff.y);
+       float dvdx = __uint_as_float(diff.z);
+       float dvdy = __uint_as_float(diff.w);
+
        int shader;
        float3 P, Ng;
 
@@ -132,6 +139,14 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
        shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time, bounce, transparent_bounce);
        sd.I = sd.N;
 
+       /* update differentials */
+       sd.dP.dx = sd.dPdu * dudx + sd.dPdv * dvdx;
+       sd.dP.dy = sd.dPdu * dudy + sd.dPdv * dvdy;
+       sd.du.dx = dudx;
+       sd.du.dy = dudy;
+       sd.dv.dx = dvdx;
+       sd.dv.dy = dvdy;
+
        if(is_light_pass(type)) {
                RNG rng = cmj_hash(i, 0);
                compute_light_pass(kg, &sd, &L, rng, (type == SHADER_EVAL_COMBINED),
index 2e3022e2c026417b03ebb2e0c2059b56485614ff..aa317ab672fcd410811f68c932c38e7c64aa2a39 100644 (file)
@@ -26,6 +26,10 @@ m_num_pixels(num_pixels)
        m_primitive.resize(num_pixels);
        m_u.resize(num_pixels);
        m_v.resize(num_pixels);
+       m_dudx.resize(num_pixels);
+       m_dudy.resize(num_pixels);
+       m_dvdx.resize(num_pixels);
+       m_dvdy.resize(num_pixels);
 }
 
 BakeData::~BakeData()
@@ -33,13 +37,21 @@ BakeData::~BakeData()
        m_primitive.clear();
        m_u.clear();
        m_v.clear();
+       m_dudx.clear();
+       m_dudy.clear();
+       m_dvdx.clear();
+       m_dvdy.clear();
 }
 
-void BakeData::set(int i, int prim, float uv[2])
+void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
 {
        m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
        m_u[i] = uv[0];
        m_v[i] = uv[1];
+       m_dudx[i] = dudx;
+       m_dudy[i] = dudy;
+       m_dvdx[i] = dvdx;
+       m_dvdy[i] = dvdy;
 }
 
 int BakeData::object()
@@ -67,6 +79,16 @@ uint4 BakeData::data(int i)
                );
 }
 
+uint4 BakeData::differentials(int i)
+{
+       return make_uint4(
+                 __float_as_int(m_dudx[i]),
+                 __float_as_int(m_dudy[i]),
+                 __float_as_int(m_dvdx[i]),
+                 __float_as_int(m_dvdy[i])
+                 );
+}
+
 BakeManager::BakeManager()
 {
        m_bake_data = NULL;
@@ -102,11 +124,12 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
 
        /* setup input for device task */
        device_vector<uint4> d_input;
-       uint4 *d_input_data = d_input.resize(limit);
+       uint4 *d_input_data = d_input.resize(limit * 2);
        size_t d_input_size = 0;
 
        for(size_t i = 0; i < limit; i++) {
                d_input_data[d_input_size++] = bake_data->data(i);
+               d_input_data[d_input_size++] = bake_data->differentials(i);
        }
 
        if(d_input_size == 0)
@@ -114,7 +137,7 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
 
        /* run device task */
        device_vector<float4> d_output;
-       d_output.resize(d_input_size);
+       d_output.resize(limit);
 
        /* needs to be up to data for attribute access */
        device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
index 830a95130658401304ea33d75cc1e6f7522e71a7..ea403f7d39a81eb902faf8360788044daa1dfb5d 100644 (file)
@@ -29,10 +29,11 @@ public:
        BakeData(const int object, const int tri_offset, const int num_pixels);
        ~BakeData();
 
-       void set(int i, int prim, float uv[2]);
+       void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
        int object();
        int size();
        uint4 data(int i);
+       uint4 differentials(int i);
        bool is_valid(int i);
 
 private:
@@ -42,6 +43,10 @@ private:
        vector<int>m_primitive;
        vector<float>m_u;
        vector<float>m_v;
+       vector<float>m_dudx;
+       vector<float>m_dudy;
+       vector<float>m_dvdx;
+       vector<float>m_dvdy;
 };
 
 class BakeManager {