]> git.tdb.fi Git - libs/gl.git/blob - source/texturecube.cpp
Complete rewrite of extension handling
[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
36         ifmt = fmt;
37         size = sz;
38 }
39
40 void TextureCube::allocate(unsigned level)
41 {
42         if(allocated&(1<<level))
43                 return;
44
45         for(unsigned i=0; i<6; ++i)
46                 image(enumerate_faces(i), level, get_base_pixelformat(ifmt), UNSIGNED_BYTE, 0);
47 }
48
49 void TextureCube::image(TextureCubeFace face, unsigned level, PixelFormat fmt, DataType type, const void *data)
50 {
51         if(size==0)
52                 throw invalid_operation("TextureCube::image");
53
54         unsigned s = get_level_size(level);
55         if(s==0)
56                 throw invalid_argument("TextureCube::image");
57
58         Bind _bind(this, true);
59         glTexImage2D(face, level, ifmt, s, s, 0, fmt, type, data);
60
61         // XXX Allocation should be tracked per-face, but we'll run out of bits
62         allocated |= 1<<level;
63         if(gen_mipmap && level==0)
64         {
65                 for(; s; s>>=1, ++level) ;
66                 allocated |= (1<<level)-1;
67         }
68 }
69
70 unsigned TextureCube::get_level_size(unsigned level)
71 {
72         return size>>level;
73 }
74
75 TextureCubeFace TextureCube::enumerate_faces(unsigned i)
76 {
77         switch(i)
78         {
79         case 0: return POSITIVE_X;
80         case 1: return NEGATIVE_X;
81         case 2: return POSITIVE_Y;
82         case 3: return NEGATIVE_Y;
83         case 4: return POSITIVE_Z;
84         case 5: return NEGATIVE_Z;
85         default: throw out_of_range("TextureCube::enumerate_faces");
86         }
87 }
88
89 const Vector3 &TextureCube::get_face_direction(TextureCubeFace face)
90 {
91         switch(face)
92         {
93         case POSITIVE_X: return directions[0];
94         case NEGATIVE_X: return directions[1];
95         case POSITIVE_Y: return directions[2];
96         case NEGATIVE_Y: return directions[3];
97         case POSITIVE_Z: return directions[4];
98         case NEGATIVE_Z: return directions[5];
99         default: throw invalid_argument("TextureCube::get_face_direction");
100         }
101 }
102
103 const Vector3 &TextureCube::get_s_direction(TextureCubeFace face)
104 {
105         switch(face)
106         {
107         case POSITIVE_X: return directions[5];
108         case NEGATIVE_X: return directions[4];
109         case POSITIVE_Y: return directions[0];
110         case NEGATIVE_Y: return directions[0];
111         case POSITIVE_Z: return directions[0];
112         case NEGATIVE_Z: return directions[1];
113         default: throw invalid_argument("TextureCube::get_s_direction");
114         }
115 }
116
117 const Vector3 &TextureCube::get_t_direction(TextureCubeFace face)
118 {
119         switch(face)
120         {
121         case POSITIVE_X: return directions[3];
122         case NEGATIVE_X: return directions[3];
123         case POSITIVE_Y: return directions[4];
124         case NEGATIVE_Y: return directions[5];
125         case POSITIVE_Z: return directions[3];
126         case NEGATIVE_Z: return directions[3];
127         default: throw invalid_argument("TextureCube::get_t_direction");
128         }
129 }
130
131 Vector3 TextureCube::get_texel_direction(TextureCubeFace face, unsigned u, unsigned v)
132 {
133         float s = (u+0.5f)*2.0f/size-1.0f;
134         float t = (v+0.5f)*2.0f/size-1.0f;
135         const Vector3 &fv = get_face_direction(face);
136         const Vector3 &sv = get_s_direction(face);
137         const Vector3 &tv = get_t_direction(face);
138         return Vector3(fv.x+s*sv.x, fv.y+t*tv.y, fv.z+s*sv.z+t*tv.z);
139 }
140
141 } // namespace GL
142 } // namespace Msp