tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / slideshow / source / engine / opengl / TransitionImpl.cxx
blob1e9c661d6c094219ecfbc4fd25e2214dc2d8222a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2008 by Sun Microsystems, Inc.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <glm/gtc/matrix_transform.hpp>
30 #include <glm/gtc/type_ptr.hpp>
31 #include <vcl/opengl/OpenGLHelper.hxx>
32 #include <vcl/opengl/OpenGLContext.hxx>
33 #include <sal/log.hxx>
35 #include <algorithm>
36 #include <array>
38 #include <comphelper/random.hxx>
40 #include "Operation.hxx"
41 #include "TransitionImpl.hxx"
42 #include <cmath>
44 TransitionScene::TransitionScene(TransitionScene const& rOther)
45 : maLeavingSlidePrimitives(rOther.maLeavingSlidePrimitives)
46 , maEnteringSlidePrimitives(rOther.maEnteringSlidePrimitives)
47 , maOverallOperations(rOther.maOverallOperations)
48 , maSceneObjects(rOther.maSceneObjects)
52 TransitionScene& TransitionScene::operator=(const TransitionScene& rOther)
54 TransitionScene aTmp(rOther);
55 swap(aTmp);
56 return *this;
59 void TransitionScene::swap(TransitionScene& rOther)
61 using std::swap;
63 swap(maLeavingSlidePrimitives, rOther.maLeavingSlidePrimitives);
64 swap(maEnteringSlidePrimitives, rOther.maEnteringSlidePrimitives);
65 swap(maOverallOperations, rOther.maOverallOperations);
66 swap(maSceneObjects, rOther.maSceneObjects);
69 OGLTransitionImpl::~OGLTransitionImpl()
73 void OGLTransitionImpl::uploadModelViewProjectionMatrices()
75 double EyePos(10.0);
76 double const RealF(1.0);
77 double const RealN(-1.0);
78 double const RealL(-1.0);
79 double RealR(1.0);
80 double const RealB(-1.0);
81 double RealT(1.0);
82 double ClipN(EyePos+5.0*RealN);
83 double ClipF(EyePos+15.0*RealF);
84 double ClipL(RealL*8.0);
85 double ClipR(RealR*8.0);
86 double ClipB(RealB*8.0);
87 double ClipT(RealT*8.0);
89 glm::mat4 projection = glm::frustum<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
90 //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
91 glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
92 1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
93 1.0);
94 projection = glm::scale(projection, scale);
95 glm::mat4 modelview = glm::translate(glm::mat4(), glm::vec3(0, 0, -EyePos));
97 GLint location = glGetUniformLocation( m_nProgramObject, "u_projectionMatrix" );
98 if( location != -1 ) {
99 glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection));
100 CHECK_GL_ERROR();
103 location = glGetUniformLocation( m_nProgramObject, "u_modelViewMatrix" );
104 if( location != -1 ) {
105 glUniformMatrix4fv(location, 1, false, glm::value_ptr(modelview));
106 CHECK_GL_ERROR();
110 static std::vector<int> uploadPrimitives(const Primitives_t& primitives)
112 int size = 0;
113 for (const Primitive& primitive: primitives)
114 size += primitive.getVerticesByteSize();
116 CHECK_GL_ERROR();
117 glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
118 CHECK_GL_ERROR();
119 Vertex *buf = static_cast<Vertex*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
121 std::vector<int> indices;
122 int last_pos = 0;
123 for (const Primitive& primitive: primitives) {
124 indices.push_back(last_pos);
125 int num = primitive.writeVertices(buf);
126 buf += num;
127 last_pos += num;
130 CHECK_GL_ERROR();
131 glUnmapBuffer(GL_ARRAY_BUFFER);
132 CHECK_GL_ERROR();
133 return indices;
136 bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
138 m_nProgramObject = makeShader();
139 if (!m_nProgramObject)
140 return false;
142 CHECK_GL_ERROR();
143 glUseProgram( m_nProgramObject );
144 CHECK_GL_ERROR();
146 const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
147 for(const auto& rSceneObject : rSceneObjects) {
148 rSceneObject->prepare(m_nProgramObject);
151 GLint location = glGetUniformLocation( m_nProgramObject, "leavingSlideTexture" );
152 if( location != -1 ) {
153 glUniform1i( location, 0 ); // texture unit 0
154 CHECK_GL_ERROR();
157 location = glGetUniformLocation( m_nProgramObject, "enteringSlideTexture" );
158 if( location != -1 ) {
159 glUniform1i( location, 2 ); // texture unit 2
160 CHECK_GL_ERROR();
163 uploadModelViewProjectionMatrices();
165 m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
166 m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
167 m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
168 m_nTimeLocation = glGetUniformLocation( m_nProgramObject, "time" );
170 glGenVertexArrays(1, &m_nVertexArrayObject);
171 glBindVertexArray(m_nVertexArrayObject);
173 glGenBuffers(1, &m_nVertexBufferObject);
174 glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
176 // In practice both leaving and entering slides share the same primitives.
177 m_nFirstIndices = uploadPrimitives(getScene().getLeavingSlide());
179 // Attribute bindings
180 m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position");
181 if (m_nPositionLocation != -1) {
182 glEnableVertexAttribArray(m_nPositionLocation);
183 glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
184 CHECK_GL_ERROR();
187 m_nNormalLocation = glGetAttribLocation(m_nProgramObject, "a_normal");
188 if (m_nNormalLocation != -1) {
189 glEnableVertexAttribArray(m_nNormalLocation);
190 glVertexAttribPointer( m_nNormalLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
191 CHECK_GL_ERROR();
194 m_nTexCoordLocation = glGetAttribLocation(m_nProgramObject, "a_texCoord");
195 if (m_nTexCoordLocation != -1) {
196 glEnableVertexAttribArray(m_nTexCoordLocation);
197 glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
198 CHECK_GL_ERROR();
201 glBindBuffer(GL_ARRAY_BUFFER, 0);
202 CHECK_GL_ERROR();
204 prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
205 return true;
208 void OGLTransitionImpl::finish()
210 const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
211 for(const auto& rSceneObject : rSceneObjects) {
212 rSceneObject->finish();
215 finishTransition();
217 CHECK_GL_ERROR();
218 if( m_nProgramObject ) {
219 glDeleteBuffers(1, &m_nVertexBufferObject);
220 m_nVertexBufferObject = 0;
221 glDeleteVertexArrays(1, &m_nVertexArrayObject);
222 m_nVertexArrayObject = 0;
223 glDeleteProgram( m_nProgramObject );
224 m_nProgramObject = 0;
226 CHECK_GL_ERROR();
229 void OGLTransitionImpl::prepare( double, double )
233 void OGLTransitionImpl::cleanup()
237 void OGLTransitionImpl::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
241 void OGLTransitionImpl::finishTransition()
245 void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
247 CHECK_GL_ERROR();
248 applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
250 glUniform1f( m_nTimeLocation, nTime );
252 glActiveTexture( GL_TEXTURE2 );
253 glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex );
254 glActiveTexture( GL_TEXTURE0 );
256 displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
257 CHECK_GL_ERROR();
260 void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
261 double SlideWidth, double SlideHeight, double DispWidth, double DispHeight, OpenGLContext *pContext )
263 const double SlideWidthScale = SlideWidth/DispWidth;
264 const double SlideHeightScale = SlideHeight/DispHeight;
266 CHECK_GL_ERROR();
267 glBindVertexArray(m_nVertexArrayObject);
268 prepare( SlideWidth, SlideHeight );
270 CHECK_GL_ERROR();
271 displaySlides_( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale, pContext );
272 CHECK_GL_ERROR();
273 displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
274 CHECK_GL_ERROR();
277 void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale )
279 const Operations_t& rOverallOperations(maScene.getOperations());
280 glm::mat4 matrix;
281 for(const auto& rOperation : rOverallOperations)
282 rOperation->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale);
283 CHECK_GL_ERROR();
284 if (m_nOperationsTransformLocation != -1) {
285 glUniformMatrix4fv(m_nOperationsTransformLocation, 1, false, glm::value_ptr(matrix));
286 CHECK_GL_ERROR();
290 static void displayPrimitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, std::vector<int>::const_iterator first)
292 for (const Primitive& primitive: primitives)
293 primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++);
296 void
297 OGLTransitionImpl::displaySlide(
298 const double nTime,
299 const sal_Int32 glSlideTex, const Primitives_t& primitives,
300 double SlideWidthScale, double SlideHeightScale )
302 CHECK_GL_ERROR();
303 glBindTexture(GL_TEXTURE_2D, glSlideTex);
304 CHECK_GL_ERROR();
305 if (m_nSceneTransformLocation != -1) {
306 glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
307 CHECK_GL_ERROR();
309 displayPrimitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale, m_nFirstIndices.cbegin());
310 CHECK_GL_ERROR();
313 void
314 OGLTransitionImpl::displayUnbufferedSlide(
315 const double nTime,
316 const sal_Int32 glSlideTex, const Primitives_t& primitives,
317 double SlideWidthScale, double SlideHeightScale )
319 CHECK_GL_ERROR();
320 glBindTexture(GL_TEXTURE_2D, glSlideTex);
321 CHECK_GL_ERROR();
322 glBindVertexArray(0);
323 CHECK_GL_ERROR();
324 glBindBuffer(GL_ARRAY_BUFFER, 0);
325 CHECK_GL_ERROR();
326 if (m_nSceneTransformLocation != -1) {
327 glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
328 CHECK_GL_ERROR();
330 for (const Primitive& primitive: primitives)
331 primitive.display(m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale);
332 CHECK_GL_ERROR();
333 glBindVertexArray(m_nVertexArrayObject);
334 CHECK_GL_ERROR();
335 glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
336 CHECK_GL_ERROR();
339 void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
341 const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
342 CHECK_GL_ERROR();
343 for(const auto& rSceneObject : rSceneObjects)
344 rSceneObject->display(m_nSceneTransformLocation, m_nPrimitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
345 CHECK_GL_ERROR();
348 void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const
350 glm::mat4 matrix;
351 applyOperations( matrix, nTime, WidthScale, HeightScale );
353 CHECK_GL_ERROR();
354 if (primitiveTransformLocation != -1) {
355 glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
356 CHECK_GL_ERROR();
359 GLuint nVertexArrayObject;
360 glGenVertexArrays(1, &nVertexArrayObject);
361 CHECK_GL_ERROR();
362 glBindVertexArray(nVertexArrayObject);
363 CHECK_GL_ERROR();
365 GLuint nBuffer;
366 glGenBuffers(1, &nBuffer);
367 CHECK_GL_ERROR();
368 glBindBuffer(GL_ARRAY_BUFFER, nBuffer);
369 CHECK_GL_ERROR();
370 glBufferData(GL_ARRAY_BUFFER, getVerticesByteSize(), Vertices.data(), GL_STATIC_DRAW);
372 glEnableVertexAttribArray(0);
373 CHECK_GL_ERROR();
374 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
375 CHECK_GL_ERROR();
376 glDrawArrays( GL_TRIANGLES, 0, Vertices.size() );
377 CHECK_GL_ERROR();
379 glDeleteBuffers(1, &nBuffer);
380 CHECK_GL_ERROR();
382 glDeleteVertexArrays(1, &nVertexArrayObject);
383 CHECK_GL_ERROR();
386 void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const
388 glm::mat4 matrix;
389 applyOperations( matrix, nTime, WidthScale, HeightScale );
391 CHECK_GL_ERROR();
392 if (primitiveTransformLocation != -1) {
393 glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
394 CHECK_GL_ERROR();
396 glDrawArrays( GL_TRIANGLES, first, Vertices.size() );
398 CHECK_GL_ERROR();
401 void Primitive::applyOperations(glm::mat4& matrix, double nTime, double WidthScale, double HeightScale) const
403 for(const auto & rOperation : Operations)
404 rOperation->interpolate(matrix, nTime, WidthScale, HeightScale);
405 matrix = glm::scale(matrix, glm::vec3(WidthScale, HeightScale, 1));
408 void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight ) const
410 // fixme: allow various model spaces, now we make it so that
411 // it is regular -1,-1 to 1,1, where the whole display fits in
412 glm::mat4 matrix;
413 if (DispHeight > DispWidth)
414 matrix = glm::scale(matrix, glm::vec3(DispHeight/DispWidth, 1, 1));
415 else
416 matrix = glm::scale(matrix, glm::vec3(1, DispWidth/DispHeight, 1));
417 CHECK_GL_ERROR();
418 if (sceneTransformLocation != -1) {
419 glUniformMatrix4fv(sceneTransformLocation, 1, false, glm::value_ptr(matrix));
420 CHECK_GL_ERROR();
422 displayPrimitives(maPrimitives, primitiveTransformLocation, nTime, 1, 1, maFirstIndices.cbegin());
423 CHECK_GL_ERROR();
426 void SceneObject::pushPrimitive(const Primitive &p)
428 maPrimitives.push_back(p);
431 SceneObject::SceneObject()
432 : maPrimitives()
436 SceneObject::~SceneObject()
440 namespace
443 class Iris : public SceneObject
445 public:
446 Iris() = default;
448 virtual void prepare(GLuint program) override;
449 virtual void display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight) const override;
450 virtual void finish() override;
452 private:
453 GLuint maTexture = 0;
454 GLuint maBuffer = 0;
455 GLuint maVertexArray = 0;
458 void Iris::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) const
460 glBindVertexArray(maVertexArray);
461 CHECK_GL_ERROR();
462 glBindTexture(GL_TEXTURE_2D, maTexture);
463 CHECK_GL_ERROR();
464 SceneObject::display(sceneTransformLocation, primitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
467 void Iris::prepare(GLuint program)
469 CHECK_GL_ERROR();
470 static const GLubyte img[3] = { 80, 80, 80 };
472 glGenTextures(1, &maTexture);
473 glBindTexture(GL_TEXTURE_2D, maTexture);
474 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
475 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
476 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
477 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
478 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
479 CHECK_GL_ERROR();
481 glGenVertexArrays(1, &maVertexArray);
482 glBindVertexArray(maVertexArray);
484 glGenBuffers(1, &maBuffer);
485 glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
486 maFirstIndices = uploadPrimitives(maPrimitives);
488 // Attribute bindings
489 GLint location = glGetAttribLocation(program, "a_position");
490 if (location != -1) {
491 glEnableVertexAttribArray(location);
492 glVertexAttribPointer( location, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
493 CHECK_GL_ERROR();
496 location = glGetAttribLocation(program, "a_normal");
497 if (location != -1) {
498 glEnableVertexAttribArray(location);
499 glVertexAttribPointer( location, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
500 CHECK_GL_ERROR();
503 location = glGetAttribLocation(program, "a_texCoord");
504 if (location != -1) {
505 glEnableVertexAttribArray(location);
506 glVertexAttribPointer( location, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
507 CHECK_GL_ERROR();
510 glBindBuffer(GL_ARRAY_BUFFER, 0);
513 void Iris::finish()
515 CHECK_GL_ERROR();
516 glDeleteBuffers(1, &maBuffer);
517 CHECK_GL_ERROR();
518 glDeleteVertexArrays(1, &maVertexArray);
519 CHECK_GL_ERROR();
520 glDeleteTextures(1, &maTexture);
521 CHECK_GL_ERROR();
526 namespace
529 class ReflectionTransition : public OGLTransitionImpl
531 public:
532 ReflectionTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
533 : OGLTransitionImpl(rScene, rSettings)
536 private:
537 virtual GLuint makeShader() const override;
538 virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
540 virtual void prepareTransition( sal_Int32, sal_Int32, OpenGLContext* ) override {
541 glDisable(GL_CULL_FACE);
544 virtual void finishTransition() override {
545 glEnable(GL_CULL_FACE);
549 GLuint ReflectionTransition::makeShader() const
551 return OpenGLHelper::LoadShaders( u"reflectionVertexShader"_ustr, u"reflectionFragmentShader"_ustr );
554 void ReflectionTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
555 double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
557 CHECK_GL_ERROR();
558 applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
560 sal_Int32 texture;
561 Primitives_t slide;
562 if (nTime < 0.5) {
563 texture = glLeavingSlideTex;
564 slide = getScene().getLeavingSlide();
565 } else {
566 texture = glEnteringSlideTex;
567 slide = getScene().getEnteringSlide();
570 displaySlide( nTime, texture, slide, SlideWidthScale, SlideHeightScale );
571 CHECK_GL_ERROR();
574 std::shared_ptr<OGLTransitionImpl>
575 makeReflectionTransition(
576 Primitives_t&& rLeavingSlidePrimitives,
577 Primitives_t&& rEnteringSlidePrimitives,
578 Operations_t&& rOverallOperations,
579 const TransitionSettings& rSettings)
581 return std::make_shared<ReflectionTransition>(
582 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives), std::move(rOverallOperations), SceneObjects_t()),
583 rSettings);
588 namespace
591 class SimpleTransition : public OGLTransitionImpl
593 public:
594 SimpleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
595 : OGLTransitionImpl(rScene, rSettings)
599 private:
600 virtual GLuint makeShader() const override;
602 virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
605 GLuint SimpleTransition::makeShader() const
607 return OpenGLHelper::LoadShaders( u"basicVertexShader"_ustr, u"basicFragmentShader"_ustr );
610 void SimpleTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
611 double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
613 CHECK_GL_ERROR();
614 applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
616 CHECK_GL_ERROR();
617 displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
618 displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
619 CHECK_GL_ERROR();
622 std::shared_ptr<OGLTransitionImpl>
623 makeSimpleTransition(
624 Primitives_t&& rLeavingSlidePrimitives,
625 Primitives_t&& rEnteringSlidePrimitives,
626 Operations_t&& rOverallOperations,
627 SceneObjects_t&& rSceneObjects,
628 const TransitionSettings& rSettings)
630 return std::make_shared<SimpleTransition>(
631 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
632 std::move(rOverallOperations), std::move(rSceneObjects)),
633 rSettings);
636 std::shared_ptr<OGLTransitionImpl>
637 makeSimpleTransition(
638 Primitives_t&& rLeavingSlidePrimitives,
639 Primitives_t&& rEnteringSlidePrimitives,
640 Operations_t&& rOverallOperations,
641 const TransitionSettings& rSettings = TransitionSettings())
643 return makeSimpleTransition(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
644 std::move(rOverallOperations), SceneObjects_t(), rSettings);
647 std::shared_ptr<OGLTransitionImpl>
648 makeSimpleTransition(
649 Primitives_t&& rLeavingSlidePrimitives,
650 Primitives_t&& rEnteringSlidePrimitives,
651 SceneObjects_t&& rSceneObjects,
652 const TransitionSettings& rSettings)
654 return makeSimpleTransition(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
655 Operations_t(), std::move(rSceneObjects), rSettings);
658 std::shared_ptr<OGLTransitionImpl>
659 makeSimpleTransition(
660 Primitives_t&& rLeavingSlidePrimitives,
661 Primitives_t&& rEnteringSlidePrimitives,
662 const TransitionSettings& rSettings = TransitionSettings())
664 return makeSimpleTransition(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
665 Operations_t(), SceneObjects_t(), rSettings);
670 std::shared_ptr<OGLTransitionImpl> makeOutsideCubeFaceToLeft()
672 Primitive Slide;
674 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
675 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
677 Primitives_t aLeavingPrimitives;
678 aLeavingPrimitives.push_back(Slide);
680 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),90,false,false,0.0,1.0));
682 Primitives_t aEnteringPrimitives;
683 aEnteringPrimitives.push_back(Slide);
685 Operations_t aOperations;
686 aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),-90,false,true,0.0,1.0));
688 return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aOperations));
691 std::shared_ptr<OGLTransitionImpl> makeInsideCubeFaceToLeft()
693 Primitive Slide;
695 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
696 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
698 Primitives_t aLeavingPrimitives;
699 aLeavingPrimitives.push_back(Slide);
701 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),-90,false,false,0.0,1.0));
703 Primitives_t aEnteringPrimitives;
704 aEnteringPrimitives.push_back(Slide);
706 Operations_t aOperations;
707 aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),90,false,true,0.0,1.0));
709 return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aOperations));
712 std::shared_ptr<OGLTransitionImpl> makeFallLeaving()
714 Primitive Slide;
716 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
717 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
719 Primitives_t aEnteringPrimitives;
720 aEnteringPrimitives.push_back(Slide);
722 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(1,0,0),glm::vec3(0,-1,0), 90,true,true,0.0,1.0));
723 Primitives_t aLeavingPrimitives;
724 aLeavingPrimitives.push_back(Slide);
726 TransitionSettings aSettings;
727 aSettings.mbUseMipMapEntering = false;
729 return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), aSettings);
732 std::shared_ptr<OGLTransitionImpl> makeTurnAround()
734 Primitive Slide;
735 TransitionSettings aSettings;
737 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
738 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
739 Primitives_t aLeavingPrimitives;
740 aLeavingPrimitives.push_back(Slide);
742 Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
743 aLeavingPrimitives.push_back(Slide);
745 Slide.Operations.clear();
746 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0),-180,true,false,0.0,1.0));
747 Primitives_t aEnteringPrimitives;
748 aEnteringPrimitives.push_back(Slide);
750 Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
751 aEnteringPrimitives.push_back(Slide);
753 Operations_t aOperations;
754 aOperations.push_back(makeSTranslate(glm::vec3(0, 0, -1.5),true, 0, 0.5));
755 aOperations.push_back(makeSTranslate(glm::vec3(0, 0, 1.5), true, 0.5, 1));
756 aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0),glm::vec3(0, 0, 0), -180, true, true, 0.0, 1.0));
758 return makeReflectionTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aOperations), aSettings);
761 std::shared_ptr<OGLTransitionImpl> makeTurnDown()
763 Primitive Slide;
765 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
766 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
767 Primitives_t aLeavingPrimitives;
768 aLeavingPrimitives.push_back(Slide);
770 Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 0.0001), false, -1.0, 0.0));
771 Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), -90, true, 0.0, 1.0));
772 Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), 90, false, -1.0, 0.0));
773 Primitives_t aEnteringPrimitives;
774 aEnteringPrimitives.push_back(Slide);
776 TransitionSettings aSettings;
777 aSettings.mbUseMipMapLeaving = false;
779 return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), aSettings);
782 std::shared_ptr<OGLTransitionImpl> makeIris()
784 Primitive Slide;
786 Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
787 Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
788 Primitives_t aEnteringPrimitives;
789 aEnteringPrimitives.push_back (Slide);
791 Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.000001), false, -1, 0));
792 Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, -0.000002), false, 0.5, 1));
793 Primitives_t aLeavingPrimitives;
794 aLeavingPrimitives.push_back (Slide);
797 Primitive irisPart;
798 int i, nSteps = 24, nParts = 7;
799 double t = 1.0/nSteps, lx = 1, ly = 0, of=2.2, f=1.42;
801 for (i=1; i<=nSteps; i++) {
802 double x = cos ((3*2*M_PI*t)/nParts);
803 double y = -sin ((3*2*M_PI*t)/nParts);
804 double cx = (f*x + 1)/2;
805 double cy = (f*y + 1)/2;
806 double lcx = (f*lx + 1)/2;
807 double lcy = (f*ly + 1)/2;
808 double cxo = (of*x + 1)/2;
809 double cyo = (of*y + 1)/2;
810 double lcxo = (of*lx + 1)/2;
811 double lcyo = (of*ly + 1)/2;
812 irisPart.pushTriangle (glm::vec2 (lcx, lcy),
813 glm::vec2 (lcxo, lcyo),
814 glm::vec2 (cx, cy));
815 irisPart.pushTriangle (glm::vec2 (cx, cy),
816 glm::vec2 (lcxo, lcyo),
817 glm::vec2 (cxo, cyo));
818 lx = x;
819 ly = y;
820 t += 1.0/nSteps;
823 std::shared_ptr<Iris> pIris = std::make_shared<Iris>();
824 double angle = 87;
826 for (i = 0; i < nParts; i++) {
827 irisPart.Operations.clear ();
828 double rx, ry;
830 rx = cos ((2*M_PI*i)/nParts);
831 ry = sin ((2*M_PI*i)/nParts);
832 irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), angle, true, 0.0, 0.5));
833 irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), -angle, true, 0.5, 1));
834 if (i > 0) {
835 irisPart.Operations.push_back (makeSTranslate (glm::vec3(rx, ry, 0), false, -1, 0));
836 irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), i*360.0/nParts, false, -1, 0));
837 irisPart.Operations.push_back (makeSTranslate (glm::vec3(-1, 0, 0), false, -1, 0));
839 irisPart.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 1), false, -2, 0.0));
840 irisPart.Operations.push_back (makeSRotate (glm::vec3(1, .5, 0), glm::vec3(1, 0, 0), -30, false, -1, 0));
841 pIris->pushPrimitive (irisPart);
844 SceneObjects_t aSceneObjects;
845 aSceneObjects.push_back (pIris);
847 TransitionSettings aSettings;
848 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
850 return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aSceneObjects), aSettings);
853 namespace
856 class RochadeTransition : public ReflectionTransition
858 public:
859 RochadeTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
860 : ReflectionTransition(rScene, rSettings)
863 private:
864 virtual void displaySlides_(double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext) override;
867 void RochadeTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
869 applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
871 if( nTime > .5) {
872 displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
873 displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
874 } else {
875 displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
876 displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
880 std::shared_ptr<OGLTransitionImpl>
881 makeRochadeTransition(
882 Primitives_t&& rLeavingSlidePrimitives,
883 Primitives_t&& rEnteringSlidePrimitives,
884 const TransitionSettings& rSettings)
886 return std::make_shared<RochadeTransition>(
887 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
888 rSettings)
894 std::shared_ptr<OGLTransitionImpl> makeRochade()
896 Primitive Slide;
897 TransitionSettings aSettings;
899 double w, h;
901 w = 2.2;
902 h = 10;
904 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
905 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
907 Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.25, -0.25, true, 0, 1));
908 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1));
909 Primitives_t aLeavingSlide;
910 aLeavingSlide.push_back(Slide);
912 Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
913 aLeavingSlide.push_back(Slide);
915 Slide.Operations.clear();
916 Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.75, 0.25, true, 0, 1));
917 Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, -h), false, -1, 0));
918 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1));
919 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), 45, true, false, -1, 0));
920 Primitives_t aEnteringSlide;
921 aEnteringSlide.push_back(Slide);
923 Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
924 aEnteringSlide.push_back(Slide);
926 return makeRochadeTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
929 static double randFromNeg1to1()
931 return comphelper::rng::uniform_real_distribution(-1.0, std::nextafter(1.0, DBL_MAX));
934 // TODO(Q3): extract to basegfx
935 static glm::vec3 randNormVectorInXYPlane()
937 glm::vec3 toReturn(randFromNeg1to1(),randFromNeg1to1(),0.0);
938 return glm::normalize(toReturn);
941 template<typename T>
942 static T clamp(const T& rIn)
944 return glm::clamp(rIn, T(-1.0), T(1.0));
947 std::shared_ptr<OGLTransitionImpl> makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles )
949 double dAngle(2*M_PI/static_cast<double>( nPointsOnCircles ));
950 if(nCircles < 2 || nPointsOnCircles < 4)
951 return makeNByMTileFlip(1,1);
952 float Radius(1.0/static_cast<double>( nCircles ));
953 float dRadius(Radius);
954 float LastRadius(0.0);
955 float NextRadius(2*Radius);
957 /// now we know there is at least two circles
958 /// the first will always be a full circle
959 /// the last will always be the outer shell of the slide with a circle hole
961 //add the full circle
962 std::vector<glm::vec2> unScaledTexCoords;
963 float TempAngle(0.0);
964 for(unsigned int Point(0); Point < nPointsOnCircles; ++Point)
966 unScaledTexCoords.emplace_back( cos(TempAngle - M_PI_2) , sin(TempAngle- M_PI_2) );
968 TempAngle += dAngle;
971 Primitives_t aLeavingSlide;
972 Primitives_t aEnteringSlide;
974 Primitive EnteringSlide;
975 Primitive LeavingSlide;
976 for(int Point(0); Point + 1 < nPointsOnCircles; ++Point)
978 EnteringSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5 , 0.5 ) );
979 LeavingSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5, 0.5) );
981 EnteringSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius * unScaledTexCoords[ 0 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ nPointsOnCircles - 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) );
982 LeavingSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) );
984 glm::vec3 axis(randNormVectorInXYPlane());
985 EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
986 LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
987 EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) );
989 aEnteringSlide.push_back(EnteringSlide);
990 aLeavingSlide.push_back(LeavingSlide);
991 LastRadius = Radius;
992 Radius = NextRadius;
993 NextRadius += dRadius;
996 for(int i(1); i < nCircles - 1; ++i)
998 Primitive LeavingSlide;
999 Primitive EnteringSlide;
1000 for(int Side(0); Side < nPointsOnCircles - 1; ++Side)
1002 EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1003 EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1005 LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1006 LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1009 EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1010 EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1012 LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1013 LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1015 glm::vec3 axis(randNormVectorInXYPlane());
1016 EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
1017 LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
1018 EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) );
1020 aEnteringSlide.push_back(EnteringSlide);
1021 aLeavingSlide.push_back(LeavingSlide);
1023 LastRadius = Radius;
1024 Radius = NextRadius;
1025 NextRadius += dRadius;
1028 Radius = sqrt(2.0);
1029 Primitive LeavingSlide;
1030 Primitive EnteringSlide;
1031 for(int Side(0); Side < nPointsOnCircles - 1; ++Side)
1034 EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1035 EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) );
1037 LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1038 LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) );
1041 EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1042 EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) );
1044 LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1045 LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) );
1047 glm::vec3 axis(randNormVectorInXYPlane());
1048 EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) );
1049 LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) );
1050 EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) );
1052 aEnteringSlide.push_back(EnteringSlide);
1053 aLeavingSlide.push_back(LeavingSlide);
1056 return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
1059 std::shared_ptr<OGLTransitionImpl> makeHelix( sal_uInt16 nRows )
1061 double invN(1.0/static_cast<double>(nRows));
1062 double iDn = 0.0;
1063 double iPDn = invN;
1064 Primitives_t aLeavingSlide;
1065 Primitives_t aEnteringSlide;
1066 for(unsigned int i(0); i < nRows; ++i)
1068 Primitive Tile;
1070 Tile.pushTriangle(glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iDn ) , glm::vec2( 0.0 , iPDn ));
1072 Tile.pushTriangle(glm::vec2( 1.0 , iPDn ) , glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iPDn ));
1074 Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , 180 ,
1075 true, std::min(std::max(static_cast<double>(i - nRows/2.0)*invN/2.0,0.0),1.0),
1076 std::min(std::max(static_cast<double>(i + nRows/2.0)*invN/2.0,0.0),1.0) ) );
1078 aLeavingSlide.push_back(Tile);
1080 Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , -180 , false,0.0,1.0) );
1082 aEnteringSlide.push_back(Tile);
1084 iDn += invN;
1085 iPDn += invN;
1088 return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
1091 static float fdiv(int a, int b)
1093 return static_cast<float>(a)/b;
1096 static glm::vec2 vec(float x, float y, float nx, float ny)
1098 x = x < 0.0 ? 0.0 : x;
1099 x = std::min(x, nx);
1100 y = y < 0.0 ? 0.0 : y;
1101 y = std::min(y, ny);
1102 return glm::vec2(fdiv(x, nx), fdiv(y, ny));
1105 std::shared_ptr<OGLTransitionImpl> makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m )
1107 Primitives_t aLeavingSlide;
1108 Primitives_t aEnteringSlide;
1110 for (int x = 0; x < n; x++)
1112 for (int y = 0; y < n; y++)
1114 Primitive aTile;
1115 glm::vec2 x11 = vec(x, y, n, m);
1116 glm::vec2 x12 = vec(x, y+1, n, m);
1117 glm::vec2 x21 = vec(x+1, y, n, m);
1118 glm::vec2 x22 = vec(x+1, y+1, n, m);
1120 aTile.pushTriangle(x21, x11, x12);
1121 aTile.pushTriangle(x22, x21, x12);
1123 aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, 180 , true, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f));
1124 aLeavingSlide.push_back(aTile);
1126 aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, -180, false, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f));
1127 aEnteringSlide.push_back(aTile);
1131 return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
1134 Primitive& Primitive::operator=(const Primitive& rvalue)
1136 Primitive aTmp(rvalue);
1137 swap(aTmp);
1138 return *this;
1141 Primitive::Primitive(const Primitive& rvalue)
1142 : Operations(rvalue.Operations)
1143 , Vertices(rvalue.Vertices)
1147 void Primitive::swap(Primitive& rOther)
1149 using std::swap;
1151 swap(Operations, rOther.Operations);
1152 swap(Vertices, rOther.Vertices);
1155 void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2)
1157 std::vector<glm::vec3> Verts;
1158 std::vector<glm::vec2> Texs;
1159 Verts.reserve(3);
1160 Texs.reserve(3);
1162 Verts.emplace_back( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 );
1163 Verts.emplace_back( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 );
1164 Verts.emplace_back( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 );
1166 //figure out if they're facing the correct way, and make them face the correct way.
1167 glm::vec3 Normal( glm::cross( Verts[0] - Verts[1] , Verts[1] - Verts[2] ) );
1168 if(Normal.z >= 0.0)//if the normal is facing us
1170 Texs.push_back(SlideLocation0);
1171 Texs.push_back(SlideLocation1);
1172 Texs.push_back(SlideLocation2);
1174 else // if the normal is facing away from us, make it face us
1176 Texs.push_back(SlideLocation0);
1177 Texs.push_back(SlideLocation2);
1178 Texs.push_back(SlideLocation1);
1179 Verts.clear();
1180 Verts.emplace_back( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 );
1181 Verts.emplace_back( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 );
1182 Verts.emplace_back( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 );
1185 Vertices.push_back({Verts[0], glm::vec3(0, 0, 1), Texs[0]}); //all normals always face the screen when untransformed.
1186 Vertices.push_back({Verts[1], glm::vec3(0, 0, 1), Texs[1]}); //all normals always face the screen when untransformed.
1187 Vertices.push_back({Verts[2], glm::vec3(0, 0, 1), Texs[2]}); //all normals always face the screen when untransformed.
1190 namespace
1193 class DiamondTransition : public SimpleTransition
1195 public:
1196 DiamondTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1197 : SimpleTransition(rScene, rSettings)
1200 private:
1201 virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
1204 Primitives_t makeLeavingSlide(double nTime)
1206 Primitive Slide2;
1207 if( nTime >= 0.5 ) {
1208 double m = 1 - nTime;
1210 Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (m,0), glm::vec2 (0,m));
1211 Slide2.pushTriangle (glm::vec2 (nTime,0), glm::vec2 (1,0), glm::vec2 (1,m));
1212 Slide2.pushTriangle (glm::vec2 (1,nTime), glm::vec2 (1,1), glm::vec2 (nTime,1));
1213 Slide2.pushTriangle (glm::vec2 (0,nTime), glm::vec2 (m,1), glm::vec2 (0,1));
1214 } else {
1215 double l = 0.5 - nTime;
1216 double h = 0.5 + nTime;
1218 Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0.5,l));
1219 Slide2.pushTriangle (glm::vec2 (0.5,l), glm::vec2 (1,0), glm::vec2 (h,0.5));
1220 Slide2.pushTriangle (glm::vec2 (1,0), glm::vec2 (1,1), glm::vec2 (h,0.5));
1221 Slide2.pushTriangle (glm::vec2 (h,0.5), glm::vec2 (1,1), glm::vec2 (0.5,h));
1222 Slide2.pushTriangle (glm::vec2 (0.5,h), glm::vec2 (1,1), glm::vec2 (0,1));
1223 Slide2.pushTriangle (glm::vec2 (l,0.5), glm::vec2 (0.5,h), glm::vec2 (0,1));
1224 Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (l,0.5), glm::vec2 (0,1));
1225 Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (0.5,l), glm::vec2 (l,0.5));
1227 Slide2.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.00000001), false, -1, 0));
1228 Primitives_t aLeavingSlidePrimitives;
1229 aLeavingSlidePrimitives.push_back (Slide2);
1231 return aLeavingSlidePrimitives;
1234 void DiamondTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
1235 double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
1237 CHECK_GL_ERROR();
1238 applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
1240 CHECK_GL_ERROR();
1241 displayUnbufferedSlide( nTime, glLeavingSlideTex, makeLeavingSlide(nTime), SlideWidthScale, SlideHeightScale );
1242 displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
1243 CHECK_GL_ERROR();
1246 std::shared_ptr<OGLTransitionImpl>
1247 makeDiamondTransition(const TransitionSettings& rSettings)
1249 Primitive Slide1;
1250 Slide1.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1251 Slide1.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1252 Primitives_t aEnteringSlidePrimitives;
1253 aEnteringSlidePrimitives.push_back (Slide1);
1254 Primitives_t aLeavingSlidePrimitives;
1255 aLeavingSlidePrimitives.push_back (Slide1);
1256 return std::make_shared<DiamondTransition>(TransitionScene(std::move(aLeavingSlidePrimitives), std::move(aEnteringSlidePrimitives)), rSettings);
1261 std::shared_ptr<OGLTransitionImpl> makeDiamond()
1263 TransitionSettings aSettings;
1264 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1266 return makeDiamondTransition(aSettings);
1269 std::shared_ptr<OGLTransitionImpl> makeVenetianBlinds( bool vertical, int parts )
1271 static double t30 = tan( M_PI/6.0 );
1272 double ln = 0;
1273 double p = 1.0/parts;
1275 Primitives_t aLeavingSlide;
1276 Primitives_t aEnteringSlide;
1277 for( int i=0; i<parts; i++ ) {
1278 Primitive Slide;
1279 double n = (i + 1)/static_cast<double>(parts);
1280 if( vertical ) {
1281 Slide.pushTriangle (glm::vec2 (ln,0), glm::vec2 (n,0), glm::vec2 (ln,1));
1282 Slide.pushTriangle (glm::vec2 (n,0), glm::vec2 (ln,1), glm::vec2 (n,1));
1283 Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0), glm::vec3(n + ln - 1, 0, -t30*p), -120, true, true, 0.0, 1.0));
1284 } else {
1285 Slide.pushTriangle (glm::vec2 (0,ln), glm::vec2 (1,ln), glm::vec2 (0,n));
1286 Slide.pushTriangle (glm::vec2 (1,ln), glm::vec2 (0,n), glm::vec2 (1,n));
1287 Slide.Operations.push_back(makeRotateAndScaleDepthByHeight(glm::vec3(1, 0, 0), glm::vec3(0, 1 - n - ln, -t30*p), -120, true, true, 0.0, 1.0));
1289 aLeavingSlide.push_back (Slide);
1291 if( vertical ) {
1292 Slide.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), glm::vec3(2*n - 1, 0, 0), -60, false, -1, 0));
1293 Slide.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), glm::vec3(n + ln - 1, 0, 0), 180, false, -1, 0));
1294 } else {
1295 Slide.Operations.push_back(makeSRotate(glm::vec3(1, 0, 0), glm::vec3(0, 1 - 2*n, 0), -60, false, -1, 0));
1296 Slide.Operations.push_back(makeSRotate(glm::vec3(1, 0, 0), glm::vec3(0, 1 - n - ln, 0), 180, false, -1, 0));
1298 aEnteringSlide.push_back (Slide);
1299 ln = n;
1302 return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
1305 namespace
1308 class FadeSmoothlyTransition : public OGLTransitionImpl
1310 public:
1311 FadeSmoothlyTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1312 : OGLTransitionImpl(rScene, rSettings)
1315 private:
1316 virtual GLuint makeShader() const override;
1319 GLuint FadeSmoothlyTransition::makeShader() const
1321 return OpenGLHelper::LoadShaders( u"basicVertexShader"_ustr, u"fadeFragmentShader"_ustr );
1324 std::shared_ptr<OGLTransitionImpl>
1325 makeFadeSmoothlyTransition(
1326 Primitives_t&& rLeavingSlidePrimitives,
1327 Primitives_t&& rEnteringSlidePrimitives,
1328 const TransitionSettings& rSettings)
1330 return std::make_shared<FadeSmoothlyTransition>(
1331 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
1332 rSettings)
1338 std::shared_ptr<OGLTransitionImpl> makeFadeSmoothly()
1340 Primitive Slide;
1342 Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1343 Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1344 Primitives_t aLeavingSlide;
1345 aLeavingSlide.push_back (Slide);
1346 Primitives_t aEnteringSlide;
1347 aEnteringSlide.push_back (Slide);
1349 TransitionSettings aSettings;
1350 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1352 return makeFadeSmoothlyTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
1355 namespace
1358 class FadeThroughColorTransition : public OGLTransitionImpl
1360 public:
1361 FadeThroughColorTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, bool white)
1362 : OGLTransitionImpl(rScene, rSettings), useWhite( white )
1365 private:
1366 virtual GLuint makeShader() const override;
1367 bool useWhite;
1370 GLuint FadeThroughColorTransition::makeShader() const
1372 return OpenGLHelper::LoadShaders( u"basicVertexShader"_ustr, u"fadeBlackFragmentShader"_ustr,
1373 useWhite ? "#define use_white" : "", "" );
1376 std::shared_ptr<OGLTransitionImpl>
1377 makeFadeThroughColorTransition(
1378 Primitives_t&& rLeavingSlidePrimitives,
1379 Primitives_t&& rEnteringSlidePrimitives,
1380 const TransitionSettings& rSettings,
1381 bool white)
1383 return std::make_shared<FadeThroughColorTransition>(
1384 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
1385 rSettings, white)
1391 std::shared_ptr<OGLTransitionImpl> makeFadeThroughColor( bool white )
1393 Primitive Slide;
1395 Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1396 Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1397 Primitives_t aLeavingSlide;
1398 aLeavingSlide.push_back (Slide);
1399 Primitives_t aEnteringSlide;
1400 aEnteringSlide.push_back (Slide);
1402 TransitionSettings aSettings;
1403 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1405 return makeFadeThroughColorTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings, white);
1408 namespace
1411 class PermTextureTransition : public OGLTransitionImpl
1413 protected:
1414 PermTextureTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1415 : OGLTransitionImpl(rScene, rSettings)
1416 , m_nHelperTexture(0)
1419 virtual void finishTransition() override;
1420 virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1422 private:
1423 /** various data */
1424 GLuint m_nHelperTexture;
1427 void PermTextureTransition::finishTransition()
1429 CHECK_GL_ERROR();
1430 if ( m_nHelperTexture )
1432 glDeleteTextures( 1, &m_nHelperTexture );
1433 m_nHelperTexture = 0;
1435 CHECK_GL_ERROR();
1438 constexpr auto permutation2D = []() constexpr {
1439 int permutation256 [256]= {
1440 215, 100, 200, 204, 233, 50, 85, 196,
1441 71, 141, 122, 160, 93, 131, 243, 234,
1442 162, 183, 36, 155, 4, 62, 35, 205,
1443 40, 102, 33, 27, 255, 55, 214, 156,
1444 75, 163, 134, 126, 249, 74, 197, 228,
1445 72, 90, 206, 235, 17, 22, 49, 169,
1446 227, 89, 16, 5, 117, 60, 248, 230,
1447 217, 68, 138, 96, 194, 170, 136, 10,
1448 112, 238, 184, 189, 176, 42, 225, 212,
1449 84, 58, 175, 244, 150, 168, 219, 236,
1450 101, 208, 123, 37, 164, 110, 158, 201,
1451 78, 114, 57, 48, 70, 142, 106, 43,
1452 232, 26, 32, 252, 239, 98, 191, 94,
1453 59, 149, 39, 187, 203, 190, 19, 13,
1454 133, 45, 61, 247, 23, 34, 20, 52,
1455 118, 209, 146, 193, 222, 18, 1, 152,
1456 46, 41, 91, 148, 115, 25, 135, 77,
1457 254, 147, 224, 161, 9, 213, 223, 250,
1458 231, 251, 127, 166, 63, 179, 81, 130,
1459 139, 28, 120, 151, 241, 86, 111, 0,
1460 88, 153, 172, 182, 159, 105, 178, 47,
1461 51, 167, 65, 66, 92, 73, 198, 211,
1462 245, 195, 31, 220, 140, 76, 221, 186,
1463 154, 185, 56, 83, 38, 165, 109, 67,
1464 124, 226, 132, 53, 229, 29, 12, 181,
1465 121, 24, 207, 199, 177, 113, 30, 80,
1466 3, 97, 188, 79, 216, 173, 8, 145,
1467 87, 128, 180, 237, 240, 137, 125, 104,
1468 15, 242, 119, 246, 103, 143, 95, 144,
1469 2, 44, 69, 157, 192, 174, 14, 54,
1470 218, 82, 64, 210, 11, 6, 129, 21,
1471 116, 171, 99, 202, 7, 107, 253, 108
1473 std::array<unsigned char, 256 * 256> a{};
1474 for (int y = 0; y < 256; y++)
1475 for (int x = 0; x < 256; x++)
1476 a[x + y * 256] = permutation256[(y + permutation256[x]) & 0xff];
1477 return a;
1478 }();
1480 void initPermTexture(GLuint *texID)
1482 CHECK_GL_ERROR();
1483 glGenTextures(1, texID);
1484 glBindTexture(GL_TEXTURE_2D, *texID);
1485 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RED, GL_UNSIGNED_BYTE,
1486 permutation2D.data());
1487 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1488 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1489 CHECK_GL_ERROR();
1492 void PermTextureTransition::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
1494 CHECK_GL_ERROR();
1495 GLint location = glGetUniformLocation( m_nProgramObject, "permTexture" );
1496 if( location != -1 ) {
1497 glActiveTexture(GL_TEXTURE1);
1498 CHECK_GL_ERROR();
1499 if( !m_nHelperTexture )
1500 initPermTexture( &m_nHelperTexture );
1502 glActiveTexture(GL_TEXTURE0);
1503 CHECK_GL_ERROR();
1505 glUniform1i( location, 1 ); // texture unit 1
1506 CHECK_GL_ERROR();
1508 CHECK_GL_ERROR();
1513 namespace
1516 class StaticNoiseTransition : public PermTextureTransition
1518 public:
1519 StaticNoiseTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1520 : PermTextureTransition(rScene, rSettings)
1523 private:
1524 virtual GLuint makeShader() const override;
1527 GLuint StaticNoiseTransition::makeShader() const
1529 return OpenGLHelper::LoadShaders( u"basicVertexShader"_ustr, u"staticFragmentShader"_ustr );
1532 std::shared_ptr<OGLTransitionImpl>
1533 makeStaticNoiseTransition(
1534 Primitives_t&& rLeavingSlidePrimitives,
1535 Primitives_t&& rEnteringSlidePrimitives,
1536 const TransitionSettings& rSettings)
1538 return std::make_shared<StaticNoiseTransition>(
1539 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
1540 rSettings)
1546 std::shared_ptr<OGLTransitionImpl> makeStatic()
1548 Primitive Slide;
1550 Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1551 Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1552 Primitives_t aLeavingSlide;
1553 aLeavingSlide.push_back (Slide);
1554 Primitives_t aEnteringSlide;
1555 aEnteringSlide.push_back (Slide);
1557 TransitionSettings aSettings;
1558 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1560 return makeStaticNoiseTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
1563 namespace
1566 class DissolveTransition : public PermTextureTransition
1568 public:
1569 DissolveTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1570 : PermTextureTransition(rScene, rSettings)
1573 private:
1574 virtual GLuint makeShader() const override;
1577 GLuint DissolveTransition::makeShader() const
1579 return OpenGLHelper::LoadShaders( u"basicVertexShader"_ustr, u"dissolveFragmentShader"_ustr );
1582 std::shared_ptr<OGLTransitionImpl>
1583 makeDissolveTransition(
1584 Primitives_t&& rLeavingSlidePrimitives,
1585 Primitives_t&& rEnteringSlidePrimitives,
1586 const TransitionSettings& rSettings)
1588 return std::make_shared<DissolveTransition>(
1589 TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
1590 rSettings)
1596 std::shared_ptr<OGLTransitionImpl> makeDissolve()
1598 Primitive Slide;
1600 Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1601 Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1602 Primitives_t aLeavingSlide;
1603 aLeavingSlide.push_back (Slide);
1604 Primitives_t aEnteringSlide;
1605 aEnteringSlide.push_back (Slide);
1607 TransitionSettings aSettings;
1608 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1610 return makeDissolveTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
1613 namespace
1616 class VortexTransition : public PermTextureTransition
1618 public:
1619 VortexTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, int nNX, int nNY)
1620 : PermTextureTransition(rScene, rSettings)
1621 , maNumTiles(nNX,nNY)
1623 mvTileInfo.resize(6*maNumTiles.x*maNumTiles.y);
1624 mnFramebuffers[0] = 0;
1625 mnFramebuffers[1] = 0;
1626 mnDepthTextures[0] = 0;
1627 mnDepthTextures[1] = 0;
1630 private:
1631 virtual void finishTransition() override;
1632 virtual GLuint makeShader() const override;
1633 virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1634 virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
1636 GLint mnSlideLocation = -1;
1637 GLint mnTileInfoLocation = -1;
1638 GLuint mnTileInfoBuffer = 0u;
1639 GLint mnShadowLocation = -1;
1640 std::array<GLuint, 2> mnFramebuffers;
1641 std::array<GLuint, 2> mnDepthTextures;
1643 glm::ivec2 maNumTiles;
1645 std::vector<GLfloat> mvTileInfo;
1648 void VortexTransition::finishTransition()
1650 PermTextureTransition::finishTransition();
1652 CHECK_GL_ERROR();
1653 glDeleteTextures(2, mnDepthTextures.data());
1654 mnDepthTextures = {0u, 0u};
1655 CHECK_GL_ERROR();
1656 glDeleteFramebuffers(2, mnFramebuffers.data());
1657 mnFramebuffers = {0u, 0u};
1658 glDeleteBuffers(1, &mnTileInfoBuffer);
1659 mnTileInfoBuffer = 0u;
1660 mnSlideLocation = -1;
1661 mnTileInfoLocation = -1;
1662 mnShadowLocation = -1;
1663 CHECK_GL_ERROR();
1666 GLuint VortexTransition::makeShader() const
1668 return OpenGLHelper::LoadShaders( u"vortexVertexShader"_ustr, u"vortexFragmentShader"_ustr, u"vortexGeometryShader"_ustr );
1671 glm::mat4 lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up) {
1672 glm::vec3 f = glm::normalize(center - eye);
1673 glm::vec3 u = glm::normalize(up);
1674 glm::vec3 s = glm::normalize(glm::cross(f, u));
1675 u = glm::cross(s, f);
1677 return glm::mat4(s.x, u.x, -f.x, 0,
1678 s.y, u.y, -f.y, 0,
1679 s.z, u.z, -f.z, 0,
1680 -glm::dot(s, eye), -glm::dot(u, eye), glm::dot(f, eye), 1);
1683 void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
1685 CHECK_GL_ERROR();
1686 PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
1687 CHECK_GL_ERROR();
1689 mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide");
1690 mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo");
1691 GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
1692 mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow");
1693 GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix");
1694 GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix");
1695 GLint location = glGetUniformLocation(m_nProgramObject, "leavingShadowTexture");
1696 glUniform1i(location, 2);
1697 location = glGetUniformLocation(m_nProgramObject, "enteringShadowTexture");
1698 glUniform1i(location, 3);
1699 CHECK_GL_ERROR();
1701 glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles));
1702 CHECK_GL_ERROR();
1704 glGenBuffers(1, &mnTileInfoBuffer);
1705 CHECK_GL_ERROR();
1707 // We store the (x,y) indexes of the tile each vertex belongs to in a float, so they must fit.
1708 assert(maNumTiles.x < 256);
1709 assert(maNumTiles.y < 256);
1711 // Two triangles, i.e. six vertices, per tile
1713 int n = 0;
1714 for (int x = 0; x < maNumTiles.x; x++)
1716 for (int y = 0; y < maNumTiles.y; y++)
1718 for (int v = 0; v < 6; v++)
1720 mvTileInfo[n] = x + (y << 8) + (v << 16);
1721 n++;
1727 glBindBuffer(GL_ARRAY_BUFFER, mnTileInfoBuffer);
1728 CHECK_GL_ERROR();
1729 glEnableVertexAttribArray(mnTileInfoLocation);
1730 CHECK_GL_ERROR();
1731 glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1732 CHECK_GL_ERROR();
1733 glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof(GLfloat), mvTileInfo.data(), GL_STATIC_DRAW);
1734 CHECK_GL_ERROR();
1736 glBindBuffer(GL_ARRAY_BUFFER, 0);
1737 CHECK_GL_ERROR();
1739 double EyePos(10.0);
1740 double const RealF(1.0);
1741 double const RealN(-1.0);
1742 double const RealL(-2.0);
1743 double RealR(2.0);
1744 double const RealB(-2.0);
1745 double RealT(2.0);
1746 double ClipN(EyePos+5.0*RealN);
1747 double ClipF(EyePos+15.0*RealF);
1748 double ClipL(RealL*8.0);
1749 double ClipR(RealR*8.0);
1750 double ClipB(RealB*8.0);
1751 double ClipT(RealT*8.0);
1753 glm::mat4 projection = glm::ortho<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
1754 //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
1755 glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
1756 1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
1757 1.0);
1758 projection = glm::scale(projection, scale);
1759 glUniformMatrix4fv(nOrthoProjectionMatrix, 1, false, glm::value_ptr(projection));
1761 glm::mat4 view = lookAt(glm::vec3(-1, 1, EyePos), glm::vec3(-0.5, 0.5, 0), glm::vec3(0, 1, 0));
1762 glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view));
1764 // Generate the framebuffers and textures for the shadows.
1765 glGenTextures(2, mnDepthTextures.data());
1766 glGenFramebuffers(2, mnFramebuffers.data());
1768 for (int i : {0, 1}) {
1769 glBindTexture(GL_TEXTURE_2D, mnDepthTextures[i]);
1770 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
1771 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1772 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1773 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1774 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1776 glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[i]);
1777 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[i], 0);
1778 glDrawBuffer(GL_NONE); // No color buffer is drawn to.
1780 // Always check that our framebuffer is ok
1781 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
1782 SAL_WARN("slideshow.opengl", "Wrong framebuffer!");
1783 return;
1787 pContext->restoreDefaultFramebuffer();
1788 glBindTexture(GL_TEXTURE_2D, 0);
1790 glActiveTexture( GL_TEXTURE2 );
1791 glBindTexture( GL_TEXTURE_2D, mnDepthTextures[0] );
1792 glActiveTexture( GL_TEXTURE3 );
1793 glBindTexture( GL_TEXTURE_2D, mnDepthTextures[1] );
1794 glActiveTexture( GL_TEXTURE0 );
1797 void VortexTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * pContext )
1799 CHECK_GL_ERROR();
1800 applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
1801 glUniform1f( m_nTimeLocation, nTime );
1802 glUniform1f( mnShadowLocation, 1.0 );
1804 std::array<GLint, 4> viewport;
1805 glGetIntegerv(GL_VIEWPORT, viewport.data());
1806 glViewport(0, 0, 2048, 2048);
1808 glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[0]);
1809 glClear(GL_DEPTH_BUFFER_BIT);
1810 glUniform1f( mnSlideLocation, 0.0 );
1811 displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
1813 glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[1]);
1814 glClear(GL_DEPTH_BUFFER_BIT);
1815 glUniform1f( mnSlideLocation, 1.0 );
1816 displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
1818 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
1819 pContext->restoreDefaultFramebuffer();
1820 glUniform1f( mnShadowLocation, 0.0 );
1821 glUniform1f( mnSlideLocation, 0.0 );
1822 displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
1823 glUniform1f( mnSlideLocation, 1.0 );
1824 displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
1825 CHECK_GL_ERROR();
1828 std::shared_ptr<OGLTransitionImpl>
1829 makeVortexTransition(Primitives_t&& rLeavingSlidePrimitives,
1830 Primitives_t&& rEnteringSlidePrimitives,
1831 const TransitionSettings& rSettings,
1832 int NX,
1833 int NY)
1835 return std::make_shared<VortexTransition>(TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
1836 rSettings,
1837 NX, NY);
1842 std::shared_ptr<OGLTransitionImpl> makeVortex()
1844 const int NX = 96, NY = 96;
1845 Primitive Slide;
1847 for (int x = 0; x < NX; x++)
1849 for (int y = 0; y < NY; y++)
1851 Slide.pushTriangle (glm::vec2 (fdiv(x,NX),fdiv(y,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY)));
1852 Slide.pushTriangle (glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y+1,NY)));
1855 Primitives_t aLeavingSlide;
1856 aLeavingSlide.push_back (Slide);
1857 Primitives_t aEnteringSlide;
1858 aEnteringSlide.push_back (Slide);
1860 TransitionSettings aSettings;
1861 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1862 aSettings.mnRequiredGLVersion = 3.2f;
1864 return makeVortexTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings, NX, NY);
1867 namespace
1870 class RippleTransition : public OGLTransitionImpl
1872 public:
1873 RippleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, const glm::vec2& rCenter)
1874 : OGLTransitionImpl(rScene, rSettings),
1875 maCenter(rCenter)
1879 private:
1880 virtual GLuint makeShader() const override;
1881 virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1882 virtual void prepare( double SlideWidth, double SlideHeight ) override;
1884 glm::vec2 maCenter;
1885 GLint maSlideRatioLocation = -1;
1888 GLuint RippleTransition::makeShader() const
1890 return OpenGLHelper::LoadShaders( u"basicVertexShader"_ustr, u"rippleFragmentShader"_ustr );
1893 void RippleTransition::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
1895 GLint nCenterLocation = glGetUniformLocation(m_nProgramObject, "center");
1896 CHECK_GL_ERROR();
1898 glUniform2fv(nCenterLocation, 1, glm::value_ptr(maCenter));
1899 CHECK_GL_ERROR();
1901 maSlideRatioLocation = glGetUniformLocation(m_nProgramObject, "slideRatio");
1902 CHECK_GL_ERROR();
1905 void RippleTransition::prepare( double SlideWidth, double SlideHeight )
1907 if( maSlideRatioLocation != -1 )
1908 glUniform1f( maSlideRatioLocation, SlideWidth / SlideHeight );
1911 std::shared_ptr<OGLTransitionImpl>
1912 makeRippleTransition(Primitives_t&& rLeavingSlidePrimitives,
1913 Primitives_t&& rEnteringSlidePrimitives,
1914 const TransitionSettings& rSettings)
1916 // The center point should be adjustable by the user, but we have no way to do that in the UI
1917 return std::make_shared<RippleTransition>(TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
1918 rSettings,
1919 glm::vec2(0.5, 0.5));
1924 std::shared_ptr<OGLTransitionImpl> makeRipple()
1926 Primitive Slide;
1928 Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1929 Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1931 Primitives_t aLeavingSlide;
1932 aLeavingSlide.push_back (Slide);
1934 Primitives_t aEnteringSlide;
1935 aEnteringSlide.push_back (Slide);
1937 TransitionSettings aSettings;
1938 aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1940 return makeRippleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
1943 static void createHexagon(Primitive& aHexagon, const int x, const int y, const int NX, const int NY)
1945 if (y % 4 == 0)
1947 aHexagon.pushTriangle(vec(x-1, y-1, NX, NY), vec(x, y-2, NX, NY), vec(x, y+0.5, NX, NY));
1948 aHexagon.pushTriangle(vec(x, y-2, NX, NY), vec(x+1, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1949 aHexagon.pushTriangle(vec(x+1, y-1, NX, NY), vec(x+1, y, NX, NY), vec(x, y+0.5, NX, NY));
1950 aHexagon.pushTriangle(vec(x+1, y, NX, NY), vec(x, y+1, NX, NY), vec(x, y+0.5, NX, NY));
1951 aHexagon.pushTriangle(vec(x, y+1, NX, NY), vec(x-1, y, NX, NY), vec(x, y+0.5, NX, NY));
1952 aHexagon.pushTriangle(vec(x-1, y, NX, NY), vec(x-1, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1954 else
1956 aHexagon.pushTriangle(vec(x-2, y-1, NX, NY), vec(x-1, y-2, NX, NY), vec(x, y+0.5, NX, NY));
1957 aHexagon.pushTriangle(vec(x-1, y-2, NX, NY), vec(x, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1958 aHexagon.pushTriangle(vec(x, y-1, NX, NY), vec(x, y, NX, NY), vec(x, y+0.5, NX, NY));
1959 aHexagon.pushTriangle(vec(x, y, NX, NY), vec(x-1, y+1, NX, NY), vec(x, y+0.5, NX, NY));
1960 aHexagon.pushTriangle(vec(x-1, y+1, NX, NY), vec(x-2, y, NX, NY), vec(x, y+0.5, NX, NY));
1961 aHexagon.pushTriangle(vec(x-2, y, NX, NY), vec(x-2, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1965 namespace
1968 class GlitterTransition : public PermTextureTransition
1970 public:
1971 GlitterTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1972 : PermTextureTransition(rScene, rSettings)
1976 private:
1977 virtual GLuint makeShader() const override;
1978 virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1979 virtual void cleanup() override;
1981 GLuint maBuffer = 0;
1984 GLuint GlitterTransition::makeShader() const
1986 return OpenGLHelper::LoadShaders( u"glitterVertexShader"_ustr, u"glitterFragmentShader"_ustr );
1989 struct ThreeFloats
1991 GLfloat x, y, z;
1994 void GlitterTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
1996 CHECK_GL_ERROR();
1997 PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
1998 CHECK_GL_ERROR();
2000 glGenBuffers(1, &maBuffer);
2001 glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
2003 // Upload the center of each hexagon.
2004 const Primitive& primitive = getScene().getLeavingSlide()[0];
2005 std::vector<ThreeFloats> vertices;
2006 for (int i = 2; i < primitive.getVerticesCount(); i += 18) {
2007 const glm::vec3& center = primitive.getVertex(i);
2008 for (int j = 0; j < 18; ++j)
2009 vertices.push_back({center.x, center.y, center.z});
2011 glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
2013 GLint location = glGetAttribLocation(m_nProgramObject, "center");
2014 if (location != -1) {
2015 glEnableVertexAttribArray(location);
2016 glVertexAttribPointer( location, 3, GL_FLOAT, false, 0, nullptr );
2017 CHECK_GL_ERROR();
2020 glBindBuffer(GL_ARRAY_BUFFER, 0);
2023 void GlitterTransition::cleanup()
2025 CHECK_GL_ERROR();
2026 glDeleteBuffers(1, &maBuffer);
2027 CHECK_GL_ERROR();
2030 std::shared_ptr<OGLTransitionImpl>
2031 makeGlitterTransition(Primitives_t&& rLeavingSlidePrimitives,
2032 Primitives_t&& rEnteringSlidePrimitives,
2033 const TransitionSettings& rSettings)
2035 return std::make_shared<GlitterTransition>(TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
2036 rSettings);
2041 std::shared_ptr<OGLTransitionImpl> makeGlitter()
2043 const int NX = 80;
2044 const int NY = NX * 4 / 3;
2046 Primitives_t aSlide;
2047 Primitives_t aEmptySlide;
2048 Primitive aHexagon;
2050 for (int y = 0; y < NY+2; y+=2)
2051 for (int x = 0; x < NX+2; x+=2)
2052 createHexagon(aHexagon, x, y, NX, NY);
2054 aSlide.push_back(aHexagon);
2056 return makeGlitterTransition(std::move(aSlide), std::move(aEmptySlide), TransitionSettings());
2059 namespace
2062 class HoneycombTransition : public PermTextureTransition
2064 public:
2065 HoneycombTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
2066 : PermTextureTransition(rScene, rSettings)
2068 mnDepthTextures[0] = 0;
2069 mnDepthTextures[1] = 0;
2072 private:
2073 virtual void finishTransition() override;
2074 virtual GLuint makeShader() const override;
2075 virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
2076 virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
2078 GLint maHexagonSizeLocation = -1;
2079 GLint maSelectedTextureLocation = -1;
2080 GLint mnShadowLocation = -1;
2081 GLuint mnFramebuffer = 0u;
2082 std::array<GLuint, 2> mnDepthTextures;
2085 void HoneycombTransition::finishTransition()
2087 PermTextureTransition::finishTransition();
2089 CHECK_GL_ERROR();
2090 glActiveTexture( GL_TEXTURE2 );
2091 glBindTexture( GL_TEXTURE_2D, 0 );
2092 glActiveTexture( GL_TEXTURE3 );
2093 glBindTexture( GL_TEXTURE_2D, 0 );
2094 glActiveTexture( GL_TEXTURE0 );
2095 CHECK_GL_ERROR();
2096 glDeleteTextures(2, mnDepthTextures.data());
2097 mnDepthTextures = {0u, 0u};
2098 CHECK_GL_ERROR();
2099 glDeleteFramebuffers(1, &mnFramebuffer);
2100 mnFramebuffer = 0u;
2101 CHECK_GL_ERROR();
2104 GLuint HoneycombTransition::makeShader() const
2106 return OpenGLHelper::LoadShaders( u"honeycombVertexShader"_ustr, u"honeycombFragmentShader"_ustr, u"honeycombGeometryShader"_ustr );
2109 void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
2111 CHECK_GL_ERROR();
2112 PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
2114 CHECK_GL_ERROR();
2115 maHexagonSizeLocation = glGetUniformLocation(m_nProgramObject, "hexagonSize");
2116 maSelectedTextureLocation = glGetUniformLocation( m_nProgramObject, "selectedTexture" );
2117 mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow");
2118 GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix");
2119 GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix");
2120 GLint location = glGetUniformLocation(m_nProgramObject, "colorShadowTexture");
2121 glUniform1i(location, 2);
2122 location = glGetUniformLocation(m_nProgramObject, "depthShadowTexture");
2123 glUniform1i(location, 3);
2124 CHECK_GL_ERROR();
2126 // We want to see the entering slide behind the leaving one.
2127 glEnable(GL_BLEND);
2128 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2129 CHECK_GL_ERROR();
2131 double EyePos(10.0);
2132 double const RealF(1.0);
2133 double const RealN(-1.0);
2134 double const RealL(-4.0);
2135 double RealR(4.0);
2136 double const RealB(-4.0);
2137 double RealT(4.0);
2138 double ClipN(EyePos+5.0*RealN);
2139 double ClipF(EyePos+15.0*RealF);
2140 double ClipL(RealL*8.0);
2141 double ClipR(RealR*8.0);
2142 double ClipB(RealB*8.0);
2143 double ClipT(RealT*8.0);
2145 glm::mat4 projection = glm::ortho<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
2146 //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
2147 glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
2148 1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
2149 1.0);
2150 projection = glm::scale(projection, scale);
2151 glUniformMatrix4fv(nOrthoProjectionMatrix, 1, false, glm::value_ptr(projection));
2153 glm::mat4 view = lookAt(glm::vec3(0, 0, EyePos), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
2154 glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view));
2156 // Generate the framebuffer and textures for the shadows.
2157 glGenTextures(2, mnDepthTextures.data());
2158 glActiveTexture(GL_TEXTURE2);
2159 glBindTexture(GL_TEXTURE_2D, mnDepthTextures[0]);
2160 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2048, 2048, 0, GL_RGBA, GL_FLOAT, nullptr);
2161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2166 glActiveTexture(GL_TEXTURE3);
2167 glBindTexture(GL_TEXTURE_2D, mnDepthTextures[1]);
2168 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
2169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2174 glActiveTexture(GL_TEXTURE0);
2175 glGenFramebuffers(1, &mnFramebuffer);
2176 glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffer);
2177 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mnDepthTextures[0], 0);
2178 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[1], 0);
2180 // Always check that our framebuffer is ok
2181 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
2182 SAL_WARN("slideshow.opengl", "Wrong framebuffer!");
2183 return;
2186 pContext->restoreDefaultFramebuffer();
2189 void HoneycombTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
2190 double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext )
2192 CHECK_GL_ERROR();
2193 applyOverallOperations(nTime, SlideWidthScale, SlideHeightScale);
2194 glUniform1f(m_nTimeLocation, nTime);
2195 glUniform1f(mnShadowLocation, 1.0);
2196 CHECK_GL_ERROR();
2198 const float borderSize = 0.15f;
2200 std::array<GLint, 4> viewport;
2201 glGetIntegerv(GL_VIEWPORT, viewport.data());
2202 glViewport(0, 0, 2048, 2048);
2203 glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffer);
2204 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2205 glUniform1f(mnShadowLocation, 1.0);
2206 glUniform1f(maSelectedTextureLocation, 1.0);
2207 glUniform1f(maHexagonSizeLocation, 1.0f - borderSize);
2208 displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2209 glUniform1f(maHexagonSizeLocation, 1.0f + borderSize);
2210 displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2212 // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work.
2213 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
2214 pContext->restoreDefaultFramebuffer();
2215 glUniform1f(mnShadowLocation, 0.0);
2216 glUniform1f(maSelectedTextureLocation, 0.0);
2217 glUniform1f(maHexagonSizeLocation, 1.0f - borderSize);
2218 displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale);
2219 glUniform1f(maHexagonSizeLocation, 1.0f + borderSize);
2220 displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale);
2221 glUniform1f(maSelectedTextureLocation, 1.0);
2222 glUniform1f(maHexagonSizeLocation, 1.0f - borderSize);
2223 displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2224 glUniform1f(maHexagonSizeLocation, 1.0f + borderSize);
2225 displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2226 CHECK_GL_ERROR();
2229 std::shared_ptr<OGLTransitionImpl>
2230 makeHoneycombTransition(Primitives_t&& rLeavingSlidePrimitives,
2231 Primitives_t&& rEnteringSlidePrimitives,
2232 const TransitionSettings& rSettings)
2234 // The center point should be adjustable by the user, but we have no way to do that in the UI
2235 return std::make_shared<HoneycombTransition>(TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
2236 rSettings);
2241 std::shared_ptr<OGLTransitionImpl> makeHoneycomb()
2243 const int NX = 21;
2244 const int NY = 21;
2246 TransitionSettings aSettings;
2247 aSettings.mnRequiredGLVersion = 3.2f;
2249 Primitives_t aSlide;
2250 Primitive aHexagon;
2251 for (int y = 0; y < NY+2; y+=2)
2252 for (int x = 0; x < NX+2; x+=2)
2253 aHexagon.pushTriangle(glm::vec2((y % 4) ? fdiv(x, NX) : fdiv(x + 1, NX), fdiv(y, NY)), glm::vec2(1, 0), glm::vec2(0, 0));
2254 aSlide.push_back(aHexagon);
2256 return makeHoneycombTransition(std::vector(aSlide), std::vector(aSlide), aSettings);
2259 std::shared_ptr<OGLTransitionImpl> makeNewsflash()
2261 Primitive Slide;
2263 Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
2264 Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
2265 Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),3000,true,0,0.5));
2266 Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),true,0,0.5));
2267 Slide.Operations.push_back(makeSTranslate(glm::vec3(-10000, 0, 0),false, 0.5, 2));
2268 Primitives_t aLeavingSlide;
2269 aLeavingSlide.push_back(Slide);
2271 Slide.Operations.clear();
2272 Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),-3000,true,0.5,1));
2273 Slide.Operations.push_back(makeSTranslate(glm::vec3(-100, 0, 0),false, -1, 1));
2274 Slide.Operations.push_back(makeSTranslate(glm::vec3(100, 0, 0),false, 0.5, 1));
2275 Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),false,-1,1));
2276 Slide.Operations.push_back(makeSScale(glm::vec3(100,100,100),glm::vec3(0,0,0),true,0.5,1));
2277 Primitives_t aEnteringSlide;
2278 aEnteringSlide.push_back(Slide);
2280 Operations_t aOverallOperations;
2281 aOverallOperations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0.2,0.2,0),1080,true,0,1));
2283 return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), std::move(aOverallOperations));
2286 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */