Cycles: window texture coordinates now work with orthographic cameras, this
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 8 Jun 2013 10:51:33 +0000 (10:51 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 8 Jun 2013 10:51:33 +0000 (10:51 +0000)
was an old issue since the first version.

intern/cycles/kernel/kernel_camera.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/shaders/node_texture_coordinate.osl
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_tex_coord.h

index a23586a53a4d7bbdc3224ab17f78cd3bbc93639a..4b9ef8893f708698c699e4f569f1e717cd794238 100644 (file)
@@ -245,6 +245,12 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo
 
 /* Utilities */
 
+__device_inline float3 camera_position(KernelGlobals *kg)
+{
+       Transform cameratoworld = kernel_data.cam.cameratoworld;
+       return make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
+}
+
 __device_inline float camera_distance(KernelGlobals *kg, float3 P)
 {
        Transform cameratoworld = kernel_data.cam.cameratoworld;
@@ -258,5 +264,30 @@ __device_inline float camera_distance(KernelGlobals *kg, float3 P)
                return len(P - camP);
 }
 
+__device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P)
+{
+       if(kernel_data.cam.type != CAMERA_PANORAMA) {
+               /* perspective / ortho */
+               if(sd->object == ~0 && kernel_data.cam.type == CAMERA_PERSPECTIVE)
+                       P += camera_position(kg);
+
+               Transform tfm = kernel_data.cam.worldtondc;
+               return transform_perspective(&tfm, P);
+       }
+       else {
+               /* panorama */
+               Transform tfm = kernel_data.cam.worldtocamera;
+
+               if(sd->object != ~0)
+                       P = normalize(transform_point(&tfm, P));
+               else
+                       P = normalize(transform_direction(&tfm, P));
+
+               float2 uv = direction_to_panorama(kg, P);
+
+               return make_float3(uv.x, uv.y, 0.0f);
+       }
+}
+
 CCL_NAMESPACE_END
 
index 908c5a91768e632d3174a814435d576fe3f2193b..347c066962aa1603024d0731bff3b477f75027ad 100644 (file)
@@ -402,9 +402,9 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
 {
        /* vectors */
        sd->P = ray->D;
-       sd->N = -sd->P;
-       sd->Ng = -sd->P;
-       sd->I = -sd->P;
+       sd->N = -ray->D;
+       sd->Ng = -ray->D;
+       sd->I = -ray->D;
        sd->shader = kernel_data.background.shader;
        sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
 #ifdef __OBJECT_MOTION__
@@ -437,6 +437,10 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
        sd->du = differential_zero();
        sd->dv = differential_zero();
 #endif
+
+       /* for NDC coordinates */
+       sd->ray_P = ray->P;
+       sd->ray_dP = ray->dP;
 }
 
 /* BSDF */
index 11cdad6bb44d2df0f2abdb825e1ed145db069496..771c79ba637b56835fdf552ac56d040876f045da 100644 (file)
@@ -572,6 +572,10 @@ typedef struct ShaderData {
        ShaderClosure closure;
 #endif
 
+       /* ray start position, only set for backgrounds */
+       float3 ray_P;
+       differential3 ray_dP;
+
 #ifdef __OSL__
        struct KernelGlobals *osl_globals;
 #endif
index f2311e14c3a2aa19f37bba360aaf4629960c9140..fd3f349286b1abae2217e581439fd84922346f38 100644 (file)
@@ -43,6 +43,7 @@
 #include "kernel_primitive.h"
 #include "kernel_projection.h"
 #include "kernel_accumulate.h"
+#include "kernel_camera.h"
 #include "kernel_shader.h"
 
 CCL_NAMESPACE_BEGIN
@@ -653,12 +654,36 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
 bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
                                                  TypeDesc type, bool derivatives, void *val)
 {
-       /* Ray Length */
        if (name == u_path_ray_length) {
+               /* Ray Length */
                float f = sd->ray_length;
                return set_attribute_float(f, type, derivatives, val);
        }
-       
+       else if (name == u_ndc) {
+               /* NDC coordinates with special exception for otho */
+               OSLThreadData *tdata = kg->osl_tdata;
+               OSL::ShaderGlobals *globals = &tdata->globals;
+               float3 ndc[3];
+
+               if((globals->raytype & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
+                       ndc[0] = camera_world_to_ndc(kg, sd, sd->ray_P);
+
+                       if(derivatives) {
+                               ndc[1] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx) - ndc[0];
+                               ndc[2] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy) - ndc[0];
+                       }
+               }
+               else {
+                       ndc[0] = camera_world_to_ndc(kg, sd, sd->P);
+
+                       if(derivatives) {
+                               ndc[1] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx) - ndc[0];
+                               ndc[2] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy) - ndc[0];
+                       }
+               }
+
+               return set_attribute_float3(ndc, type, derivatives, val);
+       }
        else
                return false;
 }
