Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
DVDTextureTarget.cpp
Go to the documentation of this file.
1
2
3/***********************************************************************
4 created: Wed, 8th Feb 2012
5 author: Lukas E Meindl (based on code by Paul D Turner)
6*************************************************************************/
7/***************************************************************************
8 * Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 ***************************************************************************/
31
32#include "CEGUI/Logger.h"
33#include "CEGUI/RenderQueue.h"
34#include "CEGUI/PropertyHelper.h"
35
38
41
42#ifndef GLM_FORCE_DEPTH_ZERO_TO_ONE
43#define GLM_FORCE_DEPTH_ZERO_TO_ONE
44#endif
45
46#include "glm/glm.hpp"
47#include "glm/gtc/matrix_transform.hpp"
48
49namespace CEGUI
50{
52constexpr double S_YFOV_TAN = 0.267949192431123;
53
54DVDTextureTarget::DVDTextureTarget( CEGUIRenderer& owner, const Sizef resolution )
55 : _owner( owner )
56{
59 declareRenderSize( resolution );
60}
61
63{
65
67 {
69 {
70 Divide::DIVIDE_UNEXPECTED_CALL();
71 }
72 }
73}
74
75void DVDTextureTarget::draw( const GeometryBuffer& buffer )
76{
77 buffer.draw();
78}
79
80void DVDTextureTarget::draw( const RenderQueue& queue )
81{
82 queue.draw();
83}
84
86{
87 setArea(Rectf(_area.getPosition(), sz));
89}
90
92{
93 const Sizef sz(_area.getSize());
94 // Some drivers crash when clearing a 0x0 RTT. This is a workaround for those cases.
95 if (sz.d_width < 1.0f || sz.d_height < 1.0f)
96 {
97 return;
98 }
99
100 _requiresClear = true;
101}
102
104{
105 thread_local size_t FBO_INDEX = 0u;
106
107 using namespace Divide;
108
109 if ( _renderTarget._targetID != INVALID_RENDER_TARGET_ID )
110 {
112 {
113 Divide::DIVIDE_UNEXPECTED_CALL();
114 }
115 }
116
117 _sampler._wrapU = TextureWrap::CLAMP_TO_EDGE;
118 _sampler._wrapV = TextureWrap::CLAMP_TO_EDGE;
119 _sampler._wrapW = TextureWrap::CLAMP_TO_EDGE;
120 _sampler._minFilter = TextureFilter::LINEAR;
121 _sampler._magFilter = TextureFilter::LINEAR;
122 _sampler._mipSampling = TextureMipSampling::NONE;
124
125 TextureDescriptor descriptor
126 {
127 ._mipMappingState = MipMappingState::OFF
128 };
129
130 RenderTargetDescriptor editorDesc = {};
131 editorDesc._attachments =
132 {
133 InternalRTAttachmentDescriptor{ descriptor, _sampler, RTAttachmentType::COLOUR, RTColourAttachmentSlot::SLOT_0}
134 };
135
136 Util::StringFormat( editorDesc._name, "CEGUI_Target_{}", FBO_INDEX++ );
137 editorDesc._resolution = { DEFAULT_SIZE , DEFAULT_SIZE };
139
140 _requiresClear = true;
141
142 auto attachment = _renderTarget._rt->getAttachment( RTAttachmentType::COLOUR );
143 _CEGUITexture->setDVDTexture( Divide::GetResourceRef( attachment->texture() ), _area.getSize());
144}
145
147{
148 // Some drivers (hint: Intel) segfault when glTexImage2D is called with
149 // any of the dimensions being 0. The downside of this workaround is very
150 // small. We waste a tiny bit of VRAM on cards with sane drivers and
151 // prevent insane drivers from crashing CEGUI.
152 Sizef sz(_area.getSize());
153 if (sz.d_width < 1.0f || sz.d_height < 1.0f)
154 {
155 sz.d_width = 1.0f;
156 sz.d_height = 1.0f;
157 }
158 else if (sz.d_width > (1 << 13) || sz.d_height > (1 << 13))
159 {
160 sz.d_width = 1 << 13;
161 sz.d_height = 1 << 13;
162 }
163
164 _renderTarget._rt->resize(Divide::to_U16(sz.d_width), Divide::to_U16(sz.d_height));
165
166 clear();
167
169 _CEGUITexture->setDVDTexture( Divide::GetResourceRef(attachment->texture()), sz);
170}
171
173{
174 _CEGUITexture = &static_cast<DVDTexture&>(_owner.createTexture( GenerateTextureName(), Divide::INVALID_HANDLE<Divide::Texture>, _area.getSize() ));
175 _requiresClear = true;
176}
177
179{
180 thread_local uint TEX_INDEX = 0;
181
182 String tmp( "_ogl_tt_tex_" );
183 tmp.append( PropertyHelper<uint>::toString( TEX_INDEX++ ) );
184
185 return tmp;
186}
187
188
190{
192}
193
194void DVDTextureTarget::setArea( const Rectf& area )
195{
196 _area = area;
197 _matrixValid = false;
198
199 RenderTargetEventArgs args( this );
200 TextureTarget::fireEvent( RenderTarget::EventAreaChanged, args );
201}
202
204{
205 using namespace Divide;
206
207 GFX::CommandBuffer* cmdBuffer = _owner.cmdBuffer();
208
209 GFX::BeginRenderPassCommand beginRenderPassCmd{};
210 beginRenderPassCmd._target = _renderTarget._targetID;
211 beginRenderPassCmd._name = "Render CEGUI";
212 if ( _requiresClear )
213 {
214 beginRenderPassCmd._clearDescriptor[to_base( RTColourAttachmentSlot::SLOT_0 )] = { VECTOR4_ZERO, true};
215 _requiresClear = false;
216 }
217 beginRenderPassCmd._descriptor._drawMask[to_base( RTColourAttachmentSlot::SLOT_0 )] = true;
218 GFX::EnqueueCommand( *cmdBuffer, beginRenderPassCmd );
219
220 if ( !_matrixValid )
221 {
222 updateMatrix();
223 }
224
227}
228
230{
231 Divide::GFX::EnqueueCommand<Divide::GFX::EndRenderPassCommand>(*_owner.cmdBuffer() );
232}
233
234void DVDTextureTarget::unprojectPoint( const GeometryBuffer& buff, const Vector2f& p_in, Vector2f& p_out ) const
235{
236 if ( !_matrixValid )
237 {
238 updateMatrix();
239 }
240
241 const DVDGeometryBuffer& gb = static_cast<const DVDGeometryBuffer&>(buff);
242
244 Divide::to_I32(_area.left()),
245 Divide::to_I32(_area.top()),
246 Divide::to_I32(_area.getWidth()),
247 Divide::to_I32(_area.getHeight())
248 );
249
250 double in_x = 0.0, in_y = 0.0, in_z = 0.0;
251
252 glm::ivec4 viewPort = glm::ivec4( vp[0], vp[1], vp[2], vp[3] );
253 const glm::mat4& projMatrix = _matrix;
254 const glm::mat4& modelMatrix = gb.getMatrix();
255
256 // unproject the ends of the ray
257 glm::vec3 unprojected1;
258 glm::vec3 unprojected2;
259 in_x = vp[2] * 0.5;
260 in_y = vp[3] * 0.5;
261 in_z = -_viewDistance;
262 unprojected1 = glm::unProject( glm::vec3( in_x, in_y, in_z ), modelMatrix, projMatrix, viewPort );
263 in_x = p_in.d_x;
264 in_y = vp[3] - p_in.d_y;
265 in_z = 0.0;
266 unprojected2 = glm::unProject( glm::vec3( in_x, in_y, in_z ), modelMatrix, projMatrix, viewPort );
267
268 // project points to orientate them with GeometryBuffer plane
269 glm::vec3 projected1;
270 glm::vec3 projected2;
271 glm::vec3 projected3;
272 in_x = 0.0;
273 in_y = 0.0;
274 projected1 = glm::project( glm::vec3( in_x, in_y, in_z ), modelMatrix, projMatrix, viewPort );
275 in_x = 1.0;
276 in_y = 0.0;
277 projected2 = glm::project( glm::vec3( in_x, in_y, in_z ), modelMatrix, projMatrix, viewPort );
278 in_x = 0.0;
279 in_y = 1.0;
280 projected3 = glm::project( glm::vec3( in_x, in_y, in_z ), modelMatrix, projMatrix, viewPort );
281
282 // calculate vectors for generating the plane
283 const glm::vec3 pv1 = projected2 - projected1;
284 const glm::vec3 pv2 = projected3 - projected1;
285 // given the vectors, calculate the plane normal
286 const glm::vec3 planeNormal = glm::cross( pv1, pv2 );
287 // calculate plane
288 const glm::vec3 planeNormalNormalized = glm::normalize( planeNormal );
289 const double pl_d = -glm::dot( projected1, planeNormalNormalized );
290 // calculate vector of picking ray
291 const glm::vec3 rv = unprojected1 - unprojected2;
292 // calculate intersection of ray and plane
293 const double pn_dot_r1 = glm::dot( unprojected1, planeNormal );
294 const double pn_dot_rv = glm::dot( rv, planeNormal );
295 const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
296 const double is_x = unprojected1.x - rv.x * tmp1;
297 const double is_y = unprojected1.y - rv.y * tmp1;
298
299 p_out.d_x = static_cast<float>(is_x);
300 p_out.d_y = static_cast<float>(is_y);
301
302 p_out = p_in; // CrazyEddie wanted this
303}
304
306{
307 const float w = _area.getWidth();
308 const float h = _area.getHeight();
309
310 // We need to check if width or height are zero and act accordingly to prevent running into issues
311 // with divisions by zero which would lead to undefined values, as well as faulty clipping planes
312 // This is mostly important for avoiding asserts
313 const bool widthAndHeightNotZero = w != 0.0f && h != 0.0f;
314
315 const float aspect = widthAndHeightNotZero ? w / h : 1.0f;
316 const float midx = widthAndHeightNotZero ? w * 0.5f : 0.5f;
317 const float midy = widthAndHeightNotZero ? h * 0.5f : 0.5f;
318 _viewDistance = midx / (aspect * S_YFOV_TAN);
319
320 const glm::vec3 eye = glm::vec3( midx, midy, float( -_viewDistance ) );
321 const glm::vec3 center = glm::vec3( midx, midy, 1 );
322 const glm::vec3 up = glm::vec3( 0, -1, 0 );
323
324 //Older glm versions use degrees as parameter here by default (Unless radians are forced via GLM_FORCE_RADIANS). Newer versions of glm exlusively use radians.
325#if (GLM_VERSION_MAJOR == 0 && GLM_VERSION_MINOR <= 9 && GLM_VERSION_PATCH < 6) && (!defined(GLM_FORCE_RADIANS))
326 const glm::mat4 projectionMatrix = glm::perspective( 30.f, aspect, float( d_viewDistance * 0.5 ), float( d_viewDistance * 2.0 ) );
327#else
328 glm::mat4 projectionMatrix = glm::perspective( glm::radians( 30.f ), aspect, float( _viewDistance * 0.5 ), float( _viewDistance * 2.0 ) );
329#endif
330
331 // Projection matrix abuse!
332 const glm::mat4 viewMatrix = glm::lookAt( eye, center, up );
333
334 _matrix = projectionMatrix * viewMatrix;
335
336 _matrixValid = true;
337}
338
339} // End of CEGUI namespace section
Texture & createTexture(const String &name) override
void destroyTexture(Texture &texture) override
void setActiveRenderTarget(RenderTarget *renderTarget)
void setViewProjectionMatrix(const glm::mat4 &viewProjectionMatrix)
Divide::GFX::CommandBuffer * cmdBuffer() const
Divide::GFXDevice & context()
const glm::mat4 & getMatrix() const
void setDVDTexture(Divide::Handle< Divide::Texture > tex, const Sizef &size)
set the Divide::Texture that this Texture is based on to the specified texture, with the specified si...
Definition: DVDTexture.cpp:307
Divide::Handle< Divide::Texture > getAttachmentTex() const
Rectf _area
holds defined area for the RenderTarget
void updateMatrix() const
helper that initialises the cached matrix
virtual ~DVDTextureTarget() override
Divide::SamplerDescriptor _sampler
A Divide sampler hash used for sampling from this texture target.
void unprojectPoint(const GeometryBuffer &buff, const Vector2f &p_in, Vector2f &p_out) const override
Divide::RenderTargetHandle _renderTarget
A handle to a Divide render target used for rendering with this DVDTextureTarget.
void resizeRenderTexture()
resize the texture
void draw(const GeometryBuffer &buffer) override
void createCEGUITexture()
helper to create CEGUI::Texture d_CEGUITexture;
void initialiseRenderTexture()
allocate and set up the texture used with the FBO.
DVDTextureTarget(CEGUIRenderer &owner, const Sizef resolution)
static String GenerateTextureName()
helper to generate unique texture names
void setArea(const Rectf &area) override
DVDTexture * _CEGUITexture
we use this to wrap _texture so it can be used by the core CEGUI lib.
double _viewDistance
tracks viewing distance (this is set up at the same time as d_matrix)
bool _matrixValid
true if saved matrix is up to date
static constexpr float DEFAULT_SIZE
default size of created texture objects
CEGUIRenderer & _owner
CEGUIRenderer that created this object.
glm::mat4 _matrix
saved copy of projection matrix
void declareRenderSize(const Sizef &sz) override
bool _requiresClear
Because Divide command buffers are deferred, clearing should be queued instead of instant.
GFXRTPool & renderTargetPool() noexcept
Definition: GFXDevice.inl:133
RenderTargetHandle allocateRT(const RenderTargetDescriptor &descriptor)
Definition: GFXRTPool.cpp:17
bool deallocateRT(RenderTargetHandle &handle)
Definition: GFXRTPool.cpp:33
Handle< Texture > texture() const
RTAttachment * getAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
bool resize(U16 width, U16 height)
Resize all attachments.
constexpr double S_YFOV_TAN
tangent of the y FOV half-angle; used to calculate viewing distance.
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U16 to_U16(const T value)
FORCE_INLINE Handle< T > GetResourceRef(const Handle< T > handle)
constexpr RenderTargetID INVALID_RENDER_TARGET_ID
constexpr I32 to_I32(const T value)
InternalRTAttachmentDescriptors _attachments
Definition: RenderTarget.h:52
RenderTargetID _targetID
Definition: RenderTarget.h:47
TextureFilter _minFilter
Texture filtering mode.
TextureWrap _wrapU
Texture wrap mode (Or S-R-T)
U8 _anisotropyLevel
The value must be in the range [0...255] and is automatically clamped by the max HW supported level.
TextureMipSampling _mipSampling