Cycles: window texture coordinates now work with orthographic cameras, this

was an old issue since the first version.
This commit is contained in:
Brecht Van Lommel
2013-06-08 10:51:33 +00:00
parent c423e3ed8f
commit c53b20b683
7 changed files with 91 additions and 49 deletions

View 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

View 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 */

View 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

View 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;
}

View 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;
}

View 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 );

View 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;
}