]> git.tdb.fi Git - libs/gl.git/blob - source/texturecube.cpp
Check the relevant extensions when using pixel formats
[libs/gl.git] / source / texturecube.cpp
1 #include "arb_texture_cube_map.h"
2 #include "bindable.h"
3 #include "error.h"
4 #include "texturecube.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 Vector3 TextureCube::directions[6] =
12 {
13         Vector3(1, 0, 0),
14         Vector3(-1, 0, 0),
15         Vector3(0, 1, 0),
16         Vector3(0, -1, 0),
17         Vector3(0, 0, 1),
18         Vector3(0, 0, -1)
19 };
20
21 TextureCube::TextureCube():
22         Texture(GL_TEXTURE_CUBE_MAP),
23         size(0),
24         allocated(0)
25 {
26         static Require _req(ARB_texture_cube_map);
27 }
28
29 void TextureCube::storage(PixelFormat fmt, unsigned sz)
30 {
31         if(size>0)
32                 throw invalid_operation("TextureCube::storage");
33         if(sz==0)
34                 throw invalid_argument("TextureCube::storage");
35         require_pixelformat(fmt);
36
37         ifmt = fmt;
38         size = sz;
39 }
40
41 void TextureCube::allocate(unsigned level)
42 {
43         if(allocated&(1<<level))
44                 return;
45
46         for(unsigned i=0; i<6; ++i)
47                 image(enumerate_faces(i), level, get_base_pixelformat(ifmt), UNSIGNED_BYTE, 0);
48 }
49
50 void TextureCube::image(TextureCubeFace face, unsigned level, PixelFormat fmt, DataType type, const void *data)
51 {
52         if(size==0)
53                 throw invalid_operation("TextureCube::image");
54
55         unsigned s = get_level_size(level);
56         if(s==0)
57                 throw invalid_argument("TextureCube::image");
58
59         Bind _bind(this, true);
60         glTexImage2D(face, level, ifmt, s, s, 0, fmt, type, data);
61
62         // XXX Allocation should be tracked per-face, but we'll run out of bits
63         allocated |= 1<<level;
64         if(gen_mipmap && level==0)
65         {
66                 for(; s; s>>=1, ++level) ;
67                 allocated |= (1<<level)-1;
68         }
69 }
70
71 unsigned TextureCube::get_level_size(unsigned level)
72 {
73         return size>>level;
74 }
75
76 TextureCubeFace TextureCube::enumerate_faces(unsigned i)
77 {
78         switch(i)
79         {
80         case 0: return POSITIVE_X;
81         case 1: return NEGATIVE_X;
82         case 2: return POSITIVE_Y;
83         case 3: return NEGATIVE_Y;
84         case 4: return POSITIVE_Z;
85         case 5: return NEGATIVE_Z;
86         default: throw out_of_range("TextureCube::enumerate_faces");
87         }
88 }
89
90 const Vector3 &TextureCube::get_face_direction(TextureCubeFace face)
91 {
92         switch(face)
93         {
94         case POSITIVE_X: return directions[0];
95         case NEGATIVE_X: return directions[1];
96         case POSITIVE_Y: return directions[2];
97         case NEGATIVE_Y: return directions[3];
98         case POSITIVE_Z: return directions[4];
99         case NEGATIVE_Z: return directions[5];
100         default: throw invalid_argument("TextureCube::get_face_direction");
101         }
102 }
103
104 const Vector3 &TextureCube::get_s_direction(TextureCubeFace face)
105 {
106         switch(face)
107         {
108         case POSITIVE_X: return directions[5];
109         case NEGATIVE_X: return directions[4];
110         case POSITIVE_Y: return directions[0];
111         case NEGATIVE_Y: return directions[0];
112         case POSITIVE_Z: return directions[0];
113         case NEGATIVE_Z: return directions[1];
114         default: throw invalid_argument("TextureCube::get_s_direction");
115         }
116 }
117
118 const Vector3 &TextureCube::get_t_direction(TextureCubeFace face)
119 {
120         switch(face)
121         {
122         case POSITIVE_X: return directions[3];
123         case NEGATIVE_X: return directions[3];
124         case POSITIVE_Y: return directions[4];
125         case NEGATIVE_Y: return directions[5];
126         case POSITIVE_Z: return directions[3];
127         case NEGATIVE_Z: return directions[3];
128         default: throw invalid_argument("TextureCube::get_t_direction");
129         }
130 }
131
132 Vector3 TextureCube::get_texel_direction(TextureCubeFace face, unsigned u, unsigned v)
133 {
134         float s = (u+0.5f)*2.0f/size-1.0f;
135         float t = (v+0.5f)*2.0f/size-1.0f;
136         const Vector3 &fv = get_face_direction(face);
137         const Vector3 &sv = get_s_direction(face);
138         const Vector3 &tv = get_t_direction(face);
139         return Vector3(fv.x+s*sv.x, fv.y+t*tv.y, fv.z+s*sv.z+t*tv.z);
140 }
141
142 } // namespace GL
143 } // namespace Msp