1 /* -*-c++-*- */
2 /* osgEarth - Geospatial SDK for OpenSceneGraph
3 * Copyright 2008-2014 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 */
19 #include "LayerDrawable"
20 #include "TerrainRenderData"
21
22 using namespace osgEarth::Drivers::RexTerrainEngine;
23
24 #undef LC
25 #define LC "[LayerDrawable] "
26
27
LayerDrawable()28 LayerDrawable::LayerDrawable() :
29 _renderType(Layer::RENDERTYPE_TERRAIN_SURFACE),
30 _drawOrder(0),
31 _layer(0L),
32 _visibleLayer(0L),
33 _imageLayer(0L),
34 _clearOsgState(false),
35 _draw(true)
36 {
37 setDataVariance(DYNAMIC);
38 setUseDisplayList(false);
39 setUseVertexBufferObjects(true);
40 _tiles.reserve(128);
41 }
42
~LayerDrawable()43 LayerDrawable::~LayerDrawable()
44 {
45 // Drawable's DTOR will release GL objects on any attached stateset;
46 // we don't want that because our Layer stateset is shared and re-usable.
47 // So detach it before OSG has a chance to do so.
48 setStateSet(0L);
49 }
50
51 namespace
52 {
53 // Hack State so we can dirty the texture attrs without dirtying the other
54 // attributes (as dirtyAllAttributes() would do.
55 struct StateEx : public osg::State
56 {
dirtyAllTextureAttributes__anon36e2559e0111::StateEx57 void dirtyAllTextureAttributes()
58 {
59 // dirtyAllTextureAttributes. (Don't call state->dirtyAllAttributes because that
60 // will mess up positional state attributes like light sources)
61 for (TextureAttributeMapList::iterator tamItr = _textureAttributeMapList.begin();
62 tamItr != _textureAttributeMapList.end();
63 ++tamItr)
64 {
65 osg::State::AttributeMap& attributeMap = *tamItr;
66 for (osg::State::AttributeMap::iterator aitr = attributeMap.begin();
67 aitr != attributeMap.end();
68 ++aitr)
69 {
70 osg::State::AttributeStack& as = aitr->second;
71 as.last_applied_attribute = 0;
72 as.changed = true;
73 }
74 }
75 }
76 };
77 }
78
79
80 void
drawImplementation(osg::RenderInfo & ri) const81 LayerDrawable::drawImplementation(osg::RenderInfo& ri) const
82 {
83 //OE_INFO << LC << (_layer ? _layer->getName() : "[empty]") << " tiles=" << _tiles.size() << std::endl;
84
85 // Get this context's state values:
86 PerContextDrawState& ds = _drawState->getPCDS(ri.getContextID());
87
88 ds.refresh(ri, _drawState->_bindings);
89
90 if (ds._layerUidUL >= 0)
91 {
92 GLint uid = _layer ? (GLint)_layer->getUID() : (GLint)-1;
93 ds._ext->glUniform1i(ds._layerUidUL, uid);
94 }
95 else
96 {
97 // This just means that the fragment shader for this layer doesn't use oe_layer_uid
98 }
99
100 for (DrawTileCommands::const_iterator tile = _tiles.begin(); tile != _tiles.end(); ++tile)
101 {
102 tile->draw(ri, *_drawState, 0L);
103 }
104
105 // If set, dirty all OSG state to prevent any leakage - this is sometimes
106 // necessary when doing custom OpenGL within a Drawable.
107 if (_clearOsgState)
108 {
109 // Dirty the texture attributes so OSG can properly reset them
110 // NOTE: cannot call state.dirtyAllAttributes, because that would invalidate
111 // positional state like light sources!
112 reinterpret_cast<StateEx*>(ri.getState())->dirtyAllTextureAttributes();
113
114 // NOTE: this is a NOOP in OSG 3.5.x, but not in 3.4.x ... Later we will need to
115 // revisit whether to call disableAllVertexArrays() in 3.5.x instead.
116 ri.getState()->dirtyAllVertexArrays();
117
118 // unbind local buffers when finished.
119 ds._ext->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
120 ds._ext->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
121
122 // gw: no need to do this, in fact it will cause positional attributes
123 // (light clip planes and lights) to immediately be reapplied under the
124 // current MVM, which will by definition be wrong!)
125 //ri.getState()->apply();
126 }
127 }
128