1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "../common/DifferentialGeometry.ih"
7#include "ospray/OSPEnums.h"
8#include "rkcommon/math/vec.ih"
9
10struct Texture2D;
11
12typedef varying vec4f (*Texture2D_get)(const uniform Texture2D *uniform self,
13    const varying DifferentialGeometry &dg);
14
15typedef varying vec3f (*Texture2D_getN)(const uniform Texture2D *uniform self,
16    const varying DifferentialGeometry &dg);
17
18struct Texture2D
19{
20  vec2i size;
21  vec2f sizef; // size, as floats; slightly smaller than 'size' to avoid range
22               // checks
23  vec2f halfTexel; // 0.5/size, needed for bilinear filtering and clamp-to-edge
24  Texture2D_get get;
25  Texture2D_getN getNormal;
26  void *data;
27  bool hasAlpha; // 4 channel texture?
28};
29
30// XXX won't work with MIPmapping: clean implementation with clamping on integer
31// coords needed then
32inline vec2f clamp2edge(const uniform Texture2D *uniform self, const vec2f p)
33{
34  return clamp(p, self->halfTexel, 1.0f - self->halfTexel);
35}
36
37inline uniform bool hasAlpha(const uniform Texture2D *uniform self)
38{
39  return (self == NULL) ? false : self->hasAlpha;
40}
41
42/*! helper function that returns the sampled value for the first
43  channel of the given texture
44
45  Right now, this function always asks the texture for all four
46  channels, and then discards all but one; later implementations may
47  have specialized 'get1f' methods with the texture
48
49  \note self may NOT be NULL!
50*/
51inline float get1f(const uniform Texture2D *uniform self,
52    const varying DifferentialGeometry &dg)
53{
54  vec4f ret = self->get(self, dg);
55  return ret.x;
56}
57
58/*! helper function that returns the sampled value for the first three
59  channels of the given texture
60
61  Right now, this function always asks the texture for all four
62  channels, and then discards all but one; later implementations may
63  have specialized 'get3f' methods with the texture
64
65  \note self may NOT be NULL!
66*/
67inline vec3f get3f(const uniform Texture2D *uniform self,
68    const varying DifferentialGeometry &dg)
69{
70  vec4f ret = self->get(self, dg);
71  return make_vec3f(ret);
72}
73
74/*! helper function that returns the sampled value of the four
75  channels of the given texture.
76
77  Note that it's up to the texture to define clearly what happens if
78  we ask for four channels even if the texture has less physical
79  channels.
80
81  \note self may NOT be NULL!
82*/
83inline vec4f get4f(const uniform Texture2D *uniform self,
84    const varying DifferentialGeometry &dg)
85{
86  return self->get(self, dg);
87}
88
89/*! helper function that returns the sampled values interpreted as a normal */
90inline vec3f getNormal(const uniform Texture2D *uniform self,
91    const varying DifferentialGeometry &dg)
92{
93  if (self == NULL)
94    return make_vec3f(0.f, 0.f, 1.f);
95  else
96    return self->getNormal(self, dg);
97}
98
99/*! helper function: get1f() with a default value if the texture is NULL */
100inline float get1f(const uniform Texture2D *uniform self,
101    const varying DifferentialGeometry &dg,
102    const varying float defaultValue)
103{
104  if (self == NULL)
105    return defaultValue;
106  else
107    return get1f(self, dg);
108}
109
110/*! helper function: get3f() with a default value if the texture is NULL */
111inline vec3f get3f(const uniform Texture2D *uniform self,
112    const varying DifferentialGeometry &dg,
113    const varying vec3f defaultValue)
114{
115  if (self == NULL)
116    return defaultValue;
117  else
118    return get3f(self, dg);
119}
120
121/*! helper function: get4f() with a default value if the texture is NULL */
122inline vec4f get4f(const uniform Texture2D *uniform self,
123    const varying DifferentialGeometry &dg,
124    const varying vec4f defaultValue)
125{
126  if (self == NULL)
127    return defaultValue;
128  else
129    return get4f(self, dg);
130}
131
132#if 0 // crashes ISPC!
133inline DifferentialGeometry dgFromTexCoord(const varying vec2f &c)
134{
135  DifferentialGeometry dg;
136  dg.primID = -1;
137  dg.st = c;
138  return dg;
139}
140#else
141inline void initDgFromTexCoord(DifferentialGeometry &dg, const varying vec2f &c)
142{
143  dg.primID = -1;
144  dg.st = c;
145}
146#endif
147