index 37460bcfc98cd778e0953eeb087bfa8ba0219ad6..9da582da5dcd002e9a236dd0447db0ac820e448d 100644 (file)
@@ -38,7 +38,7 @@ shader node_texture_coordinate(
                Object = P;
                point Pcam = transform("camera", "world", point(0, 0, 0));
                Camera = transform("camera", P + Pcam);
-               Window = transform("NDC", P + Pcam);
+               getattribute("NDC", Window);
                Normal = NormalIn;
                Reflection = I;
        }
index 16b684e79a0eed7b09680d20ef4c9c95fd931036..cfb930d92e811dc0e48db68ae826438843854a67 100644 (file)
@@ -385,14 +385,14 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
                                svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
                                break;
                        case NODE_TEX_COORD:
-                               svm_node_tex_coord(kg, sd, stack, node.y, node.z);
+                               svm_node_tex_coord(kg, sd, path_flag, stack, node.y, node.z);
                                break;
 #ifdef __EXTRA_NODES__
                        case NODE_TEX_COORD_BUMP_DX:
-                               svm_node_tex_coord_bump_dx(kg, sd, stack, node.y, node.z);
+                               svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node.y, node.z);
                                break;
                        case NODE_TEX_COORD_BUMP_DY:
-                               svm_node_tex_coord_bump_dy(kg, sd, stack, node.y, node.z);
+                               svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node.y, node.z);
                                break;
                        case NODE_CLOSURE_SET_NORMAL:
                                svm_node_set_normal(kg, sd, stack, node.y, node.z );
index 98f99a91bc6fdc3dc68b02659ddce592a42075ae..e76b50d6facb81976ec9757791ef3aa2a0246176 100644 (file)
@@ -20,38 +20,7 @@ CCL_NAMESPACE_BEGIN
 
 /* Texture Coordinate Node */
 
-__device_inline float3 svm_background_position(KernelGlobals *kg, float3 P)
-{
-       Transform cameratoworld = kernel_data.cam.cameratoworld;
-       float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
-
-       return camP + P;
-}
-
-__device_inline float3 svm_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P)
-{
-       if(kernel_data.cam.type != CAMERA_PANORAMA) {
-               if(sd->object == ~0)
-                       P = svm_background_position(kg, P);
-
-               Transform tfm = kernel_data.cam.worldtondc;
-               return transform_perspective(&tfm, P);
-       }
-       else {
-               Transform tfm = kernel_data.cam.worldtocamera;
-
-               if(sd->object != ~0)
-                       P = normalize(transform_point(&tfm, P));
-               else
-                       P = normalize(transform_direction(&tfm, P));
-
-               float2 uv = direction_to_panorama(kg, P);
-
-               return make_float3(uv.x, uv.y, 0.0f);
-       }
-}
-
-__device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+__device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
 {
        float3 data;
 
@@ -80,11 +49,14 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
                        if(sd->object != ~0)
                                data = transform_point(&tfm, sd->P);
                        else
-                               data = transform_point(&tfm, svm_background_position(kg, sd->P));
+                               data = transform_point(&tfm, sd->P + camera_position(kg));
                        break;
                }
                case NODE_TEXCO_WINDOW: {
-                       data = svm_world_to_ndc(kg, sd, sd->P);
+                       if((path_flag & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+                               data = camera_world_to_ndc(kg, sd, sd->ray_P);
+                       else
+                               data = camera_world_to_ndc(kg, sd, sd->P);
                        data.z = 0.0f;
                        break;
                }
@@ -108,7 +80,7 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
        stack_store_float3(stack, out_offset, data);
 }
 
-__device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+__device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
 {
 #ifdef __RAY_DIFFERENTIALS__
        float3 data;
@@ -138,11 +110,14 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
                        if(sd->object != ~0)
                                data = transform_point(&tfm, sd->P + sd->dP.dx);
                        else
-                               data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dx));
+                               data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg));
                        break;
                }
                case NODE_TEXCO_WINDOW: {
-                       data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
+                       if((path_flag & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+                               data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx);
+                       else
+                               data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
                        data.z = 0.0f;
                        break;
                }
@@ -169,7 +144,7 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
 #endif
 }
 
-__device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+__device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
 {
 #ifdef __RAY_DIFFERENTIALS__
        float3 data;
@@ -199,11 +174,14 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
                        if(sd->object != ~0)
                                data = transform_point(&tfm, sd->P + sd->dP.dy);
                        else
-                               data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dy));
+                               data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg));
                        break;
                }
                case NODE_TEXCO_WINDOW: {
-                       data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
+                       if((path_flag & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+                               data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy);
+                       else
+                               data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
                        data.z = 0.0f;
                        break;
                }