Line data Source code
1 0 : /*
2 :
3 : OOEnvironmentCubeMap.m
4 :
5 :
6 : Copyright (C) 2010-2013 Jens Ayton
7 :
8 : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : of this software and associated documentation files (the "Software"), to deal
10 : in the Software without restriction, including without limitation the rights
11 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : copies of the Software, and to permit persons to whom the Software is
13 : furnished to do so, subject to the following conditions:
14 :
15 : The above copyright notice and this permission notice shall be included in all
16 : copies or substantial portions of the Software.
17 :
18 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : SOFTWARE.
25 :
26 : */
27 :
28 : #import "OOEnvironmentCubeMap.h"
29 : #import "OOTexture.h"
30 : #import "OOTextureInternal.h"
31 : #import "MyOpenGLView.h"
32 : #import "OOPixMap.h"
33 : #import "OOMacroOpenGL.h"
34 :
35 : #import "Universe.h"
36 : #import "PlayerEntity.h"
37 : #import "SkyEntity.h"
38 : #import "OOSunEntity.h"
39 : #import "OOPlanetEntity.h"
40 : #import "OODrawable.h"
41 : #import "OOEntityFilterPredicate.h"
42 :
43 :
44 : #if OO_USE_FBO && OO_TEXTURE_CUBE_MAP
45 :
46 : @interface OOEnvironmentCubeMap (Private)
47 :
48 : - (void) setUp;
49 :
50 : - (void) renderOnePassWithSky:(OODrawable *)sky sun:(OOSunEntity *)sun planets:(NSArray *)planets;
51 :
52 : @end
53 :
54 :
55 : @implementation OOEnvironmentCubeMap
56 :
57 : - (id) initWithSideLength:(GLuint)size
58 : {
59 : if (![[OOOpenGLExtensionManager sharedManager] fboSupported] || !OOCubeMapsAvailable())
60 : {
61 : [self release];
62 : return nil;
63 : }
64 :
65 : if ((self = [super init]))
66 : {
67 : _size = size;
68 : }
69 :
70 : return self;
71 : }
72 :
73 :
74 : - (void) dealloc
75 : {
76 : [self forceRebind];
77 :
78 : [super dealloc];
79 : }
80 :
81 :
82 : - (void) render
83 : {
84 : if (_textureName == 0) [self setUp];
85 :
86 : OO_ENTER_OPENGL();
87 :
88 : // Save stuff.
89 : OOGL(glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT));
90 : OOGLPushModelView();
91 : OOGLPushProjection();
92 :
93 : OOGL(glViewport(0, 0, _size, _size));
94 : OOGLScaleProjection(make_vector(-1.0, 1.0, 1.0)); // flip left and right
95 :
96 : /* TODO: once confirmed working (and rendering everything in the right
97 : orientation), replace with glLoadMatrix and the following:
98 : 1 0 0 0
99 : 0 1 0 0
100 : 0 0 -1 -2
101 : 0 0 -1 0
102 :
103 : ...and appropriate rotations thereof.
104 : */
105 :
106 : OOGLResetProjection();
107 : OOGLPerspective(90.0, 1.0, 1.0, MAX_CLEAR_DEPTH);
108 :
109 : OODrawable *sky = [[UNIVERSE nearestEntityMatchingPredicate:HasClassPredicate parameter:[SkyEntity class] relativeToEntity:nil] drawable];
110 : OOSunEntity *sun = [UNIVERSE sun];
111 : NSArray *planets = [UNIVERSE planets];
112 :
113 : unsigned i;
114 : Vector centers[6] = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 } };
115 : Vector ups[6] = { { 0, -1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, { 0, -1, 0 }, { 0, -1, 0 } };
116 :
117 : for (i = 0; i < 6; i++)
118 : {
119 : OOGLPushProjection();
120 : Vector center = centers[i];
121 : Vector up = ups[i];
122 : OOGLLookAt(kZeroVector, center, up);
123 :
124 : OOGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbos[i]));
125 : [self renderOnePassWithSky:sky sun:sun planets:planets];
126 :
127 : OOGLPopProjection();
128 : }
129 :
130 : OOGLPopProjection();
131 : OOGLPopModelView();
132 : OOGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
133 : OOGL(glPopAttrib());
134 : }
135 :
136 :
137 : - (void) renderOnePassWithSky:(OODrawable *)sky sun:(OOSunEntity *)sun planets:(NSArray *)planets
138 : {
139 : OO_ENTER_OPENGL();
140 :
141 : OOGL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
142 : OOGL(glClearDepth(MAX_CLEAR_DEPTH));
143 : OOGL(glClear(_planets ? GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT : GL_COLOR_BUFFER_BIT));
144 :
145 : OOGL(glDepthMask(GL_FALSE));
146 : [sky renderOpaqueParts];
147 : OOGL(glDepthMask(GL_TRUE));
148 :
149 : OOGLPushModelView();
150 : OOGLResetModelView();
151 : OOGLTranslateModelView(vector_flip([PLAYER position]));
152 :
153 : NSEnumerator *planetEnum = nil;
154 : OOPlanetEntity *planet = nil;
155 : for (planetEnum = [planets objectEnumerator]; (planet = [planetEnum nextObject]); )
156 : {
157 : OOGLPushModelView();
158 : OOGLTranslateModelView(planet position]);
159 : #if NEW_PLANETS
160 : [[planet drawable] renderOpaqueParts];
161 : #else
162 : [planet drawUnconditionally];
163 : #endif
164 : OOGLPopModelView();
165 : }
166 :
167 : OOGLPushModelView();
168 : OOGLTranslateModelView([sun position]);
169 : [sun drawUnconditionally];
170 : OOGLPopModelView();
171 : OOGLPopModelView();
172 : }
173 :
174 : - (void) setUp
175 : {
176 : OO_ENTER_OPENGL();
177 :
178 : if (_textureName != 0) return;
179 : _planets = [UNIVERSE reducedDetail];
180 :
181 : OOGL(glGenTextures(1, &_textureName));
182 : OOGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _textureName));
183 : OOGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
184 : OOGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
185 : OOGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
186 : OOGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
187 : OOGL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
188 :
189 : OOGL(glGenFramebuffersEXT(6, _fbos));
190 : OOGL(glGenRenderbuffersEXT(6, _depthBuffers));
191 :
192 : unsigned i;
193 : for (i = 0; i < 6; i++)
194 : {
195 : GLenum textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
196 :
197 : OOGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbos[i]));
198 :
199 : OOGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _depthBuffers[i]));
200 : OOGL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, _size, _size));
201 : OOGL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, _depthBuffers[i]));
202 :
203 : OOGL(glTexImage2D(textarget, 0, GL_RGBA8, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
204 : OOGL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, textarget, _textureName, 0));
205 : }
206 :
207 : #ifndef NDEBUG
208 : GLenum status;
209 : OOGL(status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
210 : if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
211 : {
212 : OOLogERR(@"environmentCube.fbo.setup.failed", @"Failed to set up FBO for environment cube map - status is %u.", status);
213 : DESTROY(self);
214 : }
215 :
216 : OOCheckOpenGLErrors(@"after setting up environment cube map FBO");
217 : #endif
218 : OOGL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
219 : OOGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
220 : OOGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
221 : }
222 :
223 :
224 : // OOTexture stuff.
225 :
226 : - (void) apply
227 : {
228 : OO_ENTER_OPENGL();
229 : OOGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _textureName));
230 : }
231 :
232 :
233 : - (NSSize) dimensions
234 : {
235 : return NSMakeSize(_size, _size);
236 : }
237 :
238 :
239 : - (void) forceRebind
240 : {
241 : OO_ENTER_OPENGL();
242 : if (_textureName == 0) return;
243 :
244 : OOGL(glDeleteTextures(1, &_textureName));
245 : _textureName = 0;
246 :
247 : OOGL(glDeleteFramebuffersEXT(6, _fbos));
248 : OOGL(glDeleteRenderbuffersEXT(6, _depthBuffers));
249 : }
250 :
251 :
252 : - (BOOL) isCubeMap
253 : {
254 : return YES;
255 : }
256 :
257 :
258 : - (struct OOPixMap) copyPixMapRepresentation
259 : {
260 : OOPixMap pixmap = OOAllocatePixMap(_size, _size * 6, 4, 0, 0);
261 : if (!OOIsValidPixMap(pixmap)) return kOONullPixMap;
262 :
263 : OO_ENTER_OPENGL();
264 :
265 : unsigned i;
266 : for (i = 0; i < 6; i++)
267 : {
268 : OOGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbos[i]));
269 : OOGL(glReadBuffer(GL_COLOR_ATTACHMENT0_EXT));
270 : uint8_t *target = pixmap.pixels;
271 : target += pixmap.rowBytes * _size * i;
272 : OOGL(glReadPixels(0, 0, _size, _size, GL_RGBA, GL_UNSIGNED_BYTE, target));
273 : }
274 :
275 : OOGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
276 : return pixmap;
277 : }
278 :
279 : @end
280 :
281 : #endif
|