1// Copyright 2009-2021 Intel Corporation 2// SPDX-License-Identifier: Apache-2.0 3 4#pragma once 5 6#include "math.isph" 7 8#define __define_ispc_vector2(TYPE,ABB) \ 9 struct Vec2##ABB { \ 10 TYPE x; TYPE y; \ 11 }; \ 12 13#define __define_ispc_vector3(TYPE,ABB) \ 14 struct Vec3##ABB { \ 15 TYPE x,y,z; \ 16 }; \ 17 struct Vec3##ABB##a { \ 18 TYPE x,y,z,w; \ 19 }; \ 20 21#define __define_ispc_vector4(TYPE,ABB) \ 22 struct Vec4##ABB { \ 23 TYPE x,y,z,w; \ 24 }; \ 25 26__define_ispc_vector2(int,i); 27__define_ispc_vector2(unsigned int,ui); 28__define_ispc_vector2(unsigned int8,uc); 29__define_ispc_vector2(float,f); 30 31__define_ispc_vector3(int,i); 32__define_ispc_vector3(unsigned int,ui); 33__define_ispc_vector3(unsigned int8,uc); 34__define_ispc_vector3(float,f); 35 36__define_ispc_vector4(int,i); 37__define_ispc_vector4(unsigned int,ui); 38__define_ispc_vector4(unsigned int8,uc); 39__define_ispc_vector4(float,f); 40 41#undef __define_ispc_vector2 42#undef __define_ispc_vector3 43#undef __define_ispc_vector4 44 45 46 47 48/*! defines all constructors "make_Vec2[T]" for 2-vector type */ 49#define __define_ispc_constructors2(UV,TYPE,ABB,ITYPE,IABB) \ 50 inline UV Vec2##ABB make_Vec2##ABB(const UV ITYPE x, \ 51 const UV ITYPE y) \ 52 { \ 53 UV Vec2##ABB ret; \ 54 ret.x = x; \ 55 ret.y = y; \ 56 return ret; \ 57 } \ 58 inline UV Vec2##ABB make_Vec2##ABB(const UV ITYPE x) \ 59 { \ 60 UV Vec2##ABB ret; \ 61 ret.x = x; \ 62 ret.y = x; \ 63 return ret; \ 64 } \ 65 66/*! defines all constructors "make_Vec3[T]" and "make_Vec3[T]a" for 67 3-vector type */ 68#define __define_ispc_constructors3(UV,TYPE,ABB,ITYPE,IABB) \ 69 inline UV Vec3##ABB make_Vec3##ABB(const UV ITYPE x) \ 70 { \ 71 UV Vec3##ABB ret; \ 72 ret.x = x; \ 73 ret.y = x; \ 74 ret.z = x; \ 75 return ret; \ 76 } \ 77 inline UV Vec3##ABB make_Vec3##ABB(const UV Vec3##IABB v) \ 78 { \ 79 UV Vec3##ABB ret; \ 80 ret.x = v.x; \ 81 ret.y = v.y; \ 82 ret.z = v.z; \ 83 return ret; \ 84 } \ 85 inline UV Vec3##ABB make_Vec3##ABB(const UV Vec3##IABB##a v) \ 86 { \ 87 UV Vec3##ABB ret; \ 88 ret.x = v.x; \ 89 ret.y = v.y; \ 90 ret.z = v.z; \ 91 return ret; \ 92 } \ 93 inline UV Vec3##ABB make_Vec3##ABB(const UV ITYPE x, \ 94 const UV ITYPE y, \ 95 const UV ITYPE z) \ 96 { \ 97 UV Vec3##ABB ret; \ 98 ret.x = x; \ 99 ret.y = y; \ 100 ret.z = z; \ 101 return ret; \ 102 } \ 103 inline UV Vec3##ABB make_Vec3##ABB(const UV Vec4##IABB v) \ 104 { \ 105 UV Vec3##ABB ret; \ 106 ret.x = v.x; \ 107 ret.y = v.y; \ 108 ret.z = v.z; \ 109 return ret; \ 110 } \ 111 /* the '3a' variants */ \ 112 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x) \ 113 { \ 114 UV Vec3##ABB##a ret; \ 115 ret.x = x; \ 116 ret.y = x; \ 117 ret.z = x; \ 118 ret.w = 0; \ 119 return ret; \ 120 } \ 121 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB &v) \ 122 { \ 123 UV Vec3##ABB##a ret; \ 124 ret.x = v.x; \ 125 ret.y = v.y; \ 126 ret.z = v.z; \ 127 ret.w = 0; \ 128 return ret; \ 129 } \ 130 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB##a v) \ 131 { \ 132 UV Vec3##ABB##a ret; \ 133 ret.x = v.x; \ 134 ret.y = v.y; \ 135 ret.z = v.z; \ 136 ret.w = v.w; \ 137 return ret; \ 138 } \ 139 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x, \ 140 const UV ITYPE y, \ 141 const UV ITYPE z) \ 142 { \ 143 UV Vec3##ABB##a ret; \ 144 ret.x = x; \ 145 ret.y = y; \ 146 ret.z = z; \ 147 ret.w = 0; \ 148 return ret; \ 149 } \ 150 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV ITYPE x, \ 151 const UV ITYPE y, \ 152 const UV ITYPE z, \ 153 const UV ITYPE w) \ 154 { \ 155 UV Vec3##ABB##a ret; \ 156 ret.x = x; \ 157 ret.y = y; \ 158 ret.z = z; \ 159 ret.w = w; \ 160 return ret; \ 161 } \ 162 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec3##IABB &v, \ 163 const UV ITYPE w) \ 164 { \ 165 UV Vec3##ABB##a ret; \ 166 ret.x = v.x; \ 167 ret.y = v.y; \ 168 ret.z = v.z; \ 169 ret.w = w; \ 170 return ret; \ 171 } \ 172 inline UV Vec3##ABB##a make_Vec3##ABB##a(const UV Vec4##IABB v) \ 173 { \ 174 UV Vec3##ABB##a ret; \ 175 ret.x = v.x; \ 176 ret.y = v.y; \ 177 ret.z = v.z; \ 178 ret.w = v.w; \ 179 return ret; \ 180 } \ 181 182 183 184 185 186/*! defines all constructors "make_Vec4[T]" for 4-vector type */ 187#define __define_ispc_constructors4(UV,TYPE,ABB,ITYPE,IABB) \ 188 /*! construct Vec4 from a single scalar */ \ 189 inline UV Vec4##ABB make_Vec4##ABB(const UV ITYPE f) \ 190 { \ 191 UV Vec4##ABB ret; \ 192 ret.x = f; \ 193 ret.y = f; \ 194 ret.z = f; \ 195 ret.w = f; \ 196 return ret; \ 197 } \ 198 /*! construct Vec4 from a 4 scalars */ \ 199 inline UV Vec4##ABB make_Vec4##ABB(const UV ITYPE x, \ 200 const UV ITYPE y, \ 201 const UV ITYPE z, \ 202 const UV ITYPE w) \ 203 { \ 204 UV Vec4##ABB ret; \ 205 ret.x = x; \ 206 ret.y = y; \ 207 ret.z = z; \ 208 ret.w = w; \ 209 return ret; \ 210 } \ 211 /*! construct Vec4 from another Vec4 (of another type) */ \ 212 inline UV Vec4##ABB make_Vec4##ABB(const UV Vec4##IABB v) \ 213 { \ 214 UV Vec4##ABB ret; \ 215 ret.x = v.x; \ 216 ret.y = v.y; \ 217 ret.z = v.z; \ 218 ret.w = v.w; \ 219 return ret; \ 220 } \ 221 222 223#define __define_ispc_lift_constructors4(UV,TYPE,ABB) \ 224 /*! lift Vec4 from Vec3; fill in with 0es */ \ 225 inline UV Vec4##ABB make_Vec4##ABB(const UV Vec3##ABB v) \ 226 { \ 227 UV Vec4##ABB ret; \ 228 ret.x = (TYPE)v.x; \ 229 ret.y = (TYPE)v.y; \ 230 ret.z = (TYPE)v.z; \ 231 ret.w = (TYPE)0; \ 232 return ret; \ 233 } \ 234 235#define __define_ispc_constructors_uv_t(UV,OTYPE,OABB,ITYPE,IABB) \ 236 __define_ispc_constructors2(UV,OTYPE,OABB,ITYPE,IABB) \ 237 __define_ispc_constructors3(UV,OTYPE,OABB,ITYPE,IABB) \ 238 __define_ispc_constructors4(UV,OTYPE,OABB,ITYPE,IABB) \ 239 240#define __define_ispc_constructors_uv(UV,TYPE,ABB) \ 241 __define_ispc_constructors_uv_t(UV,TYPE,ABB,int,i) \ 242 __define_ispc_constructors_uv_t(UV,TYPE,ABB,unsigned int,ui) \ 243 __define_ispc_constructors_uv_t(UV,TYPE,ABB,unsigned int8,uc) \ 244 __define_ispc_constructors_uv_t(UV,TYPE,ABB,float,f) \ 245 __define_ispc_lift_constructors4(UV,TYPE,ABB) \ 246 247#define __define_ispc_constructors(UV) \ 248 __define_ispc_constructors_uv(UV,unsigned int,ui) \ 249 __define_ispc_constructors_uv(UV,unsigned int8,uc) \ 250 __define_ispc_constructors_uv(UV,int,i) \ 251 __define_ispc_constructors_uv(UV,float,f) \ 252 253__define_ispc_constructors(uniform); 254__define_ispc_constructors(varying); 255 256#undef __define_ispc_constructors2 257#undef __define_ispc_constructors3 258#undef __define_ispc_constructors3a 259#undef __define_ispc_constructors4 260#undef __define_ispc_lift_constructors4 261#undef __define_ispc_constructors_uv 262#undef __define_ispc_constructors 263 264 265// ======================================================= 266// define 'lifted' binary operators (min/max/...) 267 268#define __lift_binaryFct(FCT,T) \ 269 /* ********************************************************* */ \ 270 /* ---- Vec2 ---- */ \ 271 /* ********************************************************* */ \ 272 /* uniform Vec2 FCT(uniform Vec2, uniform Vec2) */ \ 273 inline uniform Vec2##T FCT(const uniform Vec2##T a, \ 274 const uniform Vec2##T b) \ 275 { return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \ 276 /* Vec2 FCT(Vec2, Vec2) */ \ 277 inline varying Vec2##T FCT(const varying Vec2##T a, \ 278 const varying Vec2##T b) \ 279 { return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \ 280 /* Vec2 FCT(Vec2, uniform Vec2) */ \ 281 inline varying Vec2##T FCT(const varying Vec2##T a, \ 282 const uniform Vec2##T b) \ 283 { return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \ 284 /* Vec2 FCT(uniform Vec2, Vec2) */ \ 285 inline varying Vec2##T FCT(const uniform Vec2##T a, \ 286 const varying Vec2##T b) \ 287 { return make_Vec2##T(FCT(a.x,b.x),FCT(a.y,b.y)); } \ 288 \ 289 /* ********************************************************* */ \ 290 /* ---- Vec3 ---- */ \ 291 /* ********************************************************* */ \ 292 /* uniform Vec3 FCT(uniform Vec3, uniform Vec3) */ \ 293 inline uniform Vec3##T FCT(const uniform Vec3##T a, \ 294 const uniform Vec3##T b) \ 295 { return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 296 /* Vec3 FCT(Vec3, Vec3) */ \ 297 inline varying Vec3##T FCT(const varying Vec3##T a, \ 298 const varying Vec3##T b) \ 299 { return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 300 /* Vec3 FCT(uniformVec3, Vec3) */ \ 301 inline varying Vec3##T FCT(const uniform Vec3##T a, \ 302 const varying Vec3##T b) \ 303 { return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 304 /* Vec3 FCT(Vec3, uniformVec3) */ \ 305 inline varying Vec3##T FCT(const varying Vec3##T a, \ 306 const uniform Vec3##T b) \ 307 { return make_Vec3##T(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 308 \ 309 /* ********************************************************* */ \ 310 /* ---- Vec3a (from 3a and 3a) ---- */ \ 311 /* ********************************************************* */ \ 312 /* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */ \ 313 inline uniform Vec3##T##a FCT(const uniform Vec3##T##a a, \ 314 const uniform Vec3##T##a b) \ 315 { return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z),FCT(a.w,b.w)); } \ 316 /* Vec3a FCT(Vec3a, Vec3a) */ \ 317 inline varying Vec3##T##a FCT(const varying Vec3##T##a a, \ 318 const varying Vec3##T##a b) \ 319 { return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z),FCT(a.w,b.w)); } \ 320 \ 321 /* ********************************************************* */ \ 322 /* ---- Vec3a (from 3 and 3a) ---- */ \ 323 /* ********************************************************* */ \ 324 /* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */ \ 325 inline uniform Vec3##T##a FCT(const uniform Vec3##T a, \ 326 const uniform Vec3##T##a b) \ 327 { return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 328 /* Vec3a FCT(Vec3a, Vec3a) */ \ 329 inline varying Vec3##T##a FCT(const varying Vec3##T a, \ 330 const varying Vec3##T##a b) \ 331 { return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 332 \ 333 /* ********************************************************* */ \ 334 /* ---- Vec3a (from 3a and 3) ---- */ \ 335 /* ********************************************************* */ \ 336 /* uniform Vec3a FCT(uniform Vec3a, uniform Vec3a) */ \ 337 inline uniform Vec3##T##a FCT(const uniform Vec3##T##a a, \ 338 const uniform Vec3##T b) \ 339 { return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 340 /* Vec3a FCT(Vec3a, Vec3a) */ \ 341 inline varying Vec3##T##a FCT(const varying Vec3##T##a a, \ 342 const varying Vec3##T b) \ 343 { return make_Vec3##T##a(FCT(a.x,b.x),FCT(a.y,b.y),FCT(a.z,b.z)); } \ 344 \ 345 /* ********************************************************* */ \ 346 /* ---- Vec4 ---- */ \ 347 /* ********************************************************* */ \ 348 /* uniform Vec4 FCT(uniform Vec4, uniform Vec4) */ \ 349 inline uniform Vec4##T FCT(const uniform Vec4##T a, \ 350 const uniform Vec4##T b) \ 351 { return make_Vec4##T(FCT(a.x,b.x),FCT(a.y,b.y), \ 352 FCT(a.z,b.z),FCT(a.w,b.w)); } \ 353 /* Vec4 FCT(Vec4, Vec4) */ \ 354 inline varying Vec4##T FCT(const varying Vec4##T a, \ 355 const varying Vec4##T b) \ 356 { return make_Vec4##T(FCT(a.x,b.x),FCT(a.y,b.y), \ 357 FCT(a.z,b.z),FCT(a.w,b.w)); } \ 358 359__lift_binaryFct(min,f) 360__lift_binaryFct(max,f) 361__lift_binaryFct(min,i) 362__lift_binaryFct(max,i) 363__lift_binaryFct(min,ui) 364__lift_binaryFct(max,ui) 365 366#undef __lift_binaryFct 367 368// ======================================================= 369 370// for now, let's implement those manually - should eventually do those via a macro! 371 372inline uniform Vec3f neg(const uniform Vec3f v) 373{ return make_Vec3f(-v.x,-v.y,-v.z); } 374inline Vec3f neg(const Vec3f v) 375{ return make_Vec3f(-v.x,-v.y,-v.z); } 376inline uniform Vec3f negate(const uniform Vec3f &a) 377{ return(make_Vec3f(-a.x, -a.y, -a.z)); } 378inline varying Vec3f negate(const varying Vec3f &a) 379{ return(make_Vec3f(-a.x, -a.y, -a.z)); } 380 381 382#define __define_binary_operator_typed(opname,op,abb,type) \ 383 /* Vec2##abb */ \ 384 inline uniform Vec2##abb opname (const uniform Vec2##abb a, \ 385 const uniform Vec2##abb b) { \ 386 return make_Vec2##abb(a.x op b.x, a.y op b.y); \ 387 } \ 388 inline Vec2##abb opname (const Vec2##abb a, const Vec2##abb b) { \ 389 return make_Vec2##abb(a.x op b.x, a.y op b.y); \ 390 } \ 391 inline uniform Vec2##abb opname (const uniform Vec2##abb a, \ 392 const uniform type b) { \ 393 return make_Vec2##abb(a.x op b, a.y op b); \ 394 } \ 395 inline Vec2##abb opname (const Vec2##abb a, const type b) { \ 396 return make_Vec2##abb(a.x op b, a.y op b); \ 397 } \ 398 inline uniform Vec2##abb opname (const uniform type a, \ 399 const uniform Vec2##abb b) { \ 400 return make_Vec2##abb(a op b.x, a op b.y); \ 401 } \ 402 inline Vec2##abb opname (const type a, const Vec2##abb b) { \ 403 return make_Vec2##abb(a op b.x, a op b.y); \ 404 } \ 405 /* Vec3##abb */ \ 406 inline uniform Vec3##abb opname (const uniform Vec3##abb a, \ 407 const uniform Vec3##abb b) { \ 408 return make_Vec3##abb(a.x op b.x, a.y op b.y, a.z op b.z); \ 409 } \ 410 inline Vec3##abb opname (const Vec3##abb a, const Vec3##abb b) { \ 411 return make_Vec3##abb(a.x op b.x, a.y op b.y, a.z op b.z); \ 412 } \ 413 inline uniform Vec3##abb opname (const uniform Vec3##abb a, \ 414 const uniform type b) { \ 415 return make_Vec3##abb(a.x op b, a.y op b, a.z op b); \ 416 } \ 417 inline Vec3##abb opname (const Vec3##abb a, const type b) { \ 418 return make_Vec3##abb(a.x op b, a.y op b, a.z op b); \ 419 } \ 420 inline uniform Vec3##abb opname (const uniform type a, \ 421 const uniform Vec3##abb b) { \ 422 return make_Vec3##abb(a op b.x, a op b.y, a op b.z); \ 423 } \ 424 inline Vec3##abb opname (const type a, const Vec3##abb b) { \ 425 return make_Vec3##abb(a op b.x, a op b.y, a op b.z); \ 426 } \ 427 /* Vec3##abb##a */ \ 428 inline uniform Vec3##abb##a opname (const uniform Vec3##abb##a a, \ 429 const uniform Vec3##abb##a b) { \ 430 return make_Vec3##abb##a(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ 431 } \ 432 inline Vec3##abb##a opname (const Vec3##abb##a a, const Vec3##abb##a b) { \ 433 return make_Vec3##abb##a(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ 434 } \ 435 inline uniform Vec3##abb##a opname (const uniform Vec3##abb##a a, \ 436 const uniform type b) { \ 437 return make_Vec3##abb##a(a.x op b, a.y op b, a.z op b, a.w op b); \ 438 } \ 439 inline Vec3##abb##a opname (const Vec3##abb##a a, const type b) { \ 440 return make_Vec3##abb##a(a.x op b, a.y op b, a.z op b, a.w op b); \ 441 } \ 442 inline uniform Vec3##abb##a opname (const uniform type a, \ 443 const uniform Vec3##abb##a b) { \ 444 return make_Vec3##abb##a(a op b.x, a op b.y, a op b.z, a op b.w); \ 445 } \ 446 inline Vec3##abb##a opname (const type a, const Vec3##abb##a b) { \ 447 return make_Vec3##abb##a(a op b.x, a op b.y, a op b.z, a op b.w); \ 448 } \ 449 /* Vec4##abb */ \ 450 inline uniform Vec4##abb opname (const uniform Vec4##abb a, \ 451 const uniform Vec4##abb b) { \ 452 return make_Vec4##abb(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ 453 } \ 454 inline Vec4##abb opname (const Vec4##abb a, const Vec4##abb b) { \ 455 return make_Vec4##abb(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ 456 } \ 457 inline uniform Vec4##abb opname (const uniform Vec4##abb a, \ 458 const uniform type b) { \ 459 return make_Vec4##abb(a.x op b, a.y op b, a.z op b, a.w op b); \ 460 } \ 461 inline Vec4##abb opname (const Vec4##abb a, const type b) { \ 462 return make_Vec4##abb(a.x op b, a.y op b, a.z op b, a.w op b); \ 463 } \ 464 inline uniform Vec4##abb opname (const uniform type a, \ 465 const uniform Vec4##abb b) { \ 466 return make_Vec4##abb(a op b.x, a op b.y, a op b.z, a op b.w); \ 467 } \ 468 inline Vec4##abb opname (const type a, const Vec4##abb b) { \ 469 return make_Vec4##abb(a op b.x, a op b.y, a op b.z, a op b.w); \ 470 } 471 472#define __define_binary_operator(opname,op) \ 473 __define_binary_operator_typed(opname,op,f,float) \ 474 __define_binary_operator_typed(opname,op,i,int32) \ 475 __define_binary_operator_typed(opname,op,ui,uint32) 476 477 478// define 'regular' operators 479__define_binary_operator( operator+, + ); 480__define_binary_operator( operator-, - ); 481__define_binary_operator( operator*, * ); 482__define_binary_operator( operator/, / ); 483 484// define old functional operators as used in the embree path tracer, deprecated 485__define_binary_operator( add, + ); 486__define_binary_operator( sub, - ); 487__define_binary_operator( mul, * ); 488 489#undef __define_binary_operator 490 491inline float reduce_mul(const Vec3f v) 492{ return v.x * v.y * v.z; } 493inline uniform float reduce_mul(const uniform Vec3f v) 494{ return v.x * v.y * v.z; } 495 496inline float reduce_max(const Vec3f v) 497{ return max(max(v.x,v.y),v.z); } 498 499inline float reduce_add(const Vec3f v) 500{ return v.x+v.y+v.z; } 501 502inline uniform float reduce_add(const uniform Vec3f v) 503{ return v.x+v.y+v.z; } 504 505inline float reduce_avg(const Vec3f v) 506{ return (v.x+v.y+v.z)*(1.0f/3.0f); } 507 508inline float luminance(const Vec3f& c) 509{ return 0.212671f*c.x + 0.715160f*c.y + 0.072169f*c.z; } 510 511inline uniform bool eq(const uniform Vec2f a, const uniform Vec2f b) 512{ return a.x==b.x && a.y==b.y; } 513inline bool eq(const Vec2f a, const Vec2f b) 514{ return a.x==b.x & a.y==b.y; } 515inline uniform bool eq(const uniform Vec3f a, const uniform Vec3f b) 516{ return a.x==b.x && a.y==b.y && a.z==b.z; } 517inline bool eq(const Vec3f a, const Vec3f b) 518{ return a.x==b.x & a.y==b.y & a.z==b.z; } 519inline uniform bool eq(const uniform Vec3fa a, const uniform Vec3fa b) 520{ return a.x==b.x && a.y==b.y && a.z==b.z; } 521inline bool eq(const Vec3fa a, const Vec3fa b) 522{ return a.x==b.x & a.y==b.y & a.z==b.z; } 523 524inline uniform bool ne(const uniform Vec2f a, const uniform Vec2f b) 525{ return !eq(a,b); } 526inline bool ne(const Vec2f a, const Vec2f b) 527{ return !eq(a,b); } 528inline uniform bool ne(const uniform Vec3f a, const uniform Vec3f b) 529{ return !eq(a,b); } 530inline bool ne(const Vec3f a, const Vec3f b) 531{ return !eq(a,b); } 532inline uniform bool ne(const uniform Vec3fa a, const uniform Vec3fa b) 533{ return !eq(a,b); } 534inline bool ne(const Vec3fa a, const Vec3fa b) 535{ return !eq(a,b); } 536 537 538// ------------------------------------------------------------------ 539// dot product 540// ------------------------------------------------------------------ 541/*! computes 3D dot product for *all-uniform* Vec3fs */ 542inline uniform float dot(const uniform Vec3f a, const uniform Vec3f b) 543{ return a.x*b.x+a.y*b.y+a.z*b.z; } 544/*! computes 3D dot product for Vec3fs that produce varying results */ 545inline float dot(const Vec3f a, const Vec3f b) 546{ return a.x*b.x+a.y*b.y+a.z*b.z; } 547 548inline uniform float length(const uniform Vec3f a) { return sqrtf(dot(a,a)); } 549inline varying float length(const varying Vec3f a) { return sqrtf(dot(a,a)); } 550 551inline uniform float distance(const uniform Vec3f a, const uniform Vec3f b) { return length(a - b); } 552inline varying float distance(const varying Vec3f a, const varying Vec3f b) { return length(a - b); } 553 554 555inline uniform float dot(const uniform Vec3fa a, const uniform Vec3fa b) { return a.x*b.x+a.y*b.y+a.z*b.z; } 556inline varying float dot(const varying Vec3fa a, const varying Vec3fa b) { return a.x*b.x+a.y*b.y+a.z*b.z; } 557 558inline uniform float length(const uniform Vec3fa a) { return sqrtf(dot(a,a)); } 559inline varying float length(const varying Vec3fa a) { return sqrtf(dot(a,a)); } 560 561inline uniform float distance(const uniform Vec3fa a, const uniform Vec3fa b) { return length(a - b); } 562inline varying float distance(const varying Vec3fa a, const varying Vec3fa b) { return length(a - b); } 563 564// ------------------------------------------------------------------ 565// cross product 566// ------------------------------------------------------------------ 567/*! computes 3D cross product for *all-uniform* Vec3fs */ 568inline uniform Vec3f cross(const uniform Vec3f &a, const uniform Vec3f &b) 569{ return make_Vec3f(a.y*b.z-a.z*b.y, 570 a.z*b.x-a.x*b.z, 571 a.x*b.y-a.y*b.x); } 572/*! computes 3D cross product for Vec3fs that produce varying results */ 573inline Vec3f cross(const Vec3f &a, const Vec3f &b) 574{ return make_Vec3f(a.y*b.z-a.z*b.y, 575 a.z*b.x-a.x*b.z, 576 a.x*b.y-a.y*b.x); } 577 578 579// ------------------------------------------------------------------ 580// normalize 581// ------------------------------------------------------------------ 582/*! compute and return normalized version of uniform Vec3f passed to this fct */ 583inline uniform Vec3f normalize(const uniform Vec3f &v) 584{ return v * (1.f/sqrt(dot(v,v))); } 585/*! compute and return normalized version of varying Vec3f passed to this fct */ 586inline Vec3f normalize(const Vec3f v) 587{ return v * (1.f/sqrt(dot(v,v))); } 588/*! compute and return normalized version of varying Vec3f passed to this fct */ 589inline Vec3f normalize(const Vec3f v, float &len) 590{ len = sqrtf(dot(v,v)); return v * rcpf(len); } 591 592inline Vec3f safe_normalize(const Vec3f v) 593{ return v * (1.f/sqrt(max(1e-6f,dot(v,v)))); } 594 595/*! differentiated normalization */ 596inline varying Vec3f dnormalize(const varying Vec3f& p, const varying Vec3f& dp) 597{ 598 const float pp = dot(p,p); 599 const float pdp = dot(p,dp); 600 return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp); 601} 602 603 604inline uniform Vec3fa normalize(const uniform Vec3fa &v) { return v * (1.f/sqrt(dot(v,v))); } 605inline varying Vec3fa normalize(const varying Vec3fa v) { return v * (1.f/sqrt(dot(v,v))); } 606 607inline varying Vec3fa dnormalize(const varying Vec3fa& p, const varying Vec3fa& dp) 608{ 609 const float pp = dot(p,p); 610 const float pdp = dot(p,dp); 611 return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp); 612} 613 614 615#define __lift_unary_fct(F) \ 616 inline uniform Vec2f F(const uniform Vec2f v) \ 617 { return make_Vec2f(F(v.x),F(v.y)); } \ 618 inline Vec2f F(const Vec2f v) \ 619 { return make_Vec2f(F(v.x),F(v.y)); } \ 620 inline uniform Vec3f F(const uniform Vec3f v) \ 621 { return make_Vec3f(F(v.x),F(v.y),F(v.z)); } \ 622 inline Vec3f F(const Vec3f v) \ 623 { return make_Vec3f(F(v.x),F(v.y),F(v.z)); } \ 624 inline uniform Vec3fa F(const uniform Vec3fa v) \ 625 { return make_Vec3fa(F(v.x),F(v.y),F(v.z),F(v.w)); } \ 626 inline Vec3fa F(const Vec3fa v) \ 627 { return make_Vec3fa(F(v.x),F(v.y),F(v.z),F(v.w)); } \ 628 inline uniform Vec4f F(const uniform Vec4f v) \ 629 { return make_Vec4f(F(v.x),F(v.y),F(v.z),F(v.w)); } \ 630 inline Vec4f F(const Vec4f v) \ 631 { return make_Vec4f(F(v.x),F(v.y),F(v.z),F(v.w)); } 632 633__lift_unary_fct(absf) 634__lift_unary_fct(rcpf) 635__lift_unary_fct(expf) 636__lift_unary_fct(logf) 637 638__lift_unary_fct(floor) 639__lift_unary_fct(abs) 640__lift_unary_fct(rcp) 641__lift_unary_fct(exp) 642__lift_unary_fct(frac) 643__lift_unary_fct(sqr) 644 645#undef __lift_unary_fct 646 647/*! make RGBA from RGB */ 648inline Vec4f make_Vec4f(const Vec3f rgb, const float a) 649{ return make_Vec4f(rgb.x,rgb.y,rgb.z,a); } 650 651/*! make RGBA from RGB */ 652inline uniform Vec4f make_Vec4f(const uniform Vec3f rgb, const uniform float a) 653{ return make_Vec4f(rgb.x,rgb.y,rgb.z,a); } 654 655// // ------------------------------------------------------------------ 656// // vector functions (abs,rcp,...): 657// // ------------------------------------------------------------------ 658// /*! return vector of absolute values of input vector */ 659// inline uniform Vec3f abs(const uniform Vec3f v) 660// { return make_Vec3f(abs(v.x),abs(v.y),abs(v.z)); } 661// /*! return vector of absolute values of input vector */ 662// inline Vec3f abs(const Vec3f v) 663// { return make_Vec3f(abs(v.x),abs(v.y),abs(v.z)); } 664// /*! return vector of reciprocals of input vector */ 665// inline uniform Vec3f rcp(const uniform Vec3f v) 666// { return make_Vec3f(rcp(v.x),rcp(v.y),rcp(v.z)); } 667// /*! return vector of reciprocals of input vector */ 668// inline Vec3f rcp(const Vec3f v) 669// { return make_Vec3f(rcp(v.x),rcp(v.y),rcp(v.z)); } 670 671#define __define_lerp2(ABB) \ 672 inline uniform Vec2##ABB lerp(uniform float factor, const uniform Vec2##ABB a, const uniform Vec2##ABB b) \ 673 { \ 674 return make_Vec2##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y)); \ 675 } \ 676 inline Vec2##ABB lerp(float factor, const Vec2##ABB a, const Vec2##ABB b) \ 677 { \ 678 return make_Vec2##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y)); \ 679 } 680 681#define __define_lerp3(ABB) \ 682 inline uniform Vec3##ABB lerp(uniform float factor, const uniform Vec3##ABB a, const uniform Vec3##ABB b) \ 683 { \ 684 return make_Vec3##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z)); \ 685 } \ 686 inline Vec3##ABB lerp(float factor, const Vec3##ABB a, const Vec3##ABB b) \ 687 { \ 688 return make_Vec3##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z)); \ 689 } \ 690 691#define __define_lerp3a(ABB) \ 692 inline uniform Vec3##ABB##a lerp(uniform float factor, const uniform Vec3##ABB##a a, const uniform Vec3##ABB##a b) \ 693 { \ 694 return make_Vec3##ABB##a(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \ 695 } \ 696 inline Vec3##ABB##a lerp(float factor, const Vec3##ABB##a a, const Vec3##ABB##a b) \ 697 { \ 698 return make_Vec3##ABB##a(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \ 699 } 700 701#define __define_lerp4(ABB) \ 702 inline uniform Vec4##ABB lerp(uniform float factor, const uniform Vec4##ABB a, const uniform Vec4##ABB b) \ 703 { \ 704 return make_Vec4##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \ 705 } \ 706 inline Vec4##ABB lerp(float factor, const Vec4##ABB a, const Vec4##ABB b) \ 707 { \ 708 return make_Vec4##ABB(lerp(factor, a.x, b.x), lerp(factor, a.y, b.y), lerp(factor, a.z, b.z), lerp(factor, a.w, b.w)); \ 709 } 710 711__define_lerp2(f) 712__define_lerp2(i) 713__define_lerp2(ui) 714__define_lerp2(uc) 715__define_lerp3(f) 716__define_lerp3(i) 717__define_lerp3(ui) 718__define_lerp3(uc) 719//__define_lerp3a(i) 720//__define_lerp3a(ui) 721//__define_lerp3a(uc) 722__define_lerp4(f) 723__define_lerp4(i) 724__define_lerp4(ui) 725__define_lerp4(uc) 726 727#undef __define_lerp2 728#undef __define_lerp3 729#undef __define_lerp4 730 731inline Vec2i make_Vec2i(const Vec2f &a) 732{ return make_Vec2i((int)a.x, (int)a.y); } 733 734inline Vec2i integer_cast(const Vec2f &a) 735{ return make_Vec2i(a); } 736 737inline Vec2f clamp(const Vec2f &a, const uniform Vec2f &b, const uniform Vec2f &c) 738{ return(make_Vec2f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y))); } 739 740 741inline uniform Vec3i operator*(const uniform Vec3i &a, const uniform int b) 742{ return(make_Vec3i(a.x * b, a.y * b, a.z * b)); } 743 744inline uniform Vec3i operator+(const uniform Vec3i &a, const uniform Vec3i &b) 745{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); } 746 747inline Vec3i operator+(const varying Vec3i &a, const varying Vec3i &b) 748{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); } 749 750// Workaround for compiler bug. 751inline Vec3i operator+(const uniform Vec3i &a, const varying Vec3i &b) 752{ return(make_Vec3i(a.x + b.x, a.y + b.y, a.z + b.z)); } 753 754inline Vec3i operator+(const varying Vec3i &a, const varying int32 b) 755{ return(make_Vec3i(a.x + b, a.y + b, a.z + b)); } 756 757inline uniform Vec3i operator+(const uniform Vec3i &a, const uniform int b) 758{ return(make_Vec3i(a.x + b, a.y + b, a.z + b)); } 759 760inline uniform Vec3i operator-(const uniform Vec3i &a, const uniform int b) 761{ return(make_Vec3i(a.x - b, a.y - b, a.z - b)); } 762 763inline Vec3i operator-(const varying Vec3i &a, const uniform Vec3i &b) 764{ return(make_Vec3i(a.x - b.x, a.y - b.y, a.z - b.z)); } 765 766inline Vec3i operator-(const varying Vec3i &a, const varying Vec3i &b) 767{ return(make_Vec3i(a.x - b.x, a.y - b.y, a.z - b.z)); } 768 769inline Vec3i operator-(const varying Vec3i &a, const varying int32 b) 770{ return(make_Vec3i(a.x - b, a.y - b, a.z - b)); } 771 772inline uniform Vec3i operator/(const uniform Vec3i &a, const uniform int b) 773{ return(make_Vec3i(a.x / b, a.y / b, a.z / b)); } 774 775inline Vec3f float_cast(const Vec3i &a) 776{ return make_Vec3f(a); } 777 778inline Vec3i integer_cast(const Vec3f &a) 779{ return make_Vec3i(a); } 780 781inline Vec3i operator>>(const Vec3i &a, const int b) 782{ return(make_Vec3i(a.x >> b, a.y >> b, a.z >> b)); } 783 784inline Vec3i operator<<(const Vec3i &a, const int b) 785{ return(make_Vec3i(a.x << b, a.y << b, a.z << b)); } 786 787inline Vec3i bitwise_AND(const Vec3i &a, const int b) 788{ return(make_Vec3i(a.x & b, a.y & b, a.z &b)); } 789 790inline Vec3f powf(const Vec3f v, const float f) 791{ return make_Vec3f(powf(v.x,f),powf(v.y,f),powf(v.z,f)); } 792 793inline uniform Vec3f powf(const uniform Vec3f v, const uniform float f) 794{ return make_Vec3f(powf(v.x,f),powf(v.y,f),powf(v.z,f)); } 795 796inline Vec3f clamp(const Vec3f &a, const uniform Vec3f &b, const uniform Vec3f &c) 797{ return(make_Vec3f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); } 798 799inline Vec3f clamp(const Vec3f &a, const Vec3f &b, const Vec3f &c) 800{ return(make_Vec3f(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); } 801 802inline Vec3i clamp(const Vec3i &a, const uniform Vec3i &b, const uniform Vec3i &c) 803{ return(make_Vec3i(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z))); } 804 805//! The next machine representable number from 'a' in the direction of 'b'. 806inline uniform Vec3f nextafter(const uniform Vec3i &a, const uniform Vec3i &b) 807{ return(make_Vec3f(nextafter(a.x, b.x), nextafter(a.y, b.y), nextafter(a.z, b.z))); } 808 809inline varying float reduce_min(const varying Vec3f &a) 810{ return min(min(a.x, a.y), a.z); } 811 812inline uniform float reduce_min(const uniform Vec3f &a) 813{ return min(min(a.x, a.y), a.z); } 814 815inline uniform float reduce_min(const uniform Vec3i &a) 816{ return min(min(a.x, a.y), a.z); } 817 818inline varying float reduce_min(const varying Vec3i &a) 819{ return min(min(a.x, a.y), a.z); } 820 821inline varying float reduce_min(const varying Vec4f &a) 822{ return min(min(a.x, a.y), min(a.z, a.w)); } 823 824inline uniform float reduce_min(const uniform Vec4f &a) 825{ return min(min(a.x, a.y), min(a.z, a.w)); } 826 827inline uniform float reduce_max(const uniform Vec3i &a) 828{ return max(max(a.x, a.y), a.z); } 829 830inline varying float reduce_max(const varying Vec3i &a) 831{ return max(max(a.x, a.y), a.z); } 832 833inline varying float reduce_max(const varying Vec3f &a) 834{ return max(max(a.x, a.y), a.z); } 835 836inline uniform float reduce_max(const uniform Vec3f &a) 837{ return max(max(a.x, a.y), a.z); } 838 839inline varying float reduce_max(const varying Vec4f &a) 840{ return max(max(a.x, a.y), max(a.z, a.w)); } 841 842inline uniform float reduce_max(const uniform Vec4f &a) 843{ return max(max(a.x, a.y), max(a.z, a.w)); } 844 845inline uniform float reduce_add(const uniform Vec3f &a) 846{ return a.x+a.y+a.z; } 847 848inline uniform float reduce_avg(const uniform Vec3f &a) 849{ return reduce_add(a)*(1.0f/3.0f); } 850 851inline uniform float luminance(const uniform Vec3f& c) 852{ return 0.212671f*c.x + 0.715160f*c.y + 0.072169f*c.z; } 853 854inline varying Vec3f pow(const varying Vec3f &a, const varying float b) 855{ return make_Vec3f(pow(a.x, b), pow(a.y, b), pow(a.z, b)); } 856 857inline varying Vec4f pow(const varying Vec4f &a, const varying float b) 858{ return make_Vec4f(pow(a.x, b), pow(a.y, b), pow(a.z, b), pow(a.w, b)); } 859 860inline uniform bool isnan(uniform Vec3f v) 861{ return isnan(v.x+v.y+v.z); } 862 863inline bool isnan(Vec3f v) 864{ return isnan(v.x+v.y+v.z); } 865 866inline uniform bool isnan(uniform Vec3fa v) 867{ return isnan(v.x+v.y+v.z); } 868 869inline bool isnan(Vec3fa v) 870{ return isnan(v.x+v.y+v.z); } 871 872typedef Vec3fa Vec3ff; 873typedef Vec3f Vec3f_; 874 875inline uniform Vec3f make_Vec3f_(uniform float w) { uniform Vec3f r; r.x = w; r.y = w; r.z = w; return r; } 876inline varying Vec3f make_Vec3f_(varying float w) { varying Vec3f r; r.x = w; r.y = w; r.z = w; return r; } 877 878inline uniform Vec3f make_Vec3f_(uniform Vec3f v) { uniform Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; } 879inline varying Vec3f make_Vec3f_(varying Vec3f v) { varying Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; } 880 881inline uniform Vec3f make_Vec3f_(uniform Vec3fa v) { uniform Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; } 882inline varying Vec3f make_Vec3f_(varying Vec3fa v) { varying Vec3f r; r.x = v.x; r.y = v.y; r.z = v.z; return r; } 883 884inline uniform Vec3ff make_Vec3ff(uniform float w) { uniform Vec3ff r; r.x = w; r.y = w; r.z = w; r.w = w; return r; } 885inline varying Vec3ff make_Vec3ff(varying float w) { varying Vec3ff r; r.x = w; r.y = w; r.z = w; r.w = w; return r; } 886 887inline uniform Vec3ff make_Vec3ff(uniform Vec3f v) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; } 888inline varying Vec3ff make_Vec3ff(varying Vec3f v) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; } 889 890inline uniform Vec3ff make_Vec3ff(uniform Vec3fa v) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; } 891inline varying Vec3ff make_Vec3ff(varying Vec3fa v) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = 0.0f; return r; } 892 893inline uniform Vec3ff make_Vec3ff(uniform Vec3f v, uniform float w) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; } 894inline varying Vec3ff make_Vec3ff(varying Vec3f v, varying float w) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; } 895 896inline uniform Vec3ff make_Vec3ff(uniform Vec3fa v, uniform float w) { uniform Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; } 897inline varying Vec3ff make_Vec3ff(varying Vec3fa v, varying float w) { varying Vec3ff r; r.x = v.x; r.y = v.y; r.z = v.z; r.w = w; return r; } 898 899inline uniform Vec3ff make_Vec3ff(uniform float x, uniform float y, uniform float z, uniform float w) { uniform Vec3ff r; r.x = x; r.y = y; r.z = z; r.w = w; return r; } 900inline varying Vec3ff make_Vec3ff(varying float x, varying float y, varying float z, varying float w) { varying Vec3ff r; r.x = x; r.y = y; r.z = z; r.w = w; return r; } 901 902inline void out(uniform Vec3f v) { print("(%,%,%)",v.x,v.y,v.z); } 903inline void out(Vec3f v) { print("\n(%\n %\n %)",v.x,v.y,v.z); } 904inline void out(uniform Vec3i v) { print("(%,%,%)",v.x,v.y,v.z); } 905inline void out(Vec3i v) { print("\n(%\n %\n %)",v.x,v.y,v.z); } 906 907 908// ------------------------------------------------------- 909// set/get functions for vectors 910// should eventually get moved to macros so they work for all types 911// ------------------------------------------------------- 912 913/*! set vector 'v's value in dimension 'd' to 'f' */ 914inline void set(uniform Vec3f &v, const uniform uint32 dim, const uniform float f) 915{ (&v.x)[dim] = f; } 916 917/*! get vector 'v's value in dimension 'd' */ 918inline uniform float get(const uniform Vec3f &v, const uniform uint32 dim) 919{ return (&v.x)[dim]; } 920inline float get(const Vec3f &v, const uniform uint32 dim) 921{ return (&v.x)[dim]; } 922 923 924// ------------------------------------------------------- 925// sRGB conversion functions 926// ------------------------------------------------------- 927#define APPROXIMATE_SRGB 928 929inline float linear_to_srgb(const float f) 930{ 931 const float c = max(f, 0.f); 932#ifdef APPROXIMATE_SRGB 933 return pow(c, 1.f/2.2f); 934#else 935 return c <= 0.0031308f ? 12.92f*c : pow(c, 1.f/2.4f)*1.055f - 0.055f; 936#endif 937} 938 939inline Vec4f linear_to_srgba(const Vec4f c) 940{ 941 return make_Vec4f(linear_to_srgb(c.x), 942 linear_to_srgb(c.y), 943 linear_to_srgb(c.z), 944 max(c.w, 0.f)); // alpha is never gamma-corrected 945} 946 947inline uint32 linear_to_srgba8(const Vec4f c) 948{ 949#if 1 950 Vec4f l = 255.f * min(linear_to_srgba(c), make_Vec4f(1.f)); 951 return 952 ((uint32)l.x << 0) | 953 ((uint32)l.y << 8) | 954 ((uint32)l.z << 16) | 955 ((uint32)l.w << 24); 956#else 957// TODO use ISPC's float_to_srgb8 once it is fixed (issue #1198) 958 return 959 (float_to_srgb8(c.x) << 0) | 960 (float_to_srgb8(c.y) << 8) | 961 (float_to_srgb8(c.z) << 16) | 962 ((uint32)clamp(c.w, 0.f, 1.f) << 24); // alpha is never gamma-corrected 963#endif 964} 965 966inline float srgb_to_linear(const float f) 967{ 968 const float c = max(f, 0.f); 969#ifdef APPROXIMATE_SRGB 970 return pow(c, 2.2f); 971#else 972 return c <= 0.04045f ? c/12.92f : pow((c + 0.055f)/1.055f, 2.4f); 973#endif 974} 975 976inline Vec4f srgba_to_linear(const Vec4f c) 977{ 978 return make_Vec4f(srgb_to_linear(c.x), 979 srgb_to_linear(c.y), 980 srgb_to_linear(c.z), 981 max(c.w, 0.f)); // alpha is never gamma-corrected 982} 983 984// TODO implement srgba8_to_linear with a 256 entry LUT 985 986#undef APPROXIMATE_SRGB 987