vec3 calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2) { vec3 edge21 = pos2 - pos1; vec3 edge10 = pos1 - pos0; vec3 edge02 = pos0 - pos2; vec3 d21 = normalize(edge21); vec3 d10 = normalize(edge10); vec3 d02 = normalize(edge02); vec3 dists; float d = dot(d21, edge02); dists.x = sqrt(dot(edge02, edge02) - d * d); d = dot(d02, edge10); dists.y = sqrt(dot(edge10, edge10) - d * d); d = dot(d10, edge21); dists.z = sqrt(dot(edge21, edge21) - d * d); return dists; } vec2 calc_barycentric_co(int vertid) { vec2 bary; bary.x = float((vertid % 3) == 0); bary.y = float((vertid % 3) == 1); return bary; } #ifdef HAIR_SHADER /* Hairs uv and col attributes are passed by bufferTextures. */ # define DEFINE_ATTR(type, attr) uniform samplerBuffer attr # define GET_ATTR(type, attr) hair_get_customdata_##type(attr) # define barycentric_get() hair_get_barycentric() # define barycentric_resolve(bary) hair_resolve_barycentric(bary) vec3 orco_get(vec3 local_pos, mat4 modelmatinv, vec4 orco_madd[2], const samplerBuffer orco_samp) { /* TODO: fix ORCO with modifiers. */ vec3 orco = (modelmatinv * vec4(local_pos, 1.0)).xyz; return orco_madd[0].xyz + orco * orco_madd[1].xyz; } float hair_len_get(int id, const samplerBuffer len) { return texelFetch(len, id).x; } vec4 tangent_get(const samplerBuffer attr, mat3 normalmat) { /* Unsupported */ return vec4(0.0); } #else /* MESH_SHADER */ # define DEFINE_ATTR(type, attr) in type attr # define GET_ATTR(type, attr) attr /* Calculated in geom shader later with calc_barycentric_co. */ # define barycentric_get() vec2(0) # define barycentric_resolve(bary) bary vec3 orco_get(vec3 local_pos, mat4 modelmatinv, vec4 orco_madd[2], vec4 orco) { /* If the object does not have any deformation, the orco layer calculation is done on the fly * using the orco_madd factors. * We know when there is no orco layer when orco.w is 1.0 because it uses the generic vertex * attrib (which is [0,0,0,1]). */ if (orco.w == 0.0) { return orco.xyz * 0.5 + 0.5; } else { return orco_madd[0].xyz + local_pos * orco_madd[1].xyz; } } float hair_len_get(int id, const float len) { return len; } vec4 tangent_get(vec4 attr, mat3 normalmat) { vec4 tangent; tangent.xyz = normalmat * attr.xyz; tangent.w = attr.w; float len_sqr = dot(tangent.xyz, tangent.xyz); /* Normalize only if vector is not null. */ if (len_sqr > 0.0) { tangent.xyz *= inversesqrt(len_sqr); } return tangent; } #endif /* Assumes GPU_VEC4 is color data. So converting to luminance like cycles. */ #define float_from_vec4(v) dot(v.rgb, vec3(0.2126, 0.7152, 0.0722)) #define float_from_vec3(v) avg(v.rgb) #define float_from_vec2(v) v.r #define vec2_from_vec4(v) vec2(avg(v.rgb), v.a) #define vec2_from_vec3(v) vec2(avg(v.rgb), 1.0) #define vec2_from_float(v) vec2(v) #define vec3_from_vec4(v) v.rgb #define vec3_from_vec2(v) v.rrr #define vec3_from_float(v) vec3(v) #define vec4_from_vec3(v) vec4(v, 1.0) #define vec4_from_vec2(v) v.rrrg #define vec4_from_float(v) vec4(vec3(v), 1.0) /* TODO: Move to shader_shared. */ #define RAY_TYPE_CAMERA 0 #define RAY_TYPE_SHADOW 1 #define RAY_TYPE_DIFFUSE 2 #define RAY_TYPE_GLOSSY 3 #ifdef GPU_FRAGMENT_SHADER # define FrontFacing gl_FrontFacing #else # define FrontFacing true #endif struct ClosureDiffuse { float weight; vec3 color; vec3 N; vec3 sss_radius; uint sss_id; }; struct ClosureTranslucent { float weight; vec3 color; vec3 N; }; struct ClosureReflection { float weight; vec3 color; vec3 N; float roughness; }; struct ClosureRefraction { float weight; vec3 color; vec3 N; float roughness; float ior; }; struct ClosureHair { float weight; vec3 color; float offset; vec2 roughness; vec3 T; }; struct ClosureVolumeScatter { float weight; vec3 scattering; float anisotropy; }; struct ClosureVolumeAbsorption { float weight; vec3 absorption; }; struct ClosureEmission { float weight; vec3 emission; }; struct ClosureTransparency { float weight; vec3 transmittance; float holdout; }; struct GlobalData { /** World position. */ vec3 P; /** Surface Normal. Normalized, overridden by bump displacement. */ vec3 N; /** Raw interpolated normal (non-normalized) data. */ vec3 Ni; /** Geometric Normal. */ vec3 Ng; /** Curve Tangent Space. */ vec3 curve_T, curve_B, curve_N; /** Barycentric coordinates. */ vec2 barycentric_coords; vec3 barycentric_dists; /** Ray properties (approximation). */ int ray_type; float ray_depth; float ray_length; /** Hair time along hair length. 0 at base 1 at tip. */ float hair_time; /** Hair time along width of the hair. */ float hair_time_width; /** Hair thickness in world space. */ float hair_thickness; /** Index of the strand for per strand effects. */ int hair_strand_id; /** Is hair. */ bool is_strand; }; GlobalData g_data; #ifndef GPU_FRAGMENT_SHADER /* Stubs. */ vec3 dF_impl(vec3 v) { return vec3(0.0); } void dF_branch(float fn, out vec2 result) { result = vec2(0.0); } #elif 0 /* TODO(@fclem): User Option? */ /* Fast derivatives */ vec3 dF_impl(vec3 v) { return vec3(0.0); } void dF_branch(float fn, out vec2 result) { result.x = DFDX_SIGN * dFdx(fn); result.y = DFDY_SIGN * dFdy(fn); } #else /* Precise derivatives */ int g_derivative_flag = 0; vec3 dF_impl(vec3 v) { if (g_derivative_flag > 0) { return DFDX_SIGN * dFdx(v); } else if (g_derivative_flag < 0) { return DFDY_SIGN * dFdy(v); } return vec3(0.0); } # define dF_branch(fn, result) \ if (true) { \ g_derivative_flag = 1; \ result.x = (fn); \ g_derivative_flag = -1; \ result.y = (fn); \ g_derivative_flag = 0; \ result -= vec2((fn)); \ } #endif /* TODO(fclem): Remove. */ #define CODEGEN_LIB