From 3e29fd4373e5895454594d77a81fed2820826457 Mon Sep 17 00:00:00 2001 From: Ivan Pelipenko Date: Tue, 25 Aug 2020 21:57:31 +0300 Subject: [PATCH] initial commit --- .gitignore | 2 + AUTHORS.txt | 2 + CMakeLists.txt | 55 + LICENSE.txt | 165 ++ coeffs_brdf.png | Bin 0 -> 32788 bytes core/glbuffer.cpp | 88 + core/glbuffer.h | 58 + core/glcubemap.cpp | 281 ++++ core/glcubemap.h | 67 + core/glframebuffer.cpp | 315 ++++ core/glframebuffer.h | 89 ++ core/glframebuffer_mipmap.cpp | 50 + core/glframebuffer_mipmap.h | 50 + core/glmaterial.cpp | 151 ++ core/glmaterial.h | 124 ++ core/glmesh.cpp | 426 +++++ core/glmesh.h | 110 ++ core/glprimitives.cpp | 437 +++++ core/glprimitives.h | 104 ++ core/glshaders.cpp | 146 ++ core/glshaders.h | 31 + core/glshaders_headers.h | 127 ++ core/glshaders_types.cpp | 97 ++ core/glshaders_types.h | 144 ++ core/gltexturearray.cpp | 96 ++ core/gltexturearray.h | 56 + core/gltransform.cpp | 441 +++++ core/gltransform.h | 119 ++ core/gltypes.cpp | 373 +++++ core/gltypes.h | 303 ++++ core/glvertexobject.cpp | 119 ++ core/glvertexobject.h | 64 + core/hdr.cpp | 125 ++ core/hdr_p.h | 26 + core/qglengine_version.h | 27 + formats/loader_assimp.cpp | 267 ++++ formats/loader_assimp.h | 27 + formats/loader_qgl.cpp | 67 + formats/loader_qgl.h | 28 + glcamera.cpp | 110 ++ glcamera.h | 70 + globject.cpp | 717 +++++++++ globject.h | 313 ++++ glrendererbase.cpp | 294 ++++ glrendererbase.h | 80 + glscene.cpp | 540 +++++++ glscene.h | 146 ++ gltexture_manager.cpp | 201 +++ gltexture_manager.h | 65 + glwidget.cpp | 240 +++ glwidget.h | 104 ++ icons/add-type-camera.png | Bin 0 -> 14827 bytes icons/add-type-empty.png | Bin 0 -> 10989 bytes icons/add-type-geo.png | Bin 0 -> 10226 bytes icons/add-type-light.png | Bin 0 -> 14284 bytes icons/alpha.png | Bin 0 -> 158 bytes icons/application-exit.png | Bin 0 -> 32537 bytes icons/collapse.png | Bin 0 -> 13144 bytes icons/configure.png | Bin 0 -> 32993 bytes icons/dialog-cancel.png | Bin 0 -> 45200 bytes icons/dialog-close.png | Bin 0 -> 39321 bytes icons/document-edit.png | Bin 0 -> 30106 bytes icons/document-import.png | Bin 0 -> 16611 bytes icons/document-new.png | Bin 0 -> 24844 bytes icons/document-open.png | Bin 0 -> 8621 bytes icons/document-save-all.png | Bin 0 -> 26721 bytes icons/document-save.png | Bin 0 -> 22676 bytes icons/edit-clear-locationbar-rtl.png | Bin 0 -> 20226 bytes icons/edit-clear.png | Bin 0 -> 54801 bytes icons/edit-copy.png | Bin 0 -> 14072 bytes icons/edit-delete.png | Bin 0 -> 22776 bytes icons/edit-find.png | Bin 0 -> 43469 bytes icons/edit-paste.png | Bin 0 -> 14413 bytes icons/edit-rename.png | Bin 0 -> 4859 bytes icons/expand.png | Bin 0 -> 14692 bytes icons/format-fill-color.png | Bin 0 -> 44130 bytes icons/go-jump.png | Bin 0 -> 7200 bytes icons/go-top.png | Bin 0 -> 31581 bytes icons/group.png | Bin 0 -> 12826 bytes icons/layer-visible-off.png | Bin 0 -> 53079 bytes icons/layer-visible-on.png | Bin 0 -> 49905 bytes icons/light-+.png | Bin 0 -> 16851 bytes icons/list-add.png | Bin 0 -> 35372 bytes icons/object-flip-horizontal.png | Bin 0 -> 25165 bytes icons/object-flip-vertical.png | Bin 0 -> 22264 bytes icons/picker.png | Bin 0 -> 26844 bytes icons/qglview.png | Bin 0 -> 82318 bytes icons/qglview.xcf | Bin 0 -> 170453 bytes icons/transform-move.png | Bin 0 -> 24712 bytes icons/transform-rotate.png | Bin 0 -> 20621 bytes icons/transform-scale.png | Bin 0 -> 8092 bytes icons/type-camera.png | Bin 0 -> 33163 bytes icons/type-empty.png | Bin 0 -> 2071 bytes icons/type-geo.png | Bin 0 -> 5538 bytes icons/type-light.png | Bin 0 -> 2899 bytes icons/view-refresh.png | Bin 0 -> 40505 bytes mouse_controller.cpp | 289 ++++ mouse_controller.h | 84 + openglwindow.cpp | 113 ++ openglwindow.h | 54 + plugin/CMakeLists.txt | 18 + plugin/qglview_designerplugin.cpp | 14 + plugin/qglview_designerplugin.h | 22 + plugin/qglviewplugin.cpp | 95 ++ plugin/qglviewplugin.h | 33 + qglview.cpp | 299 ++++ qglview.h | 293 ++++ qglview.qrc | 46 + qglview_test/main.cpp | 34 + qglview_test/qglview_window.cpp | 251 +++ qglview_test/qglview_window.h | 119 ++ qglview_test/qglview_window.ui | 978 +++++++++++ renderer.cpp | 382 +++++ renderer.h | 136 ++ renderer_base.cpp | 442 +++++ renderer_base.h | 68 + renderer_material.cpp | 132 ++ renderer_material.h | 54 + renderer_selection.cpp | 218 +++ renderer_selection.h | 68 + renderer_service.cpp | 490 ++++++ renderer_service.h | 108 ++ shaders.qrc | 19 + shaders/ds_final.glsl | 22 + shaders/ds_geom.glsl | 71 + shaders/ds_light.glsl | 181 +++ shaders/ds_tonemap.glsl | 25 + shaders/fxaa.frag | 2223 ++++++++++++++++++++++++++ shaders/fxaa.vert | 11 + shaders/fxaa_v3.h | 2048 ++++++++++++++++++++++++ shaders/selection.glsl | 19 + shaders/selection_apply.glsl | 25 + shaders/selection_frame.glsl | 24 + shaders/selection_halo.glsl | 42 + shaders/service_fill.glsl | 24 + shaders/service_frame.glsl | 51 + shaders/service_line.glsl | 17 + shaders/sum.glsl | 25 + tonemapping_proc.cpp | 186 +++ tonemapping_proc.h | 66 + widgets/CMakeLists.txt | 26 + widgets/material_editor.cpp | 237 +++ widgets/material_editor.h | 67 + widgets/material_editor.ui | 637 ++++++++ widgets/material_map_editor.cpp | 150 ++ widgets/material_map_editor.h | 60 + widgets/material_map_editor.ui | 506 ++++++ widgets/materials_editor.cpp | 207 +++ widgets/materials_editor.h | 66 + widgets/materials_editor.ui | 251 +++ widgets/object_editor.cpp | 268 ++++ widgets/object_editor.h | 62 + widgets/object_editor.ui | 782 +++++++++ widgets/primitiveeditor.cpp | 259 +++ widgets/primitiveeditor.h | 68 + widgets/primitiveeditor.ui | 597 +++++++ widgets/propertyeditor.cpp | 426 +++++ widgets/propertyeditor.h | 95 ++ widgets/scene_tree.cpp | 504 ++++++ widgets/scene_tree.h | 100 ++ widgets/scene_tree.ui | 425 +++++ widgets/treewidget_p.h | 51 + widgets/view_editor.cpp | 179 +++ widgets/view_editor.h | 67 + widgets/view_editor.ui | 511 ++++++ widgets/widgets.qrc | 18 + 166 files changed, 24675 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS.txt create mode 100644 CMakeLists.txt create mode 100644 LICENSE.txt create mode 100644 coeffs_brdf.png create mode 100644 core/glbuffer.cpp create mode 100644 core/glbuffer.h create mode 100644 core/glcubemap.cpp create mode 100644 core/glcubemap.h create mode 100644 core/glframebuffer.cpp create mode 100644 core/glframebuffer.h create mode 100644 core/glframebuffer_mipmap.cpp create mode 100644 core/glframebuffer_mipmap.h create mode 100644 core/glmaterial.cpp create mode 100644 core/glmaterial.h create mode 100644 core/glmesh.cpp create mode 100644 core/glmesh.h create mode 100644 core/glprimitives.cpp create mode 100644 core/glprimitives.h create mode 100644 core/glshaders.cpp create mode 100644 core/glshaders.h create mode 100644 core/glshaders_headers.h create mode 100644 core/glshaders_types.cpp create mode 100644 core/glshaders_types.h create mode 100644 core/gltexturearray.cpp create mode 100644 core/gltexturearray.h create mode 100644 core/gltransform.cpp create mode 100644 core/gltransform.h create mode 100644 core/gltypes.cpp create mode 100644 core/gltypes.h create mode 100644 core/glvertexobject.cpp create mode 100644 core/glvertexobject.h create mode 100644 core/hdr.cpp create mode 100644 core/hdr_p.h create mode 100644 core/qglengine_version.h create mode 100644 formats/loader_assimp.cpp create mode 100644 formats/loader_assimp.h create mode 100644 formats/loader_qgl.cpp create mode 100644 formats/loader_qgl.h create mode 100644 glcamera.cpp create mode 100644 glcamera.h create mode 100644 globject.cpp create mode 100644 globject.h create mode 100644 glrendererbase.cpp create mode 100644 glrendererbase.h create mode 100644 glscene.cpp create mode 100644 glscene.h create mode 100644 gltexture_manager.cpp create mode 100644 gltexture_manager.h create mode 100644 glwidget.cpp create mode 100644 glwidget.h create mode 100644 icons/add-type-camera.png create mode 100644 icons/add-type-empty.png create mode 100644 icons/add-type-geo.png create mode 100644 icons/add-type-light.png create mode 100644 icons/alpha.png create mode 100644 icons/application-exit.png create mode 100644 icons/collapse.png create mode 100644 icons/configure.png create mode 100644 icons/dialog-cancel.png create mode 100644 icons/dialog-close.png create mode 100644 icons/document-edit.png create mode 100644 icons/document-import.png create mode 100644 icons/document-new.png create mode 100644 icons/document-open.png create mode 100644 icons/document-save-all.png create mode 100644 icons/document-save.png create mode 100644 icons/edit-clear-locationbar-rtl.png create mode 100644 icons/edit-clear.png create mode 100644 icons/edit-copy.png create mode 100644 icons/edit-delete.png create mode 100644 icons/edit-find.png create mode 100644 icons/edit-paste.png create mode 100644 icons/edit-rename.png create mode 100644 icons/expand.png create mode 100644 icons/format-fill-color.png create mode 100644 icons/go-jump.png create mode 100644 icons/go-top.png create mode 100644 icons/group.png create mode 100644 icons/layer-visible-off.png create mode 100644 icons/layer-visible-on.png create mode 100644 icons/light-+.png create mode 100644 icons/list-add.png create mode 100644 icons/object-flip-horizontal.png create mode 100644 icons/object-flip-vertical.png create mode 100644 icons/picker.png create mode 100644 icons/qglview.png create mode 100644 icons/qglview.xcf create mode 100644 icons/transform-move.png create mode 100644 icons/transform-rotate.png create mode 100644 icons/transform-scale.png create mode 100644 icons/type-camera.png create mode 100644 icons/type-empty.png create mode 100644 icons/type-geo.png create mode 100644 icons/type-light.png create mode 100644 icons/view-refresh.png create mode 100644 mouse_controller.cpp create mode 100644 mouse_controller.h create mode 100644 openglwindow.cpp create mode 100644 openglwindow.h create mode 100644 plugin/CMakeLists.txt create mode 100644 plugin/qglview_designerplugin.cpp create mode 100644 plugin/qglview_designerplugin.h create mode 100644 plugin/qglviewplugin.cpp create mode 100644 plugin/qglviewplugin.h create mode 100644 qglview.cpp create mode 100644 qglview.h create mode 100644 qglview.qrc create mode 100644 qglview_test/main.cpp create mode 100644 qglview_test/qglview_window.cpp create mode 100644 qglview_test/qglview_window.h create mode 100644 qglview_test/qglview_window.ui create mode 100644 renderer.cpp create mode 100644 renderer.h create mode 100644 renderer_base.cpp create mode 100644 renderer_base.h create mode 100644 renderer_material.cpp create mode 100644 renderer_material.h create mode 100644 renderer_selection.cpp create mode 100644 renderer_selection.h create mode 100644 renderer_service.cpp create mode 100644 renderer_service.h create mode 100644 shaders.qrc create mode 100644 shaders/ds_final.glsl create mode 100644 shaders/ds_geom.glsl create mode 100644 shaders/ds_light.glsl create mode 100644 shaders/ds_tonemap.glsl create mode 100644 shaders/fxaa.frag create mode 100644 shaders/fxaa.vert create mode 100644 shaders/fxaa_v3.h create mode 100644 shaders/selection.glsl create mode 100644 shaders/selection_apply.glsl create mode 100644 shaders/selection_frame.glsl create mode 100644 shaders/selection_halo.glsl create mode 100644 shaders/service_fill.glsl create mode 100644 shaders/service_frame.glsl create mode 100644 shaders/service_line.glsl create mode 100644 shaders/sum.glsl create mode 100644 tonemapping_proc.cpp create mode 100644 tonemapping_proc.h create mode 100644 widgets/CMakeLists.txt create mode 100644 widgets/material_editor.cpp create mode 100644 widgets/material_editor.h create mode 100644 widgets/material_editor.ui create mode 100644 widgets/material_map_editor.cpp create mode 100644 widgets/material_map_editor.h create mode 100644 widgets/material_map_editor.ui create mode 100644 widgets/materials_editor.cpp create mode 100644 widgets/materials_editor.h create mode 100644 widgets/materials_editor.ui create mode 100644 widgets/object_editor.cpp create mode 100644 widgets/object_editor.h create mode 100644 widgets/object_editor.ui create mode 100644 widgets/primitiveeditor.cpp create mode 100644 widgets/primitiveeditor.h create mode 100644 widgets/primitiveeditor.ui create mode 100644 widgets/propertyeditor.cpp create mode 100644 widgets/propertyeditor.h create mode 100644 widgets/scene_tree.cpp create mode 100644 widgets/scene_tree.h create mode 100644 widgets/scene_tree.ui create mode 100644 widgets/treewidget_p.h create mode 100644 widgets/view_editor.cpp create mode 100644 widgets/view_editor.h create mode 100644 widgets/view_editor.ui create mode 100644 widgets/widgets.qrc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a2cb3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.svn +CMakeLists.txt.user* diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..7dd5dfb --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,2 @@ +peri4 = Пелипенко Иван +andrey = Бычков Андрей diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d852ec4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.0) +project(qglengine) +find_package(QAD REQUIRED) +set(_DOMAIN "org.SHS") +set(_COMPANY "SHS") +find_qt(Qt5 Core Gui OpenGL Xml) +if (NOT Qt5) + message(WARNING "Building ${PROJECT_NAME} available only on Qt5!") +else() + find_package(OpenGL REQUIRED) + set_version(qglengine + MAJOR 1 + MINOR 0 + REVISION 0 + BUILD "${BUILD_NUMBER}" + SUFFIX rc + OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/core/qglengine_version.h") + + qt_sources(SRC) + qt_sources(FSRC DIR "formats") + list(APPEND SRC ${FSRC}) + qt_sources(FSRC DIR "core") + list(APPEND SRC ${FSRC}) + qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM) + file(GLOB PHS "*_p.h" "formats/*_p.h" "core/*_p.h") + list(REMOVE_ITEM out_HDR "${PHS}") + import_version(qglengine_core qglengine) + set_deploy_property(qglengine_core SHARED + LABEL "QGLEngine core library" + FULLNAME "${_DOMAIN}.qglengine_core" + COMPANY "${_COMPANY}" + INFO "QGLEngine core library") + make_rc(qglengine_core _RC) + qt_add_library(qglengine_core SHARED out_CPP ${_RC}) + qt_generate_export_header(qglengine_core) + list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/qglengine_core_export.h") + qt_target_include_directories(qglengine_core PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core") + qt_target_link_libraries(qglengine_core qad_utils qad_widgets assimp ${OPENGL_LIBRARIES}) + message(STATUS "Building QGLEngine version ${qglengine_VERSION} (SHARED)") + list(APPEND QT_MULTILIB_LIST qglengine_core) + add_subdirectory(widgets) + copy_to_parent("") + sdk_install("qglengine" FALSE "qglengine_core" "${out_HDR}" "${out_QM}") + if (NOT DEFINED ANDROID_PLATFORM) + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin") + #add_subdirectory(plugin) + endif() + endif() + + qt_sources(test_SRC DIR "qglview_test") + qt_wrap(${test_SRC} CPPS test_CPP) + qt_add_executable(qglengine_test test_CPP) + qt_target_link_libraries(qglengine_test qglengine_core qglengine_widgets) + qt_target_include_directories(qglengine_test PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core" "${CMAKE_CURRENT_SOURCE_DIR}/widgets") +endif() diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/coeffs_brdf.png b/coeffs_brdf.png new file mode 100644 index 0000000000000000000000000000000000000000..ec34d285dc6b032aeb6e469d9eb91ae8d8438449 GIT binary patch literal 32788 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�m$5COulAtSlazvyA z%1R-r1KZrrJAJZj7w`cm;9-IaDV65If`<{{kV-ngoRu_Jk z@lXB<{Qjm^0oEnA=Mz%F@g(4LRQ>r&<1hR&W3-Mt%L;zvIKLlQkAC@0f05;^cmdhz$K^zYa2FK#tp{g*I;a6)$+&-=yW(eifmHvZwx(%+T*`!xhu z|NWo;tu{6vAF*=el;%^9d{|fISo^Qbzg=yQ_!fR4?Dxz0^*@MS|LdRs_5aKN^AFJm z`jh{+ZS;p}BYH9Y*$xjp@)=+tY_#q42l@YQgq{BEwC%LLPk2AxY5PN9`t$G4Kf$!6 zkKgB<50Zn#*Ks5daJ=NbN12`g{`|M?g!3SMx*az. +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "glbuffer.h" + + +Buffer::Buffer(GLenum target, GLenum _usage) { + target_ = target; + usage_ = _usage; + buffer_ = 0; + prev_size = 0; +} + + +Buffer::~Buffer() { +} + + +void Buffer::init(QOpenGLExtraFunctions * f) { + if (!isInit()) { + f->glGenBuffers(1, &buffer_); + } +} + + +void Buffer::destroy(QOpenGLExtraFunctions * f) { + if (buffer_ != 0) { + f->glDeleteBuffers(1, &buffer_); + } + buffer_ = 0; +} + + +void Buffer::bind(QOpenGLExtraFunctions * f) { + //qDebug() << "bind" << target_ << buffer_; + f->glBindBuffer(target_, buffer_); +} + + +void Buffer::release(QOpenGLExtraFunctions * f) { + f->glBindBuffer(target_, 0); +} + + +void * Buffer::map(QOpenGLExtraFunctions * f, GLbitfield mode, int size) { + if (size < 0) size = prev_size; + return f->glMapBufferRange(target_, 0, size, mode); +} + + +void Buffer::unmap(QOpenGLExtraFunctions * f) { + f->glUnmapBuffer(target_); +} + + +bool Buffer::resize(QOpenGLExtraFunctions * f, int new_size) { + if (new_size <= 0) return false; + //qDebug() << "check resize buffer" << buffer_ << "bytes" << new_size << ", old =" << prev_size; + if (new_size <= prev_size) return false; + prev_size = new_size; + //qDebug() << "resize buffer " << buffer_ << target_ << "for" << new_size << "bytes"; + f->glBufferData(target_, new_size, 0, usage_); + return true; +} + + +void Buffer::load(QOpenGLExtraFunctions * f, const void * data, int size, int offset) { + if (!data || size <= 0) return; + //qDebug() << "load buffer" << buffer_ << "bytes" << size; + f->glBufferSubData(target_, offset, size, data); +} diff --git a/core/glbuffer.h b/core/glbuffer.h new file mode 100644 index 0000000..2cf4c5f --- /dev/null +++ b/core/glbuffer.h @@ -0,0 +1,58 @@ +/* + QGL Buffer + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLBUFFER_H +#define GLBUFFER_H + +#include "gltypes.h" + + +class Buffer +{ + friend class ObjectBase; +public: + Buffer(GLenum target, GLenum usage = GL_DYNAMIC_DRAW); + ~Buffer(); + + void init (QOpenGLExtraFunctions * f); + void destroy (QOpenGLExtraFunctions * f); + + void bind (QOpenGLExtraFunctions * f); + void release (QOpenGLExtraFunctions * f); + void * map (QOpenGLExtraFunctions * f, GLbitfield mode, int size = -1); + void unmap (QOpenGLExtraFunctions * f); + + // returns true if size changed + bool resize (QOpenGLExtraFunctions * f, int new_size); + void load (QOpenGLExtraFunctions * f, const void * data, int size, int offset = 0); + + GLuint ID() const {return buffer_;} + GLenum usage() const {return usage_;} + GLenum target() const {return target_;} + void setTarget(GLenum t) {target_ = t;} + bool isInit() const {return buffer_ != 0;} + +private: + GLenum target_, usage_; + GLuint buffer_; + int prev_size; + +}; + + +#endif // GLBUFFER_H diff --git a/core/glcubemap.cpp b/core/glcubemap.cpp new file mode 100644 index 0000000..19b8750 --- /dev/null +++ b/core/glcubemap.cpp @@ -0,0 +1,281 @@ +/* + QGL CubeTexture + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "gltypes.h" +#include "glcubemap.h" +#include "hdr_p.h" + +using namespace QGLEngineShaders; + + +QVector loadFileHDR(const QString & path, QSize * size) { + if (size) *size = QSize(); + QVector ret; + QFile f(path); + if (!f.open(QIODevice::ReadOnly)) { + qDebug() << "[QGLEngine] Can`t open" << path; + return ret; + } + QTextStream ts(&f); + QString line = ts.readLine(256); + if (line != "#?RADIANCE") return ret; + QSize sz; + while (!ts.atEnd()) { + line = ts.readLine(256); + if (line.startsWith("FORMAT")) { + line.remove(0, 7); + if (!line.startsWith("32-bit")) { + qDebug() << "[QGLEngine] File" << path << "has unknown format!"; + return ret; + } + } + if (line.mid(1, 2) == "Y ") { + QStringList sl = line.trimmed().split(" "); + sl.removeAll(""); + if (sl.size() != 4) { + qDebug() << "[QGLEngine] File" << path << "has unknown size!"; + return ret; + } + sz.setWidth (sl[3].toInt()); + sz.setHeight(sl[1].toInt()); + //qDebug() << "found size" << sz; + break; + } + } + if (sz.isEmpty()) return ret; + f.seek(ts.pos()); + QDataStream ds(&f); + int count = sz.width() * sz.height(); + QVector data(count*3); + if (!RGBE_ReadPixels_RLE(&ds, data.data(), sz.width(), sz.height())) + return ret; + + if (size) *size = sz; + ret.resize(count); + //QColor col; + //QImage im(sz, QImage::Format_ARGB32); + //QRgb * imdata = (QRgb*)im.bits(); + for (int i = 0; i < count; ++i) { + QVector3D p(pow(data[i*3 + 2], 1. / 2.2), + pow(data[i*3 + 1], 1. / 2.2), + pow(data[i*3 + 0], 1. / 2.2)); + ret[i] = p; + //col = QColor::fromRgbF(piClamp(p[0], 0.f, 1.f), + // piClamp(p[1], 0.f, 1.f), + // piClamp(p[2], 0.f, 1.f)); + //imdata[i] = col.rgb(); + } + //im.save("_hdr.png"); + + return ret; +} + + +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +QVector faceHDR(const QVector & data, QSize sz, QSize & fsz, int face) { + QVector ret; + if (data.isEmpty() || sz.isNull()) return ret; + QRect fr; + int fw = sz.width () / 4; + int fh = sz.height() / 3; + fsz = QSize(fw, fh); + ret.reserve(fw * fh); + switch (face) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + fr.setRect(fw, fh, fw, fh); + for (int x = fr.left(); x <= fr.right(); ++x) { + for (int y = fr.top(); y <= fr.bottom(); ++y) { + ret << data[y*sz.width() + x]; + } + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + fr.setRect(fw*3, fh, fw, fh); + for (int x = fr.right(); x >= fr.left(); --x) { + for (int y = fr.bottom(); y >= fr.top(); --y) { + ret << data[y*sz.width() + x]; + } + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + fr.setRect( 0, fh, fw, fh); + for (int y = fr.bottom(); y >= fr.top(); --y) { + for (int x = fr.left(); x <= fr.right(); ++x) { + ret << data[y*sz.width() + x]; + } + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + fr.setRect(fw*2, fh, fw, fh); + for (int y = fr.top(); y <= fr.bottom(); ++y) { + for (int x = fr.right(); x >= fr.left(); --x) { + ret << data[y*sz.width() + x]; + } + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + fr.setRect(fw, 0, fw, fh); + for (int x = fr.left(); x <= fr.right(); ++x) { + for (int y = fr.top(); y <= fr.bottom(); ++y) { + ret << data[y*sz.width() + x]; + } + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + fr.setRect(fw, fh*2, fw, fh); + for (int x = fr.left(); x <= fr.right(); ++x) { + for (int y = fr.top(); y <= fr.bottom(); ++y) { + ret << data[y*sz.width() + x]; + } + } + break; + default: break; + } + if (fr.isEmpty()) return ret; + //qDebug() << ret.size() << fr; + return ret; +} + + + +CubeTexture::CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format): f(f_) { + size = _size; + format_ = _format; + id_ = 0; + changed_ = false; +} + + +bool CubeTexture::init() { + if (isInit()) return true; + f->glGenTextures(1, &id_); + f->glBindTexture(GL_TEXTURE_CUBE_MAP, id_); + f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + //glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + changed_ = false; + return id_ > 0; +} + + +void CubeTexture::destroy() { + if (!isInit()) return; + f->glDeleteTextures(1, &id_); + id_ = 0; +} + + +void CubeTexture::bind(int channel) { + init(); + f->glActiveTexture(GL_TEXTURE0 + channel); + f->glBindTexture(GL_TEXTURE_CUBE_MAP, id_); +} + + +void CubeTexture::release() { + f->glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + + +void CubeTexture::loadHDR(const QVector & data, QSize sz) { + bind(); + QSize fsz; + QVector fd; + for (int i = 0; i < 6; ++i) { + fd = faceHDR(data, sz, fsz, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); + //qDebug() << "load cube" << fd[0]; + //f->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + f->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format_, fsz.width(), fsz.height(), 0, GL_RGB, GL_FLOAT, fd.isEmpty() ? 0 : fd.constData()); + //qDebug() << QString::number(GetLastError(), 16); + } + f->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); +} + + +void CubeTexture::setFileHDR(const QString & path) { + hdr_path = path; + changed_ = true; +} + + +void CubeTexture::load() { + if (!changed_) return; + init(); + if (!hdr_path.isEmpty()) { + QSize sz; + QVector data = loadFileHDR(hdr_path, &sz); + loadHDR(data, sz); + } else { + destroy(); + bind(); + for (int i = 0; i < 6; ++i) { + f->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format_, 1, 1, 0, GL_RGB, GL_FLOAT, 0); + } + f->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + } + changed_ = false; +} + +/* +void CubeTexture::load() { + if (isEmpty()) return; + create(); + if (!path(0).isEmpty()) loadFront(path(0)); + if (!path(1).isEmpty()) loadBack(path(1)); + if (!path(2).isEmpty()) loadLeft(path(2)); + if (!path(3).isEmpty()) loadRight(path(3)); + if (!path(4).isEmpty()) loadTop(path(4)); + if (!path(5).isEmpty()) loadBottom(path(5)); +} + + +void CubeTexture::loadFromDirectory(const QString & dir) { + QDir d(dir); QFileInfoList sl; + sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadFront(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBack(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadLeft(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadRight(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadTop(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBottom(sl[0].absoluteFilePath()); +} + + +void CubeTexture::loadPathesFromDirectory(const QString & dir) { + QDir d(dir); QFileInfoList sl; + sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[0] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[1] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[2] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[3] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[4] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[5] = sl[0].absoluteFilePath(); +} +*/ diff --git a/core/glcubemap.h b/core/glcubemap.h new file mode 100644 index 0000000..6f5ed5d --- /dev/null +++ b/core/glcubemap.h @@ -0,0 +1,67 @@ +/* + QGL CubeTexture + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLCUBEMAP_H +#define GLCUBEMAP_H + +#include "glshaders_types.h" +#include "chunkstream.h" + +QVector loadFileHDR(const QString & path, QSize * size = 0); + +class CubeTexture { +public: + CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format = GL_RGB16F); + bool init(); + void destroy(); + void bind(int channel = 0); + void release(); + void resize(int _size) {size = _size; changed_ = true;} + void loadHDR(const QVector & data, QSize sz); + void setFileHDR(const QString & path); + QString fileHDR() const {return hdr_path;} + //void loadFromDirectory(const QString & dir); + //void loadFront(const QString & path) {bind(); pathes[0] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_X);} + //void loadBack(const QString & path) {bind(); pathes[1] = path; createGLTexture(id_, rotateQImageRight(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);} + //void loadLeft(const QString & path) {bind(); pathes[2] = path; createGLTexture(id_, QImage(path).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);} + //void loadRight(const QString & path) {bind(); pathes[3] = path; createGLTexture(id_, rotateQImage180(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);} + //void loadTop(const QString & path) {bind(); pathes[4] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);} + //void loadBottom(const QString & path) {bind(); pathes[5] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);} + //void load(); + //bool isEmpty() const {foreach (const QString & i, pathes) if (!i.isEmpty()) return false; return true;} + GLenum format() const {return format_;} + void setFormat(GLenum f) {format_ = f; changed_ = true;} + GLuint id() const {return id_;} + bool isInit() const {return id_ != 0;} + //const QString & path(int side) const {return pathes[side];} + //void setPath(int side, const QString & p) {pathes[side] = p;} + //void loadPathesFromDirectory(const QString & dir); + void load(); +private: + + QOpenGLExtraFunctions * f; + bool changed_; + int size; + GLenum format_; + GLuint id_; + QString hdr_path; + //QVector pathes; +}; + + +#endif // GLCUBEMAP_H diff --git a/core/glframebuffer.cpp b/core/glframebuffer.cpp new file mode 100644 index 0000000..88e5c92 --- /dev/null +++ b/core/glframebuffer.cpp @@ -0,0 +1,315 @@ +/* + QGL Framebuffer + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include +#include "glframebuffer.h" +#include + + +Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments_, bool withDepth, GLenum colorFormat_, GLenum _target): f(f_), + pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) { + is_depth = withDepth; + target_ = _target; + color_formats.fill(colorFormat_, colorAttachments_); + colors.fill(0, colorAttachments_); + fbo = drbo = 0; + tex_d = 0; + wid = hei = 0; + pbo_queried = 0; + is_changed = false; +} + + +Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, QVector colors_, bool withDepth, GLenum _target): f(f_), + pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) { + is_depth = withDepth; + target_ = _target; + color_formats = colors_; + colors.fill(0, colors_.size()); + fbo = drbo = 0; + tex_d = 0; + wid = hei = 0; + pbo_queried = 0; + is_changed = false; +} + + +Framebuffer::~Framebuffer() { + deleteGLFramebuffer(fbo); + deleteGLRenderbuffer(drbo); + for (int i = 0; i < colors.size(); ++i) + deleteGLTexture(f, colors[i]); + deleteGLTexture(f, tex_d); +} + + +void Framebuffer::resize(int width, int height, bool force) { + if ((wid == width) && (hei == height) && !force) return; + wid = width; + hei = height; + deleteGLFramebuffer(fbo); + f->glGenFramebuffers(1, &fbo); + f->glBindFramebuffer(GL_FRAMEBUFFER, fbo); + for (int i = 0; i < colors.size(); ++i) { + deleteGLTexture(f, colors[i]); + createGLTexture(f, colors[i], width, height, color_formats[i], target_); + f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + f->glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, 4); + //f->glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); + f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0); + } + if (is_depth) { + deleteGLTexture(f, tex_d); + deleteGLRenderbuffer(drbo); + f->glGenRenderbuffers(1, &drbo); + f->glBindRenderbuffer(GL_RENDERBUFFER, drbo); + f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); + f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drbo); + createGLTexture(f, tex_d, width, height, GL_DEPTH_COMPONENT); + f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + //f->glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); + f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0); + } + f->glBindFramebuffer(GL_FRAMEBUFFER, 0); + if (pbo.isInit()) { + enablePixelBuffer(); + } + is_changed = false; +} + + +QImage Framebuffer::grab() const { + return QImage(); +} + + +void Framebuffer::queryPoint(int index, QPoint p) { + pbo_queried = 0; + if (index < 0 || index >= colors.size()) return; + if (!rect().contains(p) || !pbo.isInit()) return; + f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); + pbo.bind(f); + f->glReadPixels(p.x(), height() - p.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0); + pbo_queried = 1; + pbo.release(f); +} + + +void Framebuffer::queryPoints(int index, QRect rect_, GLenum pixel_format) { + pbo_queried = 0; + if (index < 0 || index >= colors.size()) return; + rect_ &= rect(); + if (rect_.isEmpty() || !pbo.isInit()) return; + f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); + pbo.bind(f); + f->glReadPixels(rect_.x(), height() - rect_.bottom(), rect_.width(), rect_.height(), GL_RGBA, pixel_format, 0); + pbo_queried = rect_.width() * rect_.height(); + pbo.release(f); +} + + +void Framebuffer::queryImage(int index) { + queryPoints(index, rect()); +} + + +uint Framebuffer::getPoint() const { + if (!pbo.isInit() || (pbo_queried == 0)) return 0; + uint ret = 0; + pbo.bind(f); + void * map = pbo.map(f, GL_MAP_READ_BIT, sizeof(uint)); + if (map) + memcpy(&ret, map, sizeof(uint)); + pbo.unmap(f); + pbo.release(f); + return ret; +} + + +QVector Framebuffer::getPointsByte() const { + QVector ret; + if (!pbo.isInit() || (pbo_queried == 0)) return ret; + ret.resize(pbo_queried); + pbo.bind(f); + void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(uint)); + if (map) + memcpy(ret.data(), map, pbo_queried * sizeof(uint)); + pbo.unmap(f); + pbo.release(f); + return ret; +} + + +QVector Framebuffer::getPointsFloat() const { + QVector ret; + if (!pbo.isInit() || (pbo_queried == 0)) return ret; + ret.resize(pbo_queried); + pbo.bind(f); + void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(QVector4D)); + if (map) + memcpy(ret.data(), map, pbo_queried * sizeof(QVector4D)); + pbo.unmap(f); + pbo.release(f); + return ret; +} + + +QImage Framebuffer::getImage() const { + QImage ret; + if (!pbo.isInit() || (pbo_queried == 0)) return ret; + ret = QImage(size(), QImage::Format_RGBA8888); + int bytes = width() * height() * 4; + pbo.bind(f); + void * map = pbo.map(f, GL_MAP_READ_BIT, bytes); + if (map) + memcpy(ret.bits(), map, bytes); + pbo.unmap(f); + pbo.release(f); + return ret; +} + + +QVector Framebuffer::grabF(int index) const { + QVector ret; + if (index < 0 || index >= colors.size()) return ret; + f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); + ret.resize(wid * hei * 4); + f->glReadPixels(0, 0, wid, hei, GL_RGBA, GL_FLOAT, ret.data()); + return ret; +} + + +void Framebuffer::blit(int index_from, GLuint fb_to, int index_to, QRect from, QRect to, GLbitfield mask, GLenum filter) const { + if (index_from < 0 || index_from >= colors.size()) return; + GLenum e = GL_COLOR_ATTACHMENT0 + index_to; + f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_to); + f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index_from); + f->glDrawBuffers(1, &e); + f->glBlitFramebuffer(from.x(), from.y(), from.right(), from.bottom(), to.x(), to.y(), to.right(), to.bottom(), mask, filter); +} + + +void Framebuffer::bind() { + if (is_changed) resize(wid, hei); + if (fbo == 0) return; + f->glGetIntegerv(GL_VIEWPORT, prev_view); + f->glBindFramebuffer(GL_FRAMEBUFFER, fbo); + setWriteBuffers(); + f->glReadBuffer(GL_COLOR_ATTACHMENT0); + f->glViewport(0, 0, wid, hei); +} + + +void Framebuffer::release() { + is_changed = false; + if (fbo == 0) return; + f->glBindFramebuffer(GL_FRAMEBUFFER, 0); + f->glViewport(prev_view[0], prev_view[1], prev_view[2], prev_view[3]); +} + + +void Framebuffer::setWriteBuffer(int index) { + unsetWriteBuffers(); + GLenum e = GL_COLOR_ATTACHMENT0 + index; + f->glDrawBuffers(1, &e); +} + + +void Framebuffer::setWriteBuffers(const int * indeces, int count) { + unsetWriteBuffers(); + QVector buffers; + for (int i = 0; i < count; ++i) + buffers << GL_COLOR_ATTACHMENT0 + indeces[i]; + f->glDrawBuffers(buffers.size(), buffers.constData()); +} + + +void Framebuffer::setWriteBuffers() { + QVector buffers; + for (int i = 0; i < colors.size(); ++i) + buffers << GL_COLOR_ATTACHMENT0 + i; + f->glDrawBuffers(buffers.size(), buffers.constData()); +} + + +void Framebuffer::unsetWriteBuffers() { + QVector buffers(colors.size(), GL_NONE); + f->glDrawBuffers(buffers.size(), buffers.constData()); +} + + +void Framebuffer::enablePixelBuffer() { + pbo.init(f); + pbo.bind(f); + pbo.resize(f, width()*height()*4*4); + pbo.release(f); +} + + +void Framebuffer::setColorTextureFiltering(int index, GLenum filter) { + bindColorTexture(index); + f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, filter); + f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, filter); +} + + +void Framebuffer::bindColorTexture(int index, int channel) { + if (index < 0 || index >= colors.size()) return; + f->glActiveTexture(GL_TEXTURE0 + channel); + f->glBindTexture(GL_TEXTURE_2D, colors[index]); +} + + +void Framebuffer::bindColorTextures() { + for (int i = colors.size() - 1; i >= 0; --i) { + f->glActiveTexture(GL_TEXTURE0 + i); + f->glBindTexture(GL_TEXTURE_2D, colors[i]); + //f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + //f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } +} + + +void Framebuffer::bindDepthTexture(int channel) { + f->glActiveTexture(GL_TEXTURE0 + channel); + f->glBindTexture(GL_TEXTURE_2D, tex_d); +} + + +void Framebuffer::deleteGLRenderbuffer(GLuint & drbo) { + if (drbo != 0) + f->glDeleteRenderbuffers(1, &drbo); + drbo = 0; +} + + +void Framebuffer::deleteGLFramebuffer(GLuint & fbo) { + if (fbo != 0) + f->glDeleteFramebuffers(1, &fbo); + fbo = 0; +} diff --git a/core/glframebuffer.h b/core/glframebuffer.h new file mode 100644 index 0000000..cc6549e --- /dev/null +++ b/core/glframebuffer.h @@ -0,0 +1,89 @@ +/* + QGL Framebuffer + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLFRAMEBUFFER_H +#define GLFRAMEBUFFER_H + +#include "glbuffer.h" + + +class Framebuffer +{ + friend class FramebufferMipmap; +public: + Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments = 1, bool withDepth = true, GLenum colorFormat = GL_RGBA8, GLenum _target = GL_TEXTURE_2D); + Framebuffer(QOpenGLExtraFunctions * f_, QVector colors_, bool withDepth = true, GLenum _target = GL_TEXTURE_2D); + virtual ~Framebuffer(); + + GLuint id() const {return fbo;} + GLuint colorTexture(int index = 0) const {return colors[index];} + //GLenum colorFormat() const {return color_format;} + GLuint depthTexture() const {return tex_d;} + GLenum target() const {return target_;} + bool isInit() const {return fbo != 0;} + int width() const {return wid;} + int height() const {return hei;} + QSize size() const {return QSize(wid, hei);} + QRect rect() const {return QRect(0, 0, wid, hei);} + QImage grab() const; + QVector grabF(int index) const; + void queryPoint(int index, QPoint p); + void queryPoints(int index, QRect rect, GLenum pixel_format = GL_UNSIGNED_BYTE); + void queryImage(int index); + uint getPoint() const; + QVector getPointsByte() const; + QVector getPointsFloat() const; + QImage getImage() const; + int queriedPoints() const {return pbo_queried;} + void blit(int index_from, GLuint fb_to, int index_to, QRect from, QRect to, GLbitfield mask = GL_COLOR_BUFFER_BIT, GLenum filter = GL_NEAREST) const; + + void resize(int width, int height, bool force = false); + void bind(); + void release(); + void setReadBuffer(int index) {glReadBuffer(GL_COLOR_ATTACHMENT0 + index);} + void setWriteBuffer(int index); + void setWriteBuffers(const int * indeces, int count); + void setWriteBuffers(const QVector & indeces) {setWriteBuffers(indeces.constData(), indeces.size());} + void setWriteBuffers(); + void unsetWriteBuffers(); + //void setColorFormat(GLenum format) {color_format = format; is_changed = true;} + void enablePixelBuffer(); + void setColorTextureFiltering(int index, GLenum filter); + + void copyDepthFrom(GLuint tex) {;} + void bindColorTexture(int index, int channel = 0); + void bindColorTextures(); + void bindDepthTexture(int channel); + +private: + void deleteGLRenderbuffer(GLuint & drbo); + void deleteGLFramebuffer(GLuint & fbo); + + bool is_depth, is_changed; + int pbo_queried; + QOpenGLExtraFunctions * f; + mutable Buffer pbo; + QVector colors; + QVector color_formats; + GLenum target_; + GLuint fbo, drbo, tex_d; + GLint prev_view[4], wid, hei; + +}; + +#endif // GLFRAMEBUFFER_H diff --git a/core/glframebuffer_mipmap.cpp b/core/glframebuffer_mipmap.cpp new file mode 100644 index 0000000..6a38962 --- /dev/null +++ b/core/glframebuffer_mipmap.cpp @@ -0,0 +1,50 @@ +/* + QGL FramebufferMipmap + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include +#include "glframebuffer_mipmap.h" +#include + + +FramebufferMipmap::FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels): src_fb(fb) { + index_from = index_from_; + for (int i = 0; i < levels; ++i) + fbo << new Framebuffer(fb.f, 1, false, fb.color_formats[index_from]); +} + + +FramebufferMipmap::~FramebufferMipmap() { + +} + + +void FramebufferMipmap::resize() { + QSize sz = src_fb.size(); + for (int i = 0; i < fbo.size(); ++i) { + sz /= 2; + fbo[i]->resize(sz.width(), sz.height()); + } +} + + +void FramebufferMipmap::create() { + if (fbo.isEmpty()) return; + src_fb.blit(index_from, fbo[0]->id(), 0, src_fb.rect(), fbo[0]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR); + for (int i = 0; i < fbo.size() - 1; ++i) + fbo[i]->blit(0, fbo[i + 1]->id(), 0, fbo[i]->rect(), fbo[i + 1]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR); +} diff --git a/core/glframebuffer_mipmap.h b/core/glframebuffer_mipmap.h new file mode 100644 index 0000000..1bd9781 --- /dev/null +++ b/core/glframebuffer_mipmap.h @@ -0,0 +1,50 @@ +/* + QGL FramebufferMipmap + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLFRAMEBUFFER_MIPMAP_H +#define GLFRAMEBUFFER_MIPMAP_H + +#include "glframebuffer.h" + + +class FramebufferMipmap +{ +public: + FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels = 2); + virtual ~FramebufferMipmap(); + + int levelsCount() const {return fbo.size();} + int lastLevel() const {return fbo.size() - 1;} + Framebuffer & plane(int level) {return *fbo[level];} + Framebuffer & lastPlane() {return *fbo[lastLevel()];} + int width (int level) const {return fbo[level]->wid;} + int height(int level) const {return fbo[level]->hei;} + QSize size(int level) const {return fbo[level]->size();} + QRect rect(int level) const {return fbo[level]->rect();} + + void resize(); + void create(); + +private: + int index_from; + const Framebuffer & src_fb; + QVector fbo; + +}; + +#endif // GLFRAMEBUFFER_MIPMAP_H diff --git a/core/glmaterial.cpp b/core/glmaterial.cpp new file mode 100644 index 0000000..7afb341 --- /dev/null +++ b/core/glmaterial.cpp @@ -0,0 +1,151 @@ +/* + QGL Material + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "gltypes.h" +#include "gltexture_manager.h" +#include "qglview.h" + +using namespace QGLEngineShaders; + + +Map::Map() { + bitmap_id = 0; + color_amount = 1.f; + color_offset = 0.f; + bitmap_scale = QPointF(1., 1.); + use_bitmap = false; + _changed = true; + _layer = 0; +} + + +void Map::setBitmapPath(const QString & p) { + bitmap_path = p; + _changed = true; +} + + +void Map::load(TextureManager * tm) { + if (bitmap_id == 0) + bitmap_id = tm->loadTexture(bitmap_path, true, _type == mtNormal); +} + + +void Map::copyToQGLMap(QGLMap & m) const { + m.amount = color_amount; + m.offset = color_offset; + m.scale = QVector2D(bitmap_scale); + if (hasBitmap() && use_bitmap) { + m.array_index = tarMaps; + m.map_index = _layer; + } else { + m.array_index = tarEmpty; + m.map_index = (_type == mtNormal ? emrBlue : emrWhite); + } +} + + + + +Material::Material(const QString _name)/*: map_reflection(512)*/ { + setTypes(); + name = _name; + color_diffuse = Qt::white; + color_emission = Qt::black; + glass = false; + transparency = reflectivity = 0.f; + map_roughness.color_amount = 0.75f; + map_metalness.color_amount = 0.25f; + iof = 1.f; + dispersion = 0.05f; + _changed = true; + _index = 0; +} + + +uint Material::hash() { + return qHash(name); +} + + +bool Material::hasTransparency() const { + return float(color_diffuse.alphaF()) * (1.f - transparency) < 1.f; +} + + +bool Material::isMapsChanged() const { + return map_diffuse ._changed || + map_normal ._changed || + map_metalness._changed || + map_roughness._changed || + map_emission ._changed || + map_relief ._changed; +} + + +bool Material::isMapChanged(int type) const { + switch (type) { + case mtDiffuse : return map_diffuse ._changed; + case mtNormal : return map_normal ._changed; + case mtMetalness: return map_metalness._changed; + case mtRoughness: return map_roughness._changed; + case mtEmission : return map_emission ._changed; + case mtRelief : return map_relief ._changed; + } + return false; +} + + +void Material::load(TextureManager * tm) { + map_diffuse .load(tm); + map_normal .load(tm); + map_metalness.load(tm); + map_roughness.load(tm); + map_emission .load(tm); + map_relief .load(tm); +} + + +void Material::setMapsChanged() { + map_diffuse ._changed = true; + map_normal ._changed = true; + map_metalness._changed = true; + map_roughness._changed = true; + map_emission ._changed = true; + map_relief ._changed = true; +} + + +void Material::setTypes() { + map_diffuse ._type = mtDiffuse ; + map_normal ._type = mtNormal ; + map_metalness._type = mtMetalness; + map_roughness._type = mtRoughness; + map_emission ._type = mtEmission ; + map_relief ._type = mtRelief ; +} + + +void Material::detectMaps() { + map_diffuse .use_bitmap = !map_diffuse .bitmap_path.isEmpty(); + map_normal .use_bitmap = !map_normal .bitmap_path.isEmpty(); + map_metalness.use_bitmap = !map_metalness.bitmap_path.isEmpty(); + map_roughness.use_bitmap = !map_roughness.bitmap_path.isEmpty(); + map_emission .use_bitmap = !map_emission .bitmap_path.isEmpty(); + map_relief .use_bitmap = !map_relief .bitmap_path.isEmpty(); +} diff --git a/core/glmaterial.h b/core/glmaterial.h new file mode 100644 index 0000000..661d3dc --- /dev/null +++ b/core/glmaterial.h @@ -0,0 +1,124 @@ +/* + QGL Material + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLMATERIAL_H +#define GLMATERIAL_H + +#include "glshaders_types.h" +#include "chunkstream.h" + + +class Map { +public: + Map(); + void setBitmapPath(const QString & p); + void clearBitmap() {setBitmapPath(QString());} + bool hasBitmap() const {return !bitmap_path.isEmpty();} + void load(TextureManager * tm); + void copyToQGLMap(QGLEngineShaders::QGLMap & m) const; + QString bitmap_path; + GLuint bitmap_id; + QPointF bitmap_offset; + QPointF bitmap_scale; + float color_amount; + float color_offset; + bool use_bitmap; + + bool _changed; + int _type, _layer; +}; + +class Material { +public: + Material(const QString _name = QString()); + uint hash(); + bool hasTransparency() const; + bool isMapsChanged() const; + bool isMapChanged(int type) const; + void load(TextureManager * tm); + void setMapsChanged(); + void setTypes(); + void detectMaps(); + QString name; + QColor color_diffuse; + QColor color_emission; + bool glass; + float transparency; + float reflectivity; + float iof; + float dispersion; + Map map_diffuse ; + Map map_normal ; + Map map_metalness; + Map map_roughness; + Map map_emission ; + Map map_relief ; + bool _changed; + int _index; + //GLCubeTexture map_reflection; +}; + + +inline QDataStream & operator <<(QDataStream & s, const Map & m) { + ChunkStream cs; + cs.add(1, m.bitmap_path).add(2, m.color_amount).add(3, m.color_offset).add(6, m.bitmap_scale) + .add(7, m.use_bitmap); + s << cs.data(); return s; +} +inline QDataStream & operator >>(QDataStream & s, Map & m) { + ChunkStream cs(s); + cs.readAll(); + cs.get(1, m.bitmap_path).get(2, m.color_amount).get(3, m.color_offset).get(6, m.bitmap_scale) + .get(7, m.use_bitmap); + return s; +} + +inline QDataStream & operator <<(QDataStream & s, const Material * m) { + ChunkStream cs; + cs.add(1, m->name).add(2, m->color_diffuse).add(4, m->color_emission) + .add(5, m->transparency).add(6, m->reflectivity).add(7, m->glass).add(8, m->map_diffuse).add(9, m->map_normal) + .add(10, m->map_relief).add(11, m->map_metalness).add(12, m->map_roughness).add(13, m->map_emission); + s << /*qCompress*/(cs.data()); return s; +} +inline QDataStream & operator >>(QDataStream & s, Material *& m) { + m = new Material(); + //QByteArray ba; + //s >> ba; + //ba = qUncompres(ba); + ChunkStream cs(s); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: cs.get(m->name); break; + case 2: cs.get(m->color_diffuse); break; + case 4: cs.get(m->color_emission); break; + case 5: cs.get(m->transparency); break; + case 6: cs.get(m->reflectivity); break; + case 7: cs.get(m->glass); break; + case 8: cs.get(m->map_diffuse); break; + case 9: cs.get(m->map_normal); break; + case 10: cs.get(m->map_relief); break; + case 11: cs.get(m->map_metalness); break; + case 12: cs.get(m->map_roughness); break; + case 13: cs.get(m->map_emission); break; + } + } + m->setTypes(); + return s; +} + +#endif // GLMATERIAL_H diff --git a/core/glmesh.cpp b/core/glmesh.cpp new file mode 100644 index 0000000..1b2079d --- /dev/null +++ b/core/glmesh.cpp @@ -0,0 +1,426 @@ +/* + QGL Mesh + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "glmesh.h" +#include "globject.h" +#include + +using namespace QGLEngineShaders; + +//static int _count = 0; + +Mesh::Mesh(GLenum geom_type_): geom_type(geom_type_), + buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW), + buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW) { + hash_ = 0; + changed = hash_changed = true; + //qDebug() << "Mesh, now" << ++_count; +} + + +Mesh::~Mesh() { + //qDebug() << "~Mesh, now" << --_count; + //destroy(); +} + + +Mesh * Mesh::clone() { + Mesh * c = new Mesh(); + c->vertices_ = vertices_ ; + c->normals_ = normals_ ; + c->texcoords_ = texcoords_; + c->triangles_ = triangles_; + c->lines_ = lines_; + c->geom_type = geom_type; + c->hash_ = hash_; + c->hash_changed = hash_changed; + //qDebug() << "clone VBO"; + return c; +} + + +void Mesh::init(QOpenGLExtraFunctions * f) { + if (!isInit()) { + buffer_geom.init(f); + buffer_ind .init(f); + changed = true; + } +} + + +void Mesh::destroy(QOpenGLExtraFunctions * f) { + buffer_geom.destroy(f); + buffer_ind .destroy(f); + QList vaol = vao_map.values(); + foreach (VertexObject* vao, vaol) + vao->destroy(f); + qDeleteAll(vao_map); + vao_map.clear(); +} + + +void Mesh::calculateNormals() { + normals_.resize(vertices_.size()); + QVector3D dv1, dv2, n; + foreach (const Vector3i & t, triangles_) { + QVector3D & v0(vertices_[t.p0]); + QVector3D & v1(vertices_[t.p1]); + QVector3D & v2(vertices_[t.p2]); + dv1 = v1 - v0, dv2 = v2 - v0; + n = QVector3D::crossProduct(dv1, dv2).normalized(); + normals_[t.p0] = n; + normals_[t.p1] = n; + normals_[t.p2] = n; + } +} + + +void Mesh::calculateTangents() { + if (vertices_.isEmpty() || texcoords_.isEmpty()) return; + if (texcoords_.size() != vertices_.size()) return; + tangents_ .resize(vertices_.size()); + bitangents_.resize(vertices_.size()); + //qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "..."; + QVector3D dv1, dv2; + QVector2D dt1, dt2; + QVector3D tan, bitan; + foreach (const Vector3i & t, triangles_) { + QVector3D & v0(vertices_ [t.p0]); + QVector3D & v1(vertices_ [t.p1]); + QVector3D & v2(vertices_ [t.p2]); + QVector2D & t0(texcoords_[t.p0]); + QVector2D & t1(texcoords_[t.p1]); + QVector2D & t2(texcoords_[t.p2]); + dv1 = v1 - v0, dv2 = v2 - v0; + dt1 = t1 - t0, dt2 = t2 - t0; + tan = (dv1 * dt2.y() - dv2 * dt1.y()).normalized(); + bitan = (dv2 * dt1.x() - dv1 * dt2.x()).normalized(); + tangents_ [t.p0] = tan; + tangents_ [t.p1] = tan; + tangents_ [t.p2] = tan; + bitangents_[t.p0] = bitan; + bitangents_[t.p1] = bitan; + bitangents_[t.p2] = bitan; + //qDebug() << " t" << t << vi << ti << dv1.toQVector3D() << "..."; + } + //qDebug() << "calculateBinormals" << vcnt << tcnt << tangents_.size(); +} + + +VertexObject * Mesh::vaoByType(int type) { + VertexObject *& vao(vao_map[type]); + if (!vao) { + vao = new VertexObject(); + } + return vao; +} + + +bool Mesh::rebuffer(QOpenGLExtraFunctions * f) { + changed = false; + if (vertices_.isEmpty()) return true; + if (normals_.isEmpty()) + calculateNormals(); + calculateTangents(); + vert_count = qMin(vertices_.size(), normals_.size()); + vert_count = qMin(vert_count, tangents_.size()); + vert_count = qMin(vert_count, bitangents_.size()); + vert_count = qMin(vert_count, texcoords_.size()); + data_.resize(vert_count); + for (int i = 0; i < vert_count; ++i) { + Vertex & v(data_[i]); + v.pos = vertices_ [i]; + v.normal = normals_ [i]; + v.tangent = tangents_ [i]; + v.bitangent = bitangents_[i]; + v.tex = texcoords_ [i]; + } + int gsize = data_.size() * sizeof(Vertex); + int tsize = triangles_.size() * sizeof(Vector3i); + int lsize = lines_.size() * sizeof(Vector2i); + + buffer_geom.bind(f); + buffer_geom.resize(f, gsize); + buffer_geom.load(f, data_.constData(), gsize); + + buffer_ind.bind(f); + if (geom_type == GL_TRIANGLES) { + buffer_ind.resize(f, tsize); + buffer_ind.load(f, triangles_.constData(), tsize); + } else { + buffer_ind.resize(f, lsize); + buffer_ind.load(f, lines_.constData(), lsize); + } + + return !isEmpty(); +} + + +void Mesh::draw(QOpenGLExtraFunctions * f, int count, int type) { + if (isEmpty()) return; + if (!isInit()) init(f); + if (changed) rebuffer(f); + //qDebug() << "draw" << geom_type << vert_count << count; + + VertexObject * vao = vaoByType(type); + vao->bindBuffers(f, buffer_geom, buffer_ind); + if (geom_type == GL_TRIANGLES) + vao->draw(f, geom_type, triangles_.size() * 3, count); + else + vao->draw(f, geom_type, lines_.size() * 2, count); +} + + +void Mesh::clear() { + vertices_ .clear(); + normals_ .clear(); + tangents_ .clear(); + bitangents_.clear(); + texcoords_ .clear(); + triangles_ .clear(); + lines_ .clear(); + data_ .clear(); + changed = hash_changed = true; +} + + +void Mesh::loadObject(QOpenGLExtraFunctions * f, const Object & object, int type) { + VertexObject * vao = vaoByType(type); + vao->loadObject(f, object); +} + + +void Mesh::loadObjects(QOpenGLExtraFunctions * f, const QVector & objects, int type) { + VertexObject * vao = vaoByType(type); + vao->loadObjects(f, objects); +} + + +void Mesh::loadSelections(QOpenGLExtraFunctions * f, const QVector & sels, int type) { + VertexObject * vao = vaoByType(type); + vao->loadSelections(f, sels); +} + + +uint Mesh::hash() const { + if (hash_changed) { + hash_changed = false; + hash_ = qHashBits(vertices_ .constData(), vertices_ .size() * sizeof(QVector3D)); + hash_ ^= qHashBits(normals_ .constData(), normals_ .size() * sizeof(QVector3D)); + hash_ ^= qHashBits(texcoords_.constData(), texcoords_.size() * sizeof(QVector2D)); + hash_ ^= qHashBits(triangles_.constData(), triangles_.size() * sizeof( Vector3i)); + hash_ ^= qHashBits(lines_ .constData(), lines_ .size() * sizeof( Vector2i)); + } + return hash_; +} + + +bool Mesh::isObjectsChanged(int type) const { + return (const_cast(this))->vaoByType(type)->isObjectsChanged(); +} + + +bool Mesh::isSelectionChanged(int type) const { + return (const_cast(this))->vaoByType(type)->isSelectionChanged(); +} + + +void Mesh::setObjectsChanged(int type, bool yes) { + vaoByType(type)->setObjectsChanged(yes); +} + + +void Mesh::setSelectionChanged(int type, bool yes) { + vaoByType(type)->setSelectionChanged(yes); +} + + +void Mesh::setAllObjectsChanged(bool yes) { + QMapIterator it(vao_map); + while (it.hasNext()) + it.next().value()->setObjectsChanged(yes); +} + + +void Mesh::setAllSelectionChanged(bool yes) { + QMapIterator it(vao_map); + while (it.hasNext()) + it.next().value()->setSelectionChanged(yes); +} + + +void Mesh::translatePoints(const QVector3D & dp) { + QMatrix4x4 m; + m.translate(dp); + transformPoints(m); +} + + +void Mesh::scalePoints(const QVector3D & dp) { + QMatrix4x4 m; + m.scale(dp); + transformPoints(m); +} + + +void Mesh::rotatePoints(const double & angle, const QVector3D & a) { + QMatrix4x4 m; + m.rotate(angle, a); + transformPoints(m); +} + + +void Mesh::transformPoints(const QMatrix4x4 & mat) { + if (vertices_.isEmpty()) return; + int vcnt = vertices_.size(), ncnt = normals_.size(); + for (int i = 0; i < vcnt; ++i) { + vertices_[i] = (mat * QVector4D(vertices_[i], 1)).toVector3D(); + if (i < ncnt) + normals_[i] = (mat * QVector4D(normals_[i], 0)).toVector3D(); + } + changed = hash_changed = true; +} + + +void Mesh::flipNormals() { + if (vertices_.isEmpty()) return; + for (int i = 0; i < triangles_.size(); ++i) + piSwap(triangles_[i].p1, triangles_[i].p2); + for (int i = 0; i < lines_.size(); ++i) + piSwap(lines_[i].p0, lines_[i].p1); + int ncnt = normals_.size(); + for (int i = 0; i < ncnt; ++i) + normals_[i] = -normals_[i]; + changed = hash_changed = true; +} + + +void Mesh::append(const Mesh * m) { + if (!m) return; + if (m->isEmpty()) return; + if (normals_.isEmpty()) calculateNormals(); + int vcnt = vertices_.size(); + vertices_ .append(m->vertices_ ); + normals_ .append(m->normals_ ); + texcoords_.append(m->texcoords_); + QVector tri = m->triangles_; + for (int i = 0; i < tri.size(); ++i) + tri[i] += vcnt; + triangles_.append(tri); + QVector lin = m->lines_; + for (int i = 0; i < lin.size(); ++i) + lin[i] += vcnt; + lines_.append(lin); +} + + +bool Mesh::saveToFile(const QString & filename) { + if (filename.isEmpty()) return false; + QFile f(filename); + QByteArray ba; + if (f.open(QFile::WriteOnly)) { + QDataStream out(&ba, QFile::WriteOnly); + out << vertices_ << normals_ << texcoords_ << triangles_ << lines_; + ba = qCompress(ba); + f.resize(0); + f.write(ba); + f.close(); + return true; + } + return false; +} + + +bool Mesh::loadFromFile(const QString & filename) { + if (filename.isEmpty()) return false; + QFile f(filename); + QByteArray ba; + if (f.open(QFile::ReadOnly)) { + ba = f.readAll(); + if (ba.isEmpty()) return false; + ba = qUncompress(ba); + QDataStream in(ba); + in >> vertices_ >> normals_ >> texcoords_ >> triangles_ >> lines_; + changed = hash_changed = true; + f.close(); + return !isEmpty(); + } + return false; +} + + +Box3D Mesh::boundingBox() const { + if (vertices_.isEmpty()) return Box3D(); + int vcnt = vertices_.size(); + //qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "..."; + GLfloat mix, miy, miz, max, may, maz; + QVector3D v0(vertices_[0]); + mix = max = v0.x(); + miy = may = v0.y(); + miz = maz = v0.z(); + Box3D bound; + for (int i = 1; i < vcnt; ++i) { + const QVector3D & v(vertices_[i]); + if (mix > v.x()) mix = v.x(); + if (max < v.x()) max = v.x(); + if (miy > v.y()) miy = v.y(); + if (may < v.y()) may = v.y(); + if (miz > v.z()) miz = v.z(); + if (maz < v.z()) maz = v.z(); + } + bound.x = mix; + bound.y = miy; + bound.z = miz; + bound.length = max - mix; + bound.width = may - miy; + bound.height = maz - miz; + return bound; +} + + +QDataStream & operator <<(QDataStream & s, const Mesh * m) { + ChunkStream cs; + //qDebug() << "place VBO" << m.vertices_.size() << m.normals_.size() << m.texcoords_.size() << m.colors_.size() << "..."; + cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_) + .add(6, m->triangles_).add(7, m->lines_).add(10, int(m->geom_type)); + //qDebug() << "place VBO done" << cs.data().size() << "..."; + s << /*qCompress*/(cs.data()); return s; +} + + +QDataStream & operator >>(QDataStream & s, Mesh *& m) { + m = new Mesh(); + //QByteArray ba; + //s >> ba; + //ba = qUncompress(ba); + ChunkStream cs(s); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1 : cs.get(m->vertices_ ); break; + case 2 : cs.get(m->normals_ ); break; + case 3 : cs.get(m->texcoords_); break; + case 6 : cs.get(m->triangles_); break; + case 7 : cs.get(m->lines_ ); break; + case 10: m->geom_type = cs.getData(); break; + } + } + m->changed = true; + return s; +} diff --git a/core/glmesh.h b/core/glmesh.h new file mode 100644 index 0000000..e87f336 --- /dev/null +++ b/core/glmesh.h @@ -0,0 +1,110 @@ +/* + QGL Mesh + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLMESH_H +#define GLMESH_H + +#include +#include "glvertexobject.h" + + +class Mesh +{ + friend class ObjectBase; + friend class Scene; + friend class Renderer; + friend QDataStream & operator <<(QDataStream & s, const Mesh * m); + friend QDataStream & operator >>(QDataStream & s, Mesh *& m); +public: + Mesh(GLenum geom_type_ = GL_TRIANGLES); + ~Mesh(); + + Mesh * clone(); + + //GLVBO & operator =(const GLVBO & o) {return *this;} + + void init (QOpenGLExtraFunctions * f); + void destroy (QOpenGLExtraFunctions * f); + bool rebuffer(QOpenGLExtraFunctions * f); + void draw (QOpenGLExtraFunctions * f, int count, int type = 0); + void clear(); + void loadObject (QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object, int type = 0); + void loadObjects (QOpenGLExtraFunctions * f, const QVector & objects, int type = 0); + void loadSelections(QOpenGLExtraFunctions * f, const QVector & sels, int type = 0); + + int verticesCount() const {return vertices_.size();} + int trianglesCount() const {return triangles_.size();} + int linesCount() const {return lines_.size();} + bool isInit() const {return buffer_geom.isInit();} + bool isEmpty() const {return vertices_.isEmpty();} + uint hash() const; + + bool isObjectsChanged (int type = 0) const; + bool isSelectionChanged (int type = 0) const; + void setObjectsChanged (int type = 0, bool yes = true); + void setSelectionChanged(int type = 0, bool yes = true); + void setAllObjectsChanged (bool yes = true); + void setAllSelectionChanged(bool yes = true); + + QVector & vertices () {changed = hash_changed = true; return vertices_;} + QVector & normals () {changed = hash_changed = true; return normals_;} + QVector & texcoords() {changed = hash_changed = true; return texcoords_;} + QVector< Vector3i> & indicesTriangles() {changed = hash_changed = true; return triangles_;} + QVector< Vector2i> & indicesLines () {changed = hash_changed = true; return lines_;} + + void translatePoints(const QVector3D & dp); + void translatePoints(const double & x, const double & y, const double & z) {translatePoints(QVector3D(x, y, z));} + void scalePoints (const QVector3D & dp); + void scalePoints (const double & s) {scalePoints(QVector3D(s, s, s));} + void rotatePoints (const double & angle, const QVector3D & a); + void rotatePoints (const double & angle, const double & x, const double & y, const double & z) {rotatePoints(angle, QVector3D(x, y, z));} + void transformPoints(const QMatrix4x4 & mat); + void flipNormals(); + void append(const Mesh * m); + + bool saveToFile(const QString & filename); + bool loadFromFile(const QString & filename); + + Box3D boundingBox() const; + +private: + void calculateNormals(); + void calculateTangents(); + VertexObject * vaoByType(int type); + + QVector vertices_, normals_, tangents_, bitangents_; + QVector texcoords_; + QVector< Vector3i> triangles_; + QVector< Vector2i> lines_; + + QVector data_; + GLenum geom_type; + Buffer buffer_geom, buffer_ind; + QMap vao_map; + mutable uint hash_; + mutable bool hash_changed; + int vert_count; + bool changed; + +}; + + +QDataStream & operator <<(QDataStream & s, const Mesh * m); +QDataStream & operator >>(QDataStream & s, Mesh *& m); + +#endif // GLMESH_H diff --git a/core/glprimitives.cpp b/core/glprimitives.cpp new file mode 100644 index 0000000..6f6579b --- /dev/null +++ b/core/glprimitives.cpp @@ -0,0 +1,437 @@ +/* + QGL Primitives + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "glprimitives.h" +#include "glmesh.h" + + +Mesh * Primitive::plane(float width, float length) { + Mesh * ret = new Mesh(); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & i(ret->indicesTriangles ()); + float hw = width / 2.f, hl = length / 2.f; + for (int j = 0; j < 4; ++j) n << QVector3D(0., 0., 1.); + t << QVector2D(0., 0.) << QVector2D(0., 1.) << QVector2D(1., 1.) << QVector2D(1., 0.); + v << QVector3D(-hw, -hl, 0.) << QVector3D(-hw, hl, 0.) << QVector3D(hw, hl, 0.) << QVector3D(hw, -hl, 0.); + i << Vector3i(0, 2, 1) << Vector3i(0, 3, 2); + return ret; +} + + +Mesh * Primitive::cube(float width, float length, float height) { + Mesh * ret = new Mesh(); + QVector3D scale(width, length, height); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & i(ret->indicesTriangles ()); + float hs = 0.5f; + int si = 0; + QMatrix4x4 mat; + + si = v.size(); + for (int j = 0; j < 4; ++j) n << QVector3D(0., -1., 0.); + t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.); + v << QVector3D(-hs, -hs, -hs) << QVector3D(hs, -hs, -hs) << QVector3D(hs, -hs, hs) << QVector3D(-hs, -hs, hs); + i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3); + + for (int r = 0; r < 3; ++r) { + si = v.size(); + mat.rotate(90., 0., 0., 1.); + QVector3D cn = mat.map(n[0]); + for (int j = 0; j < 4; ++j) { + n << cn; + v << mat.map(QVector4D(v[j])).toVector3D(); + } + t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.); + i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3); + } + + mat.setToIdentity(); + mat.rotate(90., 1., 0.,0.); + for (int r = 0; r < 2; ++r) { + si = v.size(); + mat.rotate(180., 1., 0.,0.); + QVector3D cn = mat.map(n[0]); + for (int j = 0; j < 4; ++j) { + n << cn; + v << mat.map(QVector4D(v[j])).toVector3D(); + } + t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.); + i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3); + } + + for (int i = 0; i < v.size(); ++i) + v[i] *= scale; + + return ret; +} + + +Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float end_angle) { + Mesh * ret = new Mesh(); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & ind(ret->indicesTriangles()); + int hseg = segments_h + 1, wlseg = segments_wl + 1; + double crw, crl, a, ch, twl; + double eang = deg2rad * end_angle; + + QVector3D cp; + for (int i = 0; i <= hseg; i++) { + ch = -cos((double)i / hseg * M_PI); + cp.setZ(ch * radius); + twl = sqrt(1. - ch * ch); + crw = twl * radius; + crl = twl * radius; + int cvcnt = wlseg * 2; + for (int j = 0; j < cvcnt; j++) { + a = (double)j / (cvcnt - 1) * eang; + cp.setX(crl * cos(a)); + cp.setY(crw * sin(a)); + v << cp; + t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f); + n << cp.normalized(); + int si = v.size() - 1; + if (j > 0 && i > 0) { + ind << Vector3i(si - cvcnt - 1, si, si - 1); + ind << Vector3i(si - cvcnt, si, si - cvcnt - 1); + } + } + } + if (end_angle < 360.) { + Mesh * cap = Primitive::disc(segments_h+1, radius, 180); + cap->rotatePoints(90, 0, 1, 0); + cap->rotatePoints(-90, 0, 0, 1); + ret->append(cap); + cap->flipNormals(); + cap->rotatePoints(end_angle, 0, 0, 1); + ret->append(cap); + delete cap; + } + return ret; +} + + +Mesh * Primitive::disc(int segments, float radius, float end_angle) { + Mesh * ret = new Mesh(); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & ind(ret->indicesTriangles()); + + segments = qMax(segments + 1, 4); + QVector3D cp; + v << QVector3D(); + n << QVector3D(0, 0, 1); + t << QVector2D(0.5f, 0.5f); + end_angle *= deg2rad; + for (int i = 0; i < segments; i++) { + double a = (double)i / (segments - 1) * end_angle; + cp.setX(radius * cos(a)); + cp.setY(radius * sin(a)); + v << cp; + n << QVector3D(0, 0, 1); + t << QVector2D(cp.x() / radius + 1, cp.y() / radius + 1); + int si = v.size() - 1; + if (i > 0) ind << Vector3i(si - 1, si, 0); + } + return ret; +} + + +QVector3D coneNormal(double r, double height, double ang) { + QVector3D norm; + norm.setX(r * cos(ang)); + norm.setY(r * sin(ang)); + norm.setZ(0.); + double rl = norm.length(); + double ca = atan2(rl, height); + norm *= cos(ca); + norm.setZ(norm.length() * tan(ca)); + return norm.normalized(); +} + + +Mesh * Primitive::cone(int segments, float radius, float height) { + Mesh * ret = new Mesh(); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & ind(ret->indicesTriangles()); + + int seg = qMax(segments + 1, 4); + QVector3D cp; + for (int i = 0; i < seg; i++) { + double a = (double)i / (seg - 1) * M_2PI; + cp.setX(radius * cos(a)); + cp.setY(radius * sin(a)); + if (i > 0) { + v << QVector3D(0, 0, height); + t << QVector2D((double)(i - 1) / (seg - 1), 1.f); + double ta = ((double)i - 0.5) / (seg - 1) * M_2PI; + n << coneNormal(radius, height, ta); + } + v << cp; + t << QVector2D((double)i / (seg - 1), 0.f); + n << coneNormal(radius, height, a); + int si = v.size() - 1; + if (i > 0) + ind << Vector3i(si - 1, si - 2, si); + } + + Mesh * cap = Primitive::disc(segments, radius); + cap->flipNormals(); + ret->append(cap); + delete cap; + + return ret; +} + + +Mesh * Primitive::cylinder(int segments, float radius, float height, float end_angle) { + Mesh * ret = new Mesh(); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & ind(ret->indicesTriangles()); + + int seg = qMax(segments + 1, 4); + QVector3D cp, norm; + double eang = deg2rad * end_angle; + + for (int i = 0; i < seg; i++) { + double a = (double)i / (seg - 1) * eang; + cp.setX(radius * cos(a)); + cp.setY(radius * sin(a)); + cp.setZ(0.); + norm = cp.normalized(); + v << cp; + cp.setZ(height); + v << cp; + t << QVector2D((double)i / (seg - 1), 0.f); + t << QVector2D((double)i / (seg - 1), 1.f); + n << norm; n << norm; + int si = v.size() - 1; + if (i > 0) { + ind << Vector3i(si - 2, si - 1, si); + ind << Vector3i(si - 1, si - 2, si - 3); + } + } + + Mesh * cap = Primitive::disc(segments, radius, end_angle); + cap->flipNormals(); + ret->append(cap); + cap->translatePoints(QVector3D(0., 0., height)); + cap->flipNormals(); + ret->append(cap); + delete cap; + + if (end_angle < 360.) { + Mesh * cap = Primitive::plane(radius, height); + cap->rotatePoints(90, 1, 0, 0); + //cap->rotatePoints(-90, 0, 0, 1); + cap->translatePoints(radius/2, 0, height/2); + ret->append(cap); + cap->flipNormals(); + cap->rotatePoints(end_angle, 0, 0, 1); + ret->append(cap); + delete cap; + } + + return ret; +} + + +Mesh * Primitive::arrow(int segments, float thick, float angle) { + double cone_r = 1.5 * thick; + double cone_h = 2. * cone_r / tan(angle * deg2rad); + Mesh * ret = new Mesh(); + Mesh * m = Primitive::cylinder(segments, thick / 2., 1. - cone_h); + ret->append(m); + delete m; + m = Primitive::cone(segments, cone_r, cone_h); + m->translatePoints(QVector3D(0., 0., 1. - cone_h)); + ret->append(m); + delete m; + return ret; +} + + +Mesh * Primitive::torus(int segments_main, int segments_second, float radius_main, float radius_second, float end_angle) { + Mesh * ret = new Mesh(); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector3i> & ind(ret->indicesTriangles()); + + QVector cv, cn; + QVector ct; + segments_second = qMax(segments_second + 1, 4); + for (int i = 0; i < segments_second; i++) { + double x = (double)i / (segments_second - 1); + double a = x * M_2PI; + cv << QVector3D(radius_second * cos(a), 0., radius_second * sin(a)); + cn << cv.back().normalized(); + ct << QVector2D(0., x); + cv.back() += QVector3D(radius_main, 0., 0.); + } + + segments_main = qMax(segments_main + 1, 4); + int ccnt = cv.size(), pcnt = 0; + for (int i = 0; i < segments_main; i++) { + double x = (double)i / (segments_main - 1); + QMatrix4x4 rm; + rm.rotate(x * end_angle, 0., 0., 1.); + for (int j = 0; j < ccnt; j++) { + ct[j].setX(x); + v << rm.map(cv[j]); + n << rm.map(cn[j]); + } + t.append(ct); + if (i > 0) { + for (int j = 0; j < ccnt - 1; j++) { + ind << Vector3i(pcnt + j, pcnt + j + 1, pcnt + j - ccnt); + ind << Vector3i(pcnt + j + 1, pcnt + j + 1 - ccnt, pcnt + j - ccnt); + } + } + pcnt = v.size(); + } + if (end_angle < 360.) { + Mesh * cap = Primitive::disc(segments_second-1, radius_second); + cap->rotatePoints(90, 1, 0, 0); + cap->translatePoints(radius_main, 0, 0); + ret->append(cap); + cap->flipNormals(); + cap->rotatePoints(end_angle, 0, 0, 1); + ret->append(cap); + delete cap; + } + return ret; +} + + + + +Mesh * Primitive::cubeFrame(float width, float length, float height) { + Mesh * ret = new Mesh(GL_LINES); + QVector3D scale(width, length, height); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector2i> & i(ret->indicesLines()); + float hs = 0.5f; + v << QVector3D(-hs, -hs, -hs) << QVector3D(-hs, hs, -hs) << QVector3D( hs, hs, -hs) << QVector3D( hs, -hs, -hs); + v << QVector3D(-hs, -hs, hs) << QVector3D(-hs, hs, hs) << QVector3D( hs, hs, hs) << QVector3D( hs, -hs, hs); + for (int j = 0; j < 8; ++j) { + v[j] *= scale; + t << QVector2D(0, 0); + n << QVector3D(0,0,1); + } + for (int j = 0; j < 4; ++j) { + i << Vector2i(j, (j + 1) % 4); + i << Vector2i(j, j + 4); + i << Vector2i(j + 4, (j + 1) % 4 + 4); + } + return ret; +} + + +Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float radius) { + Mesh * ret = new Mesh(GL_LINES); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector2i> & ind(ret->indicesLines()); + int hseg = segments_h + 1, wlseg = segments_wl + 1; + double crw, crl, a, ch, twl; + + QVector3D cp; + for (int i = 0; i <= hseg; i++) { + ch = -cos((double)i / hseg * M_PI); + cp.setZ(ch * radius); + twl = sqrt(1. - ch * ch); + crw = twl * radius; + crl = twl * radius; + int cvcnt = wlseg * 2; + for (int j = 0; j < cvcnt; j++) { + a = (double)j / (cvcnt - 1) * M_2PI; + cp.setX(crl * cos(a)); + cp.setY(crw * sin(a)); + v << cp; + t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f); + n << cp.normalized(); + int si = v.size() - 1; + if (j > 0 && i > 0) { + ind << Vector2i(si, si - 1); + ind << Vector2i(si - cvcnt, si); + } + } + } + return ret; +} + + +Mesh * Primitive::coneFrame(int segments, float radius, float height) { + Mesh * ret = new Mesh(GL_LINES); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector2i> & ind(ret->indicesLines()); + + int seg = qMax(segments + 1, 4); + QVector3D cp; + for (int i = 0; i < seg; i++) { + double a = (double)i / (seg - 1) * M_2PI; + cp.setX(radius * cos(a)); + cp.setY(radius * sin(a)); + if (i > 0) { + v << QVector3D(0, 0, height); + t << QVector2D((double)(i - 1) / (seg - 1), 1.f); + double ta = ((double)i - 0.5) / (seg - 1) * M_2PI; + n << coneNormal(radius, height, ta); + } + v << cp; + t << QVector2D((double)i / (seg - 1), 0.f); + n << coneNormal(radius, height, a); + int si = v.size() - 1; + if (i > 0) { + ind << Vector2i(si - 1, si); + ind << Vector2i(si - 2, si); + } + } + + return ret; +} + + +Mesh * Primitive::lineFrame(QVector3D p0, QVector3D p1) { + Mesh * ret = new Mesh(GL_LINES); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector2i> & ind(ret->indicesLines()); + v << p0 << p1; + n << QVector3D(0,0,1) << QVector3D(0,0,1); + t << QVector2D(0,0) << QVector2D(1,0); + ind << Vector2i(0, 1); + return ret; +} diff --git a/core/glprimitives.h b/core/glprimitives.h new file mode 100644 index 0000000..7129bb1 --- /dev/null +++ b/core/glprimitives.h @@ -0,0 +1,104 @@ +/* + QGL Primitives + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLPRIMITIVE_CUBE_H +#define GLPRIMITIVE_CUBE_H + +#include "gltypes.h" + + +namespace Primitive { + + +Mesh * plane(float width = 1., float length = 1.); + +Mesh * cube(float width = 1., float length = 1., float height = 1.); + +Mesh * ellipsoid(int segments_wl, int segments_h, float radius = 1., float end_angle = 360.); + +Mesh * disc(int segments, float radius = 1., float end_angle = 360.); + +Mesh * cone(int segments, float radius = 1., float height = 1.); + +Mesh * cylinder(int segments, float radius = 1., float height = 1., float end_angle = 360.); + +Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1 + +Mesh * torus(int segments_main = 30, int segments_second = 16, float radius_main = 2.5, float radius_second = 0.5, float end_angle = 360.); + + +Mesh * lineFrame(QVector3D p0, QVector3D p1); + +Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.); + +Mesh * ellipsoidFrame(int segments_wl, int segments_h, float radius = 1.); + +Mesh * coneFrame(int segments, float radius = 1., float height = 1.); + +} + +/* +class GLPrimitivePoint: public GLObjectBase +{ +public: + GLPrimitivePoint(double size = 1., QVector3D pos = QVector3D()) {sz = 8.;} + virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); +private: + double sz; +}; + + + + +class GLPrimitiveLine: public GLObjectBase +{ +public: + GLPrimitiveLine(QVector3D p0_ = QVector3D(), QVector3D p1_ = QVector3D()) {p0 = p0_; p1 = p1_;} + virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); + QVector3D point0() const {return p0;} + QVector3D point1() const {return p1;} + void setPoint0(const QVector3D & p) {p0 = p;} + void setPoint1(const QVector3D & p) {p1 = p;} +private: + QVector3D p0, p1; +}; + + + + +class GLPrimitiveEllipsoid: public GLObjectBase +{ +public: + GLPrimitiveEllipsoid(float width = 1., float length = 1., float height = 1., int seg_wl = 10, int seg_h = 10, QVector3D pos = QVector3D()); + virtual void init(); +private: + void putTriangle(const QVector3D & v0, const QVector3D & v1, const QVector3D & v2); + float w, l, h; + int swl, sh; +}; + + +class GLPrimitiveAxis: public GLObjectBase +{ +public: + GLPrimitiveAxis() {accept_fog = accept_light = cast_shadow = rec_shadow = select_ = false;} + virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); +}; +*/ + +#endif // GLPRIMITIVE_CUBE_H diff --git a/core/glshaders.cpp b/core/glshaders.cpp new file mode 100644 index 0000000..4fff0d2 --- /dev/null +++ b/core/glshaders.cpp @@ -0,0 +1,146 @@ +/* + QGLEngineShaders + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "gltypes.h" +#include "qglview.h" +#include "glshaders.h" +#include "glshaders_headers.h" + +using namespace QGLEngineShaders; + + +bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QString & content, const QString & file, bool add_qgl, const QString & defs) { + if (type == 0 || content.isEmpty()) { + content.clear(); + return true; + } + //qDebug() << "[QGLEngine] Shader" << file << "found" << (QOpenGLShader::ShaderTypeBit)(int)type << "section ..."; + if (add_qgl) { + switch (type) { + case QOpenGLShader::Fragment: + content.prepend(qgl_fragment_head); + content.prepend(qgl_uniform); + content.prepend(qgl_structs); + break; + case QOpenGLShader::Vertex : + content.prepend(qgl_vertex_head ); + break; + case QOpenGLShader::Geometry: + content.prepend(qgl_geometry_head); + break; + } + } + content.prepend(defs); + content.prepend(qgl_common_head); + bool ret = prog->addShaderFromSourceCode(type, content.toLatin1()); + if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log(); + content.clear(); + return ret; +} + + +QString prepareDefines(const QStringList & defines) { + if (defines.isEmpty()) return QString(); + QString ret; + foreach (QString s, defines) + ret.append("#define " + s + "\n"); + return ret; +} + + +bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl, const QStringList & defines) { + if (!prog) + prog = new QOpenGLShaderProgram(); + prog->removeAllShaders(); + QFile f(file); + if (!f.open(QIODevice::ReadOnly)) { + qDebug() << "[QGLEngine] Shader" << file << "Error: can`t open file!"; + return false; + } + QTextStream ts(&f); + QString cur_shader, line, pl, defs = prepareDefines(defines); + QOpenGLShader::ShaderType type = 0; + while (!ts.atEnd()) { + line = ts.readLine(); + pl = line.trimmed().remove(' ').remove('\t').mid(2).toLower(); + pl.chop(2); + if (pl == "vertex" || pl == "vert") { + if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; + type = QOpenGLShader::Vertex; + continue; + } + if (pl == "fragment" || pl == "frag") { + if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; + type = QOpenGLShader::Fragment; + continue; + } + if (pl == "geometry" || pl == "geom") { + if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; + type = QOpenGLShader::Geometry; + continue; + } + if (pl == "tessellation_control") { + if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; + type = QOpenGLShader::TessellationControl; + continue; + } + if (pl == "tessellation_evaluation") { + if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; + type = QOpenGLShader::TessellationEvaluation; + continue; + } + cur_shader.append("\n"); + cur_shader.append(line); + } + if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; + if (!prog->link()) { + qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log(); + return false; + } + qDebug() << "[QGLEngine] Shader" << file << "ok"; + return true; +} + + +bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl, const QStringList & defines) { + if (!prog) + prog = new QOpenGLShaderProgram(); + prog->removeAllShaders(); + QString cur_shader, defs = prepareDefines(defines); + foreach (QString f, files) { + QFileInfo fi(f); + QOpenGLShader::ShaderType type = 0; + if (fi.suffix().toLower() == "vert") type = QOpenGLShader::Vertex ; + if (fi.suffix().toLower() == "frag") type = QOpenGLShader::Fragment; + if (fi.suffix().toLower() == "geom") type = QOpenGLShader::Geometry; + if (type == 0) continue; + QFile file(f); + if (!file.open(QIODevice::ReadOnly)) { + qDebug() << "[QGLEngine] Shader" << f << "Error: can`t open file!"; + return false; + } + cur_shader = file.readAll(); + if (!addShader(prog, type, cur_shader, f, add_qgl, defs)) return false; + } + if (!prog->link()) { + qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log(); + return false; + } + qDebug() << "[QGLEngine] Shader" << files << "ok"; + return true; +} diff --git a/core/glshaders.h b/core/glshaders.h new file mode 100644 index 0000000..57fc6a9 --- /dev/null +++ b/core/glshaders.h @@ -0,0 +1,31 @@ +/* + QGLEngineShaders + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLSHADERS_H +#define GLSHADERS_H + +#include "gltypes.h" + +namespace QGLEngineShaders { + +bool loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl = true, const QStringList & defines = QStringList()); +bool loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl = true, const QStringList & defines = QStringList()); + +} + +#endif // GLSHADERS_H diff --git a/core/glshaders_headers.h b/core/glshaders_headers.h new file mode 100644 index 0000000..dac5c6e --- /dev/null +++ b/core/glshaders_headers.h @@ -0,0 +1,127 @@ +/* + QGLEngineShaders + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLSHADERS_HEADERS_H +#define GLSHADERS_HEADERS_H + +namespace QGLEngineShaders { + +const int max_materials = 128; +const int max_lights = 256 ; + +const char qgl_common_head[] = + "#version 400 core\n" + ""; + +const char qgl_vertex_head[] = + "layout(location = 1 ) in vec3 qgl_Vertex ;\n" + "layout(location = 2 ) in vec3 qgl_Normal ;\n" + "layout(location = 3 ) in vec3 qgl_Tangent ;\n" + "layout(location = 4 ) in vec3 qgl_Bitangent ;\n" + "layout(location = 5 ) in vec2 qgl_Texture ;\n" + "layout(location = 6 ) in uint qgl_Material ;\n" + "layout(location = 7 ) in uint qgl_ObjectSelected;\n" + "layout(location = 8 ) in uint qgl_ObjectID ;\n" + "layout(location = 9 ) in vec4 qgl_ObjectColor ;\n" + "layout(location = 10) in mat4 qgl_ModelMatrix ;\n" + "out vec2 qgl_FragTexture;\n" + "flat out uint qgl_MaterialIndex;\n" + "uniform mat4 qgl_ViewMatrix;\n" + "uniform mat4 qgl_ViewProjMatrix;\n" + "mat3 qgl_getNormalMatrix() {return inverse(mat3(qgl_ViewMatrix * qgl_ModelMatrix));}\n" + "mat3 qgl_getTangentMatrix() {return mat3(qgl_ViewMatrix * qgl_ModelMatrix);}\n" + "vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1));}\n" + ""; + +const char qgl_fragment_head[] = + "in vec2 qgl_FragTexture;\n" + "flat in uint qgl_MaterialIndex;\n" + "out vec4 qgl_FragData[gl_MaxDrawBuffers];\n" + "vec4 qgl_materialTexture(uint type, vec2 coord, vec4 tex_shift) {\n" + " coord *= qgl_material[qgl_MaterialIndex].map[type].scale;\n" + " vec4 t = texture(qgl_texture_array[qgl_material[qgl_MaterialIndex].map[type].array_index],\n" + " vec3(coord, qgl_material[qgl_MaterialIndex].map[type].map_index));\n" + " t += tex_shift;\n" + " t.rgb = t.rgb * qgl_material[qgl_MaterialIndex].map[type].amount + qgl_material[qgl_MaterialIndex].map[type].offset;\n" + " return t;\n" + "}\n" + "#define qgl_FragColor qgl_FragData[0]\n" + ""; + +const char qgl_geometry_head[] = + ""; + +const char qgl_structs[] = + "#define QGL_MAPS_COUNT 6\n" + "#define QGL_MAP_DIFFUSE 0\n" + "#define QGL_MAP_NORMAL 1\n" + "#define QGL_MAP_METALNESS 2\n" + "#define QGL_MAP_ROUGHNESS 3\n" + "#define QGL_MAP_EMISSION 4\n" + "#define QGL_MAP_RELIEF 5\n" + "#define QGL_TEXTURE_ARRAY_EMPTY 0\n" + "#define QGL_TEXTURE_ARRAY_MAPS 1\n" + "struct QGLMap {\n" + " float offset;\n" + " float amount;\n" + " vec2 scale;\n" + " uint array_index;\n" + " uint map_index;\n" + "};\n" + "struct QGLMaterial {\n" + " vec4 color_diffuse;\n" + //" vec4 color_specular;\n" + " vec4 color_emission;\n" + " float transparency;\n" + " float reflectivity;\n" + " float iof;\n" + " float dispersion;\n" + " QGLMap map[QGL_MAPS_COUNT];\n" + "};\n" + "struct QGLLightParameter {\n" + " vec4 color;\n" + " vec4 decay_intensity;\n" + " vec4 angles;\n" + //" sampler2DShadow shadow;\n" + //" sampler2D shadowColor\n" + //" mat4 shadowMatrix;\n" + //" vec4 shadowDir0;\n" + //" vec4 shadowDir1;\n" + "};\n" + "struct QGLLightPosition {\n" + " vec4 position;\n" + " vec4 direction;\n" + "};\n" + ""; + +const char qgl_uniform[] = + "layout (std140) uniform QGLMaterialData {\n" + " QGLMaterial qgl_material[128];\n" + "};\n" + "layout (std140) uniform QGLLightParameterData {\n" + " QGLLightParameter qgl_light_parameter[256];\n" + "};\n" + "layout (std140) uniform QGLLightPositionData {\n" + " QGLLightPosition qgl_light_position[256];\n" + "};\n" + "uniform sampler2DArray qgl_texture_array[2];\n" + ""; + +} + +#endif // GLSHADERS_HEADERS_H diff --git a/core/glshaders_types.cpp b/core/glshaders_types.cpp new file mode 100644 index 0000000..fe57b1b --- /dev/null +++ b/core/glshaders_types.cpp @@ -0,0 +1,97 @@ +/* + QGLEngineShaders + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "glshaders_types.h" + + +QGLEngineShaders::QGLMap::QGLMap() { + offset = 0.; + amount = 1.; + scale = QVector2D(1., 1.); + array_index = map_index = 0; +} + + +QGLEngineShaders::QGLMaterial::QGLMaterial() { + color_diffuse = QVector4D(1., 1., 1., 0.); + color_emission = QVector4D(0., 0., 0., 0.); + transparency = 0.; + reflectivity = 0.; + iof = 0.; + dispersion = 0.; + map[mtNormal].map_index = emrBlue; + map[mtRoughness].amount = 0.75; + map[mtMetalness].amount = 0.25; +} + + +void QGLEngineShaders::prepareDrawGeom(QOpenGLExtraFunctions * f) { + //qDebug() << "prepareDrawGeom"; + + f->glEnableVertexAttribArray(pos_loc ); + f->glEnableVertexAttribArray(normal_loc ); + f->glEnableVertexAttribArray(tangent_loc ); + f->glEnableVertexAttribArray(bitangent_loc); + f->glEnableVertexAttribArray(tex_loc ); + + int size = sizeof(Vertex); + f->glVertexAttribPointer(pos_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)pos_offset ); + f->glVertexAttribPointer(normal_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)normal_offset ); + f->glVertexAttribPointer(tangent_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)tangent_offset ); + f->glVertexAttribPointer(bitangent_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)bitangent_offset); + f->glVertexAttribPointer(tex_loc , 2, GL_FLOAT, GL_FALSE, size, (const void *)tex_offset ); +} + + +void QGLEngineShaders::prepareDrawObj(QOpenGLExtraFunctions * f) { + //qDebug() << "prepareDrawObj"; + + f->glEnableVertexAttribArray(material_loc ); + f->glEnableVertexAttribArray(object_id_loc); + f->glEnableVertexAttribArray(color_loc ); + for (int i = 0; i < 4; ++i) { + f->glEnableVertexAttribArray(modelmatrix_loc + i); + } + + GLsizei size = sizeof(Object); + f->glVertexAttribIPointer(material_loc , 1, GL_UNSIGNED_INT , size, (const void *)material_offset ); + f->glVertexAttribIPointer(object_id_loc, 1, GL_UNSIGNED_INT , size, (const void *)object_id_offset); + f->glVertexAttribPointer (color_loc , 4, GL_FLOAT, GL_FALSE, size, (const void *)color_offset ); + for (int i = 0; i < 4; ++i) { + f->glVertexAttribPointer(modelmatrix_loc + i, 4, GL_FLOAT, GL_FALSE, size, (const void *)(modelmatrix_offset + sizeof(QVector4D)*i)); + } + + f->glVertexAttribDivisor(material_loc , 1); + f->glVertexAttribDivisor(object_id_loc, 1); + f->glVertexAttribDivisor(color_loc , 1); + for (int i = 0; i < 4; ++i) { + f->glVertexAttribDivisor(modelmatrix_loc + i, 1); + } + +} + + +void QGLEngineShaders::prepareDrawSel(QOpenGLExtraFunctions * f) { + //qDebug() << "prepareDrawObj"; + + f->glEnableVertexAttribArray(is_selected_loc); + GLsizei size = 1; + f->glVertexAttribIPointer(is_selected_loc, 1, GL_UNSIGNED_BYTE, size, (const void *)is_selected_offset); + f->glVertexAttribDivisor(is_selected_loc, 1); + +} diff --git a/core/glshaders_types.h b/core/glshaders_types.h new file mode 100644 index 0000000..55f44bc --- /dev/null +++ b/core/glshaders_types.h @@ -0,0 +1,144 @@ +/* + QGLEngineShaders + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLSHADERS_TYPES_H +#define GLSHADERS_TYPES_H + +#include "gltypes.h" + +namespace QGLEngineShaders { + + +/// VBO + +// geometry +const GLsizei pos_offset = 0; +const GLsizei normal_offset = sizeof(QVector3D) + pos_offset ; +const GLsizei tangent_offset = sizeof(QVector3D) + normal_offset ; +const GLsizei bitangent_offset = sizeof(QVector3D) + tangent_offset ; +const GLsizei tex_offset = sizeof(QVector3D) + bitangent_offset; + +// object +const GLsizei material_offset = 0; +const GLsizei object_id_offset = sizeof(GLuint ) + material_offset ; +const GLsizei color_offset = sizeof(GLuint ) + object_id_offset ; +const GLsizei modelmatrix_offset = sizeof(QVector4D) + color_offset; + +const GLsizei is_selected_offset = 0; + +const GLuint pos_loc = 1 ; // qgl_Vertex +const GLuint normal_loc = 2 ; // qgl_Normal +const GLuint tangent_loc = 3 ; // qgl_Tangent +const GLuint bitangent_loc = 4 ; // qgl_Bitangent +const GLuint tex_loc = 5 ; // qgl_Texture + +const GLuint material_loc = 6 ; // qgl_Material +const GLuint object_id_loc = 8 ; // qgl_ObjectID +const GLuint color_loc = 9 ; // qgl_ObjectColor +const GLuint modelmatrix_loc = 10; // qgl_ModelViewProjectionMatrix + +const GLuint is_selected_loc = 7 ; // qgl_ObjectSelected + +#pragma pack(push, 1) +struct Vertex { + QVector3D pos; + QVector3D normal; + QVector3D tangent; + QVector3D bitangent; + QVector2D tex; +}; +struct Object { + Object() { + material = object_id = 0; + color = QVector4D(1,1,1,1); + QMatrix4x4().copyDataTo(modelmatrix); + } + GLuint material; + GLuint object_id; + QVector4D color; + GLfloat modelmatrix[16]; +}; +#pragma pack(pop) + + +/// UBO + +enum BindingPoints { + bpMaterials, + bpLightParameters, + bpLightPositions, +}; + +enum MapType { + mtDiffuse = 0, + mtNormal = 1, + mtMetalness = 2, + mtRoughness = 3, + mtEmission = 4, + mtRelief = 5, +}; +enum TextureArrayRole { + tarEmpty = 0, + tarMaps = 1, +}; +enum EmptyMapRole { + emrWhite = 0, + emrBlue = 1, +}; +#define QGL_MAPS_COUNT 6 +#pragma pack(push, 1) +struct QGLMap { + QGLMap(); + GLfloat offset; + GLfloat amount; + QVector2D scale; + GLuint array_index; + GLuint map_index; + GLfloat __res_2[2]; +}; +struct QGLMaterial { + QGLMaterial(); + QVector4D color_diffuse; + QVector4D color_emission; + GLfloat transparency; + GLfloat reflectivity; + GLfloat iof; + GLfloat dispersion; + QGLMap map[QGL_MAPS_COUNT]; +}; +struct QGLLightParameter { + QVector4D color; + QVector4D decay_intensity; // [^0, ^1, ^2, intensity] + QVector4D angles; // [start, cos(start), end, cos(end)] + //GLfloat shadow; + //GLfloat shadowMatrix[16]; +}; +struct QGLLightPosition { + QVector4D position; + QVector4D direction; +}; +#pragma pack(pop) + +void prepareDrawGeom(QOpenGLExtraFunctions * f); +void prepareDrawObj (QOpenGLExtraFunctions * f); +void prepareDrawSel (QOpenGLExtraFunctions * f); + + +} + +#endif // GLSHADERS_TYPES_H diff --git a/core/gltexturearray.cpp b/core/gltexturearray.cpp new file mode 100644 index 0000000..1149ad6 --- /dev/null +++ b/core/gltexturearray.cpp @@ -0,0 +1,96 @@ +/* + QGL Texture2DArray + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "gltexturearray.h" + + +Texture2DArray::Texture2DArray(bool filter) { + target_ = GL_TEXTURE_2D_ARRAY; + texture_ = 0; + layers_ = 0; + filtering_ = filter; +} + + +Texture2DArray::~Texture2DArray() { +} + + +void Texture2DArray::init(QOpenGLExtraFunctions * f) { + if (!isInit()) { + f->glGenTextures(1, &texture_); + } +} + + +void Texture2DArray::destroy(QOpenGLExtraFunctions * f) { + if (texture_ != 0) { + f->glDeleteTextures(1, &texture_); + } + texture_ = 0; +} + + +void Texture2DArray::bind(QOpenGLExtraFunctions * f, int channel) { + f->glActiveTexture(GL_TEXTURE0 + channel); + f->glBindTexture(target_, texture_); +} + + +void Texture2DArray::release(QOpenGLExtraFunctions * f) { + f->glBindTexture(target_, 0); +} + + +bool Texture2DArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count) { + if (new_size.isNull() || layers_count <= 0) return false; + if ((size_ == new_size) && (layers_ >= layers_count)) return false; + size_ = new_size; + layers_ = layers_count; + f->glBindTexture(target_, texture_); + f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_REPEAT); + f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (filtering_) { + f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + f->glTexParameteri(target_, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8); + } else { + f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + f->glTexImage3D(target_, 0, GL_RGBA8, size_.width(), size_.height(), layers_, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + return true; +} + + +void Texture2DArray::load(QOpenGLExtraFunctions * f, const QImage & image, int layer) { + if (image.isNull() || size_.isNull() || layer < 0 || layer >= layers_) return; + QImage im = image.mirrored(false, true) + .scaled(size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation) + .convertToFormat(QImage::Format_RGBA8888); + //qDebug() << "Texture2DArray::load image" << image.size() << "to layer" << layer; + f->glTexSubImage3D(target_, 0, 0, 0, layer, size_.width(), size_.height(), 1, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits()); +} + + +void Texture2DArray::mipmaps(QOpenGLExtraFunctions * f) { + f->glBindTexture(target_, texture_); + f->glGenerateMipmap(target_); +} diff --git a/core/gltexturearray.h b/core/gltexturearray.h new file mode 100644 index 0000000..f8b32b7 --- /dev/null +++ b/core/gltexturearray.h @@ -0,0 +1,56 @@ +/* + QGL Texture2DArray + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLTEXTUREARRAY_H +#define GLTEXTUREARRAY_H + +#include "gltypes.h" + + +class Texture2DArray +{ + friend class ObjectBase; +public: + Texture2DArray(bool filter); + ~Texture2DArray(); + + void init (QOpenGLExtraFunctions * f); + void destroy (QOpenGLExtraFunctions * f); + + void bind (QOpenGLExtraFunctions * f, int channel = 0); + void release (QOpenGLExtraFunctions * f); + + // returns true if size changed + bool resize (QOpenGLExtraFunctions * f, QSize new_size, int layers_count); + void load (QOpenGLExtraFunctions * f, const QImage & image, int layer); + void mipmaps (QOpenGLExtraFunctions * f); + + GLuint ID() const {return texture_;} + bool isInit() const {return texture_ != 0;} + +private: + GLenum target_; + GLuint texture_; + QSize size_; + int layers_; + bool filtering_; + +}; + + +#endif // GLTEXTUREARRAY_H diff --git a/core/gltransform.cpp b/core/gltransform.cpp new file mode 100644 index 0000000..d92ebb7 --- /dev/null +++ b/core/gltransform.cpp @@ -0,0 +1,441 @@ +/* + QGL Transform + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +#include "gltransform.h" +#include "gltypes.h" +#include + + +inline void composeQMatrix4x4(const QVector3D & position, const QVector3D & orientation, const QVector3D & scale, QMatrix4x4 &m) { + const QMatrix3x3 rot3x3(Transform::toRotationMatrix(orientation)); + + // set up final matrix with scale, rotation and translation + m(0, 0) = scale.x() * rot3x3(0, 0); m(0, 1) = scale.y() * rot3x3(0, 1); m(0, 2) = scale.z() * rot3x3(0, 2); m(0, 3) = position.x(); + m(1, 0) = scale.x() * rot3x3(1, 0); m(1, 1) = scale.y() * rot3x3(1, 1); m(1, 2) = scale.z() * rot3x3(1, 2); m(1, 3) = position.y(); + m(2, 0) = scale.x() * rot3x3(2, 0); m(2, 1) = scale.y() * rot3x3(2, 1); m(2, 2) = scale.z() * rot3x3(2, 2); m(2, 3) = position.z(); + // no projection term + m(3, 0) = 0.0f; m(3, 1) = 0.0f; m(3, 2) = 0.0f; m(3, 3) = 1.0f; +} + +inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D & D, QVector3D & U) { + // Factor M = QR = QDU where Q is orthogonal, D is diagonal, + // and U is upper triangular with ones on its diagonal. + // Algorithm uses Gram-Schmidt orthogonalization (the QR algorithm). + // + // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then + // q0 = m0/|m0| + // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| + // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| + // + // where |V| indicates length of vector V and A*B indicates dot + // product of vectors A and B. The matrix R has entries + // + // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2 + // r10 = 0 r11 = q1*m1 r12 = q1*m2 + // r20 = 0 r21 = 0 r22 = q2*m2 + // + // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00, + // u02 = r02/r00, and u12 = r12/r11. + + // Q = rotation + // D = scaling + // U = shear + + // D stores the three diagonal entries r00, r11, r22 + // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12 + + // build orthogonal matrix Q + float invLen = 1.0f / std::sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0)); + Q(0, 0) = m(0, 0) * invLen; + Q(1, 0) = m(1, 0) * invLen; + Q(2, 0) = m(2, 0) * invLen; + + float dot = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1); + Q(0, 1) = m(0, 1) - dot * Q(0, 0); + Q(1, 1) = m(1, 1) - dot * Q(1, 0); + Q(2, 1) = m(2, 1) - dot * Q(2, 0); + invLen = 1.0f / std::sqrt(Q(0, 1) * Q(0, 1) + Q(1, 1) * Q(1, 1) + Q(2, 1) * Q(2, 1)); + Q(0, 1) *= invLen; + Q(1, 1) *= invLen; + Q(2, 1) *= invLen; + + dot = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2); + Q(0, 2) = m(0, 2) - dot * Q(0, 0); + Q(1, 2) = m(1, 2) - dot * Q(1, 0); + Q(2, 2) = m(2, 2) - dot * Q(2, 0); + dot = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2); + Q(0, 2) -= dot * Q(0, 1); + Q(1, 2) -= dot * Q(1, 1); + Q(2, 2) -= dot * Q(2, 1); + invLen = 1.0f / std::sqrt(Q(0, 2) * Q(0, 2) + Q(1, 2) * Q(1, 2) + Q(2, 2) * Q(2, 2)); + Q(0, 2) *= invLen; + Q(1, 2) *= invLen; + Q(2, 2) *= invLen; + + // guarantee that orthogonal matrix has determinant 1 (no reflections) + const float det = Q(0, 0) * Q(1, 1) * Q(2, 2) + Q(0, 1) * Q(1, 2) * Q(2, 0) + + Q(0, 2) * Q(1, 0) * Q(2, 1) - Q(0, 2) * Q(1, 1) * Q(2, 0) - + Q(0, 1) * Q(1, 0) * Q(2, 2) - Q(0, 0) * Q(1, 2) * Q(2, 1); + if (det < 0.0f) + Q *= -1.0f; + + // build "right" matrix R + QMatrix3x3 R(Qt::Uninitialized); + R(0, 0) = Q(0, 0) * m(0, 0) + Q(1, 0) * m(1, 0) + Q(2, 0) * m(2, 0); + R(0, 1) = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1); + R(1, 1) = Q(0, 1) * m(0, 1) + Q(1, 1) * m(1, 1) + Q(2, 1) * m(2, 1); + R(0, 2) = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2); + R(1, 2) = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2); + R(2, 2) = Q(0, 2) * m(0, 2) + Q(1, 2) * m(1, 2) + Q(2, 2) * m(2, 2); + + // the scaling component + D[0] = R(0, 0); + D[1] = R(1, 1); + D[2] = R(2, 2); + + // the shear component + U[0] = R(0, 1) / D[0]; + U[1] = R(0, 2) / D[0]; + U[2] = R(1, 2) / D[1]; +} + +inline bool hasScale(const QMatrix4x4 &m) { + // If the columns are orthonormal and form a right-handed system, then there is no scale + float t(m.determinant()); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + t = m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + t = m(0, 1) * m(0, 1) + m(1, 1) * m(1, 1) + m(2, 1) * m(2, 1); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + t = m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + return false; +} + +inline void decomposeQMatrix4x4(const QMatrix4x4 & m, QVector3D & position, QVector3D & orientation, QVector3D & scale) { + Q_ASSERT(m.isAffine()); + + const QMatrix3x3 m3x3(m.toGenericMatrix<3, 3>()); + + QMatrix3x3 rot3x3(Qt::Uninitialized); + if (hasScale(m)) { + decomposeQMatrix3x3(m3x3, rot3x3, scale, position); + } else { + // we know there is no scaling part; no need for QDU decomposition + scale = QVector3D(1.0f, 1.0f, 1.0f); + rot3x3 = m3x3; + } + orientation = Transform::fromRotationMatrix(rot3x3); + position = QVector3D(m(0, 3), m(1, 3), m(2, 3)); +} + + + + +Transform::Transform(): m_scale(1.0f, 1.0f, 1.0f), + m_translation(), m_eulerRotationAngles(), m_matrixDirty(false) { +} + + +Transform & Transform::operator =(const Transform & t) { + m_scale = t.m_scale; + m_translation = t.m_translation; + m_eulerRotationAngles = t.m_eulerRotationAngles; + m_matrixDirty = true; + return *this; +} + + +void Transform::setMatrix(const QMatrix4x4 & m) { + if (m != matrix()) { + m_matrix = m; + m_matrixDirty = false; + QVector3D s; + QVector3D t; + QVector3D r; + decomposeQMatrix4x4(m, t, r, s); + m_scale = s; + m_translation = t; + m_eulerRotationAngles = r; + } +} + + +void Transform::setRotationX(float r) { + if (m_eulerRotationAngles.x() == r) + return; + m_eulerRotationAngles.setX(r); + m_matrixDirty = true; +} + + +void Transform::setRotationY(float r) { + if (m_eulerRotationAngles.y() == r) + return; + m_eulerRotationAngles.setY(r); + m_matrixDirty = true; +} + + +void Transform::setRotationZ(float r) { + if (m_eulerRotationAngles.z() == r) + return; + m_eulerRotationAngles.setZ(r); + m_matrixDirty = true; +} + + +QMatrix4x4 Transform::matrix() const { + buildMatrix(); + return m_matrix; +} + + +QMatrix4x4 Transform::matrixRotate() const { + buildMatrix(); + return m_matrixR; +} + + +QMatrix4x4 Transform::matrixScale() const { + buildMatrix(); + return m_matrixS; +} + + +QMatrix4x4 Transform::matrixRotateScale() const { + buildMatrix(); + return m_matrixWT; +} + + +QVector3D Transform::direction() const { + return matrixRotate().mapVector(QVector3D(0,0,-1)).normalized(); +} + + +void Transform::buildMatrix() const { + if (m_matrixDirty) { + composeQMatrix4x4(m_translation, m_eulerRotationAngles, m_scale, m_matrix); + composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, m_scale, m_matrixWT); + composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, QVector3D(1,1,1), m_matrixR); + composeQMatrix4x4(QVector3D(), QVector3D(), m_scale, m_matrixS); + m_matrixDirty = false; + } +} + + +float Transform::rotationX() const { + return m_eulerRotationAngles.x(); +} + + +float Transform::rotationY() const { + return m_eulerRotationAngles.y(); +} + + +float Transform::rotationZ() const { + return m_eulerRotationAngles.z(); +} + + +void Transform::setScale(const QVector3D & s) { + if (s != m_scale) { + m_scale = s; + m_matrixDirty = true; + } +} + + +void Transform::setScaleX(float s) { + if (s != m_scale.x()) { + m_scale.setX(s); + m_matrixDirty = true; + } +} + + +void Transform::setScaleY(float s) { + if (s != m_scale.y()) { + m_scale.setY(s); + m_matrixDirty = true; + } +} + + +void Transform::setScaleZ(float s) { + if (s != m_scale.z()) { + m_scale.setZ(s); + m_matrixDirty = true; + } +} + + +QVector3D Transform::scale3D() const { + return m_scale; +} + + +float Transform::scale() const { + return m_scale.x(); +} + + +void Transform::setRotation(const QVector3D & r) { + if (r != m_eulerRotationAngles) { + m_eulerRotationAngles = r; + m_matrixDirty = true; + } +} + + +QVector3D Transform::rotation() const { + return m_eulerRotationAngles; +} + + +void Transform::setTranslation(const QVector3D & t) { + if (t != m_translation) { + m_translation = t; + m_matrixDirty = true; + } +} + + +void Transform::setTranslationX(float t) { + if (t != m_translation.x()) { + m_translation.setX(t); + m_matrixDirty = true; + } +} + + +void Transform::setTranslationY(float t) { + if (t != m_translation.y()) { + m_translation.setY(t); + m_matrixDirty = true; + } +} + + +void Transform::setTranslationZ(float t) { + if (t != m_translation.z()) { + m_translation.setZ(t); + m_matrixDirty = true; + } +} + + +QVector3D Transform::translation() const { + return m_translation; +} + + +QQuaternion Transform::fromAxisAndAngle(const QVector3D & axis, float angle) { + return QQuaternion::fromAxisAndAngle(axis, angle); +} + + +QQuaternion Transform::fromAxisAndAngle(float x, float y, float z, float angle) { + return QQuaternion::fromAxisAndAngle(x, y, z, angle); +} + + +QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2) { + const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); + const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); + return q2 * q1; +} + + +QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2, + const QVector3D & axis3, float angle3) { + const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); + const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); + const QQuaternion q3 = QQuaternion::fromAxisAndAngle(axis3, angle3); + return q3 * q2 * q1; +} + + +QQuaternion Transform::fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) { + return QQuaternion::fromAxes(xAxis, yAxis, zAxis); +} + + +QVector3D Transform::fromDirection(QVector3D d, float pitch) { + QVector3D ret; + d.normalize(); + ret[0] = M_PI - acos(d.z()); + ret[1] = pitch * deg2rad; + ret[2] = -atan2(d.x(), d.y()); + normalizeAngleRad(ret[0]); + normalizeAngleRad(ret[2]); + return ret * rad2deg; +} + + +QVector3D Transform::fromRotationMatrix(const QMatrix3x3 & m) { + //return QQuaternion::fromRotationMatrix(m); + float sy = sqrt(m(0,0) * m(0,0) + m(1,0) * m(1,0)); + bool singular = sy < 1.E-6; // If + float x, y, z; + if (!singular) { + x = atan2( m(2,1), m(2,2)); + y = atan2(-m(2,0), sy); + z = atan2( m(1,0), m(0,0)); + } else { + x = atan2(-m(1,2), m(1,1)); + y = atan2(-m(2,0), sy); + z = 0.; + } + return QVector3D(x, y, z) * rad2deg; +} + + +QMatrix3x3 Transform::toRotationMatrix(const QVector3D & r) { + QMatrix4x4 m; + if (r.z() != 0.f) m.rotate(r.z(), 0., 0., 1.); + if (r.y() != 0.f) m.rotate(r.y(), 0., 1., 0.); + if (r.x() != 0.f) m.rotate(r.x(), 1., 0., 0.); + return m.toGenericMatrix<3,3>(); +} + + +QMatrix4x4 Transform::rotateAround(const QVector3D & point, float angle, const QVector3D & axis) { + QMatrix4x4 m; + m.translate(point); + m.rotate(angle, axis); + m.translate(-point); + return m; +} + + +QMatrix4x4 Transform::rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) { + return QMatrix4x4(xAxis.x(), yAxis.x(), zAxis.x(), 0.0f, + xAxis.y(), yAxis.y(), zAxis.y(), 0.0f, + xAxis.z(), yAxis.z(), zAxis.z(), 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} diff --git a/core/gltransform.h b/core/gltransform.h new file mode 100644 index 0000000..f1e42de --- /dev/null +++ b/core/gltransform.h @@ -0,0 +1,119 @@ +/* + QGL Transform + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLTRANSFORM_H +#define GLTRANSFORM_H + +#include +#include +#include +#include + + +class Transform { + friend QDataStream & operator >>(QDataStream & s, Transform & v); +public: + Transform(); + Transform & operator =(const Transform & t); + + float scale() const; + QVector3D scale3D() const; + QVector3D rotation() const; + QVector3D translation() const; + QMatrix4x4 matrix() const; + QMatrix4x4 matrixRotate() const; + QMatrix4x4 matrixScale() const; + QMatrix4x4 matrixRotateScale() const; + QVector3D direction() const; + + float rotationX() const; + float rotationY() const; + float rotationZ() const; + + void setScale(float s) {setScale(QVector3D(s, s, s));} + void setScale(const QVector3D & s); + void setScaleX(float s); + void setScaleY(float s); + void setScaleZ(float s); + + void setRotation(const QVector3D & r); + void setRotationX(float r); + void setRotationY(float r); + void setRotationZ(float r); + + void setTranslation(const QVector3D & t); + void setTranslationX(float t); + void setTranslationY(float t); + void setTranslationZ(float t); + + void setMatrix(const QMatrix4x4 & matrix); + void setDirty(bool yes = true) {m_matrixDirty = yes;} + + + static QQuaternion fromAxisAndAngle(const QVector3D & axis, float angle); + static QQuaternion fromAxisAndAngle(float x, float y, float z, float angle); + + static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2); + static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2, + const QVector3D & axis3, float angle3); + static QQuaternion fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis); + + static QVector3D fromDirection(QVector3D d, float pitch = 0.f); + static QVector3D fromRotationMatrix(const QMatrix3x3 & m); + static QMatrix3x3 toRotationMatrix(const QVector3D & r); + + static QMatrix4x4 rotateAround(const QVector3D & point, float angle, const QVector3D & axis); + static QMatrix4x4 rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis); + +protected: + void buildMatrix() const; + + QVector3D m_scale; + QVector3D m_translation; + QVector3D m_eulerRotationAngles; + + mutable QMatrix4x4 m_matrix, m_matrixWT, m_matrixR, m_matrixS; + mutable bool m_matrixDirty; + +}; + + +inline QDataStream & operator <<(QDataStream & s, const Transform & v) { + //ChunkStream cs; + //cs.add(1, v.matrix()); + //s << cs.data(); return s; + s << v.matrix(); return s; +} +inline QDataStream & operator >>(QDataStream & s, Transform & v) { + //ChunkStream cs(s); + //while (!cs.atEnd()) { + // switch (cs.read()) { + // case 1: v.setMatrix(cs.getData()); break; + // } + //} + //return s; + QMatrix4x4 m; + s >> m; + v.setMatrix(m); + v.m_matrixDirty = true; + return s; +} + +#endif // QT3DCORE_QTRANSFORM_H diff --git a/core/gltypes.cpp b/core/gltypes.cpp new file mode 100644 index 0000000..22493de --- /dev/null +++ b/core/gltypes.cpp @@ -0,0 +1,373 @@ +/* + QGLView Types + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "glcamera.h" +#include "qglview.h" +#include "gltexture_manager.h" + +#include + +//__GLWidget__ * currentQGLView; +//QMutex globMutex; + + +QString readCharsUntilNull(QDataStream & s) { + QString str; + char ch; + s.readRawData(&ch, 1); + while (ch != '\0') { + str += ch; + s.readRawData(&ch, 1); + } + return str; +} + + +QString findFile(const QString & file, const QStringList & pathes) { + QFileInfo fi(QString(file).replace("\\", "/")); + //qDebug() << "search" << file << "in" << pathes; + if (fi.exists()) return fi.absoluteFilePath(); + QString fn = fi.fileName(); + if (fn.contains("/")) fn = fn.mid(fn.lastIndexOf("/")); + foreach (QString p, pathes) { + QFileInfoList fil = QDir(p).entryInfoList(QStringList(fn), QDir::Files | QDir::NoDotAndDotDot); + //qDebug() << "findFile" << fn << "in" << p << "->" << fil.size(); + if (!fil.isEmpty()) + return fil[0].absoluteFilePath(); + } + return QString(); +} + + +void glDrawQuad(QOpenGLShaderProgram * prog, QVector4D * corner_dirs, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { + //glResetAllTransforms(); + glSetPolygonMode(GL_FILL); + glDisable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + int loc = prog ? prog->attributeLocation("qgl_Color") : -1, + locv = prog ? prog->attributeLocation("qgl_Vertex") : -1, + loct = prog ? prog->attributeLocation("qgl_Texture") : -1, + locc = prog ? prog->attributeLocation("view_corner") : -1; + //if (prog) {qDebug() << locv << loct << locc;} + QOpenGLFunctions * glFuncs = QOpenGLContext::currentContext()->functions(); + if (prog) { + static const GLfloat cols [] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; + static const GLfloat verts[] = {x, y, x+w, y, x, y+h, x+w, y+h}; + static const GLfloat texs [] = {0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f}; + GLfloat vcs[] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + if (corner_dirs) { + vcs[0] = corner_dirs[0].x(); vcs[1] = corner_dirs[0].y(); vcs[2] = corner_dirs[0].z(); + vcs[3] = corner_dirs[1].x(); vcs[4] = corner_dirs[1].y(); vcs[5] = corner_dirs[1].z(); + vcs[6] = corner_dirs[2].x(); vcs[7] = corner_dirs[2].y(); vcs[8] = corner_dirs[2].z(); + vcs[9] = corner_dirs[3].x(); vcs[10] = corner_dirs[3].y(); vcs[11] = corner_dirs[3].z(); + } + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glFuncs->glBindBuffer(GL_ARRAY_BUFFER, 0); + glFuncs->glEnableVertexAttribArray(loc); + glFuncs->glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, cols); + glFuncs->glEnableVertexAttribArray(locv); + glFuncs->glVertexAttribPointer(locv, 2, GL_FLOAT, 0, 0, verts); + glFuncs->glEnableVertexAttribArray(loct); + glFuncs->glVertexAttribPointer(loct, 2, GL_FLOAT, 0, 0, texs); + glFuncs->glEnableVertexAttribArray(locc); + glFuncs->glVertexAttribPointer(locc, 3, GL_FLOAT, 0, 0, vcs); + glFuncs->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glFuncs->glDisableVertexAttribArray(loc); + glFuncs->glDisableVertexAttribArray(locv); + glFuncs->glDisableVertexAttribArray(loct); + glFuncs->glDisableVertexAttribArray(locc); + } else { + glBegin(GL_TRIANGLE_STRIP); + glColor4f(1.f, 1.f, 1.f, 1.f); + glTexCoord2f(0.f, 0.f); glVertex2f(x, y); + glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); + glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); + glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); + glEnd(); + } +} + + +QMatrix4x4 getGLMatrix(GLenum matrix) { + GLfloat gm[16]; + glGetFloatv(matrix, gm); + float qm[16]; + for (int i = 0; i < 16; ++i) + qm[i] = gm[i]; + return QMatrix4x4(qm).transposed(); +} + + +void setGLMatrix(QMatrix4x4 matrix) { + GLfloat gm[16]; + float qm[16]; + matrix.transposed().copyDataTo(qm); + for (int i = 0; i < 16; ++i) + gm[i] = qm[i]; + glLoadMatrixf(gm); +} + + +void qglMultMatrix(const QMatrix4x4 & m) { + GLfloat gm[16]; + float qm[16]; + m.transposed().copyDataTo(qm); + for (int i = 0; i < 16; ++i) + gm[i] = qm[i]; + glMultMatrixf(gm); +} + + +void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format, const GLenum & target) { + //glClearError(); + if (tex == 0) { + f->glGenTextures(1, &tex); + f->glBindTexture(target, tex); + } + //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32) + f->glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr); + else { + int type = GL_UNSIGNED_BYTE; + int fmt = GL_RGBA; + if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGBA32F || format == GL_RGBA16F) + type = GL_FLOAT; + if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGB8 || format == GL_RGB) + fmt = GL_RGB; + f->glTexImage2D(target, 0, format, width, height, 0, fmt, type, nullptr); + //glGenerateMipmap(target); + //qDebug() << "glTexImage2D" << width << height << QString::number(t, 16); + } + //qDebug() << QString::number(glGetError(), 16); +} + + +void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format, const GLenum & target) { + if (tex == 0) { + f->glGenTextures(1, &tex); + } + f->glBindTexture(target, tex); + QImage im = image.mirrored(false, true).convertToFormat(QImage::Format_RGBA8888); + //const QImage & cim(im); + f->glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT); + f->glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT); + f->glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT); + if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) { + f->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + f->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + f->glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8); + } else { + f->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + f->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + glClearError(); + f->glTexImage2D(target, 0, format, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits()); + if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) { + f->glGenerateMipmap(target); + } + //qDebug() << target << format << tex << im.width() << im.height() << im.bits() << QString::number(glGetError(), 16); +} + + +QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_) { + QMatrix4x4 ret; + float t = 1.f / (tanf(angle * deg2rad / 2.f)), e = 2.4e-7f; + if (aspect >= 1.) { + ret(0, 0) = t / aspect; + ret(1, 1) = t; + } else { + ret(0, 0) = t; + ret(1, 1) = t * aspect; + } + ret(2, 2) = e - 1.f;//far_ / (far_ - near_) - 1.; + ret(2, 3) = (e - 2.f) * near_;//2. * far_ * near_ / (far_ - near_); + ret(3, 2) = -1.f; + ret(3, 3) = 0.f; + return ret; +} + + +QImage rotateQImageLeft(const QImage & im) { + QImage ri(im.height(), im.width(), im.format()); + QPainter p(&ri); + p.rotate(90); + p.drawImage(0, -im.height(), im); + p.end(); + return ri; +} + + +QImage rotateQImageRight(const QImage & im) { + QImage ri(im.height(), im.width(), im.format()); + QPainter p(&ri); + p.rotate(-90); + p.drawImage(-im.width(), 0, im); + p.end(); + return ri; +} + + + + +QColor colorFromString(const QString & str) { + QString s = str.trimmed(); + int i = s.indexOf("\t"); + float r, g, b; + r = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t"); + g = s.left(i).toFloat(); s = s.right(s.length() - i - 1); + b = s.toFloat(); + return QColor(r * 255.f, g * 255.f, b * 255.f); +} + + +QVector3D orthToVector(const QVector3D & v, const float & scale) { + if (v.isNull()) return QVector3D(); + QVector3D rv, fn, sn; + if (v.x() != 0.f) rv.setZ(1.); + else if (v.y() != 0.f) rv.setX(1.); + else rv.setY(1.); + fn = QVector3D::crossProduct(v, rv).normalized(); + sn = QVector3D::crossProduct(v, fn).normalized(); + return fn * urand(scale) + sn * urand(scale); +} + + +QVector3D rotateVector(const QVector3D & v, const QVector3D & a) { + QMatrix4x4 m; + m.rotate(a.z(), 0., 0., 1.); + m.rotate(a.y(), 0., 1., 0.); + m.rotate(a.x(), 1., 0., 0.); + return m * v; +} + + +void setVectorLength(QVector3D & v, const float & l) { + float vl = v.length(); + if (vl == 0.f) return; + float c = l / vl; + v *= c; +} + + +void lengthenVector(QVector3D & v, const float & l) { + float vl = v.length(); + if (l == 0.f || vl == 0.f) return; + float c = 1.f + l / vl; + v *= c; +} + + +Vector2i::Vector2i(const QString & str) { + QString s = str.trimmed(); + int i = s.indexOf("\t"); + p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); + p1 = s.toInt(); +} + + +Vector3i::Vector3i(const QString & str) { + QString s = str.trimmed(); + int i = s.indexOf("\t"); + p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); i = s.indexOf("\t"); + p1 = s.left(i).toInt(); s = s.right(s.length() - i - 1); + p2 = s.toInt(); +} + + +void glEnableDepth() { + glEnable(GL_DEPTH_TEST); + //glDepthFunc(GL_GREATER); + glDepthFunc(GL_LESS); + glDepthMask(GL_TRUE); +} + + +void glDisableDepth() { + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); +} + + +void glClearFramebuffer(const QColor & color, bool depth) { + glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + //glClearDepth(0.); + if (depth) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT); +} + + + + +Box3D::Box3D(const QVector & points) { + x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f; + if (points.isEmpty()) return; + float ix, iy, iz, ax, ay, az; + ix = ax = points[0].x(); + iy = ay = points[0].y(); + iz = az = points[0].z(); + for (int i = 1; i < points.size(); ++i) { + ix = qMin(ix, points[i].x()); ax = qMax(ax, points[i].x()); + iy = qMin(iy, points[i].y()); ay = qMax(ay, points[i].y()); + iz = qMin(iz, points[i].z()); az = qMax(az, points[i].z()); + } + x = ix; + y = iy; + z = iz; + length = ax - ix; + width = ay - iy; + height = az - iz; +} + + +QVector Box3D::corners() const { + QVector ret; + ret << QVector3D(x, y, z) << QVector3D(x, y + width, z) << QVector3D(x, y, z + height) << QVector3D(x, y + width, z + height) + << QVector3D(x + length, y, z) << QVector3D(x + length, y + width, z) + << QVector3D(x + length, y, z + height) << QVector3D(x + length, y + width, z + height); + return ret; +} + + +Box3D & Box3D::operator |=(const Box3D & o) { + if (o.isEmpty()) return *this; + if (isEmpty()) *this = o; + else { + GLfloat mx = x + length, my = y + width, mz = z + height; + GLfloat omx = o.x + o.length, omy = o.y + o.width, omz = o.z + o.height; + x = qMin(x, o.x); y = qMin(y, o.y); z = qMin(z, o.z); + mx = qMax(mx, omx); my = qMax(my, omy); mz = qMax(mz, omz); + length = mx - x; width = my - y; height = mz - z; + } + return *this; +} + + +QVector3D vectorFromString(const QString & str) { + QTextStream s(const_cast(&str), QIODevice::ReadOnly); + QVector3D ret; + float f(0.f); + s >> f; ret.setX(f); + s >> f; ret.setY(f); + s >> f; ret.setZ(f); + return ret; +} diff --git a/core/gltypes.h b/core/gltypes.h new file mode 100644 index 0000000..5550643 --- /dev/null +++ b/core/gltypes.h @@ -0,0 +1,303 @@ +/* + QGLView Types + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLTYPES_H +#define GLTYPES_H + +#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__ +# define WINDOWS +#endif +#if __QNX__ || __QNXNTO__ +# define QNX +#endif +#ifdef __APPLE__ +# define MAC +#endif +#ifndef WINDOWS +# ifndef QNX +# ifndef MAC +# define LINUX +# endif +# endif +#endif +#if __GNUC__ +# define CC_GCC +#elif _MSC_VER +# define CC_VC +#endif + + +#include +//#ifndef WINDOWS +//# ifdef MAC +//# include +//# include +//# include +//# else +//# include +//# include +//# include +//# endif +//#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QNX +# include +# include +#else +# include +# include +#endif +#include +#include "qglengine_version.h" + + +//#ifdef WINDOWS +//# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +//# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +//#endif + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif +#ifndef M_2PI +# define M_2PI 6.28318530717958647692 +#endif +#ifndef M_PI_3 +# define M_PI_3 1.04719755119659774615 +#endif + +#ifndef GL_RGBA16F +# define GL_RGBA16F GL_RGBA16F_ARB +#endif + +using std::complex; + +#ifndef PIP_VERSION +typedef long long llong; +typedef unsigned char uchar; +typedef unsigned short int ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned long long ullong; +typedef long double ldouble; + +const float deg2rad = atanf(1.f) / 45.f; +const float rad2deg = 45.f / atanf(1.f); + +# ifdef WINDOWS +inline int random() {return rand();} +# endif +#else +#define random randomi +#endif + +#ifdef CC_VC +inline float round(const float & v) {return floor(v + 0.5);} +#endif +inline float randomu() {return float(random()) / RAND_MAX;} + +inline const QSizeF operator *(const QSizeF & f, const QSizeF & s) {return QSizeF(f.width() * s.width(), f.height() * s.height());} +#ifndef PIP_VERSION +template inline void piSwap(T & f, T & s) {T t(f); f = s; s = t;} +template inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;} +template inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);} +template inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;} +template inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);} +template inline Type piClamp(const Type & v, const Type & min, const Type & max) {return (v > max ? max : (v < min ? min : v));} +inline ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);} +inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} +#endif +// return [-1, 1] +inline float urand(const float & scale = 1.) {return ((float)rand() / RAND_MAX - .5f) * (scale + scale);} +// return [0, 1] +inline float uprand(const float & scale = 1.) {return ((float)rand() / RAND_MAX) * scale;} +QString readCharsUntilNull(QDataStream & s); +QString findFile(const QString & file, const QStringList & pathes); +inline QColor operator *(const QColor & c, float v) {return QColor(piClamp(c.red() * v, 0, 255), piClamp(c.green() * v, 0, 255), piClamp(c.blue() * v, 0, 255), piClamp(c.alpha() * v, 0, 255));} +inline QColor operator /(const QColor & c, float v) {return QColor(piClamp(c.red() / v, 0, 255), piClamp(c.green() / v, 0, 255), piClamp(c.blue() / v, 0, 255), piClamp(c.alpha() / v, 0, 255));} + + +inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());} +inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();} +inline void glSetCapEnabled(GLenum cap, bool on = true) {if (on) glEnable(cap); else glDisable(cap);} +inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);} +inline void deleteGLTexture(QOpenGLExtraFunctions * f, GLuint & tex) {if (tex != 0) f->glDeleteTextures(1, &tex); tex = 0;} +void glEnableDepth(); +void glDisableDepth(); +void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true); +void glDrawQuad(QOpenGLShaderProgram * prog = nullptr, QVector4D * corner_dirs = nullptr, GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f); +void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); +void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); +QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_); +QImage rotateQImageLeft(const QImage & im); +QImage rotateQImageRight(const QImage & im); +inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);} + +class QGLView; +class MouseController; +class ObjectBase; +class AimedObject; +class Light; +class Camera; +class Texture; +class CubeTexture; +class Map; +class Material; +class TextureManager; +class Texture2DArray; +class Framebuffer; +class FramebufferMipmap; +class VertexObject; +class Mesh; +class Scene; +class RendererBase; +class Renderer; +class RendererMaterial; +class RendererService; +class RendererSelection; + +enum RenderPass { + rpSolid, + rpTransparent, +}; + +typedef QList ObjectBaseList; + +struct Box3D { + GLfloat x; + GLfloat y; + GLfloat z; + GLfloat width; + GLfloat length; + GLfloat height; + GLfloat angle_z; + GLfloat angle_xy; + GLfloat angle_roll; + Box3D() {x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f;} + Box3D(const QVector3D & center, GLfloat hwid, GLfloat hlen, GLfloat hhei) {x = center.x() - hwid; y = center.y() - hlen; z = center.z() - hhei; width = 2 * hwid; length = 2 * hlen; height = 2 * hhei; angle_z = angle_xy = angle_roll = 0.f;} + Box3D(const QVector & points); + bool isEmpty() const {return (qAbs(width) < 1E-6f) && (qAbs(length) < 1E-6f) && (qAbs(height) < 1E-6f);} + QVector3D randomPoint() const {return QVector3D(uprand(length) + x, uprand(width) + y, uprand(height) + z);} + QVector3D pos() const {return QVector3D(x, y, z);} + QVector3D size() const {return QVector3D(length, width, height);} + QVector3D center() const {return QVector3D(length / 2.f + x, width / 2.f + y, height / 2.f + z);} + QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);} + QVector corners() const; + void setPos(const QVector3D & p) {x = p.x(); y = p.y(); z = p.z();} + void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();} + void setSize(const QVector3D & s) {length = s.x(); width = s.y(); height = s.z();} + Box3D & moveTo(const QVector3D & v) {x = v.x(); y = v.y(); z = v.z(); return *this;} + Box3D & move(const QVector3D & v) {x += v.x(); y += v.y(); z += v.z(); return *this;} + Box3D movedTo(const QVector3D & v) const {Box3D t(*this); t.x = v.x(); t.y = v.y(); t.z = v.z(); return t;} + Box3D moved(const QVector3D & v) const {Box3D t(*this); t.x += v.x(); t.y += v.y(); t.z += v.z(); return t;} + Box3D & operator |=(const Box3D & o); +}; + +inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {start (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;} + + +#pragma pack(push, 1) +struct Vector2i { + Vector2i(int p0_ = 0, int p1_ = 0) {p0 = p0_; p1 = p1_;} + Vector2i(const QString & str); + Vector2i movedX(const int & o) {return Vector2i(p0 + o, p1);} + Vector2i movedY(const int & o) {return Vector2i(p0, p1 + o);} + Vector2i moved(const int & x, const int & y) {return Vector2i(p0 + x, p1 + y);} + GLint p0; + GLint p1; + bool operator ==(const Vector2i & o) const {return p0 == o.p0 && p1 == o.p1;} + bool operator !=(const Vector2i & o) const {return p0 != o.p0 || p1 != o.p1;} + void operator +=(int v) {p0 += v; p1 += v;} + QVector2D toQVector2D() const {return QVector2D(p0, p1);} +}; +#pragma pack(pop) + +inline Vector2i operator +(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 + s.p0, f.p1 + s.p1);} +inline Vector2i operator -(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 - s.p0, f.p1 - s.p1);} +inline Vector2i operator /(const Vector2i & f, const int & s) {return Vector2i(f.p0 / s, f.p1 / s);} +inline uint qHash(const Vector2i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));} +inline QDebug operator <<(QDebug d, const Vector2i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << "}"; return d.space();} + +inline QDataStream & operator <<(QDataStream & s, const Vector2i & v) {s << v.p0 << v.p1; return s;} +inline QDataStream & operator >>(QDataStream & s, Vector2i & v) {s >> v.p0 >> v.p1; return s;} + + +#pragma pack(push, 1) +struct Vector3i { + Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {p0 = p0_; p1 = p1_; p2 = p2_;} + Vector3i(const QString & str); + Vector3i movedX(const int & o) {return Vector3i(p0 + o, p1, p2);} + Vector3i movedY(const int & o) {return Vector3i(p0, p1 + o, p2);} + Vector3i movedZ(const int & o) {return Vector3i(p0, p1, p2 + o);} + Vector3i moved(const int & x, const int & y, const int & z) {return Vector3i(p0 + x, p1 + y, p2 + z);} + GLint p0; + GLint p1; + GLint p2; + bool operator ==(const Vector3i & o) const {return p0 == o.p0 && p1 == o.p1 && p2 == o.p2;} + bool operator !=(const Vector3i & o) const {return p0 != o.p0 || p1 != o.p1 || p2 != o.p2;} + void operator +=(int v) {p0 += v; p1 += v; p2 += v;} + QVector3D toQVector3D() const {return QVector3D(p0, p1, p2);} +}; +#pragma pack(pop) + +inline Vector3i operator +(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 + s.p0, f.p1 + s.p1, f.p2 + s.p2);} +inline Vector3i operator -(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 - s.p0, f.p1 - s.p1, f.p2 - s.p2);} +inline Vector3i operator /(const Vector3i & f, const int & s) {return Vector3i(f.p0 / s, f.p1 / s, f.p2 / s);} +inline uint qHash(const Vector3i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24)) ^ ((v.p2 << 16) | (v.p2 >> 16));} +inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << ", " << v.p2 << "}"; return d.space();} + +inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;} +inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;} + + +QVector3D vectorFromString(const QString & str); +QColor colorFromString(const QString & str); +inline QVector4D QColor2QVector(const QColor & c) {return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());} +inline float cosABV(const QVector3D & v0, const QVector3D & v1) { + float l = v0.length() * v1.length(); + if (l == 0.f) return 0.; + return (QVector3D::dotProduct(v0, v1)) / l; +} +inline void normalizeAngleRad(float & a) {while (a < 0.) a += M_2PI; while (a >= M_2PI) a -= M_2PI;} +inline void normalizeAngleDeg(float & a) {while (a < 0.) a += 360. ; while (a >= 360. ) a -= 360. ;} +inline QVector3D projection(const QVector3D & v, const QVector3D & to) {return to.normalized() * v.length() * cosABV(v, to);} +QVector3D orthToVector(const QVector3D & v, const float & scale = 1.); +QVector3D rotateVector(const QVector3D & v, const QVector3D & a); +void setVectorLength(QVector3D & v, const float & l); +void lengthenVector(QVector3D & v, const float & l); +inline float squareLength(const QVector3D & from, const QVector3D & to) {return (to.x() - from.x())*(to.x() - from.x()) + (to.y() - from.y())*(to.y() - from.y()) + (to.z() - from.z())*(to.z() - from.z());} +inline QVector3D directionFromAngles(const QVector3D & a) {return rotateVector(QVector3D(1., 0., 0.), a);} +inline float frac(const float & x, const float & b) {return x - int(x / b) * b;} + + +#endif // GLTYPES_H diff --git a/core/glvertexobject.cpp b/core/glvertexobject.cpp new file mode 100644 index 0000000..e4a5437 --- /dev/null +++ b/core/glvertexobject.cpp @@ -0,0 +1,119 @@ +/* + QGL VertexObject + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "glvertexobject.h" + +using namespace QGLEngineShaders; + + +VertexObject::VertexObject(): + buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW), + buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) { + vao_ = 0; + buffers_binded = false; + objects_changed = selected_changed = true; +} + + +VertexObject::~VertexObject() { +} + + +void VertexObject::init(QOpenGLExtraFunctions * f) { + if (!isInit()) { + buffer_obj.init(f); + buffer_sel.init(f); + f->glGenVertexArrays(1, &vao_); + } +} + + +void VertexObject::destroy(QOpenGLExtraFunctions * f) { + if (vao_ != 0) { + buffer_obj.destroy(f); + buffer_sel.destroy(f); + f->glDeleteVertexArrays(1, &vao_); + } + vao_ = 0; +} + + +void VertexObject::bind(QOpenGLExtraFunctions * f) { + //qDebug() << "bind" << target_ << buffer_; + f->glBindVertexArray(vao_); +} + + +void VertexObject::release(QOpenGLExtraFunctions * f) { + f->glBindVertexArray(0); +} + + +void VertexObject::bindBuffers(QOpenGLExtraFunctions * f, Buffer & geom, Buffer & elem, bool force) { + if (!force && buffers_binded) return; + buffers_binded = true; + + init(f); + bind(f); + + geom.bind(f); + prepareDrawGeom(f); + + elem.bind(f); + + buffer_obj.bind(f); + prepareDrawObj(f); + + buffer_sel.bind(f); + prepareDrawSel(f); + + release(f); +} + + +void VertexObject::loadObject(QOpenGLExtraFunctions * f, const Object & object) { + loadBuffer(f, buffer_obj, &object, sizeof(Object)); +} + + +void VertexObject::loadObjects(QOpenGLExtraFunctions * f, const QVector & objects) { + loadBuffer(f, buffer_obj, objects.constData(), objects.size() * sizeof(Object)); +} + + +void VertexObject::loadSelections(QOpenGLExtraFunctions * f, const QVector & sels) { + loadBuffer(f, buffer_sel, sels.constData(), sels.size()); +} + + +void VertexObject::draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count) { + bind(f); + f->glDrawElementsInstanced(geom_type, vert_cout, GL_UNSIGNED_INT, 0, obj_count); + release(f); +} + + +void VertexObject::loadBuffer(QOpenGLExtraFunctions * f, Buffer & buf, const void * data, int size) { + buf.init(f); + if (!data) return; + buf.bind(f); + buf.resize(f, size); + buf.load(f, data, size); +} diff --git a/core/glvertexobject.h b/core/glvertexobject.h new file mode 100644 index 0000000..58b0894 --- /dev/null +++ b/core/glvertexobject.h @@ -0,0 +1,64 @@ +/* + QGL VertexObject + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLVERTEXOBJECT_H +#define GLVERTEXOBJECT_H + +#include "glbuffer.h" +#include "glshaders_types.h" + + +class VertexObject +{ + friend class Mesh; +public: + VertexObject(); + ~VertexObject(); + + void init (QOpenGLExtraFunctions * f); + void destroy (QOpenGLExtraFunctions * f); + + void bind (QOpenGLExtraFunctions * f); + void release (QOpenGLExtraFunctions * f); + + void bindBuffers (QOpenGLExtraFunctions * f, Buffer & geom, Buffer & elem, bool force = false); + void loadObject (QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object); + void loadObjects (QOpenGLExtraFunctions * f, const QVector & objects); + void loadSelections(QOpenGLExtraFunctions * f, const QVector & sels); + + void draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count); + + GLuint ID() const {return vao_;} + bool isInit() const {return vao_ != 0;} + + bool isObjectsChanged() const {return objects_changed;} + bool isSelectionChanged() const {return selected_changed;} + void setObjectsChanged(bool yes = true) {objects_changed = yes;} + void setSelectionChanged(bool yes = true) {selected_changed = yes;} + +private: + void loadBuffer(QOpenGLExtraFunctions * f, Buffer & buf, const void * data, int size); + + GLuint vao_; + Buffer buffer_obj, buffer_sel; + bool buffers_binded, objects_changed, selected_changed; + +}; + + +#endif // GLVERTEXOBJECT_H diff --git a/core/hdr.cpp b/core/hdr.cpp new file mode 100644 index 0000000..d1e2248 --- /dev/null +++ b/core/hdr.cpp @@ -0,0 +1,125 @@ +/* + QGL HDR + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "hdr_p.h" +#include "qmath.h" + +#define RGBE_DATA_RED 2 +#define RGBE_DATA_GREEN 1 +#define RGBE_DATA_BLUE 0 +/* number of floats per pixel */ +#define RGBE_DATA_SIZE 3 + + +void rgbe2float(float *red, float *green, float *blue, uchar rgbe[4]) { + float f; + if (rgbe[3]) { + f = static_cast(ldexp(1.0,rgbe[3]-(int)(128+8))); + *red = rgbe[0] * f; + *green = rgbe[1] * f; + *blue = rgbe[2] * f; + } + else + *red = *green = *blue = 0.0; +} + + +/* simple read routine. will not correctly handle run length encoding */ +bool RGBE_ReadPixels(QDataStream * fp, float * data, int numpixels) { + uchar rgbe[4]; + while(numpixels-- > 0) { + if (fp->readRawData((char*)rgbe, sizeof(rgbe)) < 1) + return false; + rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE],rgbe); + data += RGBE_DATA_SIZE; + } + return true; +} + + +bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines) { + uchar rgbe[4], *ptr, *ptr_end; + int i, count; + uchar buf[2]; + QByteArray scanline_buffer; + + if ((scanline_width < 8)||(scanline_width > 0x7fff)) + /* run length encoding is not allowed so read flat*/ + return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines); + scanline_buffer.resize(4*scanline_width); + /* read in each successive scanline */ + while(num_scanlines > 0) { + if (fp->readRawData((char*)rgbe,sizeof(rgbe)) < 1) { + return false; + } + if ((rgbe[0] != 2)||(rgbe[1] != 2)||(rgbe[2] & 0x80)) { + /* this file is not run length encoded */ + rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],&data[RGBE_DATA_BLUE],rgbe); + data += RGBE_DATA_SIZE; + return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines-1); + } + if ((((int)rgbe[2])<<8 | rgbe[3]) != scanline_width) { + return false; + } + ptr = (uchar*)scanline_buffer.data(); + /* read each of the four channels for the scanline into the buffer */ + for(i=0;i<4;i++) { + ptr_end = (uchar*)scanline_buffer.data() + ((i+1)*scanline_width); + while(ptr < ptr_end) { + if (fp->readRawData((char*)buf,sizeof(buf[0])*2) < 1) { + return false; + } + if (buf[0] > 128) { + /* a run of the same value */ + count = buf[0]-128; + if ((count == 0)||(count > ptr_end - ptr)) { + return false; + } + while(count-- > 0) + *ptr++ = buf[1]; + } + else { + /* a non-run */ + count = buf[0]; + if ((count == 0)||(count > ptr_end - ptr)) { + return false; + } + *ptr++ = buf[1]; + if (--count > 0) { + if (fp->readRawData((char*)ptr,sizeof(*ptr)*count) < 1) { + return false; + } + ptr += count; + } + } + } + } + /* now convert data from buffer into floats */ + for(i=0;i. +*/ + +#ifndef HDR_P_H +#define HDR_P_H + +#include + +bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines); + +#endif // HDR_P_H diff --git a/core/qglengine_version.h b/core/qglengine_version.h new file mode 100644 index 0000000..0895067 --- /dev/null +++ b/core/qglengine_version.h @@ -0,0 +1,27 @@ +// This file generated by CMake set_version() version 2 + +#ifndef QGLENGINE_QGLENGINE_VERSION_H +#define QGLENGINE_QGLENGINE_VERSION_H + + +// Project + +#define QGLENGINE_VERSION_MAJOR 1 +#define QGLENGINE_VERSION_MINOR 0 +#define QGLENGINE_VERSION_REVISION 0 +#define QGLENGINE_VERSION_BUILD 9999 +#define QGLENGINE_VERSION_SUFFIX "rc" +#define QGLENGINE_VERSION_NAME "1.0.0_rc" +#define QGLENGINE_MAKE_VERSION(major, minor, revision) ((major << 16) | (minor << 8) | revision) +#define QGLENGINE_VERSION QGLENGINE_MAKE_VERSION(QGLENGINE_VERSION_MAJOR, QGLENGINE_VERSION_MINOR, QGLENGINE_VERSION_REVISION) + + +// Tools + +#define QGLENGINE_CMAKE_VERSION "3.17.1" +#define QGLENGINE_CXX_COMPILER "GNU 8.1.0" +#define QGLENGINE_BUILD_DATE "22.08.2020 00:51" +#define QGLENGINE_ARCH "i386" + + +#endif // QGLENGINE_QGLENGINE_VERSION_H diff --git a/formats/loader_assimp.cpp b/formats/loader_assimp.cpp new file mode 100644 index 0000000..fe53b77 --- /dev/null +++ b/formats/loader_assimp.cpp @@ -0,0 +1,267 @@ +/* + QGL Loader Assimp + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "loader_assimp.h" +#include "glscene.h" +#include "glmesh.h" +#include "glmaterial.h" +#include "globject.h" +#include +#include +#include +#include +#include + +QString fromAiString (const aiString & s) {return QString::fromLocal8Bit(s.C_Str());} +QColor fromAiColor (const aiColor4D & c) {return QColor::fromRgbF(piClamp(c.r, 0.f, 1.f), piClamp(c.g, 0.f, 1.f), piClamp(c.b, 0.f, 1.f));} +QVector3D fromAiVector3D(const aiVector3D & v) {return QVector3D(v.x, v.y, v.z);} + Vector3i fromAiFace (const aiFace & v) {return Vector3i(v.mIndices[0], v.mIndices[1], v.mIndices[2]);} +QMatrix4x4 fromAiMatrix4D(const aiMatrix4x4 & v) {return QMatrix4x4(v.a1, v.a2, v.a3, v.a4, + v.b1, v.b2, v.b3, v.b4, + v.c1, v.c2, v.c3, v.c4, + v.d1, v.d2, v.d3, v.d4);} +bool isAiMeshTriangles(const aiMesh * m) {return (m->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) == aiPrimitiveType_TRIANGLE;} + + +Mesh * assimpMesh(const aiMesh * m) { + if (!m) return 0; + if (!isAiMeshTriangles(m)) return 0; + Mesh * ret = new Mesh(); + int vcnt = m->mNumVertices, tcnt = m->mNumFaces; + + QVector & v(ret->vertices()); v.resize(vcnt); + QVector & t(ret->texcoords()); t.resize(vcnt); + QVector< Vector3i> & ind(ret->indicesTriangles()); + + for (int i = 0; i < vcnt; ++i) + v[i] = fromAiVector3D(m->mVertices[i]); + + if (m->HasNormals()) { + QVector & n(ret->normals()); + n.resize(vcnt); + for (int i = 0; i < vcnt; ++i) + n[i] = fromAiVector3D(m->mNormals[i]); + } + + if (m->HasTextureCoords(0)) { + for (int i = 0; i < vcnt; ++i) + t[i] = fromAiVector3D(m->mTextureCoords[0][i]).toVector2D(); + } + + if (m->HasFaces()) { + ind.resize(tcnt); + for (int i = 0; i < tcnt; ++i) + ind[i] = fromAiFace(m->mFaces[i]); + } else { + tcnt = vcnt / 3; + ind.resize(tcnt); + int si = 0; + for (int i = 0; i < tcnt; ++i) { + si = i+i+i; + ind[i] = Vector3i(si, si+1, si+2); + } + } + + //qDebug() << "add mesh" << v.size() << ret->normals().size() << ret->texcoords().size() << ret->indices().size(); + + return ret; +} + + +QColor aiMatColor(const aiMaterial * m, const char * key, uint s0, uint s1, const QColor & def = Qt::white) { + aiColor4D col; + aiReturn r = m->Get(key, s0, s1, col); + //qDebug() << key << r << col.r << col.g << col.b; + if (r != aiReturn_SUCCESS) return def; + return fromAiColor(col); +} +float aiMatFloat(const aiMaterial * m, const char * key, uint s0, uint s1, float def = 0.f) { + float ret; + aiReturn r = m->Get(key, s0, s1, ret); + if (r != aiReturn_SUCCESS) return def; + return ret; +} +QString aiMatString(const aiMaterial * m, const char * key, uint s0, uint s1) { + aiString p; + aiReturn r = const_cast(m)->Get(key, s0, s1, p); + //qDebug() << "GetTexture" << key << s0 << r << fromAiString(p); + if (r != aiReturn_SUCCESS) return QString(); + return fromAiString(p); +} +Material * assimpMaterial(const aiMaterial * m) { + if (!m) return 0; + Material * ret = new Material(); + ///WARNING: no function GetName() in aiMaterial in stable release + //ret->name = fromAiString(const_cast(m)->GetName()); + aiString name; + const_cast(m)->Get(AI_MATKEY_NAME,name); + ret->name = fromAiString(name); + //qDebug() << "mat" << ret->name; + //for (int i = 0; i < m->mNumProperties; ++i) { + // qDebug()<< fromAiString(m->mProperties[i]->mKey);// << "=" << aiMatFloat(m, m->mProperties[i]->mKey.C_Str(), 0, 0); + //} + ret->color_diffuse = aiMatColor(m, AI_MATKEY_COLOR_DIFFUSE); + ret->color_emission = aiMatColor(m, AI_MATKEY_COLOR_EMISSIVE); + float shine = aiMatFloat(m, AI_MATKEY_SHININESS, -1.f); + if (shine >= 0) { + ret->map_roughness.color_amount = 0.8f - (shine / 100.f * 0.6f); + //qDebug() << "shine" << shine; + } + ret->map_diffuse .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_DIFFUSE(0)); + ret->map_normal .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_NORMALS(0)); + //ret->map_metalness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SPECULAR(0)); + ret->map_roughness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SHININESS(0)); + ret->map_emission .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_EMISSIVE(0)); + ret->transparency = 1.f - aiMatFloat(m, AI_MATKEY_OPACITY, 1.f); + ret->detectMaps(); + ret->setTypes(); + return ret; +} + + +Light * assimpLight(const aiLight * l) { + if (!l) return 0; + if (l->mType != aiLightSource_POINT && l->mType != aiLightSource_SPOT) + return 0; + Light * ret = new Light(); + ret->setName(fromAiString(l->mName)); + ret->setPos(fromAiVector3D(l->mPosition)); + ret->setDirection(fromAiVector3D(l->mDirection)); + ret->decay_const = l->mAttenuationConstant ; + ret->decay_linear = l->mAttenuationLinear ; + ret->decay_quadratic = l->mAttenuationQuadratic; + ret->angle_start = l->mAngleInnerCone * rad2deg; + ret->angle_end = l->mAngleOuterCone * rad2deg; + if (l->mType == aiLightSource_SPOT) + ret->light_type = Light::Cone; + QVector3D col(l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b); + ret->intensity = col.length(); + col /= ret->intensity; + ret->setColor(QColor::fromRgbF(col[0], col[1], col[2])); + return ret; +} + + +ObjectBaseList assimpObject(const aiNode * n, const QVector & meshes, aiMesh ** ai_meshes, + const QVector & materials, + const QMap & light_by_name, QVector & out_lights) { + if (!n) return ObjectBaseList(); + ObjectBaseList ret; + ObjectBase * obj = 0; + QString name = fromAiString(n->mName); + Light * light = light_by_name.value(name, 0); + if (light) { + obj = light->clone(); + out_lights << (Light*)obj; + } else + obj = new ObjectBase(); + obj->setName(name); + obj->setMatrix(fromAiMatrix4D(n->mTransformation)); + ret << obj; + //qDebug() << "add object" << ret << ret->name(); + if (!light) { + //qDebug() << name << "has" << n->mNumMeshes << "meshes"; + for (uint i = 0; i < n->mNumMeshes; ++i) { + int mi = n->mMeshes[i]; + if (meshes[mi]) { + if (obj->mesh()) { + obj = obj->clone(false); + ret << obj; + } + obj->setMesh(meshes[mi]); + int mati = ai_meshes[mi]->mMaterialIndex; + if (mati >= 0 || mati < materials.size()) + obj->setMaterial(materials[mati]); + //ret->setMesh(meshes[mi]); + //qDebug() << "set mesh" << mi << ret->mesh(); + //break; + } + } + } + for (uint i = 0; i < n->mNumChildren; ++i) { + ObjectBaseList cl = assimpObject(n->mChildren[i], meshes, ai_meshes, materials, light_by_name, out_lights); + foreach (ObjectBase * c, cl) + obj->addChild(c); + } + + return ret; +} + + +Scene * loadScene(const QString & filepath) { + if (filepath.isEmpty()) return 0; + qDebug() << "[Loader Assimp] Import" << filepath << "..."; + Assimp::Importer importer; + const aiScene * ais = importer.ReadFile(filepath.toUtf8(), aiProcess_Triangulate | + aiProcess_SortByPType | + aiProcess_GenUVCoords | + aiProcess_TransformUVCoords); + if (!ais) { + qDebug() << "[Loader Assimp] Error: \"" + QString(importer.GetErrorString()) + "\""; + return 0; + } + qDebug() << "[Loader Assimp] Imported" << ais->mNumMeshes << "meshes"; + QVector meshes; + for (uint i = 0; i < ais->mNumMeshes; ++i) + meshes << assimpMesh(ais->mMeshes[i]); + QVector materials; + for (uint i = 0; i < ais->mNumMaterials; ++i) + materials << assimpMaterial(ais->mMaterials[i]); + QVector lights; + for (uint i = 0; i < ais->mNumLights; ++i) + lights << assimpLight(ais->mLights[i]); + QMap light_by_name; + foreach (Light * l, lights) + if (l) + light_by_name[l->name()] = l; + + QVector out_lights; + ObjectBaseList rootl = assimpObject(ais->mRootNode, meshes, ais->mMeshes, materials, light_by_name, out_lights); + if (rootl.isEmpty()) return 0; + ObjectBase * root = rootl[0]; + root->transferTransformToChildren(true); + + ObjectBaseList rcl = root->children(true); + foreach (ObjectBase * c, rcl) { + foreach (Light * l, out_lights) { + if (c->name() == (l->name() + ".Target")) { + l->setDistance((l->worldPos() - c->worldPos()).length()); + delete c; + break; + } + } + } + root->cleanTree(); + + Scene * scene = new Scene(); + scene->setName(root->name()); + foreach (ObjectBase * o, root->children()) + scene->addObject(o); + lights.removeAll(0); + qDeleteAll(lights); + + return scene; +} + + +QStringList supportedFormats() { + Assimp::Importer importer; + aiString ret; + importer.GetExtensionList(ret); + return fromAiString(ret).toLower().split(";"); +} diff --git a/formats/loader_assimp.h b/formats/loader_assimp.h new file mode 100644 index 0000000..348c32f --- /dev/null +++ b/formats/loader_assimp.h @@ -0,0 +1,27 @@ +/* + QGL Loader Assimp + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef LOADER_ASSIMP_H +#define LOADER_ASSIMP_H + +#include "gltypes.h" + +Scene * loadScene(const QString & filepath); +QStringList supportedFormats(); + +#endif // LOADER_ASSIMP_H diff --git a/formats/loader_qgl.cpp b/formats/loader_qgl.cpp new file mode 100644 index 0000000..9e04190 --- /dev/null +++ b/formats/loader_qgl.cpp @@ -0,0 +1,67 @@ +/* + QGL Loader QGL + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "loader_qgl.h" +#include "glscene.h" +#include + + +Scene * loadFromQGLFile(const QString & filepath) { + QFile f(filepath); + if (!f.exists()) { + qDebug() << "[Loader QGL] Error: can`t open \"" + filepath + "\""; + return 0; + } + f.open(QIODevice::ReadOnly); + QDataStream s(&f); + s.setVersion(QDataStream::Qt_5_0); + char sign[4]; + s.readRawData(sign, 4); + if ((sign[0] != 'Q') || (sign[1] != 'G') || (sign[2] != 'L') || (sign[3] != 'E')) { + qDebug() << "[Loader QGL] Error: \"" + filepath + "\" is not valid QGLEngine file!"; + return 0; + } + ushort version = 0x1; + f.peek((char*)&version, 2); + if (version != 1) { + qDebug() << "[Loader QGL] Error: \"" + filepath + "\" unsupported version!"; + return 0; + } + Scene * ret = 0; + s.skipRawData(2); + s >> ret; + //root->buildTransform(); + qDebug() << "[Loader QGL] Loaded" << ret->objectsCount(true) << "objects from" << filepath; + return ret; +} + + +bool saveToQGLFile(const QString & filepath, const Scene * scene) { + QFile f(filepath); + if (!f.open(QIODevice::ReadWrite)) + return false; + f.resize(0); + QDataStream s(&f); + s.setVersion(QDataStream::Qt_5_0); + char sign[4] = {'Q', 'G', 'L', 'E'}; + ushort version = 0x1; + s.writeRawData(sign, 4); + s.writeRawData((char*)&version, 2); + s << scene; + return true; +} diff --git a/formats/loader_qgl.h b/formats/loader_qgl.h new file mode 100644 index 0000000..72aed12 --- /dev/null +++ b/formats/loader_qgl.h @@ -0,0 +1,28 @@ +/* + QGL Loader QGL + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef LOADER_QGL_H +#define LOADER_QGL_H + +#include "gltypes.h" +#include + +Scene * loadFromQGLFile(const QString & filepath); +bool saveToQGLFile(const QString & filepath, const Scene * scene); + +#endif // LOADER_QGL_H diff --git a/glcamera.cpp b/glcamera.cpp new file mode 100644 index 0000000..d7dda9a --- /dev/null +++ b/glcamera.cpp @@ -0,0 +1,110 @@ +/* + QGL Camera + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "gltypes.h" +#include "qglview.h" + + +Camera::Camera() { + type_ = glCamera; + fov_ = 60.; + roll_ = 0.; + //setRotationX(90.f); + depth_start = 0.1f; + mirror_x = mirror_y = false; +} + + +QMatrix4x4 Camera::offsetMatrix() const { + QMatrix4x4 ret; + ret.translate(parent_ ? -offset_ : -aim()); + return ret; +} + +/* +void Camera::localTransform(QMatrix4x4 & m) { + return; + if (parent_) + m *= parent_->worldTransform(); + QMatrix4x4 ret; + //qDebug() << "local camera"; + ret.translate(0., 0., -distance()); + ret.rotate(angles_.y(), 1., 0., 0.); + ret.rotate(angles_.x(), 0., 1., 0.); + ret.rotate(angles_.z(), 0., 0., 1.); + //m *= ret.inverted(); +} +*/ + +void Camera::assign(const Camera & c) { + trans = c.trans; + aim_dist = c.aim_dist; + fov_ = c.fov_; + mirror_x = c.mirror_x; + mirror_y = c.mirror_y; + depth_start = c.depth_start; + buildTransform(); +} + + +ObjectBase * Camera::clone(bool withChildren) { + Camera * o = new Camera(*this); + //GLObjectBase::clone(withChildren); + o->is_init = false; + o->name_ = name_;// + "_copy"; + o->scene_ = nullptr; + o->children_.clear(); + if (withChildren) { + for (int i = 0; i < children_.size(); ++i) + o->addChild(children_[i]->clone(withChildren)); + } + o->trans = trans; + o->aim_dist = aim_dist; + o->fov_ = fov_; + o->roll_ = roll_; + o->mirror_x = mirror_x; + o->mirror_y = mirror_y; + o->depth_start = depth_start; + o->meta = meta; + return o; +} + + +QMatrix4x4 Camera::viewMatrix() const { + QMatrix4x4 ret; + //qDebug() << pos() << aim(); + ret.translate(0., 0., -distance()); + ret.rotate(-roll_, 0., 0., 1.); + ret *= trans.matrixRotateScale().inverted(); + //ret.rotate(angles_.y(), 1., 0., 0.); + //ret.rotate(angles_.x(), 0., 1., 0.); + //pm.translate(-aim_); + if (parent_) { + QMatrix4x4 pmat = parent_->worldTransform(); + offset_ = pmat.column(3).toVector3D(); + pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; + pmat.translate(aim()); + ret *= pmat.inverted(); + } + return ret; +} + + +QMatrix4x4 Camera::projectionMatrix(double aspect) const { + return glMatrixPerspective(fov_, aspect, depth_start); +} diff --git a/glcamera.h b/glcamera.h new file mode 100644 index 0000000..c8743f8 --- /dev/null +++ b/glcamera.h @@ -0,0 +1,70 @@ +/* + QGL Camera + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLCAMERA_H +#define GLCAMERA_H + +#include "globject.h" + +//extern QMatrix4x4 globCameraMatrix; +//extern Camera * currentCamera; + +class Camera: public AimedObject +{ + friend class QGLView; + friend class GLParticlesSystem; + friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p); + friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p); +public: + Camera(); + + void setFOV(const float & f) {fov_ = f;} + void setAngles(const QVector3D & a) {setRotation(a);} + void setAngleZ(const float & a) {setRotationZ(a);} + void setAngleXY(const float & a) {setRotationX(a);} + void setAngleRoll(const float & a) {roll_ = a;} + void setDepthStart(const float & d) {depth_start = d;} + void setMirrorX(bool yes) {mirror_x = yes;} + void setMirrorY(bool yes) {mirror_y = yes;} + + float FOV() const {return fov_;} + float angleZ() const {return rotationZ();} + float angleXY() const {return rotationX();} + float angleRoll() const {return roll_;} + float depthStart() const {return depth_start;} + bool isMirrorX() const {return mirror_x;} + bool isMirrorY() const {return mirror_y;} + void assign(const Camera & c); + + virtual ObjectBase * clone(bool withChildren = true); + QMatrix4x4 viewMatrix() const; + QMatrix4x4 projectionMatrix(double aspect) const; + QMatrix4x4 offsetMatrix() const; + + QMatrix4x4 fullViewMatrix() const {return viewMatrix() * offsetMatrix();} + +private: + mutable QVector3D offset_; + GLfloat fov_, roll_; + GLfloat depth_start; + bool mirror_x; + bool mirror_y; + +}; + +#endif // GLCAMERA_H diff --git a/globject.cpp b/globject.cpp new file mode 100644 index 0000000..bad61ee --- /dev/null +++ b/globject.cpp @@ -0,0 +1,717 @@ +/* + QGL ObjectBase & Light + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "globject.h" +#include "glcamera.h" +#include "glscene.h" +#include "glmesh.h" +#include +//static int _count = 0; + +ObjectBase::ObjectBase(Mesh * geom, Material * mat) { + type_ = glMesh; + render_mode = View; + prev_pass = rpSolid; + parent_ = nullptr; + color_ = Qt::white; + is_root = is_init = selected_ = false; + visible_ = accept_fog = accept_light = cast_shadow = rec_shadow = select_ = true; + line_width = -1.; + id_ = 0; + blend_src = GL_SRC_ALPHA; + blend_dest = GL_ONE_MINUS_SRC_ALPHA; + type_ = glMesh; + raw_matrix = selected_aim = false; + mat_.setToIdentity(); + scene_ = nullptr; + mesh_ = geom; + material_ = mat; + //qDebug() << "ObjectBase, now" << ++_count; +} + + +ObjectBase::~ObjectBase() { + //qDebug() << "~ObjectBase, now" << --_count; + if (parent_) parent_->children_.removeAll(this); + if (scene_) { + scene_->__objectDeleted(this); + scene_->setTreeChanged(); + scene_->setTreeStructChanged(); + } + foreach (ObjectBase * c, children_) { + c->parent_ = nullptr; + delete c; + } +} + + +ObjectBase * ObjectBase::clone(bool withChildren) { + ObjectBase * o = new ObjectBase(); + o->prev_pass = prev_pass; + o->is_init = false; + o->accept_light = accept_light; + o->accept_fog = accept_fog; + o->visible_ = visible_; + o->color_ = color_; + o->type_ = type_; + o->raw_matrix = raw_matrix; + o->mat_ = mat_; + o->trans = trans; + o->itransform_ = itransform_; + o->bound = bound; + o->name_ = name_;// + "_copy"; + o->blend_src = blend_src; + o->blend_dest = blend_dest; + o->pos_h = pos_h; + o->material_ = material_; + o->mesh_ = mesh_; + o->meta = meta; + o->scene_ = nullptr; + if (withChildren) { + for (int i = 0; i < children_.size(); ++i) + o->addChild(children_[i]->clone(withChildren)); + } + return o; +} + + +void ObjectBase::destroy() { + if (mesh_) delete mesh_; +} + + +void ObjectBase::init() { + calculateBoundingBox(); + //material_.reflection.create(); + //qDebug() << "init" << vbo.buffer_; + is_init = true; +} + + +RenderPass ObjectBase::pass() const { + RenderPass ret = rpSolid; + if (material_) + if (material_->hasTransparency()) + ret = rpTransparent; + return ret; +} + + +void ObjectBase::setScene(Scene * v) { + scene_ = v; + foreach (ObjectBase * c, children_) + c->setScene(v); +} + + +void ObjectBase::addChild(ObjectBase * o) { + if (o == this) return; + if (o->parent_) + o->parent_->children_.removeAll(o); + children_ << o; + o->parent_ = this; + o->setScene(scene_); + o->buildTransform(); + /*if (scene_) { + ObjectBaseList cl = o->children(true); + cl << o; + //foreach (ObjectBase * i, cl) { + // emit view_->objectAdded(i); + //} + }*/ + setSceneTreeChanged(); +} + + +void ObjectBase::removeChild(ObjectBase * o) { + if (o == this) return; + children_.removeAll(o); + o->parent_ = nullptr; + o->buildTransform(); + setSceneTreeChanged(); +} + + +void ObjectBase::removeChild(int index) { + children_[index]->parent_ = nullptr; + children_[index]->buildTransform(); + children_.removeAt(index); + setSceneTreeChanged(); +} + + +void ObjectBase::clearChildren(bool deleteAll) { + foreach (ObjectBase * i, children_) { + i->scene_ = nullptr; + i->parent_ = nullptr; + i->clearChildren(deleteAll); + if (deleteAll) { + delete i; + } else { + i->buildTransform(); + } + } + children_.clear(); + setSceneTreeChanged(); +} + + +ObjectBase * ObjectBase::child(int index) { + if (index < 0 || index >= children_.size()) return nullptr; + return children_[index]; +} + + +ObjectBase * ObjectBase::child(const QString & name) { + foreach (ObjectBase * i, children_) + if (i->name_ == name) return i; + return nullptr; +} + + +const ObjectBase * ObjectBase::child(int index) const { + if (index < 0 || index >= children_.size()) return nullptr; + return children_[index]; +} + + +const ObjectBase * ObjectBase::child(const QString & name) const { + foreach (ObjectBase * i, children_) + if (i->name_ == name) return i; + return nullptr; +} + + +ObjectBaseList ObjectBase::children(bool all_) { + if (!all_) return children_; + ObjectBaseList cl; + addChildren(cl, this); + return cl; +} + + +bool ObjectBase::isVisible(bool check_parents) const { + if (!check_parents) return visible_; + if (!visible_) return false; + ObjectBase * p = parent_; + while (p) { + if (!p->visible_) return false; + p = p->parent_; + } + return true; +} + + +void ObjectBase::setVisible(bool v) { + visible_ = v; + setSceneTreeChanged(); +} + + +void ObjectBase::rotateZ(GLfloat a) { + raw_matrix = false; + trans.setRotationZ(trans.rotationZ() + a); + //angles_.setZ(angles_.z() + a); + //while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); + //while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); + buildTransform(); +} + + +void ObjectBase::setRotationZ(GLfloat a) { + raw_matrix = false; + trans.setRotationZ(a); + //angles_.setZ(a); + //while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); + //while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); + buildTransform(); +} + + +void ObjectBase::setTransform(const Transform & t) { + trans = t; + buildTransform(); +} + + +void ObjectBase::addChildren(ObjectBaseList & list, ObjectBase * where) { + foreach (ObjectBase * i, where->children_) { + list << i; + addChildren(list, i); + } +} + + +void ObjectBase::calculateBoundingBox() { + bound = Box3D(); + if (mesh_) { + bound = mesh_->boundingBox(); + QVector c = bound.corners(), tc; + foreach (QVector3D p, c) + tc << (itransform_ * QVector4D(p, 1)).toVector3D(); + bound = Box3D(tc); + } + foreach (ObjectBase * i, children_) { + i->calculateBoundingBox(); + bound |= i->boundingBox(); + } +} + + +void ObjectBase::updateTransform() { + buildTransform(true); +} + + +void ObjectBase::setProperty(const QString & pn, const QVariant & v) { + meta[pn] = v; +} + + +QVariant ObjectBase::property(const QString & pn, bool * exists) const { + if (exists) *exists = meta.contains(pn); + return meta.value(pn); +} + + +bool ObjectBase::hasProperty(const QString & pn) const { + return meta.contains(pn); +} + + +void ObjectBase::removeProperty(const QString & pn) { + meta.remove(pn); +} + + +void ObjectBase::setMatrix(const QMatrix4x4 & t) { + //raw_matrix = true; + //mat_ = t; + //pos_ = mat_.column(3).toVector3D(); + //mat_.setColumn(3, QVector4D(0., 0., 0., 1.)); + raw_matrix = false; + trans.setMatrix(t); + buildTransform(); +} + + +QMatrix4x4 ObjectBase::matrix() const { + return trans.matrix(); +} + + +QVector3D ObjectBase::inParentSpace(const QVector3D & v) const { + if (!parent_) return v; + return (parent_->matrix() * QVector4D(v, 1)).toVector3D(); +} + + +void ObjectBase::transferTransformToChildren(bool only_scale) { + QMatrix4x4 m = trans.matrix(); + if (only_scale) m = trans.matrixScale(); + foreach (ObjectBase * i, children_) + i->trans.setMatrix(m * i->trans.matrix()); + if (only_scale) resetScale(); + else setMatrix(QMatrix4x4()); +} + + +void ObjectBase::cleanTree() { + for (int i = 0; i < children_.size(); ++i) { + ObjectBase * o = children_[i]; + if (!o->hasChildren() && !o->mesh() && (o->type() == glMesh)) { + delete o; + --i; + } + o->cleanTree(); + } +} + + +bool ObjectBase::isSelected(bool check_parents) const { + if (!check_parents) return selected_; + if (selected_) return true; + ObjectBase * p = parent_; + while (p) { + if (p->selected_) return true; + p = p->parent_; + } + return false; +} + + +void ObjectBase::setSelected(bool yes) { + //qDebug() << "select" << name() << view_; + if (select_) + selected_ = yes; + if (!selected_) + selected_aim = false; +} + + +ObjectBase * ObjectBase::selectedParent() const { + ObjectBase * p = parent_; + while (p) { + if (p->selected_) return p; + p = p->parent_; + } + return 0; +} + + +void ObjectBase::setMaterial(Material * m, bool with_children) { + material_ = m; + if (with_children) + foreach (ObjectBase * i, children_) i->setMaterial(m, true); + setObjectsChanged(); + if (scene_) scene_->mat_changed = scene_->tree_changed = true; +} + + +void ObjectBase::setColor(QColor c, bool with_children) { + color_ = c; + if (with_children) + foreach (ObjectBase * i, children_) i->setColor(c, true); + setObjectsChanged(); +} + + +void ObjectBase::setMesh(Mesh * v) { + if (scene_) + v = scene_->attachMesh(v); + mesh_ = v; + setSceneTreeChanged(); + setObjectsChanged(); +} + + +void ObjectBase::buildTransform(bool force) { + if (force) trans.setDirty(); + itransform_.setToIdentity(); + ObjectBase * p = parent_; + if (p) + itransform_ = p->itransform_; + //if (raw_matrix) { + // itransform_.translate(pos_); + // itransform_ *= mat_; + // //qDebug() << "raw_matrix" << itransform_; + //} else + localTransform(itransform_); + //qDebug() << name_ << itransform_; + foreach (ObjectBase * i, children_) + i->buildTransform(force); + setObjectsChanged(); +} + + +void ObjectBase::initInternal() { + init(); + foreach (ObjectBase * i, children_) i->initInternal(); +} + + +void ObjectBase::localTransform(QMatrix4x4 & m) { + m *= trans.matrix(); +} + + +void ObjectBase::setSceneTreeChanged() { + if (scene_) { + scene_->setTreeChanged(); + scene_->setTreeStructChanged(); + } + setObjectsChanged(); +} + + +void ObjectBase::setObjectsChanged() { + int p = pass(); + if (mesh_) { + mesh_->setObjectsChanged (p, true); + mesh_->setSelectionChanged(p, true); + if (prev_pass != p) { + mesh_->setObjectsChanged (prev_pass, true); + mesh_->setSelectionChanged(prev_pass, true); + } + } + prev_pass = p; +} + + +QMatrix4x4 ObjectBase::worldMatrix(QMatrix4x4 parent) const { + QMatrix4x4 mat; + //mat.translate(pos_); + //if (raw_matrix) { + // mat *= mat_; + //} else { + // if (angles_.z() != 0.f) mat.rotate(angles_.z(), 0., 0., 1.); + // if (angles_.y() != 0.f) mat.rotate(angles_.y(), 0., 1., 0.); + // if (angles_.x() != 0.f) mat.rotate(angles_.x(), 1., 0., 0.); + // mat.scale(scale_); + //} + mat = trans.matrix(); + return parent * mat; +} + + + + +AimedObject::AimedObject() { + aim_dist = 1.; +} + + +QVector3D AimedObject::worldAim() const { + QVector3D ret = worldPos() + worldDirection() * aim_dist; + return ret; +} + + +void AimedObject::setAim(const QVector3D & p) { + QVector3D dir = p - pos(); + trans.setRotation(Transform::fromDirection(dir, trans.rotationY())); + aim_dist = dir.length(); + buildTransform(); + //if (!p.isNull()) + //qDebug() << "setAim" << p << aim() << worldAim(); +} + + +QVector3D AimedObject::direction() const { + return trans.direction(); +} + + +void AimedObject::setDirection(const QVector3D & d) { + //double len = qMax(aim_.length(), 0.001f); + //aim_ = d.normalized() * len; + buildTransform(); +} + + +void AimedObject::flyCloser(double s) { + double tl = 1. / (1. + s); + move(direction() * aim_dist * (1. - tl)); + aim_dist *= tl; +} + + +void AimedObject::flyFarer(double s) { + double tl = 1. * (1. + s); + move(direction() * aim_dist * (1. - tl)); + aim_dist *= tl; +} + + +void AimedObject::flyToDistance(double d) { + move(direction() * (aim_dist - d)); + aim_dist = d; + //qDebug() << d << (aim() - pos()).length() << aim(); +} + + +void AimedObject::moveForward(const float & x, bool withZ) { + QVector3D dv = itransform_.mapVector(QVector3D(0, 0, -x)); + if (!withZ) dv[2] = 0.; + move(dv); +} + + +void AimedObject::moveLeft(const float & x, bool withZ) { + QVector3D dv = itransform_.mapVector(QVector3D(-x, 0, 0)); + if (!withZ) dv[2] = 0.; + move(dv); +} + + +void AimedObject::moveUp(const float & x, bool onlyZ) { + QVector3D dv = itransform_.mapVector(QVector3D(0, x, 0)); + if (onlyZ) dv[0] = dv[1] = 0.; + move(dv); +} + + +void AimedObject::orbitZ(const float & a) { + QVector3D pa = aim(); + rotateZ(-a); + move(pa - aim()); +} + + +void AimedObject::orbitXY(const float & a) { + QVector3D pa = aim(); + rotateX(-a); + move(pa - aim()); +} + + +void AimedObject::transformChanged() { + +} + + + + +Light::Light(): AimedObject(), shadow_map(0, true, GL_R16F) { + type_ = glLight; + light_type = Omni; + intensity = 1.; + angle_start = angle_end = 180.; + decay_linear = decay_quadratic = decay_start = 0.; + decay_const = decay_end = 1.; + setDirection(0, 0, -1.); +} + + +Light::Light(const QVector3D & p, const QColor & c, float i): AimedObject(), shadow_map(0, true, GL_R16F) { + type_ = glLight; + light_type = Omni; + intensity = i; + color_ = c; + angle_start = angle_end = 180.; + decay_linear = decay_quadratic = decay_start = 0.; + decay_const = decay_end = 1.; + setPos(p); + setDirection(0, 0, -1.); +} + + +ObjectBase * Light::clone(bool withChildren) { + Light * o = new Light(*this); + //GLObjectBase::clone(withChildren); + o->is_init = false; + o->name_ = name_;// + "_copy"; + o->scene_ = nullptr; + o->children_.clear(); + if (withChildren) { + for (int i = 0; i < children_.size(); ++i) + o->addChild(children_[i]->clone(withChildren)); + } + o->color_ = color_; + o->light_type = light_type; + o->trans = trans; + o->aim_dist = aim_dist; + o->angle_start = angle_start; + o->angle_end = angle_end; + o->intensity = intensity; + o->decay_const = decay_const; + o->decay_linear = decay_linear; + o->decay_quadratic = decay_quadratic; + o->meta = meta; + return o; +} + + +void Light::apply() { + if (scene_) scene_->setLightsChanged(); +} + + +QDataStream & operator <<(QDataStream & s, const ObjectBase * p) { + ChunkStream cs; + //qDebug() << "place" << p->name() << "..."; + cs.add(1, int(p->type_)).add(2, p->accept_light).add(3, p->accept_fog).add(4, p->visible_) + .add(5, p->cast_shadow).add(6, p->rec_shadow).add(7, p->raw_matrix).add(8, p->line_width) + .add(9, int(p->render_mode)).add(14, p->mat_).add(16, p->children_.size()) + .add(17, p->name_).add(18, p->meta).add(19, p->color_).add(20, p->trans); + //qDebug() << "place self done"; + if (p->type_ == ObjectBase::glLight) { + //qDebug() << "place light ..."; + const Light * l = (const Light*)p; + cs.add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity) + .add(104, l->decay_const).add(105, l->decay_linear).add(106, l->decay_quadratic) + .add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type)) + .add(111, l->distance()); + } + if (p->type_ == ObjectBase::glCamera) { + //qDebug() << "place camera ..."; + const Camera * c = (const Camera*)p; + cs.add(200, c->aim()).add(201, c->fov_).add(202, c->depth_start) + .add(206, c->mirror_x).add(207, c->mirror_y).add(208, c->distance()) + .add(209, c->roll_); + } + //qDebug() << "place" << p->name() << cs.data().size() << s.device()->size(); + s << cs.data(); + foreach (const ObjectBase * c, p->children_) + s << c; + return s; +} +QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { + ChunkStream cs(s); + p = nullptr; + int ccnt = 0; + Light * l = nullptr; + Camera * c = nullptr; + //qDebug() << "read obj ..."; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: { + ObjectBase::Type type = (ObjectBase::Type)cs.getData(); + switch (type) { + case ObjectBase::glMesh: p = new ObjectBase(); break; + case ObjectBase::glLight: p = new Light(); l = (Light*)p; break; + case ObjectBase::glCamera: p = new Camera(); c = (Camera*)p; break; + default : break; + } + if (p) p->type_ = type; + } break; + case 2: if (p) p->accept_light = cs.getData(); break; + case 3: if (p) p->accept_fog = cs.getData(); break; + case 4: if (p) p->visible_ = cs.getData(); break; + case 5: if (p) p->cast_shadow = cs.getData(); break; + case 6: if (p) p->rec_shadow = cs.getData(); break; + case 7: if (p) p->raw_matrix = cs.getData(); break; + case 8: if (p) p->line_width = cs.getData(); break; + case 9: if (p) p->render_mode = (ObjectBase::RenderMode)cs.getData(); break; + case 14: if (p) p->mat_ = cs.getData(); break; + case 16: if (p) ccnt = cs.getData(); break; + case 17: if (p) p->name_ = cs.getData(); break; + case 18: if (p) p->meta = cs.getData(); break; + case 19: if (p) p->color_ = cs.getData(); break; + case 20: if (p) p->trans = cs.getData(); break; + case 100: if (l) l->setAim(cs.getData()); break; + case 101: if (l) l->angle_start = cs.getData(); break; + case 102: if (l) l->angle_end = cs.getData(); break; + case 103: if (l) l->intensity = cs.getData(); break; + case 104: if (l) l->decay_const = cs.getData(); break; + case 105: if (l) l->decay_linear = cs.getData(); break; + case 106: if (l) l->decay_quadratic = cs.getData(); break; + case 107: if (l) l->decay_start = cs.getData(); break; + case 108: if (l) l->decay_end = cs.getData(); break; + case 109: if (l) l->light_type = (Light::Type)cs.getData(); break; + case 111: if (l) l->setDistance(cs.getData()); break; + case 200: if (c) c->setAim(cs.getData()); break; + case 201: if (c) c->setFOV(cs.getData()); break; + case 202: if (c) c->setDepthStart(cs.getData()); break; + case 206: if (c) c->mirror_x = cs.getData(); break; + case 207: if (c) c->mirror_y = cs.getData(); break; + case 208: if (c) c->setDistance(cs.getData()); break; + case 209: if (c) c->roll_ = cs.getData(); break; + } + } + //qDebug() << p->name() << ccnt; + for (int i = 0; i < ccnt; ++i) { + ObjectBase * c = nullptr; + s >> c; + if (!c) continue; + c->parent_ = p; + p->children_ << c; + } + p->buildTransform(); + return s; +} diff --git a/globject.h b/globject.h new file mode 100644 index 0000000..bfd9958 --- /dev/null +++ b/globject.h @@ -0,0 +1,313 @@ +/* + QGL ObjectBase & Light + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLOBJECT_H +#define GLOBJECT_H + +#include "glframebuffer.h" +#include "glmaterial.h" +#include "gltypes.h" +#include "gltransform.h" + + +class ObjectBase +{ + friend class QGLView; + friend class Scene; + friend class Renderer; + friend class RendererService; + friend class RendererSelection; + friend class MouseController; + friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p); + friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p); + friend QDataStream & operator >>(QDataStream & s, Scene *& p); +public: + enum Type {glMesh, glLight, glCamera, glParticlesSystem}; + enum RenderMode {View = 0, Point = GL_POINT, Line = GL_LINE, Fill = GL_FILL}; + + explicit ObjectBase(Mesh * geom = 0, Material * mat = 0); + virtual ~ObjectBase(); + + virtual ObjectBase * clone(bool withChildren = true); + void destroy(); + + QString name() const {return name_;} + void setName(const QString & name) {name_ = name;} + virtual void init(); + virtual void update() {} + bool isInit() const {return is_init;} + Type type() const {return type_;} + RenderPass pass() const; + + RenderMode renderMode() const {return render_mode;} + void setRenderMode(RenderMode mode) {render_mode = mode;} + + float lineWidth() const {return line_width;} + void setLineWidth(const float & width) {line_width = width;} + + ObjectBase * parent() {return parent_;} + void setParent(ObjectBase * o) {parent_ = o;} + bool hasParent() const {return parent_ != nullptr;} + bool hasChildren() const {return !children_.isEmpty();} + void setScene(Scene * v); + + void addChild(ObjectBase * o); + void removeChild(ObjectBase * o); + void removeChild(int index); + void clearChildren(bool deleteAll = false); + int childCount() const {return children_.size();} + ObjectBase * child(int index); + ObjectBase * child(const QString & name); + const ObjectBase * child(int index) const; + const ObjectBase * child(const QString & name) const; + ObjectBaseList children(bool all_ = false); + + bool isVisible(bool check_parents = false) const; + bool isHidden(bool check_parents = false) const {return !isVisible(check_parents);} + void setVisible(bool v); + void setHidden(bool v) {setVisible(!v);} + void show() {setVisible(true);} + void hide() {setVisible(false);} + + bool isReceiveShadows() const {return rec_shadow;} + bool isCastShadows() const {return cast_shadow;} + void setReceiveShadows(bool on) {rec_shadow = on;} + void setCastShadows(bool on) {cast_shadow = on;} + + void move(const QVector3D & dv) {trans.setTranslation(pos() + dv); buildTransform();} + void moveTo(const QVector3D & dv) {trans.setTranslation(dv); buildTransform();} + void move(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {move(QVector3D(dx, dy, dz)); buildTransform();} + void moveTo(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {moveTo(QVector3D(dx, dy, dz)); buildTransform();} + void moveX(GLfloat o) {trans.setTranslationX(posX() + o); buildTransform();} + void moveY(GLfloat o) {trans.setTranslationY(posY() + o); buildTransform();} + void moveZ(GLfloat o) {trans.setTranslationZ(posZ() + o); buildTransform();} + void setPosX(GLfloat o) {trans.setTranslationX(o); buildTransform();} + void setPosY(GLfloat o) {trans.setTranslationY(o); buildTransform();} + void setPosZ(GLfloat o) {trans.setTranslationZ(o); buildTransform();} + void setPos(GLfloat x, GLfloat y, GLfloat z) {trans.setTranslation(QVector3D(x, y, z)); buildTransform();} + void setPos(const QVector3D & p) {trans.setTranslation(p); buildTransform();} + void resetPos() {trans.setTranslation(QVector3D()); buildTransform();} + + QVector3D pos() const {return trans.translation();} + float posX() const {return trans.translation().x();} + float posY() const {return trans.translation().y();} + float posZ() const {return trans.translation().z();} + QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();} + QMatrix4x4 worldTransform() const {return itransform_;} + + QVector3D rotation() const {return trans.rotation();} + float rotationX() const {return rotation().x();} + float rotationY() const {return rotation().y();} + float rotationZ() const {return rotation().z();} + void rotateX(GLfloat a) {raw_matrix = false; trans.setRotationX(trans.rotationX() + a); buildTransform();} + void rotateY(GLfloat a) {raw_matrix = false; trans.setRotationY(trans.rotationY() + a); buildTransform();} + void rotateZ(GLfloat a); + void setRotationX(GLfloat a) {raw_matrix = false; trans.setRotationX(a); buildTransform();} + void setRotationY(GLfloat a) {raw_matrix = false; trans.setRotationY(a); buildTransform();} + void setRotationZ(GLfloat a); + void setRotation(const QVector3D & a) {raw_matrix = false; trans.setRotation(a); buildTransform();} + void resetRotation() {raw_matrix = false; trans.setRotation(QVector3D()); buildTransform();} + + QVector3D scale() {return trans.scale3D();} + float scaleX() {return trans.scale3D().x();} + float scaleY() {return trans.scale3D().y();} + float scaleZ() {return trans.scale3D().z();} + void scale(const QVector3D & sv) {raw_matrix = false; trans.setScale(trans.scale3D() * sv); buildTransform();} + void scale(GLfloat sx, GLfloat sy, GLfloat sz) {raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform();} + void scale(GLfloat sx, GLfloat sy) {raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform();} + void scale(GLfloat sx) {raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform();} + void scaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(trans.scale3D().x() + a); buildTransform();} + void scaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(trans.scale3D().y() + a); buildTransform();} + void scaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(trans.scale3D().z() + a); buildTransform();} + void setScale(const QVector3D & a) {raw_matrix = false; trans.setScale(a); buildTransform();} + void setScale(GLfloat a) {raw_matrix = false; trans.setScale(a); buildTransform();} + void setScaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(a); buildTransform();} + void setScaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(a); buildTransform();} + void setScaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(a); buildTransform();} + void resetScale() {raw_matrix = false; trans.setScale(1.f); buildTransform();} + + Transform transform() {return trans;} + void setTransform(const Transform & t); + void setMatrix(const QMatrix4x4 & t); + QMatrix4x4 matrix() const; + bool isRawMatrix() {return raw_matrix;} + QVector3D inParentSpace(const QVector3D & v) const; + void transferTransformToChildren(bool only_scale = false); + void cleanTree(); + + bool isAcceptLight() const {return accept_light;} + void setAcceptLight(bool yes) {accept_light = yes;} + + bool isAcceptFog() const {return accept_fog;} + void setAcceptFog(bool yes) {accept_fog = yes;} + + bool isSelected(bool check_parents = false) const; + void setSelected(bool yes); + void select() {setSelected(true);} + void deselect() {setSelected(false);} + ObjectBase * selectedParent() const; + + bool isSelectable() const {return select_;} + void setSelectable(bool yes) {select_ = yes;} + /* + bool isWriteDepth() const {return write_depth_;} + void setWriteDepth(bool yes) {write_depth_ = yes;}*/ + + GLenum srcAlpha() const {return blend_src;} + GLenum destAlpha() const {return blend_dest;} + void setSrcAlpha(GLenum mode) {blend_src = mode;} + void setDestAlpha(GLenum mode) {blend_dest = mode;} + + void setMaterial(Material * m, bool with_children = false); + Material * material() {return material_;} + + void setColor(QColor c, bool with_children = false); + QColor color() {return color_;} + + const Box3D & boundingBox() const {return bound;} + void setMesh(Mesh * v); + Mesh * mesh() {return mesh_;} + + void calculateBoundingBox(); + void updateTransform(); + + void setProperty(const QString & pn, const QVariant & v); + QVariant property(const QString & pn, bool * exists = 0) const; + bool hasProperty(const QString & pn) const; + void removeProperty(const QString & pn); + + QVector3D pos_h; + + //QVector d_vertices, d_normals, d_uvs; + +protected: + virtual void transformChanged() {} + void addChildren(ObjectBaseList & list, ObjectBase * where); + void buildTransform(bool force = false); + void initInternal(); + void setSceneTreeChanged(); + void setObjectsChanged(); + void localTransform(QMatrix4x4 & m); + QMatrix4x4 worldMatrix(QMatrix4x4 parent) const; + + int prev_pass; // Pass + bool is_init, accept_light, accept_fog, visible_, cast_shadow, rec_shadow, select_, selected_, raw_matrix; + bool is_root, selected_aim; + float line_width; + QColor color_; + uint id_; + Type type_; + RenderMode render_mode; + Box3D bound; + Transform trans; + ObjectBaseList children_; + QMatrix4x4 itransform_, mat_; + QString name_; + GLenum blend_src, blend_dest; + ObjectBase * parent_; + Scene * scene_; + Material * material_; + Mesh * mesh_; + QVariantMap meta; + +}; + +inline bool operator <(const ObjectBase & f, const ObjectBase & s) {return f.pos_h.z() < s.pos_h.z();} + + +class AimedObject: public ObjectBase { + friend class QGLView; + friend class GLRendererBase; + friend class Light; + friend class Camera; +public: + AimedObject(); + ~AimedObject() {} + QVector3D aim() const {return pos() + (direction() * aim_dist);} + QVector3D worldAim() const; + void setAim(const QVector3D & p); + QVector3D direction() const; + QVector3D worldDirection() const {return (itransform_ * QVector4D(QVector3D(0,0,-1), 0.)).toVector3D().normalized();} + void setDirection(const QVector3D & d); + void setDirection(double x, double y, double z) {setDirection(QVector3D(x, y, z));} + + double distance() const {return aim_dist;} + void setDistance(double d) {aim_dist = d;} + void flyCloser(double s); + void flyFarer(double s); + void flyToDistance(double d); + + void moveForward(const float & x, bool withZ = true); + void moveBackward(const float & x, bool withZ = true) {moveForward(-x, withZ);} + void moveLeft(const float & x, bool withZ = true); + void moveRight(const float & x, bool withZ = true) {moveLeft(-x, withZ);} + void moveUp(const float & x, bool onlyZ = false); + void moveDown(const float & x, bool onlyZ = false) {moveUp(-x, onlyZ);} + + void rotateRoll(const float & a) {rotateY(a);} + void orbitZ(const float & a); + void orbitXY(const float & a); + +protected: + void transformChanged() override; + double aim_dist; +}; + + +class Light: public AimedObject { + friend class QGLView; + friend class RendererBase; +public: + enum Type {Omni, Cone, Directional}; + + Light(); + Light(const QVector3D & p, const QColor & c = Qt::white, float i = 1.); + virtual ObjectBase * clone(bool withChildren = true); + virtual void init() {shadow_map.resize(512, 512); is_init = true;} + void apply(); + + float angle_start; + float angle_end; + float intensity; + float decay_const; + float decay_linear; + float decay_quadratic; + float decay_start; + float decay_end; + Type light_type; + Framebuffer shadow_map; + QMatrix4x4 shadow_matrix; + +protected: + +}; + +template +inline T globject_cast(ObjectBase * object) {return reinterpret_cast(object);} + +template +inline T globject_cast(const ObjectBase * object) {return reinterpret_cast(object);} + + +QDataStream & operator <<(QDataStream & s, const ObjectBase * p); +QDataStream & operator >>(QDataStream & s, ObjectBase *& p); + +inline ObjectBaseList lights2objectList(const QList & v) {ObjectBaseList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;} +inline ObjectBaseList cameras2objectList(const QList & v) {ObjectBaseList ret; foreach (Camera*i, v) ret << (ObjectBase*)i; return ret;} + +#endif // GLOBJECT_H diff --git a/glrendererbase.cpp b/glrendererbase.cpp new file mode 100644 index 0000000..edb92b6 --- /dev/null +++ b/glrendererbase.cpp @@ -0,0 +1,294 @@ +/* + QGL GLRendererBase + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "glrendererbase.h" +#include "globject.h" +#include "qglview.h" + + +GLRendererBase::GLRendererBase(QGLView * view_): view(view_) { + white_image = QImage(1, 1, QImage::Format_ARGB32); + white_image.fill(0xFFFFFFFF); + white_image_id = 0; + violent_image = QImage(1, 1, QImage::Format_ARGB32); + violent_image.fill(QColor(127, 127, 255)); + violent_image_id = 0; +} + + +void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) { + QVector3D lp = l.worldPos(), ld;// = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized(); + GLfloat pos[] = {0.f, 0.f, 0.f, 0.f}; + GLfloat dir[] = {0.f, 0.f, 0.f}; + GLfloat col[] = {0.f, 0.f, 0.f}; + pos[0] = l.light_type == Light::Directional ? -l.direction().x() : lp.x(); + pos[1] = l.light_type == Light::Directional ? -l.direction().y() : lp.y(); + pos[2] = l.light_type == Light::Directional ? -l.direction().z() : lp.z(); + pos[3] = l.light_type == Light::Directional ? 0. : 1.; + dir[0] = ld.x(); + dir[1] = ld.y(); + dir[2] = ld.z(); + //col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.f; + //col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.f; + //col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.f; + glEnable(gl_index); + //glLightfv(gl_index, GL_AMBIENT, ambient); + glLightfv(gl_index, GL_DIFFUSE, col); + glLightfv(gl_index, GL_SPECULAR, col); + glLightfv(gl_index, GL_POSITION, pos); + glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const); + glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear); + glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic); + if (l.light_type == Light::Cone) { + glLightfv(gl_index, GL_SPOT_DIRECTION, dir); + glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_end / 2.f); + glLightf(gl_index, GL_SPOT_EXPONENT, (1.f - piClamp((l.angle_end - l.angle_start) / (l.angle_end + 0.001f), 0., 1.f)) * 128.f); + } else { + glLightf(gl_index, GL_SPOT_CUTOFF, 180.); + } + +} + + +void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) { + GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f}; + if (first_pass) { + ambient[0] = view->ambientColor_.redF(); + ambient[1] = view->ambientColor_.greenF(); + ambient[2] = view->ambientColor_.blueF(); + } + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); +} + + +void GLRendererBase::setupShadersLights(int lights_count) { + /*foreach (QOpenGLShaderProgram * i, view->shaders_ppl) { + i->bind(); + i->setUniformValue("lightsCount", lights_count); + i->setUniformValue("acc_light", lights_count > 0); + //i->setUniformValue("mat", mvm); + }*/ +} + + +#define BIND_TEXTURE(ch, map) if (rp.prev_tex[ch] != mat.map.bitmap_id) { \ + rp.prev_tex[ch] = mat.map.bitmap_id; \ + glActiveTexture(GL_TEXTURE0 + ch); glBindTexture(GL_TEXTURE_2D, mat.map.bitmap_id); \ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view->feature(QGLView::qglAnisotropicLevel).toInt());} + +void GLRendererBase::setupTextures(ObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) { +} + +#undef BIND_TEXTURE + + +void GLRendererBase::setupLights(int pass, int lights_per_pass) { + /*int light_start, light_end, lmax; + light_start = pass * lights_per_pass; + light_end = qMin((pass + 1) * lights_per_pass, view->lights_.size()); + setupAmbientLight(view->ambientColor_, pass == 0); + if (!view->lights_.isEmpty()) { + setupShadersLights(light_end - light_start); + for (int i = light_start; i < light_end; ++i) + setupLight(*view->lights_[i], i - light_start, GL_LIGHT0 + i - light_start); + lmax = light_start + 8; + for (int i = light_end; i < lmax; ++i) + glDisable(GL_LIGHT0 + i - light_start); + } else { + setupShadersLights(0); + for (int i = 0; i < 8; ++i) + glDisable(GL_LIGHT0 + i); + }*/ +} + + +void GLRendererBase::applyFilteringParameters() { + /*if (view->isFeatureEnabled(QGLView::qglLinearFiltering)) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + }*/ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view->feature(QGLView::qglAnisotropicLevel).toInt()); +} + + +void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) { + /*RenderingParameters rpl; + rpl.pass = pass; + rpl.light_pass = light_pass; + rpl.shaders = shaders; + rpl.textures = textures; + rpl.light = rpl.prev_light = light; + rpl.fog = rpl.prev_fog = fog; + rpl.view_matrix = rp.view_matrix; + rpl.prev_view_matrix = rp.prev_view_matrix; + rpl.proj_matrix = rp.proj_matrix; + rpl.prev_proj_matrix = rp.prev_proj_matrix; + rpl.cam_offset_matrix = view->camera()->offsetMatrix(); + //qDebug() << "view:" << rp.view_matrix; + for (int i = 0; i < 32; ++i) rpl.prev_tex[i] = 0; + setupTextures(view->objects_, rpl, true); + glSetCapEnabled(GL_TEXTURE_2D, rpl.textures); + glSetCapEnabled(GL_BLEND, pass == ObjectBase::Transparent); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_CUBE_MAP); + glPushMatrix(); + renderSingleObject(view->objects_, rpl); + glPopMatrix();*/ +} + + +void GLRendererBase::renderSingleObject(ObjectBase & o, RenderingParameters & rpl) { +// if (!o.isInit()) +// o.init(); +// if (!o.isTexturesLoaded()) +// o.loadTextures(); +// if (!o.visible_) return; +// if (rpl.pass == o.pass_) { +// //Material & mat(o.material_); +// QMatrix4x4 curview = rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_, prevview = rpl.prev_view_matrix * rpl.cam_offset_matrix * o.itransform_; +// //setupTextures(o, rpl, false); +// //mat.apply((QOpenGLShaderProgram*)rpl.shaders); +// glSetPolygonMode(o.render_mode != ObjectBase::View ? o.render_mode : (view->rmode != ObjectBase::View ? view->rmode : GL_FILL)); +// glLineWidth(o.line_width > 0.f ? o.line_width : view->lineWidth_); +// glPointSize(o.line_width > 0.f ? o.line_width : view->lineWidth_); +// o.update(); +// /*if (o.pass_ == GLObjectBase::Transparent) { +// glActiveTexture(GL_TEXTURE0 + 3); +// if (mat.reflectivity > 0.f) { +// glEnable(GL_TEXTURE_CUBE_MAP); +// //if (!mat.map_reflection.isEmpty()) mat.map_reflection.bind(); +// //else glDisable(GL_TEXTURE_CUBE_MAP); +// } else glDisable(GL_TEXTURE_CUBE_MAP); +// if (rpl.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP); +// GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity}; +// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); +// glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); +// glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); +// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); +// glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc); +// glGetFloatv(GL_MODELVIEW_MATRIX, gm); +// glMatrixMode(GL_TEXTURE); +// ///glLoadTransposeMatrixf(gm); +// glScalef(-1., -1., -1.); +// glMatrixMode(GL_MODELVIEW); +// glActiveTexture(GL_TEXTURE0); +// }*/ +// if (rpl.shaders) { +// //qDebug() << o.name() << curview << curview->determinant(); +// //setUniformMatrices((QOpenGLShaderProgram*)rpl.shaders, rpl.proj_matrix, curview, rpl.prev_proj_matrix, prevview); +// } else { +// glMatrixMode(GL_MODELVIEW); +// //setGLMatrix(curview); +// } +// o.draw((QOpenGLShaderProgram*)rpl.shaders); +// } +// foreach (ObjectBase * i, o.children_) +// renderSingleObject(*i, rpl); +} + + +void GLRendererBase::renderShadow(Light * l, QOpenGLShaderProgram * prog, QMatrix4x4 mat) { + Camera cam; + QVector3D wp = l->worldPos(); + cam.setPos(wp); + cam.setAim(wp + (l->worldTransform() * QVector4D(l->direction())).toVector3D()); + cam.setDepthStart(view->camera()->depthStart()); + cam.setFOV(l->angle_end); + //cam.apply(1.); + /*cam.rotateXY(l->angle_end); + QVector3D rdir = l->direction * cos(l->angle_end / 2. * deg2rad); + l->dir0 = cam.direction() - rdir; + cam.rotateXY(-l->angle_end); + cam.rotateZ(l->angle_end); + l->dir1 = cam.direction() - rdir;*/ + //qDebug() << rdir << l->dir0 << l->dir1; + RenderingParameters rpl; + rpl.shaders = prog; + rpl.textures = rpl.light = rpl.fog = false; + //rpl.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + //rpl.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + rpl.cam_offset_matrix = cam.offsetMatrix(); + QMatrix4x4 mbias; + mbias.scale(0.5, 0.5, 0.5); + mbias.translate(1., 1., 1.); + l->shadow_matrix = mbias*rpl.proj_matrix*rpl.view_matrix*rpl.cam_offset_matrix*mat;//;// * mbias; + //qDebug() << mbias; + //glPushMatrix(); + //renderSingleShadow(view->objects_, rpl); + //glPopMatrix(); +} + + +void GLRendererBase::renderSingleShadow(ObjectBase & o, RenderingParameters & rpl) { +// if (!o.isInit()) +// o.init(); +// if (!o.visible_) return; +// if (rpl.shaders) { +// //qDebug() << o.name() << curview << curview->determinant(); +// //setUniformMatrices((QOpenGLShaderProgram*)rpl.shaders, rpl.proj_matrix, rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_); +// } else { +// glMatrixMode(GL_MODELVIEW); +// //setGLMatrix(rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_); +// } +// glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != ObjectBase::View ? o.render_mode : (view->rmode != ObjectBase::View ? view->rmode : GL_FILL)); +// glLineWidth(o.line_width > 0.f ? o.line_width : view->lineWidth_); +// glPointSize(o.line_width > 0.f ? o.line_width : view->lineWidth_); +// o.draw((QOpenGLShaderProgram*)rpl.shaders, true); +// foreach (ObjectBase * i, o.children_) +// renderSingleShadow(*i, rpl); +} + + + + +GLRendererBase::RenderingParameters::RenderingParameters() { + shaders = nullptr; + cur_shader = nullptr; +} + + +void GLRendererBase::RenderingParameters::prepare() { + //proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + //view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + viewproj_matrix = proj_matrix * view_matrix; + normal_matrix = view_matrix.normalMatrix(); + proj_matrix_i = proj_matrix.inverted(); + view_matrix_i = view_matrix.inverted(); + viewproj_matrix_i = viewproj_matrix.inverted(); +} + + +void GLRendererBase::RenderingParameters::setUniform(QOpenGLShaderProgram * prog) { + if (!prog) return; + prog->setUniformValue("qgl_ModelViewMatrix", view_matrix); + prog->setUniformValue("qgl_ProjectionMatrix", proj_matrix); + prog->setUniformValue("qgl_ModelViewProjectionMatrix", viewproj_matrix); + prog->setUniformValue("qgl_NormalMatrix", normal_matrix); + prog->setUniformValue("qgl_ModelViewMatrixInverse", view_matrix_i); + prog->setUniformValue("qgl_ProjectionMatrixInverse", proj_matrix_i); + prog->setUniformValue("qgl_ModelViewProjectionMatrixInverse", viewproj_matrix_i); + prog->setUniformValue("qgl_ModelViewMatrixTranspose", view_matrix.transposed()); + prog->setUniformValue("qgl_ProjectionMatrixTranspose", proj_matrix.transposed()); + prog->setUniformValue("qgl_ModelViewProjectionMatrixTranspose", viewproj_matrix.transposed()); + prog->setUniformValue("qgl_ModelViewMatrixInverseTranspose", view_matrix_i.transposed()); + prog->setUniformValue("qgl_ProjectionMatrixInverseTranspose", proj_matrix_i.transposed()); + prog->setUniformValue("qgl_ModelViewProjectionMatrixInverseTranspose", viewproj_matrix_i.transposed()); +} diff --git a/glrendererbase.h b/glrendererbase.h new file mode 100644 index 0000000..7076d7a --- /dev/null +++ b/glrendererbase.h @@ -0,0 +1,80 @@ +/* + QGL GLRendererBase + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLRENDERERBASE_H +#define GLRENDERERBASE_H + +#include "glcamera.h" +#include "glshaders.h" + +class GLRendererBase: public QObject , protected QOpenGLExtraFunctions +{ + friend class QGLView; + Q_OBJECT +public: + GLRendererBase(QGLView * view_); + virtual void prepareScene() {;} + virtual void renderScene() = 0; + + struct RenderingParameters { + RenderingParameters(); + void prepare(); + void setUniform(QOpenGLShaderProgram * prog); + int pass; + int light_pass; + bool light; + bool fog; + bool textures; + bool prev_light; + bool prev_fog; + GLuint prev_tex[32]; + void * shaders; + QMatrix4x4 view_matrix, view_matrix_i, prev_view_matrix; + QMatrix4x4 proj_matrix, proj_matrix_i, prev_proj_matrix; + QMatrix4x4 viewproj_matrix, viewproj_matrix_i; + QMatrix3x3 normal_matrix; + QMatrix4x4 cam_offset_matrix; + QOpenGLShaderProgram * cur_shader; + }; + + RenderingParameters rp; + +protected: + virtual void setupLight(const Light & l, int inpass_index, int gl_index); + virtual void setupAmbientLight(const QColor & a, bool first_pass); + virtual void setupShadersLights(int lights_count); + virtual void setupTextures(ObjectBase & object, GLRendererBase::RenderingParameters & rp, bool first_object = false); + virtual void setupShadersTextures(ObjectBase & object, GLRendererBase::RenderingParameters & rp) {} + virtual void reloadShaders() {} + virtual void init(int width, int height) {} + virtual void resize(int width, int height) {} + + void setupLights(int pass, int lights_per_pass); + inline void applyFilteringParameters(); + void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true); + void renderSingleObject(ObjectBase & o, RenderingParameters & rpl); + void renderShadow(Light * l, QOpenGLShaderProgram * prog = 0, QMatrix4x4 mat = QMatrix4x4()); + void renderSingleShadow(ObjectBase & o, RenderingParameters & rpl); + + QGLView * view; + QImage white_image, violent_image; + GLuint white_image_id, violent_image_id; + +}; + +#endif // GLRENDERERBASE_H diff --git a/glscene.cpp b/glscene.cpp new file mode 100644 index 0000000..1f51bc7 --- /dev/null +++ b/glscene.cpp @@ -0,0 +1,540 @@ +/* + QGL Scene + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "glscene.h" +#include "glcamera.h" +#include "glmesh.h" +#include "qglview.h" +#include + + +Scene::Scene() { + root_ = new ObjectBase(); + root_->setScene(this); + tree_changed = mat_changed = lights_changed = true; + destroying = false; + need_reload_materials = tree_struct_changed = true; + sel_mode_ = smSingleSelection; +} + + +Scene::~Scene() { + destroying = true; + clear(); + delete root_; +} + + +Scene * Scene::clone() { + Scene * ret = new Scene(); + ObjectBase * o = root_->clone(); + foreach (ObjectBase * co, o->children()) + ret->addObject(co); + o->clearChildren(); + delete o; + return ret; +} + + +void Scene::addObject(ObjectBase * o) { + ObjectBaseList aol = o->children(true); + attachObject(o); + foreach (ObjectBase * c, aol) + attachObject(c); + root_->addChild(o); + tree_changed = tree_struct_changed = true; +} + + +void Scene::addScene(const Scene * s) { + if (!s) return; + //qDebug() << "addScene clone ..."; + ObjectBase * o = s->root_->clone(); + o->setName(s->name()); + //qDebug() << "addScene clone ok" << o << o->children(true).size(); + addObject(o); + makeMaterialsUniqueNames(); + //qDebug() << "addScene add ok" << o; +} + + +void Scene::assignFrom(const Scene * s) { + clear(); + setName(s->name()); + foreach (Material * m, s->materials) { + Material * nm = new Material(); + *nm = *m; + nm->_changed = true; + nm->setMapsChanged(); + materials << nm; + } + for (int i = 0; i < s->root_->childCount(); ++i) { + addObject(s->root_->child(i)->clone()); + //qDebug() << i << o->child(i)->pos(); + } + tree_changed = mat_changed = lights_changed = need_reload_materials = tree_struct_changed = true; +} + + +void Scene::clear() { + selected_.clear(); + selected_top.clear(); + emitSelectionChanged(); + root_->clearChildren(true); + td_geometries << geometries; + qDeleteAll(materials); + geometries.clear(); + materials.clear(); + emit __destroyed(); + emit treeChanged();} + + +void Scene::objectsCountInternal(int * cnt, ObjectBase * where) { + ++(*cnt); + foreach (ObjectBase * i, where->children_) + objectsCountInternal(cnt, i); +} +int Scene::objectsCount(bool all) { + if (!all) return root_->childCount(); + int cnt = 0; + objectsCountInternal(&cnt, root_); + return cnt; +} + + +void Scene::removeObjectInternal(ObjectBase * o, ObjectBase * where) { + if (destroying) return; + foreach (ObjectBase * i, where->children_) { + if (o == i) { + where->removeChild(i); + setObjectMeshChanged(i); + } else + removeObjectInternal(o, i); + } +} + + +void Scene::emitSelectionChanged() { + selected_top.clear(); + foreach (ObjectBase * o, selected_) { + ObjectBase * po = o->selectedParent(); + if (!po) po = o; + if (!selected_top.contains(po)) + selected_top << po; + } + foreach (Mesh * m, geometries) + m->setAllSelectionChanged(true); + selectionChanged(); +} + + +QString Scene::uniqueName(QString n, const QSet & names) { + if (!names.contains(n)) + return n; + QString num; + while (!n.isEmpty()) { + if (n.right(1)[0].isDigit()) { + num.push_front(n.right(1)); + n.chop(1); + } else break; + } + if (!n.endsWith('_')) n += '_'; + int in = num.toInt() + 1; + QString nn = n + QString::number(in).rightJustified(3, '0'); + while (names.contains(nn)) + nn = n + QString::number(++in).rightJustified(3, '0'); + return nn; +} + + + +void Scene::removeObject(ObjectBase * o, bool inChildren) { + if (destroying) return; + o->setScene(nullptr); + setObjectMeshChanged(o); + if (inChildren) + removeObjectInternal(o, root_); + else + root_->removeChild(o); + __objectDeleted(o); + setTreeStructChanged(); +} + + +void Scene::removeObject(ObjectBase & o, bool inChildren) { + if (destroying) return; + removeObject(&o, inChildren); +} + + +void Scene::clearObjects(bool deleteAll) { + root_->clearChildren(deleteAll); + cleanUnused(); + setTreeStructChanged(); + emitSelectionChanged(); +} + + +void Scene::selectObject(ObjectBase * o, bool add_to_selection) { + //qDebug() << "selectObject" << o << add_to_selection; + if (!add_to_selection || (sel_mode_ == smSingleSelection)) clearSelection(); + if (o) { + if (!add_to_selection) o->setSelected(true); + else o->setSelected(!o->isSelected()); + gatherSelection(); + } + emitSelectionChanged(); +} + + +void Scene::selectObjects(ObjectBaseList ol, bool add_to_selection) { + if (!add_to_selection || (sel_mode_ == smSingleSelection)) clearSelection(); + foreach (ObjectBase * o, ol) { + if (!o) continue; + o->setSelected(true); + } + gatherSelection(); + emitSelectionChanged(); +} + + +void Scene::selectObjectsByMesh() { + ObjectBaseList csl = selected_; + QSet sml; + foreach (ObjectBase * o, csl) + if (o->mesh()) + sml << o->mesh(); + ObjectBaseList ol = root_->children(true); + foreach (ObjectBase * o, ol) { + if (sml.contains(o->mesh())) + o->setSelected(true); + } + gatherSelection(); + emitSelectionChanged(); +} + + +void Scene::selectObjectsByMaterial() { + ObjectBaseList csl = selected_; + QSet sml; + foreach (ObjectBase * o, csl) + if (o->material()) + sml << o->material(); + ObjectBaseList ol = root_->children(true); + foreach (ObjectBase * o, ol) { + if (sml.contains(o->material())) + o->setSelected(true); + } + gatherSelection(); + emitSelectionChanged(); +} + + +void Scene::clearSelection() { + selected_.clear(); + selected_top.clear(); + ObjectBaseList ol = root_->children(true); + foreach (ObjectBase * o, ol) { + o->selected_ = o->selected_aim = false; + } + emitSelectionChanged(); +} + + +ObjectBaseList Scene::selectedObjects(bool top_only) const { + return top_only ? selected_top : selected_; +} + + +ObjectBase * Scene::selectedObject() const { + if (selected_.isEmpty()) return 0; + return selected_[0]; +} + + +void gatherMeshes(ObjectBase * o, QSet & ums) { + if (o->mesh()) ums << o->mesh(); + for (int i = 0; i < o->childCount(); ++i) + gatherMeshes(o->child(i), ums); +} +void Scene::cleanUnused() { + QSet ums; + gatherMeshes(root_, ums); + /*QMapIterator> it(geometries_used); + while (it.hasNext()) + ums |= it.next().value().keys().toSet();*/ + for (int i = 0; i < geometries.size(); ++i) { + if (ums.contains(geometries[i])) continue; + td_geometries << geometries[i]; + geometries.removeAt(i); + --i; + } +} + + +const Box3D & Scene::boundingBox() const { + root_->calculateBoundingBox(); + return root_->boundingBox(); +} + + +Material * Scene::newMaterial(const QString & name) { + materials << new Material(name); + makeMaterialsUniqueNames(); + mat_changed = true; + return materials.back(); +} + + +void Scene::removeMaterial(Material * m) { + if (!m || !materials.contains(m)) return; + ObjectBaseList ol = root_->children(true); + foreach (ObjectBase * o, ol) + if (o->material_ == m) + o->setMaterial(0); + materials.removeAll(m); + changed_materials.removeAll(m); + mat_changed = true; +} + + +void Scene::makeMaterialsUniqueNames() { + QSet names; + foreach (Material * m, materials) { + if (m->name.isEmpty()) m->name = "default_000"; + m->name = uniqueName(m->name, names); + names << m->name; + } +} + + +ObjectBaseList Scene::objects(bool all) { + return root_->children(all); +} + + +void Scene::removeLight(Light * l) { + removeObject(l); +} + + +void Scene::dump() { + qDebug() << "Scene" << name(); + qDebug() << "Meshes:" << geometries.size(); + qDebug() << "Objects:" << root_->children(true).size(); +} + + +void Scene::gatherSelection() { + selected_.clear(); + ObjectBaseList ol = root_->children(true); + foreach (ObjectBase * o, ol) + if (o->selected_) + selected_ << o; +} + + +void Scene::attachObject(ObjectBase * o) { + if (!o) return; + o->setScene(this); + if (o->mesh()) { // search suitable mesh in this scene + o->mesh_ = attachMesh(o->mesh()); + setObjectMeshChanged(o); + } + if (o->material()) { // search suitable material in this scene + uint ohash = o->material()->hash(); + bool need_new = true; + foreach (Material * m, materials) { + if (m == o->material()) { // already exists by ptr + need_new = false; + break; + } + if (m->hash() == ohash) { // already exists by hash + need_new = false; + o->setMaterial(m); + break; + } + } + if (need_new) { // need to clone material and add to scene + Material * nmat = new Material(); + *nmat = *(o->material()); + nmat->setMapsChanged(); + o->setMaterial(nmat); + materials << nmat; + } + } + setTreeStructChanged(); +} + + +Mesh * Scene::attachMesh(Mesh * mesh) { + if (!mesh) return 0; + uint mhash = mesh->hash(); + foreach (Mesh * m, geometries) { + if (m == mesh) { // already exists by ptr + return m; + } + if (m->hash() == mhash) { // already exists by hash + return m; + } + } + // need to clone mesh and add to scene + Mesh * nmesh = mesh->clone(); + geometries << nmesh; + return nmesh; +} + + +void Scene::setTreeChanged() { + if (destroying) return; + tree_changed = true; + foreach (Mesh * m, geometries) { + m->setAllObjectsChanged(true); + m->setAllSelectionChanged(true); + } + gatherSelection(); +} + + +void Scene::setTreeStructChanged() { + tree_struct_changed = true; +} + + +void Scene::setObjectMeshChanged(ObjectBase * o) { + if (o) o->setObjectsChanged(); +} + + +void Scene::prepareTree(ObjectBase * o) { + foreach (ObjectBase * co, o->children_) { + if (co->isHidden()) continue; + switch (co->type_) { + case ObjectBase::glLight: { + Light * l = globject_cast(co); + lights_used[l->light_type] << l; + } break; + case ObjectBase::glMesh: + if (co->mesh()) { + geometries_used[co->pass()][co->mesh()] << co; + co->setObjectsChanged(); + } + break; + case ObjectBase::glCamera: + cameras_used << globject_cast(co); + break; + default: break; + } + prepareTree(co); + } +} + + +bool Scene::prepare() { + changed_materials.clear(); + foreach (Material * m, materials) { + if (m->_changed) { + need_reload_materials = tree_changed = true; + changed_materials << m; + } + } + + ObjectBaseList aol; + if (!tree_changed && !mat_changed) return false; + aol = root_->children(true); + if (tree_changed) { + geometries_used[rpSolid ].clear(); + geometries_used[rpTransparent].clear(); + lights_used.clear(); + cameras_used.clear(); + prepareTree(root_); + if (tree_struct_changed) { + tree_struct_changed = false; + cleanUnused(); + QMetaObject::invokeMethod(this, "treeChanged", Qt::QueuedConnection); + } + tree_changed = false; + lights_changed = true; + } + mat_changed = false; + return true; +} + + +void Scene::destroy(QOpenGLExtraFunctions * f) { + foreach (Mesh * g, geometries) + g->destroy(f); +} + + +void Scene::destroyUnused(QOpenGLExtraFunctions * f) { + //if (!td_geometries.isEmpty()) qDebug() << "destroyUnused" << td_geometries.size(); + foreach (Mesh * i, td_geometries) + i->destroy(f); + qDeleteAll(td_geometries); + td_geometries.clear(); +} + + +QDataStream & operator <<(QDataStream & s, const Scene * p) { + ChunkStream cs; + //qDebug() << "place" << p->name() << "..."; + QVector geom_ind, mat_ind; + ObjectBaseList cl = p->root_->children(true); + geom_ind.reserve(cl.size()); + mat_ind.reserve(cl.size()); + foreach (ObjectBase * c, cl) { + geom_ind << p->geometries.indexOf(c->mesh()); + mat_ind << p->materials.indexOf(c->material()); + } + cs.add(1, p->name_).add(10, p->geometries).add(11, p->materials) + .add(20, p->root_).add(21, geom_ind).add(22, mat_ind); + s << qCompress(cs.data()); + //s << cs.data(); + return s; +} +QDataStream & operator >>(QDataStream & s, Scene *& p) { + p = new Scene(); + //ChunkStream cs(s); + + QByteArray ba; + s >> ba; + ba = qUncompress(ba); + ChunkStream cs(ba); + + QVector geom_ind, mat_ind; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1 : cs.get(p->name_); break; + case 10: cs.get(p->geometries); break; + case 11: cs.get(p->materials); break; + case 20: cs.get(p->root_); p->root_->setScene(p); break; + case 21: cs.get(geom_ind); break; + case 22: cs.get(mat_ind); break; + } + } + p->makeMaterialsUniqueNames(); + ObjectBaseList cl = p->root_->children(true); + int cnt = qMin(qMin(cl.size(), geom_ind.size()), mat_ind.size()); + for (int i = 0; i < cnt; ++i) { + ObjectBase * c(cl[i]); + if (geom_ind[i] >= 0) c->mesh_ = p->geometries[geom_ind[i]]; + if (mat_ind [i] >= 0) c->material_ = p->materials [mat_ind [i]]; + } + return s; +} diff --git a/glscene.h b/glscene.h new file mode 100644 index 0000000..e9e39c8 --- /dev/null +++ b/glscene.h @@ -0,0 +1,146 @@ +/* + QGL Scene + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLSCENE_H +#define GLSCENE_H + +#include "gltypes.h" + + +class Scene: public QObject { + Q_OBJECT + friend class QGLView; + friend class RendererBase; + friend class Renderer; + friend class RendererMaterial; + friend class RendererService; + friend class RendererSelection; + friend class ObjectBase; + friend class Light; + friend QDataStream & operator <<(QDataStream & s, const Scene * p); + friend QDataStream & operator >>(QDataStream & s, Scene *& p); +public: + explicit Scene(); + virtual ~Scene(); + + enum SelectionMode { + smNoSelection, + smSingleSelection, + smMultiSelection, + }; + + Q_ENUMS(SelectionMode) + + QString name() const {return name_;} + void setName(const QString & name) {name_ = name;} + + bool prepare(); + + Scene * clone(); + + /// Add object \"o\" to scene and take its ownership + /// All materials and geometries used by \"o\" tree + /// copied into this scene + void addObject(ObjectBase * o); + + void addScene(const Scene * s); + void assignFrom(const Scene * s); + void clear(); + + int objectsCount(bool all = false); + ObjectBaseList objects(bool all = false); + ObjectBase * rootObject() {return root_;} + void removeObject(ObjectBase * o, bool inChildren = true); + void removeObject(ObjectBase & o, bool inChildren = true); + void clearObjects(bool deleteAll = false); + + SelectionMode selectionMode() const {return sel_mode_;} + void setSelectionMode(SelectionMode mode) {sel_mode_ = mode;} + void selectObject(ObjectBase * o, bool add_to_selection = false); + void selectObjects(ObjectBaseList ol, bool add_to_selection = false); + void selectObjectsByMesh(); + void selectObjectsByMaterial(); + void clearSelection(); + ObjectBaseList selectedObjects(bool top_only = false) const; + ObjectBase * selectedObject() const; + void cleanUnused(); + + const Box3D & boundingBox() const; + + QVector getMaterials() const {return materials;} + Material * newMaterial(const QString & name = QString()); + void removeMaterial(Material * m); + void makeMaterialsUniqueNames(); + + void removeLight(Light * l); + + void dump(); + void destroy(QOpenGLExtraFunctions * f); + void destroyUnused(QOpenGLExtraFunctions * f); + +protected: + void prepareTree(ObjectBase * o); + void gatherSelection(); + void objectsCountInternal(int * cnt, ObjectBase * where); + void removeObjectInternal(ObjectBase * o, ObjectBase * where); + void emitSelectionChanged(); + QString uniqueName(QString n, const QSet & names); + + void attachObject(ObjectBase * o); + Mesh * attachMesh(Mesh * mesh); + void setTreeChanged(); + void setTreeStructChanged(); + void setMaterialsChanged() {mat_changed = true;} + void setLightsChanged() {lights_changed = tree_changed = true;} + void setObjectMeshChanged(ObjectBase * o); + + + QString name_; + ObjectBase * root_; + bool tree_changed, mat_changed, lights_changed, destroying; + bool need_reload_materials, tree_struct_changed; + QVector mat_map_changed; + + QVector geometries, td_geometries; + QVector materials; + + QMap> geometries_used; // [pass][mesh] = ObjectBaseList + QMap> lights_used; // by Light::Type + QList cameras_used; + QVector changed_materials; + + SelectionMode sel_mode_; + ObjectBaseList selected_, selected_top; + +protected slots: + + +signals: + void __objectDeleted(ObjectBase * o); + void __destroyed(); + void treeChanged(); + //void treeStructChanged(); + void selectionChanged(); + +}; + + +QDataStream & operator <<(QDataStream & s, const Scene * p); +QDataStream & operator >>(QDataStream & s, Scene *& p); + +#endif // GLSCENE_H diff --git a/gltexture_manager.cpp b/gltexture_manager.cpp new file mode 100644 index 0000000..fb226b1 --- /dev/null +++ b/gltexture_manager.cpp @@ -0,0 +1,201 @@ +/* + QGL TextureManager + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "gltexture_manager.h" +#include "gltypes.h" + +QStringList TextureManager::search_pathes("."); + + +QVector3D colorVector(QRgb c) { + return QVector3D(((uchar*)(&c))[0] / 255.f, ((uchar*)(&c))[1] / 255.f, ((uchar*)(&c))[2] / 255.f); +} + + +QString TextureManager::findFile(const QString & path) { + return ::findFile(path, search_pathes); +} + + +GLuint TextureManager::loadTexture(const QString & path, bool ownership, bool bump) { + QString p = findFile(path); + if (p.isEmpty()) return 0; + int tid = textureID(p, bump); + if (tid > 0) { + //qDebug() << "[TextureManager] Found" << path << "as" << tid; + return tid; + } + QImage image(p); + if (bump) convertToNormal(image); + //qDebug() << p << image.width() << image.height() << image.format() << bump; + GLuint tid_ = tid; + createGLTexture(f, tid_, image);///currentQGLView->bindTexture(image, GL_TEXTURE_2D); + tid = tid_; + if (tid == 0) { + qDebug() << "[TextureManager] Can`t load" << p; + return tid; + } + qDebug() << "[TextureManager] Loaded" << p << "as" << tid; + if (ownership) { + tex_ids[bump ? 1 : 0].insert(p, tid); + tex_im [bump ? 1 : 0].insert(p, image); + } + return tid; +} + + +GLuint TextureManager::loadTexture(const QImage & im, bool ownership, bool bump) { + if (im.isNull()) return 0; + QImage image(im); + if (bump) convertToNormal(image); + GLuint tid = 0; + createGLTexture(f, tid, im);///currentQGLView->bindTexture(image, GL_TEXTURE_2D); + if (tid == 0) { + qDebug() << "[TextureManager] Can`t load image"; + return tid; + } + //qDebug() << "[TextureManager] Loaded image as" << tid; + return tid; +} + + +QImage TextureManager::loadTextureImage(const QString & path, bool bump) { + QString p = findFile(path); + if (p.isEmpty()) return QImage(); + QImage ret = tex_im[bump ? 1 : 0].value(p); + if (!ret.isNull()) return ret; + ret = QImage(p); + if (bump) convertToNormal(ret); + tex_im[bump ? 1 : 0].insert(p, ret); + return ret; +} + + +void TextureManager::reloadTexture(GLuint tid, const QString & path) { + QString p = findFile(path); + if (p.isEmpty() || (tid == 0)) return; + QImage image(p); + createGLTexture(f, tid, image); + if (tid == 0) { + qDebug() << "[TextureManager] Can`t load" << p; + return; + } + qDebug() << "[TextureManager] Reloaded" << p << "as" << tid; +} + + +void TextureManager::reloadTexture(GLuint tid, const QImage & im) { + if (im.isNull() || (tid == 0)) return; + QImage image(im); + createGLTexture(f, tid, image); + qDebug() << "[TextureManager] Reloaded" << tid; +} + + +void TextureManager::convertToNormal(QImage & im) { + if (im.isNull()) return; + QImage sim = im.convertToFormat(QImage::Format_ARGB32); + float sum[3] = {0., 0., 0.}; + llong a = 0; + const uchar * sd = sim.constBits(); + for (int i = 0; i < sim.height(); i++) { + for (int j = 0; j < sim.width(); j++) { + sum[2] += sd[a] / 255.f - 0.5f; ++a; + sum[1] += sd[a] / 255.f - 0.5f; ++a; + sum[0] += sd[a] / 255.f - 0.5f; ++a; + ++a; + } + } + float wh = sim.width() * sim.height(); + sum[0] /= wh; + sum[1] /= wh; + sum[2] /= wh; + //qDebug() << sum[0] << sum[1] << sum[2]; + if ((qAbs(sum[0]) <= 0.05f) && (qAbs(sum[1]) <= 0.05f) && (sum[2] >= 0.25f)) /// already normal + return; + //qDebug() << "convert to normal"; + QImage dim = QImage(sim.width(), sim.height(), QImage::Format_ARGB32); + int tx, ty, w = sim.width(), h = sim.height(); + a = 0; + uchar * dd = dim.bits(); + for (int i = 0; i < sim.height(); i++) { + for (int j = 0; j < sim.width(); j++) { + tx = j - 1; + tx = tx < 0 ? w + tx : tx % w; + ty = i - 1; + ty = ty < 0 ? h + ty : ty % h; + QVector3D p[3], res; + p[0] = colorVector(sim.pixel(j, i)); + p[1] = colorVector(sim.pixel(j, ty)); + p[2] = colorVector(sim.pixel(tx, i)); + res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f)); + res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f)); + tx = (j + 1) % w; + ty = (i + 1) % h; + p[1] = colorVector(sim.pixel(j, ty)); + p[2] = colorVector(sim.pixel(tx, i)); + res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f)); + res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f)); + res.setZ(1.f); + dd[a] = res.z() * 255; ++a; + dd[a] = res.y() * 255; ++a; + dd[a] = res.x() * 255; ++a; + dd[a] = 255; ++a; + } + } + im = dim; + //im.save("_normal.png"); +} + + +bool TextureManager::loadTextures() { + QFileInfoList fil; + foreach (const QString & i, tex_pathes) + loadTexture(i, true); + tex_pathes.clear(); + return true; +} + + +void TextureManager::deleteTextures() { + for (int i = 0; i < 2; ++i) { + QList texs = tex_ids[i].values(); + qDebug() << "[TextureManager] Delete" << texs.size() << "textures"; + if (!texs.isEmpty()) f->glDeleteTextures(texs.size(), &texs[0]); + tex_ids[i].clear(); + tex_im [i].clear(); + } +} + + +void TextureManager::deleteTexture(const QString & name) { + for (int i = 0; i < 2; ++i) { + if (tex_ids[i].contains(name)) { + GLuint id = tex_ids[i][name]; + f->glDeleteTextures(1, &id); + tex_ids[i].remove(name); + tex_im [i].remove(name); + } + } +} + + +void TextureManager::clearImageCache() { + tex_im[0].clear(); + tex_im[1].clear(); +} diff --git a/gltexture_manager.h b/gltexture_manager.h new file mode 100644 index 0000000..95af8b9 --- /dev/null +++ b/gltexture_manager.h @@ -0,0 +1,65 @@ +/* + QGL TextureManager + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLTEXTUREMANAGER_H +#define GLTEXTUREMANAGER_H + +#include +#include +#include +#include +#include + + +class TextureManager { +public: + TextureManager(QOpenGLExtraFunctions * f_): f(f_) {} + virtual ~TextureManager() {} + + static void addSearchPath(const QString & path) {if (!search_pathes.contains(path)) search_pathes << path;} + static void clearSearchPathes() {search_pathes.clear();} + static QStringList searchPathes() {return search_pathes;} + static QString findFile(const QString & path); + GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false); + GLuint loadTexture(const QImage & image, bool ownership = true, bool bump = false); + QImage loadTextureImage(const QString & path, bool bump = false); + void reloadTexture(GLuint tid, const QString & path); + void reloadTexture(GLuint tid, const QImage & image); + int textureID (const QString & path, bool bump = false) {return tex_ids[bump ? 1 : 0][path];} + QImage textureImage(const QString & path, bool bump = false) {return tex_im [bump ? 1 : 0][path];} + void addTexture(const QString & path) {tex_pathes << path;} + bool loadTextures(); + void deleteTextures(); + void deleteTexture(const QString & name); + void clearImageCache(); + +protected: + static void convertToNormal(QImage & im); + + static QStringList search_pathes; + + QMap tex_ids[2]; + QMap tex_im [2]; + QStringList tex_pathes; + + QOpenGLExtraFunctions * f; + +}; + + +#endif // GLTEXTUREMANAGER_H diff --git a/glwidget.cpp b/glwidget.cpp new file mode 100644 index 0000000..29bde34 --- /dev/null +++ b/glwidget.cpp @@ -0,0 +1,240 @@ +/* + QGL GLWidget + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "glwidget.h" +#include "qglview.h" +#include + + +GLWidget::GLWidget(QWidget *parent) : QWidget(parent) { + view_ = new QGLView(); + view_->setFlags(windowFlags() | Qt::FramelessWindowHint); + container = QWidget::createWindowContainer(view_, this); + lay = new QVBoxLayout(this); + lay->addWidget(container); + lay->setContentsMargins(0, 0, 0, 0); + lay->setSpacing(0); + setMouseTracking(true); + setWindowIcon(QIcon("://icons/qglview.png")); + connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked); +} + + +QColor GLWidget::backColor() const { + return view_->backColor(); +} + + +qreal GLWidget::lineWidth() const { + return view_->lineWidth(); +} + + +qreal GLWidget::FOV() const { + return view_->FOV(); +} + + +qreal GLWidget::depthStart() const { + return view_->depthStart(); +} + + +QColor GLWidget::ambientColor() const { + return view_->ambientColor(); +} + + +bool GLWidget::isLightEnabled() const { + return view_->isLightEnabled(); +} + + +bool GLWidget::isGrabMouseEnabled() const { + return view_->isGrabMouseEnabled(); +} + + +bool GLWidget::isMouseRotateEnabled() const { + return view_->isMouseRotateEnabled(); +} + + +bool GLWidget::isMouseSelectionEnabled() const { + return view_->isMouseSelectionEnabled(); +} + + +bool GLWidget::isCameraOrbit() const +{ + return view_->isCameraOrbit(); +} + + +bool GLWidget::isHoverHaloEnabled() const { + return view_->isHoverHaloEnabled(); +} + + +QColor GLWidget::hoverHaloColor() const { + return view_->hoverHaloColor(); +} + + +qreal GLWidget::hoverHaloFillAlpha() const { + return view_->hoverHaloFillAlpha(); +} + + +bool GLWidget::isSelectionHaloEnabled() const { + return view_->isSelectionHaloEnabled(); +} + + +QColor GLWidget::selectionHaloColor() const { + return view_->selectionHaloColor(); +} + + +qreal GLWidget::selectionHaloFillAlpha() const { + return view_->selectionHaloFillAlpha(); +} + + +Scene * GLWidget::scene() { + return view_->scene(); +} + + +void GLWidget::addObject(ObjectBase * o) { + view_->scene()->addObject(o); +} + + +QByteArray GLWidget::saveCamera() { + return view_->saveCamera(); +} + + +void GLWidget::restoreCamera(const QByteArray &ba) { + view_->restoreCamera(ba); +} + + +void GLWidget::stop() { + view_->stop(); +} + + +void GLWidget::start(float freq) { + view_->start(freq); +} + + +void GLWidget::setBackColor(const QColor & c) { + view_->setBackColor(c); +} + + +void GLWidget::setLineWidth(const qreal & arg) { + view_->setLineWidth(arg); +} + + +void GLWidget::setFOV(const qreal & arg) { + view_->setFOV(arg); +} + + +void GLWidget::setDepthStart(const qreal & arg) { + view_->setDepthStart(arg); +} + + +void GLWidget::setAmbientColor(const QColor & arg) { + view_->setAmbientColor(arg); +} + + +void GLWidget::setLightEnabled(const bool & arg) { + view_->setLightEnabled(arg); +} + + +void GLWidget::setGrabMouseEnabled(const bool & arg) { + view_->setGrabMouseEnabled(arg); +} + + +void GLWidget::setMouseRotateEnabled(const bool & arg) { + view_->setMouseRotateEnabled(arg); +} + + +void GLWidget::setMouseSelectionEnabled(const bool & arg) { + view_->setMouseSelectionEnabled(arg); +} + + +void GLWidget::setCameraOrbit(const bool & arg) { + view_->setCameraOrbit(arg); +} + + +void GLWidget::setHoverHaloEnabled(const bool & arg) { + view_->setHoverHaloEnabled(arg); +} + + +void GLWidget::setHoverHaloColor(const QColor & arg) { + view_->setHoverHaloColor(arg); +} + + +void GLWidget::setHoverHaloFillAlpha(const qreal & arg) { + view_->setHoverHaloFillAlpha(arg); +} + + +void GLWidget::setSelectionHaloEnabled(const bool & arg) { + view_->setSelectionHaloEnabled(arg); +} + + +void GLWidget::setSelectionHaloColor(const QColor & arg) { + view_->setSelectionHaloColor(arg); +} + + +void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) { + view_->setSelectionHaloFillAlpha(arg); +} + + +void GLWidget::viewDoubleClicked() { + if (view_->windowState() == Qt::WindowFullScreen) { + view_->showNormal(); + container = QWidget::createWindowContainer(view_, this); + lay->addWidget(container); + container->show(); + } else { + view_->setParent(nullptr); + view_->showFullScreen(); + lay->removeWidget(container); + } +} diff --git a/glwidget.h b/glwidget.h new file mode 100644 index 0000000..edef74a --- /dev/null +++ b/glwidget.h @@ -0,0 +1,104 @@ +/* + QGL GLWidget + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef GLWIDGET_H +#define GLWIDGET_H + +#include + + +class QGLView; +class ObjectBase; +class Scene; + +class GLWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) + Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth) + Q_PROPERTY (qreal FOV READ FOV WRITE setFOV) + Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart) + Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) + Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) + Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) + Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) + Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) + Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) + Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) + Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) + Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) + Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) + Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) +public: + explicit GLWidget(QWidget *parent = nullptr); + QGLView * view() {return view_;} + + QColor backColor() const; + qreal lineWidth() const; + qreal FOV() const; + qreal depthStart() const; + QColor ambientColor() const; + bool isLightEnabled() const; + bool isGrabMouseEnabled() const; + bool isMouseRotateEnabled() const; + bool isMouseSelectionEnabled() const; + bool isCameraOrbit() const; + bool isHoverHaloEnabled() const; + QColor hoverHaloColor() const; + qreal hoverHaloFillAlpha() const; + bool isSelectionHaloEnabled() const; + QColor selectionHaloColor() const; + qreal selectionHaloFillAlpha() const; + Scene * scene(); + + void addObject(ObjectBase * o); + QByteArray saveCamera(); + void restoreCamera(const QByteArray & ba); + +public slots: + void stop(); + void start(float freq = 60.0); + void setBackColor(const QColor & c); + void setLineWidth(const qreal & arg); + void setFOV(const qreal & arg); + void setDepthStart(const qreal & arg); + void setAmbientColor(const QColor & arg); + void setLightEnabled(const bool & arg); + void setGrabMouseEnabled(const bool & arg); + void setMouseRotateEnabled(const bool & arg); + void setMouseSelectionEnabled(const bool & arg); + void setCameraOrbit(const bool & arg); + void setHoverHaloEnabled(const bool & arg); + void setHoverHaloColor(const QColor & arg); + void setHoverHaloFillAlpha(const qreal & arg); + void setSelectionHaloEnabled(const bool & arg); + void setSelectionHaloColor(const QColor & arg); + void setSelectionHaloFillAlpha(const qreal & arg); + +private slots: + void viewDoubleClicked(); + +private: + QWidget * container; + QGLView * view_; + QLayout * lay; + +signals: +}; + +#endif // GLWIDGET_H diff --git a/icons/add-type-camera.png b/icons/add-type-camera.png new file mode 100644 index 0000000000000000000000000000000000000000..13b55886bebf154e159c7b28a546517bd96b4600 GIT binary patch literal 14827 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 R#ozz{002ovPDHLkV1hwxS~vgz literal 0 HcmV?d00001 diff --git a/icons/add-type-empty.png b/icons/add-type-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..df5f5b3ab51cf1bac86a9b2d2ed72afb1975838d GIT binary patch literal 10989 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 b>AC+0M4087lq_tB00000NkvXXu0mjfl1S{c literal 0 HcmV?d00001 diff --git a/icons/add-type-geo.png b/icons/add-type-geo.png new file mode 100644 index 0000000000000000000000000000000000000000..b983991176c58b64ff1a3cd3326fe80f9d9fd648 GIT binary patch literal 10226 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 literal 0 HcmV?d00001 diff --git a/icons/add-type-light.png b/icons/add-type-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a896c1a43ce58ebeeec35cc6e98df586dfc6e032 GIT binary patch literal 14284 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 literal 0 HcmV?d00001 diff --git a/icons/application-exit.png b/icons/application-exit.png new file mode 100644 index 0000000000000000000000000000000000000000..8adbcba957b33edb54413f3bc520c42c50134006 GIT binary patch literal 32537 zcmX6_cRbbq_kZ1iYhBmK$i)>!b}8BS+8G&9nYpq`%1C5id#^|&+)_r#$SU(%QOGKh zb&ZS=GP=0<-Ou;;$9>%Uc)ahu@7F!A^E%IQ&f~_J8tbt#on!(4ut-%W_eT7rH8?bwte4kCb{U!Kh}M$vFKkdlBD}{ zus1k#QO)m9uO&ukue)nSL2B$~SkSzP&{%>h_?wpU!)qRrniABQEW$Ef?Cp_~T1v@R>`w`s#nvu0EILRICmDaQ&H|N=KWpxtyHM zZSI*Hmh;2X6w5f1-C3Ws3tOHyse6xDyU_ZhqYIGnAl{2WQe^9c#jV23QU5z^RUO80PRt?3V?{0mbwYj02XVU<2S9tzYLZWo8mDtCP z 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 literal 0 HcmV?d00001 diff --git a/icons/collapse.png b/icons/collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..ec329aa1243e2708a027e7ba414374e1561050b4 GIT binary patch literal 13144 zcmd72Wl&tv7NC1*tZ@qvym6P{5*&ggxVyW%y9I{?x8M+hTW}gD!QCwc_u$%(d#hf( z_h)|0)KtyX(b{fjowdHbqLme8Fi?q60RX^|la*2h0JzszH~@_F`p|bRw*&xe9$$5B zcU2QFh_kDcrH#D>#NEf)0%GB9^BU>BT$QEc$}EH_1#68l1kpQdV-9^@7iaIr(xy$U z-)K5(=uOjymjy*jh0->>+-^9$^d-vvqmyU*UTS_H&7-+-r+j?v)+t0Xu`!g`4(k$f zG!*e&hdK}7tDZ+4SbQ0#S0h&IofO{s ziK$5e*V_oRha(Q(P$swwuv5inK~c{m`m01g^DZKpL?aw}vQp;yWU17&FSY>YRjdt4< zteaY79%h?Z0oY9KO*r#~1he(A({skwt@h5%C`IBkAF%`IL5lrKR=jm6lsGwmJnT<@ zo$4PA7)2EjfG8;=K3U5`Lh*}&zmcN7wZ)|&4oRi?n9Rf)@#brBimPgZt-#+5+OizC zUpzl?R$7RnW(Cbm8R+1*`Y6UthKbeNZYO5PMW3X`JR?6tRtNhxeUuv zCvqNI&rER0!7?p*8%70JT+tY+TFgsQwRAk1Fy=iMT}Bjz&gzdG*;U$$9z<+UCI5CM zX0;cU;>7N?JrVO@?mcmAr6@|7edzahmwIo905mRSEd4RPA{L0xtja6KR+`PRb}pUy zjMLMSlYU}odQ05uv~5ZA!r=JwW0(kIts6(6sGyztR=`oIkay)f!xn;UgK~gvU*uwo zaq8~JnXIcLugjlEh8P}HlVwIOA1L;QyY!5_a`n=4daxEw#1UK=Lo!P|{e_}O?af%b z*Q}?bqRns!DYDk8s&TW58Oek>qJ0xujcrzPt_gDSaTia_xJ`~f<1)RPeXl&K`>;vD2`ZY53TFPTceax>J!h) z1u;08Z1#;-m+tn10|)T<(F4@N(;~wN^YBOmTx>vnf%>tcc0~9_66U{KAZ$`wQ~tbJiEKj8_uX<+}elk zwjKqZ3S6#wh~DP-oVI=Q8-MRb234@ayf?o3V11b~MV4t05yyP}K8cWK=Wxya&hu+j zX7MU=PsH&)#!SN(Et6JEiv*paQ(UwXi^^5mwv)b9;fS=$e`_s`U+69}`bIvxq_h-G zFqG^P`0zBKbB^*IHspr&N<;7JnMy|IXdt6!6CjLErSJ&)XWbS0f zl?Pwz^L8YkOrDlGp)MO2CM^)j`(u=-QTNLe4&GlMA^!-vV1?CCpDB051WP&IPuYHJ z->ag1&)pQlJxm?1sFsnjkH4Vk!^1%)cr)75X$ny1Vwd_=wAl5C;Q8wQsFo~1sQb7w zCraCK%f6s)$4$-|x_T=&dWL_nULma?vK2|&ovfKvL?OW%(N&hPXvM2oL+JgHQHp0> z#WH*LFJe&Q3v0ZG?Hssaj!jL!K+!|#!j9VbeV7ED+;Ei2P)P2<56*frpM?uo^wrS6 zB77xRwNDFHW4C3nr^@^6?2SC0Ah*lxhJ?U)!N^If0A5adAyAO^P%`OXwCgr`I)8wz zsd^y0O-oo1X*&#&9U(7B7hjVjy|LdDJo*$f2 z;L03<_JIrod|d65Cgow{{Lo0M0Kk@=KC#fF!Fs)!fm^PTu{A4ZLN>r?Ml6w*%%N;a zf4x!khb})N-z1kfmDNp@yH*H*ZP?_{65f&Z;gG>&yepz5DV|p%N_af@OE519k??YY z=d}!{Xb_)K?%k>IR|<4G!M6sc*(~!=Z{E`4dbZNTDe8(F&EII(b1FHXRq6DPe>YGw z>qOmA;%PM@HKG!FE~}!8M`)&JAq&c_Zi=L_^~zI5ORD~8$xO)JBF({c6LSlouOf7Q zXdKu)5K+UZGf0KIkW^ezqtDt-t8oAL0>4d;J-5#uLT2K8gypVM1DzIoB9X+1$T>Qy z6%FJwGK3xy6>xxBUE|}*`cT{5V;BzV8BhJ{g9|FszHFI#anPY8HN~8cGuezywW%kF z%k`PPlib=rYaVhxhtV%&Ds`z%Rq8m7=-qaDtg9_#Vs*8@zeO9${N{5Lw!Pjm_Wr5# z_x6C>)9tE9+t9_T&+f;w0Jx4CXRAQej+#}gKs4w?@Dt^ES8wh;nekWYN7Gw7rE*ChVvz!*`wnj8J6$z!QCH~a1Ai) z9^A*Z8Jzg%@zzw<^<~h##O)^~_)~OH4!>j1GDMs*CCM7ZMCRKRi|>MGgo_9ivY0^J z`{zFuvqKK6Yd#PC;Y9`7-kd?TGGy0A8Cw? z@oZfNcMM-d?KGls`rrqdzi)nSJzPAsF4aeuaBi;{ETa*ZvNH(nMiW1>l{9p)mI<`a zxwoMf({5(}oOH6~D&o+fmDFa=cDC)@ zVKkTK=#X!wgt=V3IMCb5#5q;P!x(nr7mha;p1^U`h@K)qF_{>}5T065^3$`n@OH8! zhjIS{sYr(vR2ZKa4wp@{_FV8YrppKZ*sc#PmWO%cDMh<=s%6Y$XN14s24e_IJbFCJ z&z~@BG)dD3AkX>ZB>M_{J>47KI)MC*NL$AooMdi8r_ZLTYtO*GS(s14FXzdlI%c1re-({LBvL`2iUAccBL4T3U38NQA%iOv;9-LChQjARWN z(QJ=CNuon8PZuFkxga%Ra^6T}C+U$6jiar;l0QvPR;##u?XFf8el%G9Z5%tGXG)LhT@celku&k zO(rs*p|x!74kCODxbA+&aWhR+Z?KeGd))?_WK>K8y%1NAXbbt00}CoYps14OizBOM zRIkd5Aiyj3QY)l-f2i`xY91+*o}PUZMd{GdtUNf$Lb$xWH4fo0KpoblQ%L}qS;~*7 zE9)k#40riZWv$3|#O-q-#1~W%et-N}Micavd`d4^1YXmEA5{T7hLaTW-clHGTfs8D z>3SSV`oWh~CRu-E#5FV$!-F;J=rp57oW4Y;C=2?dHQhxvd6v$(i;+DXuAGjQ+fMiQ zr?x2^c1ywg{!q3G+66Z7s+s_v$~3>)RCEW~a57jpk{pxqKylJ~CQ0fNGl`f=>OQ)l z{IW&($K_|gjRfHta66G{(HMf%fHc+w*$_s>4@Z9nY)q+;(8Aq+1_4+R%(m#7SY%wY z5kHwD%cIf2W^9PPT_MVwRHWm3)y7%NzliWL_6sxV1Zk3nIjEoMj|v`o{^qew_Qkm* zP)nIcxW8xJF!?}y%0PWj{ON7m8k;giSd*lNY|-0hq|3C^E60j$dM39K`9#N$85aBS zl5{`1Ac(R2HR?rEdpY3XY_HO)tEBVUax%!9FQ|(Q*6(*S=dJc02z z((D-&|8s?7u0L&{^YXlhlr;-^y{Mcv_C$jp{+?AC`CN)WtK6+05N+qR-%)WSNFpP2 z%%?T@8PEKqn05g-H% zF5XP+YoVvJfdyD&SHq1O>hU2UYN@6|lB;_lej`gF6HNYY4%xw~x+~7|Bfsx3ZkSK= zRG4XZQDUjc4zyHe7ehvgQMHnOp)GuN=r?y}C4=Y6!c|IdhNb+E!oXpA7e_E-S~7aq zzT2C^Z}Y{!HhgN2t?h{nF16hkwB}l8a<2}j@<&4t--1EXD&5d`JXDVrO^dc_$Fi=! zP%d|C^>jy*qb2Uh37-ypUR7E0y|E2q?;O4$JBXY$9EPR*nd9Aujp7NTSs(69qPj&; z76e|Hp*vqRM^fE7=2npGo%Cn-;lgqLdWsqB1p?vW8II6X%){PeMKAXr);?@&SLy5_ z26z0DNq$I&mD8t!)YhajRw7do<@~}o(>Q#cesJwYkzhv+35|i$_9R9(sYrD26ZS{C zk>NOvUKTp9sk3*++W$f=#MnN45k2{?H+4p1&Vz0>5BOS5v!J8=oV;r;|ehwlPRUPd6Q*TR#R!&BPehB!1Yy)#(O*K5D+8f(VEvd z6QW5gJJM|&^vSjM@T+H;Yil*COGfklo$Q!1%VRkz{Jqo9&x4RZIKL|bi_FUTgbvyy+=Me`S<4IYGql6bI~oFV7aME>bW45O$I~rd{7qAehE}hVFI)P5 zYpFesTUm-?^(K~CiU^+k6ye%1*;evTD-v$u{#y^a3>j%zk^c)%V_KFtcB)PnE#Ow# zdm5&@Fg^Q$5m`x71uxT-o6=!S?(j`L^&yh^QlS8f%XxC?%*=c-rALclk;i$I2&KE3 zUO-#5((;V_!i>k5-Z;YWhaGUk*aHTUUl*k$p~lq;7uxv|*HFqt*ZH*usrJnSQvz38 zP335_aB61)bz%9fWH+M*nRo&8{>Sjoe`8@7m+U9Au&AdS3@hKI|5p}||T0{{>} zPD)(ed-)_+FV1|yBM%mI62PVrK)u9<%{^@0Pm>}p;mMIk1_@SxBLKav1u;O3DV^>6 z#BjT%d{CYUq6tDFlX_pGhKIkBQl^2BFd=)C3Fx24KeBxM6#N-os{e|CW|X01tG332 z&95dkN^Q(eKRf>l!8*R=0oXCUjJ&V!E)K5liyr;_{Q8w1Gdx6q4MbjE-UN_HW{1B! ztYmMuC+MP?CKGLwGjE$v5h+kGAkS~&7zfDG!&rV!1ClJG7pmb-#04Mbt5u9}`3Xxa zcNqHTbo=8;#7L##gKazOAEtea(k?>EDp`+?Fc#Tcrn}OQ4+y=P(@0D7%x`M##(BI3S$e_ zn;UMbghGv@)H$cw#YOJ{I=sa&DtM8%JrtG?xqMz3{9v71iM+!6nhC-Aq>a*5H6 zd#acvH2S+Zeq*mSYDTD-&l7t-8@!dxIZC?3QV6IBIJTkUK%KIxkg7{6H((@q7(_*D z)r-}2@3HjFm*HGwc5tXK{d(~CJx&JNW}Hrt%Aped1UX{Rx7;{$1L7N8ugA$)`9{vG zVM=A%h9ue4PpKISoC>32c#|v~<63Z*AKn17SU7@K5RNNAU>JfTW?9rLtIc7HI%{0` zODgO-OQBJ0INE?so!fz+wOPWdt>#Gcunue}WJp}8%mYmY!~ExiUi6YWt*YJj#>gB8 zBy|vA9A1>}2I!jdWdfYL5aPm&NJCaI4Fd~UAq6|+^Y>p6fEpc)loj$BOWtp=m7P%* zKp6=S2}3XEK-DNGtrdS{Pjz9xFkGf$%bu&8`Hw@voU?Vhcd0*>7JoDjJ68QeR)qa$5FYKoXGn0y z61Hz>{ax;EL$}+IiVg57N}Cvk+6I*YLuXW797BqeGg~{9Q>Rv)!H=LIYB#)IcG<&+ zGW2CFtV7_tJE0zZI^wMkNI&Ad`(ociXY@hHhLp(xBteoHV|zkI3 zpHHA1Egu^!orM^N5Qc&Qk{AUte)R%YU}%JMQymuq$J=0a++gu|tS$ddhZr}U1wTvK(wUuwP|jkVo8(5u;h{fy46?g(jNV+&5dEd}t1 z5_ankGqTp?onQqNt zaa2RcO1%4Hrh~99?kYXXd0=FapikP@CiqNp($Ay`g**z}gH(E2wke$EX_>8Qaq{1r zEH&R$nXrsiB2=ndz-fz95wnO<0--pe_qbvlEbzNQ1`}OwWpK8aZ?jCbLBZU_Z^R8hZuo&OtO#ETJd%4%DtlD+`=Ja`ogoR#!|5Y;}}!o7PBEgg#jX z8ICv%!O;51B?zEhASKt(iw-A-z>*=(A8uf;azg^XxDq-uX*_h1OzNvzo_wPoOe98? z9Dh7833n{l3?cc<6Fw?NifVymiqtduHVe$HGZmR6^ijjf?j#u@Z@`YiS81~k531UC zX6dC?;dLWvf0WV47{j1(sMAv!X`I5H$S0GX{q6ax#^CY(+kHf$@O6KaogPWzd!4j7 zDJdq3g7J#N3WtTJncPmV4d2TX626x^CD{I>(c_?&AKo&_kQ(BE_SR6>?3mr)PNvmJss z3}#L`9ReN>u#`Yg$_QLWx7|DsBb?)YJuyrbW2gn{0kOoU)C#=otJ)h6>EB?#H#%Nc zCj#jPTX^^mO~!qcG_YL99|iUXqf#3x!m$srd)q!&Mqu+wnWF=YCAnIL&o^g5r?K5P zQSE+@LbyKQoyzjbavNsS>*E#ox4i$pHi*t({h)BZ2Wi_r%#BqAwrQE>>3@QqvS=?qvTAyvj9t z@Dsgdzq#@91e43ANYZ9$+iGbX31`vqTo>J|tDR3HV6*W&0UU5Yzjd%}@0NDVaMztQ zf*lybZkm$K%*eBsmd~DMHXaAMT~ExqWjTve)-%T}YxZ((1Hb}U-b%*vx6g@E#i*2( z@rM_9qStt$0p}F3kp)NPQLy;%QYHH_#B1KxDlv7*Qt3sb<2h&@$*_Gj`oR_P9C7o0 z0W#B9_xB&9zchiM9rT5nXLiXx2j4E}QSDp6!`V~S#@!=j_|*F+7)kKMxeGY~)@$`B zlyMSZyF}O`9>sGv?2P?o??=#0XF$<+l-U@2aD@fAj$V`JIrXB_>1r=lAX#KOyUQ=v z%mx@5-Z`?}#P7CK#ASxpiFA;(F|LAU#5BcE?NWDNP6VD&#K~+YX6R(ScF*rFH!3;j z(op5iSM1(9JkfhTa@g(0-S42Y2e$9ZCWZUblF5~uS@DaDr}IYjdu3`Jp3xe?`pZ9_ zK^(cE$TRRuR`gM=XrH7R;-rUJmiCAvr`TcBHHItt8~&KUa`SUY=Cz1=P81H;(Mt0( z9AIDVByu~_ef49(_-);U$1n?;S&w>n-)cmFrz?kW(t&$sR`)4A5iqF5;RdS}?aPQUIHDrui;9IYLf_qY`f3Bc6d95C zIX~*(0KsK>EuI*WE=V7~sC<{V0Z07h49EJ8+VTdjli<#Y-hvA2!iAp0ShN_Z+s##iDpqXyLlc_g_buXY*0$M~4uCJt1{-L15tQ}p5 zP#hfowlXEMliN?&Ykl>#Jg5c%G-ofFT*+RB>D_IJbi({z?-v3~&FMy7Ta0?coR!zV zn1GfnfB}4#MZ`RFF0pa2ETLtsoIs2vH9M6QQk6@j2Td6Lc8k7!qVGagq*rs?I9~jf z<<9@cJRHKn(hy$2X=YK1&-oNDJf1pOuK_OqRKi&c(w3;)cf|xJC0EM%G;F(b(i-L( zEnB8C2NME~kF42kRz{YCeVm^oGdQWOBTNEmDYl)D__g%lWOO*JQFN0zi>yCi)S?Gu z?xpuR-S@`a0txdlo3zE#A1TOkU(9i4fI6@(TrE%;uJc{LO}TqpUp$53U3VKkbW1SZ zROOT87nWDe&eMo?Y`WwM?$ihIbzD6}-pMWMZkSGx_H$qLfKqXoa2f}Ao=~&2fbluY zybwyfMi5i-??q&i`aaU;`JZ?FG$v=6M?V6{p?{R67Z}?6`t@f=xp8Fkb(D2U4H?j& zf1cz;65Kopfk;4GUw>6oKz~gaLODZ2$n%h^Rg`O-)05X0@QkWGn%wSP=JTlrfX79N62ybz#2wbk4w{LJd zF>(`qMPKodUSSj zwT&9HCnVD2fx~{aHS%(3cVBR99bWa~7!_kGDTuvyT@27y>l3xDzXLLE@$VGFk;NNt zpn6-chJaTU-x?IIG(L^}LP)sL7Ag$r!#Deu&~E$3I=;iNLw}bYgw45;--o!V@6its zr~gZi8bx1vr_JejEwA4mZWO2#v`imz1A$8fWett~>Zie6agTKg^a$*=2X`BlZM6Qg z3--Z``h*>xvG|@VSs>Gz94~Ra;rbUo0d(Ey)x2>P)t?-S!JUeWHSisaL&5_Uhjb~V zZ{JhYi=jVivsuw*O~q{Kw@Q~15b2Gf8lzP0;wnSX*DyYZm|o7ICH_2e&0$_e;Fk{_ z<*FZ!J^009fOPxB@4vu6SazEcN)WF+TE%N$-8>6*hU2dezCSTdwnrd}v}j-)-m$N8 z$1+wtRT7!P^Sff*5KIVbsDC#x+M20*PaFJwYWDr#goa*$wx>SlwnZ}!pFNAoT`$r- zTYCRGET8y3;IZ52Q zTDbTdu=s1JA@}l$z-VN9C`~lTJ?O;)tzt$kBKM*%UDSb|!srDy5TN&>n-^gBv3tDs zYH@lmoq{jtLiiGE?&~+B-2qXb*P(hZRYEr5?JS2|<~Fjkxm`>{N(k*6Eu$DD^w9K7 zw|d?odU4lq9_WQ(5C&gPq6T~UJdM)AO&FoR4(*=!*B;m5leo#tn_6})_}4*ig~s_M zCteZ1ouzYQq*hl4W5-NZ8Z5wdZ%YzB9=#>M3|P5(-^o4r%BO zq5-d$OlRl~9IFSn(nORDIkg)g%#LICd_QL!fwI}!D0QQ4PFn_b-7Xp3y%f9XBJdx* z)58Ug3!r-s+IO!a^V=~x8-|@iR@hT$FcHO#qUwp;JqrKc~%Du>T`T@~uQM-J8L48F9y!J`6< z_eLMe7GRvPu7ND0GuP=aXiy*6*4|^rjsxT7Q}D;oh6kWUi~_LYgA?7~63d%{=XY8Q z@>T8Het>n9ZXnLXM#e<1mo^ZciMU{Xwg~?MuHcW^>bC?w2A7CHI|WJa4E+FpvKJv9 zxb*A*&vD#MN49#Q5h(2@=x!6l&wkvI0XC+{*K$sd0lfH`g8iKN&vUwe=?Dkk2HatJ ziJ+c~|2=5|L>7U1x3)8Hm<+<{LsQ2{cKGqQ6Rw~a(K$ILa$Y+rzrnoG)%gbENRW_~ zXZOjS=&9jpJD?BTHecMrjl;F1(}R0Xoy|8Dqu|f3PNA=z^7LE^D7%J5H@yh#z@q8$ zbA!syr1m#tTG<@|La4CQ6Km>A*~DNwz3L|72+U0p6U652ncvwh0+pVJ?cIQ!#~0R2 zO1qClzuafN_WoCc=(^p(M2RX{x_{^-A{KHU_`xR%o_!LzWnTc`x62H^^}0JNY(aQ! zllx8giT~s6^5XVACqLIyho8|V!|GWRma*3vd`{~demi_;!-Jr8q99M(-maA`QK4=s z{!8ud*4MmVdn9La0Dsv`&^*jY3e_ta&Znm$*sIHT^6>yZ$MGh&8mtI&ab$i@_XXXW zJ_nUqKr@FPlthEhKyAS3+;Na)?ZhGcd1o$#b3p^>;$@vCyde$QOOVuC@%-$@5$ZMp z2hGKTt$92L^$SWa}sm}=r-X8D1Y}hzZS76d1A??TOLuXKaqYGz`%_fFzA(oKR#6ghP-k8 zgW{I)j8W!9Hq@iD1X0@Eb}!Y`1S|rcq!>Bqh&kg>i$INdTV5#qV!P)B;f#CiOS>?E@wo(;3a)!zva}%seM93veCS}J(_)7{QSXMA zY;iI-ZXatoQU=b48X)IK*Wfp+9)P-hL`SZ;?yNTFyY!%D1L%%Gxk`GI0J1eHQLH-C z@l@86-zOM_B=*b@yp04zvN)>{GN)dS(x4?XZB07cYI4)vA4dH_Z?ZPAU8i z(C$$nwuA9>X zjV@fy`C6FBK#~bGxHHO;Dnf0|d3CAyKO1{*CAdX=1jfTe&HIKc^KJ8y@Zy=6k_kK! zUNem7==~xWd$x`*MAdZfX;Wp`0PJf;unl`4!Gbjx-mY{)$+$^R>gYSsT3h; z$VYPa6eCw6FNPfVPu^oYS96-~i+KVKv4<#TP;q|(`+BICBm^TfO+ zn1j;qr#&Wb}+^4Qnh(EG> zE3SVVwxPqVU4FYGwdc%T96OnQrL2fjBiNiN!Zu_!tOL4VSmE_3fbrCXpv@%2y0pf$ zM$F$`=#+%mxd$QZt85OOxo`9O!v0z2r{e^@t;&inRW?78G{y1#a3JUT!Nz(TTB$Ne z07!tFu#oqdYTq7JEcaFx$eE=?nh!Au$4=@|sG>?&TNYkKO$Dd3TcNnt_z}m7KJ?<>O1OaEt8FKZP>Tr|EGSaiGt7f4HN=svvBnr1 zW|mQ__)u4TZI4vvVdEgwSB`k&f&bkl* zs`_2YzE)J0!H4nnb|)N8E?H_i48|%B&tYlebc?KmuJu)BhyN5(vUhH*kBtBjXh4_E z6&9*yNq<)sj7XhIH_im}0$kWpPF(@pgR3zlBHTI5s&MuIG}~#T1?~?Az=dHg-AL_P zQ!pZs; z*gu{-lUu&>6@uit%$@Y^=dm+13(HzMZEKo=1kEcSo11T+jP&xJDRP)Wxz(V-f>DCU z)tLv<$_6TKh@}xMY@@TTz59^~P}jJ|`4WMJw`US=uA(s~0~mV+-Okm(dd}8?cdv;B zv=?T4V*|*8WE)@>sGCywwOfg}HCUjaBvO+XGJ5#8*WD(xvKC=XU>uKdqP$1mDj(pI~$b_8wOt{ zjXo7k?H|0|HnU9Ye(V&ze-MS`2K_sM@Pp$T^5;3y9jG2hd4)CSTfO~PUa~tJ?iSJ? zSJ~Xml6tf+sX^_F(^c9#Ro5eId&J^pceqNI$PEYL0>r`a^stFDBkrn}z%&qRrV z5SRYHBZ`V(qbT9W<&>Fo{$6_uV~l!9aIs}5oORX*SYOb~PuO-@;2%8X{~{y|%DC4W z@ue@U!6r0RhyV{)5L#VB{VTXDWFTjZF;&%=Q}gS>}6XC*1p!+ zNf!McVX+^V^?U9j!@(BInVG@2MV~dp7n&>1g%`9xv@rj^r+tRzcbeJG5QEE0wt$ zELzz4UnH}d|Epv+;9;KmVcIR-ZGPh!9|(>>Fzjonk0$dea{ysg3@;K0L~(*E5M~?o zCEtab6qi!J9Yi7%*XgT#rR22|(O)bhhj{4cuK))1f51Gg2gm+;`A^J>&z-4AlHEAwQB5}&1(OK1WP**Yj zy4tKRmR;{CnBa1fpqCq=pXeuCDMS9pyxs#lxDKHzyimD87D9{-Mgy!rKH}m*kQiIw zb7B#DBgX_eHfj>Xa7T9+8n_`SnUH;xW3eOIW^NmX`M1R=&{0S{zBQ;aTDOr=m&BZZ zHN9e&;pyvvUD?9(O+nZCBW=j9<&aNUm{OQBQ(1JxX315|Jn}@GBcu8sKa|Ysaxuru zbEH{nf;21Yfl3Gt20=bH&;t%38WR&>1U3@-TW5f#2*CZ_d;1C6 zI+Si$qX+G|&uunIH-rZ>MOL+^d?>NzC1G=HcMll(e|K_>y=Stm=@~tRt7LNh#@ndme3e?0ESdfChUW?TOBVk|Y|Yzix%L;A2_P$4izdh*?vs;lu@)fFpF7 z;26<$wI^^JL9-wx6&svd*#_ezV~zrGvCl*RmyUfSKVc8k6Go24=!?IeqZ&}`n(=-X zOk18~v`Ju$yZt1XKHaz2P@9lMK56(?i0Zbn@aLk{U#2G2y(;gFS5f#gZ@FF#qx-R5 zqVroAEF7V9W=|mZQ)@KYQf{;A`+5RQH$sU8X~vP@>ck}MstIX!O%5&z7F8k}f_h5S zPbqJxLjluETEM$;ifIBncsqw6_`sj2cClOyu7ol+lc_vJcJO|{G4)qyiNsO^SeTnW zMS8k=q?KicKczM37UHDHL^l73m;K4G`H}2JBjY)N1|VfeA((@T2oe2iW0AtHOi^?* z9~I}8dWX@ei!H0Hjh)3n3Bpms!!x95Y{2|8%08qw%d;$3F zryL++<9vs2DkL<}D?Z?(r=PN!xA@k`E2c@X(H4&?683yM=&IKH9;*W@|BLM0-Pg^u zb9UjzUx5TY_^U(y3CsKyF-ss|_(it|>`T+?68ZkcF8`t-f`tJZxZ(HU;9BEZ?u|P7OzT?1hG+t?K;1}0Oz9Zag62Ne9pA0I zUN(As*Dr)JtLH}%j4D-ZMRoX*kxT9u<11ExMei|9-~Lyw+-k^DHFRCg@q`@>}(Bi#oXIKgk~A{0}7c%2?#f6y%+E zD4p+Pv&)J~`T>H1HGTGT(a?L-kVYYwgUJZQ)CyT9MT!E&_#U;cqz+a=LkSYy|J`&i znBCxKzhiE?)1MQ|p$0iSoe5@_k-UQ6|B>Us^Mz21Tg@wQsScO0KM-+7TV(8)xTqem zT`X@X4^3_Qk4kDno%8#U&(_|)!&U#V#`#>!0PsqM16Y{g0c%GLRUnxAV}~b(HCDm~ z{~`~0;NBmWn?JA446J_!F(3(raF_8;yCfcLmcGU|8(sKV&tY`I4c}_uyf2Ee2~@RL zH&#}t1DBB-F5&LjYU}D;-u#hXR6=+eSova(WtdMsxwGt$=-)F`=@y;yOdjCp4Z1qt qr0sTNzi9aIKkMQ_I@GHFB3g{2xK^WFsq*T=0?0`#N>xi3hyFjbTPhL& literal 0 HcmV?d00001 diff --git a/icons/configure.png b/icons/configure.png new file mode 100644 index 0000000000000000000000000000000000000000..2a819572c7bcc8f25e768bfcd8c9ded46763853b GIT binary patch literal 32993 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 literal 0 HcmV?d00001 diff --git a/icons/dialog-cancel.png b/icons/dialog-cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..ace88ab0b4ad7d743e0173d7638eae6b807afe7d GIT binary patch literal 45200 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 literal 0 HcmV?d00001 diff --git a/icons/dialog-close.png b/icons/dialog-close.png new file mode 100644 index 0000000000000000000000000000000000000000..6072634c29af12ad1fefccab20f4940c7d56379a GIT binary patch literal 39321 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 Zw~$@LQ$lmWGh0-nthuQLb7CE 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 literal 0 HcmV?d00001 diff --git a/icons/document-open.png b/icons/document-open.png new file mode 100644 index 0000000000000000000000000000000000000000..63380e488e814f13da2c451a95966598e21a5e15 GIT binary patch literal 8621 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 literal 0 HcmV?d00001 diff --git a/icons/document-save-all.png b/icons/document-save-all.png new file mode 100644 index 0000000000000000000000000000000000000000..73405f7b1085a7c9c351718a1f07ba7e7302b789 GIT binary patch literal 26721 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 literal 0 HcmV?d00001 diff --git a/icons/document-save.png b/icons/document-save.png new file mode 100644 index 0000000000000000000000000000000000000000..aee3e22af7b53836812f8d83e0edeff787e2fdef GIT binary patch literal 22676 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

#LTh$(1r~g>qHU4oRx!1ACkLe zWy&&xX3vRN*ccE=W+!;prt zq>veB4nkE*mK07d2`woME2?tjxuU1P9Y}seG)tBpx2Ht2oY8pAh0<)yMG@GJVac6C;It)ZRLMk`uh9tS+Q#69ekUX{G-wgDBoAuF2Qn( zK)dtX=A3VE;^s)2^g0<$Ug%AgIyq!A7BrhopFX{jgP_pd+-z}^%4%zC%QZAKWcaxp zKUUBG_~~4hTOJvZEWiOqmIzLWI;9X^7t4`SQ`|R(Lvcz%6mcHXcEUistW(m$ad8gA zLUg=m$GMkv;)wt8v@=d38B*Gb{i3~ujqVxI64}C%9O4vl5inwnP!E|Um=h{W*nc_CRexa|gZv>8EUY%*eELboE%wlK` z+p=Yg#eXdxHa|ExSm5Uh5QdkWA`Uz^#dj-zJ7L5M8P75}hiM9hXSNc9f>pYsR% zw6v#xqtX#bj^}3uP)k77HMo`hHao}b$RABp_40flq@!dOSMKbL88aH;!<{f;LZ-E~ zH8XMI#5xXvIu3(+{s%C~2?B6&+N)6^8NvWQBKV*fqxzk36*B8+55&VT_zU1D1r-2r zLE*$jW%tA*N}DAb?+Js)EQbz^2J#O16^YT#LU7FK8E84-+>e7Or-h2`q*EjcjY*@3 z4~@)_WXbWUf;&|tyiU=+GQXgO-t_Qyk5U5~Do+S#IrAp4c%IX3FEdZ`0bxztDJjZNh&Pb)btk|AsLO}rk zqoum4E{^ww$|h|K3jv-3bCj7Xykn)5SpYmv!MU!d)R#U!rFG!cap|F=GZGM#dB}l< z3jiqHhlhtPey#`>0tY~z17LW=h7BVdH*Or})^L;SOA0#8zwz`UhoGB zj3qfJHg)ddKK&h)!9Y~}rUs+kgH_gm{Dt?XwGt_&n;ZIu&t@72}=Ju zuIyQ^^mW_{0Ohae`|y`V=L?5|Fa|gf>i9S3n&<9KI|>iba1_r~XjU@c-8`2JgN$pY zQ^j_w5bkqyN`ArwJ8YpK)&z5_0#1H05W{K)>~rNPU^b}f?`~inhFAzZAJp6z$`2*5 zlRq&1b9f#;DCe3vXVO%UDG#@RFu*ttIPjX56W0AOizROml_%K)QElzJp3IQnn z;XG6k@;uB42f)a>b?b%z0ALMp2o(8qfWIIMAgmrlt^71y3QcMW;2&+?8&T}*9Dk7w z2i83_<=lX*90C*u^f$-K>;5tTg7WLRIY&VN0Gavo=eI&t0L*@<|8wPU1O?_LaJIX< zTUY^L0f;HX9Sgv&4cJOXnwC)ET?J*NN>EoP+8Z;ZBZ`}U_y}pK&WQ5z4?0Wy3J420 zUO>es(D76U+!v7XxDjnLgxA?s&xqtzSOXYNV-cWb;!$W!&uJ9^r7Tb@f>sZhS7|(E ze#uy1sNi|HXZYjFJHnMb?^Fj|0Km3W4S*_w001aHw*ZFMtXTsvC_vQ!Ai>kf5DP%{ z-Nr4Jv@L@G6&V#9Edy#HP)O8tLJ(P0WTn%D$<_c>^g6PQe>&w44FLFsPAuHi&%Wg? zZ|MXJ0GxeJ-M@~1^z~o`K*J&TjCXBe#j}PudGONNbz=mD>fN})l_5(UVvH&>wGj^qFbXrnT_WQ+WS(*kOkzs1^VWI27PdSO)MdlZitz=tDqdz)~OL zu~G@^xwuoeb`_cEJ~+k13NFOCXJN-1{NQC}2NN7ka=vZXX^3M`QNQ=pXR∓pp;T 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٦sES)bG z3pFu!;36pj<_?4-ZUD=?BqVU3-%ux8{{Hq(shv9bP){G5y;q)YOHH3CzsutO21PpC z*ub83)!&TIPIilu?CVDnfX)Sow(jyic6p2p!u)v_@RQFEa_AWWFxgL1RaE_bScnJ| z$?u~_C}5VDTJmJfF*5? zLPi3l1gePy77+;)UWo+$#^BfPe{4#RNA{E5^xA2dg2muXcN^lu7K1n~871=ZMU&HL z5Cf(FS^coVZ%(vl{KwEh??-nN_$y0uzZ&OENLg5s_U(~zZ(mE7>)^(v^FC}g8;#wA z6M?*pc#A&B7fS-nSN!TPUWtG zDVGnYo^MCl%4}qoBw>d6*X@~@@SwYA1X-EMNKK8$`Q`yW|KP?IrMN?}$}`Zf0F*7@ zFh~RtB)L3JYNoCtU;hbi?VGzt@tbE)l6$jRM-H;ozt}c}hn_i(?-Ds^z}FEBuXJ=~ zqrGb|bm+AM=T@(-e_B~`huKnz11v-&aIEo`&;*MK%nMgbHZ3&2BEHsgMXm26J00H5%|gS2mBH%g_prEX(Kz;nSEGc5%rwm^6RP| zaHc1_c|cDg00Rsf;JM`I{=OX83oF)sHt@^ui5&Q9(2vdY8729Ba+DudLwGi;Z#O22 z0nenQxB4pZPn-nGa+;*!s&w8+4Gq=Oz<>Yut&^ho0R6s90!sho6PPF@VAhd91(Co4 zMG06{5+K6lF5aTLzbW{6S9<)8JB$t0B>7{4e3*bSE+u01y`t5m%KdPVO`9i}?QzMU z8yW2X$nJxu8_LQGzExb9K8kSYt88%B=$QY}ilU^?W~anu9X#K2gnX&o^8A#7NET@( z3AFT#;{FHs@HO?+?cJN}aO1U+NjkePyD-o;jzwEp&OQ~1Ipt_Q`Xu6$Goxhxkb7F3 z^aR){*hag>jLcN0_Ws$II=PBieAE2d7q3^&XPTsYN9PbyQ{p)Ru9>j�o?yj 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 literal 0 HcmV?d00001 diff --git a/icons/edit-copy.png b/icons/edit-copy.png new file mode 100644 index 0000000000000000000000000000000000000000..a8178caadb5061e9a75b9ed798ce89490c1d1b29 GIT binary patch literal 14072 zcmZ8|c{r5e+xGK}kr~PwikQh-%94Z%GeXGPLLp0w5LvQsGb0Hpl*(?V4JG?pmKh;r z-}g+&8Z-96EZ_8dzxREQ@B4?x;h4Fe`&!QHJg@t{V=c`M4{(cd0|0Qq*hv2h0D$aA z5PW5#2&rBBt9{3}YwkuX?l90@9* zBKZg<0(t>=TECNUJ;Pat-EaTkZB8$)Cr5$p>UVz8MkGBv__UyhPVSBTxOZwz>f|kB z*GXHGO4~)x@^6meHvTIe>Gme~tgNl>O=?MulwZF$*g-ijZ{aD?9w(~&;Dm&~Jc<3V z87mJcJB;4Y0)tk2e@wwiamnf;7Jx%dS#c1AI`#3nEFT!uOPwk)9n1vM^|{(5u283% z&ZNG&Fcznf=;P>e@Y_42V1ztWS^ejSA_Gm~sMup=+VET;nKUW!*x{(3;hZ+DcK9T4 zmZT&3_|(y7r!63t$g}v-);N0u6?0gNm(yhpvns()5Y(5Nz$nhqMP3FCUN7;jOcUJ1Dd18gNnF`oRL+~421o=-lL z53t|f7L-5+t9>^5&*vb0!eRA`FX|q`}GNK%IefdUa$zH3h8P#URWk7 zj!MRNhC*7Z%%K2D`QB0RWPH4fsk!+t+d#RRAmf+u@$rQva^T;)N5Q|(;!-e6Lo14LjTylTvcEIyuWkD!_Tj5Gbx~G zI5Iwd#%NkuM*ey$yyxxg=axU+mSNldU2jFx{X0cEHpG)#@98eBtjxYW6PyL~HXZ|? zagq_5elfC* zVmZb}=4}w`m5UnQEKH|4v~2Rhr;QLuw_t-6js$V#N9$1KImQWtg@UV@DD`DoT^^|r-1vHQF$Rwl!fk`cOyE#&t*~ww&Aof~Nra>R*!3x) zV^mM^CLvtbAumoGr_=WtjmtxoKM(|(>0e*5E;$`XYUahM6UKLE*tUhHp(wb;i zUS{ye+>fU|MVnawAy)*!`N&DRe7rbK_I_v*K^bb?#(>spYi9v!AD|GUhmhGkiul0p zz7B?hEnr%{>aI8VFfoT+h}y@afT;{z@Zz2gLD66-*+#Kt@7Yx8B}&Uq=l9iD$D~5o z9*FgUXkzHJSJ!7gQ?7s5d;nlBcPIbZspKS|>z#(9O`Zt?i>wAkD8X@31N0EK%!7>D z7!syJ%YMz_f*{>Vf^d=+Ew6v~oKpceE&E7Br$3`Z@a;zu+fT190ADl0g;VI+9gGVy zFXR=SwH(P4qlH&%3SnYr!Ho@=4V4}2A8;})R%lgOL4f|zl_3`4$TOc4fd!6jK?(Br z;K**~qB&{)a~>0z2(?;&Nq@Vhoh&W!b<#Zo2ZU&`Bh?B`?4>ueUXMXeEj&QS;NPA?PL-)Qqx#!n#rD30sK(s!gj(C2e2 z(fIh?OUI#3r)l;aY#)rxuUdp8!4Gcv1-3z{D(<$x4Z*(>gEtSiY<{eli&D&wj8UmS zD5`zN9FP~xz|ozpfNH{^G6yZVoi4RZw+doD$Wym8PB@Cg-uW#>xWU8k&andf?l5>$ zynC}r*NyWo|40hI>%w|}&0$%8_3($9izPnw_}guL~rB@ zfZQ~YSAXpHe9g;G9-k7oa_DbueN{%MXm_odm*jCJBuD2H=)=()u`l>`v;#X(OI5K6l|EcZ%-U;MMin9clO8HC~Iq|$?sWBZv3 zW*95dYXiaHm9BIp37?{GxGSBCz^!l+4!|_0AtP+|cfcT)pQY`Tk}gX&-s^nuW#s3J zk#@HXAm{{Iz`J^p�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

  • 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 Hdh~w)Jq`wb literal 0 HcmV?d00001 diff --git a/icons/edit-delete.png b/icons/edit-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..38f11cd5f521da653ebd61cf861f6581d9531a0f GIT binary patch literal 22776 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 Of$REadNn%e$o~NX&zs2r literal 0 HcmV?d00001 diff --git a/icons/edit-find.png b/icons/edit-find.png new file mode 100644 index 0000000000000000000000000000000000000000..140e58102a8c8325000261e28ec5122467132104 GIT binary patch literal 43469 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 literal 0 HcmV?d00001 diff --git a/icons/edit-rename.png b/icons/edit-rename.png new file mode 100644 index 0000000000000000000000000000000000000000..4b47837baa0108c5e764dbd4fe91e1e610fcbe19 GIT binary patch literal 4859 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 literal 0 HcmV?d00001 diff --git a/icons/expand.png b/icons/expand.png new file mode 100644 index 0000000000000000000000000000000000000000..6a963b61b699cf104ab82038abecb820d64d3a26 GIT binary patch literal 14692 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 AIRF3v literal 0 HcmV?d00001 diff --git a/icons/go-jump.png b/icons/go-jump.png new file mode 100644 index 0000000000000000000000000000000000000000..7437eff297aa1c839b925e550834c62da0a5fd9d GIT binary patch literal 7200 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 literal 0 HcmV?d00001 diff --git a/icons/go-top.png b/icons/go-top.png new file mode 100644 index 0000000000000000000000000000000000000000..489674e3379516967efab01f8f70d1b88c310517 GIT binary patch literal 31581 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 z z>2ogX8W7^^=>`}TztlH>#HYb<^P`@|W`dcyZQ=n3mO?Cir+50`kD?W&7SR8z(R@_4eFn? zsT7p`fpi_Lx<*XPn&$jkOsfE|0tN#y%Z9#T6B|X`Bocpv2on)$$eE}}KX8`jL9S=~ zFT-8`UiAwSlb`!X9fOvQ#2%!F)`6Z;VYM53o|7p|*8w!ErzU`uL+fspC^f$Cix?yJ z)DA||!B)Bo=ln*ZYbSS*lxjO|OrK*=)30nrYYWP_0)Yso#ar@4V+Qvfy?MVEXIwxt z$_zg+0xXI8@x{e zhi1;QP_OARwU2Us%g*~S(Yl%W-UB)sd;cKTXSOf~WoL16_#x$-95p^OK#w#(fN#F` z3b76Rr2$ayp@vWg5SduPImsw+j_PD*N*RvLX?hYgsywEGi$%7+ropx%FQ);~Q*^Zl za|=l~TYceTDfAR5_8`xla`!mu3!R1`M{mPAL=P?VM(^fLJc|WM)0s~vfrwL>eWJz^ z=`bNvFFFT*Bg@YXvr1&y_Rs-BZ;yy?;Ir+;VG{JD?WLBj^nW*5BMt|#_&`@*%o<@s`Y+EN9)j?Ppt#czKY&SkPvj=B6= zy0y9ATv5#qGj^?figQf3z<h2qtvtUBLnPC1f z7Zbx7PBGA zvL9L%^4P^4xrkObcNZU21W)~iCcTva-lpf0wS7fR^sN#NuSc&{LT27+$HAxQU^ zz6ZC<8@A@!!&dd@yE5};Yu_@2I&j~<564hb+w>s5=a2y7O8CS6sk51f+}n&}eyCjs zuwjWy{#sAMq9_m4z^nzgJS8xW6b5R^?l7IV&UZ3ljbI6xnPheIe*D#^u&f-JM8ae3 zU+}_hP|0uk+Bh_Ez{7T#UnC`TY_O`V?ClDh(!3r9X-UFL;K!Mr5e#qeYNq*XGtgX( z{^Psj1=h9|jSft**QYMBPiyaZY^_M%d4Y!Y&Q)843(qBW2;I>agOLC_P_nHw!yz|> z(^{VCW%a9G1*OFidx5hd;wKP%_gWhrhFuKg;u7j78~F5vG-j@pz+FXlDKs%Sp07}b zlBVC!yjFZP@FuM#=IY28z<8eb?_pUNHQ1e?C%S96tpzB5RTAYTPX5|CN-#{}a<=LN zlcapmuPxD^Ha#?m(VtbCBigXit2cwDP{75=qvux3h28Cu&Vz_~W3qw7#cNc+NUVa& zR3qRw)J>aU_ULx#8iL*6=pp(de6CiP3RsO_5%ib()NLl6l(?i-0&x6Nl=-a_{|N(@ zd;0cz-o)O)(CZh zZxJ))rjz$SY2)q<0gm6BEb^b&@rDevix`1l&O?Q;?5B^{FBbIM-pF+KmTZ(Q>yl-W zPE`_Jr7wUyXF|x&9|I?3GvXddzczYQx)`*(_B26vx&&=Q8=7kj`8oAv>b%F`zIAj@ z!d-MHi5-&0GB$9USY8vHJG(!7e>kMM^X2sTqys2zFUo@U8l{%B#4OT2&D&t_+H~Lg z&L*XT!fCzMSV&n@02k%wVCsj)ZUfDyOK~*0B?RgW*zuIFpzyc|1Z8hOiDIxfOLN0Z zg65XWPeiQ>;H++9n7`zZos_)C$xYmfyp>H4HDWYe{2qp^28?pgn5d6xfzYxwSqZZ} zKuI~x|1bokdX9+LzG(Mr7#QsIcpHa4d8REKUS$e(ajT`*(=772xf{uTmd}4yBd=6L zFf(61TS6*TzX1;Nj8n9B5njnGI#lEvAn8&PDT#Cre2K|m$eQf1oP-DLd4FE02@z5X z1(0@Uab6r8Xw1q>zLQ_{D z)lc{(8VAiQ_6hU5)2x?88SI##3^d2dVDM8{7tgWtfg1e>KJC;5OuU#CKxACm{ixF+ zK3VL%iPwJnol)b{Ewvt}<&ldW&Zd7K;#_9|pRyGJZJjfQGnoU)SA?O+`kPrY#7Ptu zvb78xbnsfQ{cH>*^GFdh=u0 zbv~-;p_R?Zf20cwx*SG7iYvdVVzJ8f*#@Ob_{*~YHvL;&`SU06*!$HlRX|XY?f@He zrsFWK3dV(ecm#EJ`9xJutMI!qLyj-(372Uwdb|G9!;R10ftSON7SvAflahH{v(a3c zr9F$L5)}>=Fe0;6Y0xz=A=YWBB%O5GA`An>)uV0VPIGBGO%qpT-dwLtJ@O3~CAQI} zLoC;i_bcdWDAz^aHY9JsU7Y07QHzSx%~cfiVp!P104Ve9s5Faagz4?c#)T9}w&&{{ zp|pKqq-?svzYG%fwMWt=_0efBN0X0retdnf#V!UM@&-JvfK)9>CvX#V>t_)FQ#oIL z02b21`p<-Jm>)MXTsJ)U41@uUC)ew*i88OxF8A%+RtR&+JwVdVG((JUN0BS}8|x9v zWQLZ+=I#;6@7^>CmF}_a(n+>d$w2c6_Z~ok7q}pNKVCpQ`I>%-5zY@>(I=zFDVgp= zgBcNP@y{ZT*hoXu)!UOv^-H}cj5a)O1bl;Qm7e`${;eV!AaTf5&nuy?w34@g{ZstZ zgy?Q$2wy!Y5ytC&F+F^P`!yx*zd@KrZUW+CL(Nj0|3sBvKhd0fLuKfg7x>SZx2uAt zE4!g){Pkp&iP0EqV)R^tM5eogslTWW{W{D0f5d^ZMjH?2N^=5$SHW+A($2JFe(xti zN%X6u3VBQlg}>3p)I>*G+o;?*vO))ZzP83 zvv*e|h;;|;_#w^V#?ip(Qm|E7?~1HJH`l<0mJ?cLvi4&`L1AsQB;fseTf@(EZYhA+ zNxcw5k0jQ*SLKJJpFC^34Y~e}XZ-*`+uMLAA(Ji~$5WvO0{oshPVCu zIQ~#x+k1Y9I{bo*bmJZ~j$~59GPKF$F=lz=g@T~Q`$|DTmq0?HDMBbjS0IzheDQ*hB3}o_NDYor~9f?S@lRkOkpq+ZO643|e{?wfaB=Z^ixS@`Y=c<^p zDJ8Ir?YQEuXT1xl2f|OdpVmAK7Hj8X@7`m4bNjiVrRFoR9{(Ye>f8>Z_Vbn2A4>y+ z#WSY+Ko+L$mvtcmO|n>F04H;G0|YQ& z2Ydx_lagmuwPFMxSxn!1JNQnW|K;q^HS^*nQ%xf?z1A`=HaR@Zv7L$Z;HK>zK)TJ+ zjcLGnQnKg?Syp2+HHY82(sXmqb6&vbS`LYM(6|6#>y^gouqrJxJ;8g*J0QfM<$J0l z?kkOnSrP7dZPX(e#g)OQHMfokJ0(w3Dj2=gS~vO=+3}AT=&WDtm5`EnR|s`TTbX|= zvYDE#I^!+o1r~+orULw%Cb)lki8OVF*Da84{$K$-c;5c$;PKj_LNr9$782*kIthBk z&kRH`Zl*`Hn~Yz?EgWamA8p%08 z%$|MX=Z@MxkjbNv6hh>f@0AKuCfSXfu-Dm7|14IMuRI_?2q2gK1v>jM!lhMtq^d5x zMmWy)EN;SzeHE*FcJe?5I6upqc0Bo@1U|G&ZBE3PK0s8E{<@Cn;^*It z>SriVnWlGxf(6vaI84HiE~|^8L2O%{lzp?61bZ?I?Z`_40TbYclizk8@9DwsQ&tvw zu&(Io$1m8J>&QUdNssj2J1TQDq??VB?w(F$i)wcU&~s`Q%xdtkC<+7rvy2 zGcO@Uhd)uRZ>T zA+7HwJHGy{^sx+=FRnv(2Qq*a4xY;aW(~qd#(=1v zHvi^=gAU*>^be(5GTJS@XiT8vGo9*)KnJhIB|UwbM1sPDOnBzKkFeXbFN_OUVZlKW zRl)@60PVYZbtgdi{=4H6;^G9oD5 zB{?*rgdhk=3?U^c9l{_WC?KVPNJ~kVbUc1t}xjJ9H_9HA9D?}|h`iul< z`0zeeC7?lTv|YnA(zi6`vVsERYWN_jz@A!8D+;tW;6 z`N!i6|JT4&2Jli8{EQL{i6vw@exRkE0tsaZH-k6o8o9riQI0*?aOT3zG}T7o);wN) zO9trXJih`WU4+x~$^NE!@)e~CaKL$;U3?BidVSsTjQS7#z8O-DFRB~!Eut@Wf4+@- zHhj8VA6;Ve5?bpAIEyF?f~=Ak_jMip*FJ2X?dv?dN5pZ>LHUvgx+jJX^6eET-av0- zd6fvucli~@RSlkNDO+I2)F3-C`Ug7$-{CAf*31!iH=Z?>B zc0pr-E8?K~Wy!&Bt+ScMrQo*OXCrBIB0Ht&;S6;-eO+L)(#>O1a_VsnPo z`gVuhA6+oN^ubvj$)|wSfRlXP)|)vU!gbBT>&Eo>y|40VGR~C!X>xRvGX8{Hy~bjo zXRs?9of=1zx0}_VEsMF-tlAbq!QQmP%x-+;?{&~IHrJcS)pAESsq&6Gr%sDF5`k=M z^@9yNNqw&_-94zezn^I;Rgo*5h|$EEPtGil7wui7H$&AvV6Kkm4ZD9Z`C)e{Cq90P za|js;Op{~)2573(F_)1>ABN%25|JLyq?00vJ{;9YBppxn+xCxvKZ{D#^3Q+WQ{lHgl;r+{8{y`xY>A zmZD6(4t}0*QT^gl`x&>=HZ5GN+M_&ATrvnO>$C+BxpxRRPZ+g4THWTbz(1yIVTX|S zekgp~knIH&*TYK$(xW4&-#AUxlApcH5qb;?*gexDBE6=m3`mheYnMTHB)jbCX-$R# zYOj;GC<~c8r4;k!)!BAI({qDt<|XW*>=#n8US!Pj-DjfG&{My4%$3tVqFPa7%n*o& zmJxqzMv1j_j=b6M(ILI>;OzbiD*b-9KZyJ41cV>*0@&*Q z_3xa&WaOQ0hU4i)aN3<`M6Yg2-H=g#Tj}5KVNsnhfOPu?Rd3elIXfBqXe-fpdak3W z*x`(YgpB2(AgIBmZ2A`6sebU(3yw^c`z|C(_UcZcxpAv_`j_pO zLE~53SX_48p?RpHC^Oc=DwmtL{zq=Lg~20e^s5iyYB^R&$9EaLJ5-3sdfs7c?Nol; zk(Ht`cK(Y>!{s)CeV*_QhsL!={n71lJ>>`*{O84TvDf9=^Oc1ZbKhBlF=)em=oeE_ zzte@%CjC%dJ>s_M0){ueQ;h+iDp*z6&y4%q@Umde#Kp<{EunB}fKePy3wn10TMkYS zNxEwQ1i&6m$%V{xuiOvNqj8~o_EDS;8~Q!$_k_d#`W?s6qfzH>IcxlNg@~IdlxP(T zyd!S1mNmNaIdylsi(T%L=|#Zi+lpqQ<13^oahhi+J#EUN8gK@GmBHQ#g}s?qUxhrV z8i$S+!&e(K*hS4JEwPFne zAp%1NDwm-p-~WUZ)^YM?%h&sKogZcU)&gKN}4)=Yo zj*P<1s^dCcRvkDx-U#zRRuxvmqS#5}7yPHDAxQ=lPz3kEKO4}Yd%Yc?t{<(Z_Sv!nKEJvdDs_kXNXUj{ zibCpe+SG1lJ4L-0-hN9qjM+&(M03;%PJ4?`2Y%j4Gp7#3(n?jus66id`jI(Co570M z&{kzzPREZl!2j<{jXK5cIv-9ma zW76uM!IYcDk;>-~Jqr_nL`ND#SxV~upv3l)XRPP#{kT5jBMvTkY-n-~y+vSvNQdz0 zS*ybK!#k@sWb`??mRcbKuUfFrZ+tu7%u~O_nu&5vc`x*!H zi-VddSiJ(p;CvAmn|%g8pw_i2!u#{pF#RaU&6T}N>uDTSu{gMSt%^eWIv8;|-$CY| zn7|3SXyJ?cO)!UjapmFdk4z@d0S|t z9hpQF<(VutPBQPf7G7Eqgwi$$8=kP%#so*AGIMGq3zbNCpx5^?iWpk3n>&cj;LF(O zlL1Rl<78`}DsT#If$e{7VQ z6C6C}YRlethZ1v{8dLA@TL?lStp^@HS2HmbCMEYG@90V!{Z!C>YymnC*n4e|%S{=1 zCGaRV)sC_paAxCGqA{Vwr()hMBd3~ovDSPk2mIjPax1-;H7R}#-zF+~G)jpsv2c(5 zPLZP>c2=ndc-{+XiBG+wRgetP+55oSZyU#(jepYESWJ129}5yy^>&EOe$C`0z1Aes z&&WGeuww)34DGXi4+I)HnHP-;371}+?vR$X!oy#jLYQ8=K*@`q_uyZ1EGM0I7D4aI zeIMO>S>q0R_mtS6<~P_M?cm5yc=iD?7Z&ophxdyp*YE_lhd*mu!ZRi*su`1J+DBG< zH_K5QiXUz#sXGv%){%)voht#xNs#?_v_a)oq|%eFaJ26aL{i49cAV9!^ycPM?GR`P z4>e9tn)DBsPQ>Z(6IM#rOC!p%Oa+QS?wV|v>^he;jF?lguP^Dhyoka$rqqcY#4CtM z8_(5J^&ghjX{or0{_#w*{JRN>&(8L{37k;beu;ueUDNySfBDe21X_Ta?L_CY{WExW zc{aRC==8EVeVdw2!~zfxz}Aw?3BvaNL4pynd!BB{QE3b>lXGKC+r1;X3-as#NIK;s z+3J}@#L3uJV)=EZHx~-Oj{BWw<$F<{Z-Vauci3sCqVVln*0UBIz%On^kySNtZ|JvD zk2J{@w;1-F7wzv+K2Ptvn-b?hc5IFMNILGOAA(%%EWcbyNi+`M;7H5=;xQJPXawbE z1I@M3Sw4vu4gUC8!=yt|QXYF(A|MJEQc6A?Qsf+Fa?7gDmF^{o&{cu(?31b52p*FV z>9_mtJvZVU7?C~RYLi7aaR*}YW2n>tcK(p-qcCM8TO!f(ZKQ{i-a}L&R#BsmU3eH#dEZM~ZoG;w2=9{X&ro zXXxWGAK8;DC&kx8V>r({jA2REm>UG}?c|TO+3{V@e_r6?PVCi+`8?&^q=g{vk{60- zP)ZGviPfxhydYk*SILXGOI4N-Mh8uPbi13$5;UXa)_*3xtk5Lf)TGGsxg^oy5cP8h z*7VpsBW2#oAckggY7*39KAHR6m0RGV79o>|3CB%aimtwRZB%mV`t0MiK&nES*6cn! ze#i`sY0?}+pr0Ms*~&-RLhaqi^)W$8z-9eX~WDk#x2G$7V*%`J##i8B(M zHBWu6g_GDO!{0J{B#GncD?F5hL<$Mvo+!T7A%7D=?;)Z%c)X?)ss4qk3UIkW+nxoJ zf3o%xq_lilt!pw_)N_4RoaiD#Jbz2*|Ha^0l!haB=yMRMy^{tI>vx6&*s8!F(YKXB zwWX#}1mfM^oT)07P^Pf3Rx}e++QEf!BAr;&>jjsbE`elE_F?IbU%wUA-c0_SBKqxH z_j!y-aA;)m1)%G&EgL2lNDoR7^ZhCh zdL_L!cq~{U(T=>I103(@iZDi4KtsImlWC`kg_AGdfJaA^?~JX|Ja2@9AUr1hNxhfi)cs4LZnGD}l}Jil)>#Q%{RHb>AZ76h&F zNxLixh78v>Kv>ee&9!kZ#*Le;KE!?CIkxk_qem5rau=rsCqg&>NhwI-LGo&lPr4!8 zc7fSa1+T0~m@M_75)NL_v#n)vhcVaLpF~;HH{`hRK`hNmjY&dviCrrlaxVlo;i>-W32_r5~#u3Lc%i40n+E{c~Q^I z>BQ0@D+Cq>5u4jBU6i=4PibtRG<($xqusXR>H$$6pr6wqmTc$z5y>Bcn0|WsTX3NgA*-sXOg)f9*9Mo98SO4Q>L(#YgK zGNz5zt~#3Dbi3^cMKK54FwI0#xL5!1pRaqHPJI?Je78@yH(bM@NKw%p)|Dsf@W5U; ztRgqg!zv4q9(^=4HR=A*hZ*A4+3GubO#5797x=}@Slin%`RpYq%?R?2b*N+TJXjp{ zH3>>@HC`n&(bKabRbM5Q5`#=va4xJ;o9ajbrFn|76Ksg+J#z++!n0}I_<)c7{Z)j!od%eBqCR+i!?ug*jOudVp%X*kxIs9;0$8K{qj{{5GL>@@B zsCqEVN2&P?mdK)dKvE6%@bF|!OxA^rWyv5o>SEBYu--jxJ4C;O|LJnL{G6Q;995XKHsPT1189m^F*8P$d*2OJgd+<4Fs4NF$Y|gdH{(dSSxdQi z7-37bT<5lI7?XtTZaWQ8RV&v@hf}E4gpl2dml5u935qi{oL0jnSiZM|aWx*#KXmhb z_^6&Sa8QPu=Q;%+xmbAhDYCfT=KpVgyBgdMpNt)Fi?fLNizsVfT{jg9hkhMhv6mQA z2fj9L$=<@+sN=M*ZVCa!MqKZov4iCK@wQNUvTYP3abS+^w_sWt8J6wTX-My*S4v9B zoT6hlMT7uI1WmVmm(?V}_@k?r-$6VGAV1iUS?5aQ$el#srnr-&DA0+#jW;&Fh`~Nt zz5HFpBAk>GmXYye;s_63RYG~^GpN_vbBDErhso#t1F_mUM?&f$z1@FC)6f2v0n3a7 zlMhN5-o2%Zn)=K(wUvLpPtloutS)%O*=q{2Aq-!KXZ-fC*1LErjL!6pn%&e-k-9Q= z!7wJY;({#eF-h#+03 zHV;?(n6_j{8O^Yd7lqY2f7zY%9gc0OZPE-F=e*&O#K)fHOqoc9Gr;>gdQJ|#BsmZ* zKcbGDtth5-W0DA5E^PJI_U9)Aw^`5RWM-lkX%>}uDr1_fva%K%RP4L)!*kjJzV>&q z2^_@a_Wq|IepApgQ}BTzq6Y^%>99@EHItN|mr%W6XowCy@+A@<+)rOz%Jf2>DojE1 zoU8jfRwlk$RP>N1+mtf#q!}=kY&lyV4ZpkdT+bY&GEkF9C?#>z5jCTYO8NfBoKcf; z=>CWBUoNkKWC@Yfo7`_n&|nI$zRv*NPLbatAB9g&nY~*(;6b)(Cfsj!v%WNhWPpYH zt^N)yfh*}@0E5I{flNg-ZEqKE72$GDY!y}XUnCTgn8Olvo<|ud5pD-l=0(`03O=_C zI`urXA1m3o(it6N}Pa|YMuYf-NKAkE?4Gh3Q-ddk|I|*K7TzyVoa1tk+!7Uun z%Lvj?6C+B7WNi9kB266Dmb99w)~3z?JuBQG*VAT8ANZ@52FQBkKO*y|CdgCw&U z)*udIv!_`yc^xEaOmTNLogSnGlxPs*;F*CJK_W-L(2s6e<;)I-&z@Kup5AKn{A>rK zURKn3%v(GnS(b5Nk0yB928nSbt+qT;o#GcV1~+fKQ^X;4S^4tlB7 z^q5D8H|llQL1jsF#THx;j}~U3P_K{Ak-D%Q9h4e7$p{g5w%ecIT*U82r-^xi+tk5E zZ*sUPs>(ozCKsSy|7#hFxu1h3QU1?aZw6wE3Rlr2)hv7e)qTU4^`mr*MGPDg}g_=7H|KITEP_Q0O>U~}*_=|29Vz^idf!6rOUH7Jh?3|LSD|vv~ zq~qYKJPDibNg_=W>dine=wj#gq8d4I3$*Xwl_^2e?!WXI%P*^LlQ&kRD<#X!Y{cyL*nkSU3KbrT9uA zOXkI}XzxXkA~;C%n#MAjuR|$4yBc0qS@3YfBfB~Ej7(uCH0=1APYlg6&GrCF+F4k9 z?(M*cm8_^p&rN8D<-Lz(2zGey@#Thh=Aq}fjRlfllGO$tF#*fDIoBW?I%{-)RS7V1 z3Wa^LA#Q(Cj@z+uvi)@K@f1qPI6jBVRm?>_#Q7$`Y`}ZkWw?ima=YSAO;-W%h0sn!9#2iB0Q8jV z40AQsL?v|!(zq#5@Aa|XsjW-*qfeSXZITQhrpm!f&L=1w*<77(H%mLL{zlSmzvSbu zY~^m-B+boOj-;BW@$z0Xt?WjRL`-A<1%QV-gyYiOPZv|i4wo9Y#67y2z10=okgga$ zw1B2`I^-5xbA+{1O`5l$a}zfHkOq^aeI#3bH70o^il#Yy(KW=sxosz5llRv&2^+cz z1mD;p$LneUQ7LGlXXlJJDd+frNCLAO@Ja&94)Uk~|CMMtlkeVb)Gj>`s{?1&wqj?B zCRTJ%V|Qxj1gS9%4Ja-aA2`%QY3P3G%_jvym=8GxQbHPH;=t=`zhczFZ=u%ZHwu}C ztlp&5;GL9sxvk2^z&nViL$4p$q!07*o!(L85fWAf+W~jdC%)C;=Ph#*g{t*!H&MLpqI!pQlco_%kSYj;TL*xS#Gjq{nvCU9&z6?f5&G3fK0z z{@9ZfP`hF#Y?w;jv$E1qL;md#;-;F>?|Zo-v-w+B3X=d!Jfu*00~BI@Rq?H28r}j~ zhfgpvO>8JORVr)Nk!18Hl(})QaMVR6UvF}>{o2`hg|a@1l)Zek({+!+<+|%UG8BUf z>p;ihk{lFvE&HD5$|28f-@(usYc9asI|kE1IW^vi2vL!A zklNUfWp6CX2^`1~6xGmiE%^lBXHM)`y=2_s;H+EQ&{=6tm97}|oe94J$ z#9@~Hs@=8{*e>6>x}*5i6ZU+2;Ob#V`y*m9*j%5zg#4@vVfwy0B>0OVR?)Ta?f{03 z!k_&7oP_}-BHi#h>>CQF0WH)boNc+NC}jT1ModILp*DWtHnR5}qwCBnz3Ev`F2)U- zNdi9IZEUPXefgdal@R};#9a;e*G{}GTcZW;P$wj)C9Se4E6Dz7j^ws55C|G`MG!^82NVbeUTbzxFP~;Gb!Q8-(Yug7`0H zua{U|^QYCGuatU>irF({C`;UrYG6h6Zppym!?DnJ42d!?3B=&=V)#pbx2^mUX-<2pK6sbBEZ zh`7Tih}an*@nlf*dfVs5BNg#Kzi%*3i;rgc9;_cdI$BR3j)!vff5_OJXZXWVW;x=*{`1BQ}fbb>zQd{{*&7RKL4J@2!!fn4?bgfwTH?dbN6Sj(r~l}`UHAA&5$Hl~75t*i3L zGGBxik#GI-7<|^Y(={{!2L&_pg8lh>1lwuK%&!HeZZ@KqFvjykiu9$T>xw1&*R5t@ z9V2QjtCV@imV7{dN`e<%#?MH`duUtS23!_Pdc}f199=;%2?U6oMMG(P35rY^8Ho+ueI8 zmqZkCu9=D17EEk^mwJO97UBWN^Z^HTjkr6XuS-?M5FCBSjr@d}aQk`mmpr1IH()`x zF~z{c{a@kkNCEFjn*q*5`@|%}tY`c1G!5ABE`;wmcaaM^j?a@*dh306CvUXJQ+)P}__bCfYeb>BFJKnbUDTgrxK@74dof9X1eKit& zwHM|8{;=e=x8rM8dHI;SqZ-EJV7>tZXY?YwBt((>t335TW3%%Nf%5kI%_#v*O zGk}J`$9@^%%KRP97=NS6t1ltu%0&x?p4Bojg`KCuc+P&{GRpx|K%Z2ikV>UlhvZRm zLXdIC?ESn%4G9b^1n%MeDab=_@4hxV)Z|N!Ca|pDPC=zU9187H&Z36Ujx>>q-OSD) zd;PBnMIHf*O2RD$Op+>C+~En2dg$ix4;l#DSUYLkwNL~c&`Cn(Yb$U=%8+dP0|ga8 zUQ{l=+B>;ef}vRIctbHbBTW8&5wo>2_Pv2kOWfW(rK(li$@09XWZ=?h=h*Pu+n`pK zUOBhlY88%+-?Q??8D2BrnkN)Vz2=nm^WuV;MEu)Oh1h@0&hLCUO`A&b_Sdo9Z%s#p zn8yhDqpv;Wfc85^{}1Ef+D*7gKI8=yaUGEpJzZLBd#I;xQI2Fh>bpmhv#=IMiTSi3 zA{8CyiaTZAv?hLPJ=8H91w2e~o zx@TfT7?1x>@T23I2lncOI=1PT@;MMaz$74KnEi2#TEt4%(aQ?$h}iIUW35Eu#x;!k zE$ro0?;;#|@43-*2D$Gus~3e=4|YbaNq>>DgEaw{PPM;w-hZdog<2XV!*VX;Y=1ub z2*v!~R5+|T3OXOGbdq4O%AD{g@_6zD3b#LGH-&CM=b`81=gkml8x8uQLIp5uxPQs3 zy7=4<|4z5EAC4o^(!|M)$Zv+U=FEy`h-S8IT6S6#t#wb$=Pj3v{Ulr zZ$ld^@GD9=K~ysT6=^1d-{{UYc=lCYY}E_+2nEh{26dc8{|<7_$r$GG)uP4cGrsJ+XHxU{7G2vGS0UiQxfjGBcysRV{0x}G zRh$#1fnUBzs(2zY^GzMZ*f5TJf?BbB9qj6*y*bsw#P-+_Wc!jouhz~8 zH&V)CM*B2NX^4sS7{67YzLmTmueEyv=M&Weyn(Jt@-ctoY^eU1w=eX2k3l?PhV)07 zRn#yp0!nmwnbe>lS^fO!S=Vx0F9qokcoTZ;?dQG6hCf=JBR*wY|F?v!KG!ngfX|F>Jg!xk+oKx?q$RD9CM>Jdwx@L>qL2KZldBSb|_#~}-jbH}Z zfLR9DfQtcPYImCk@4fO6(x=?{`ZR7mC*!T{RSw6x#yRzf&ioIALRUA7rzZ?Q_Qowe z#2ukKQ>Vg$DSCp&(w&_NrVsxOzq)Wlh?s{WQL#8J5q^(~j74iBco=Y7I)b4rMm9HO z20d}lWwp19UNYNVMyTb~=m#A1qwgU|9UKE{V`r`1=ESMOV{Ty7p{VwB|FfV??gT1a zWhHka=8SH#7-R_>n$W0EWEH|7XHO;-7Unz$|MYHvq$PBK2QwdNElnGig2{fA%Azy_ zWIdQ<1<+Kb$Xz6)w|+19^}YlcuIi=q4-;pP~ysd2Kn?vL}rgL!TYaaV1f z_Iz(YpsAEQ+i=#kl#4qpsk&UFa-)3b`ssA?cXUp`>DTCJ?w*E(a%MGo-G`XICrRz| zLpXX)FgR9b^YqVU)_SwR5EXdDc>M1%2$p8u-EdFb6~SL&;>GiFBHTqogoK2doA~i2 z4ZnQ}2fChr7ogo7z}ozym&|(3CG=^HR{95wr==e@2kLd{U_RjKTE6oNN+j_haUCG- zD=^>gt7Kga+?kf4!aSqgq5Og4rNw~W@IQUcun2XVGgShFzbCD9&o?MnAKr?g8v7H$ zO41V3e7+a*7pV-2PelLl^a8`V&rm%jYoWB}?>Tqu`0jeU!;eS177TU_@)a#X{;z&3 zJy~8F9iQ>La1HvCr}6Nsw_IkP4-$?$f;%uZYJ-06IOK${=amwKb?HK#z0v)gl`HgSHJ}xbFBo;jd)}PHIjj#dLtRLrMJ6L+c$< zKJ-N4_py5j91e>W>7yZxEA+wVb}mix0LGJFh9L~@ocJv&#fLxnv=WK51}6KmSyH6E zj5`X@P8w`$?i~TukNAxc`~%4FA>&w@?)%lwwUl}!K8}7~iwRe2$x`Rj`~-n3UP$|2 zUg;9&Q$yFu2Oq{15;ck{nR;zajb)j(XVExU88X_P{At$ms%@+1^klDntkjJqP{qe5 z;QqGvu0=iOH+oCkT4>%!5(dW+_y8J=8YaFhn^0J;46-=U0SDiL6n9b~F_2HrM4!r& z6pQ>YjOQa{iPvSR!Ak*Ll(-R+p)Y#@)5SO+B<}F#FdD57{OY)UICXWWe=8^zMPSUt z))v?9i0u@a{)wT~>#*DHB2yM@jO5^DvFN0=K@XCA<@O?B8z=qBN;Bg)BbSBj3wg1b z35*O@X3+=rF!|0L5A^{@55ET2Wjz4nifK1Tw<%#!s=_xZyfHG^;s#AA$k*p)Cm}Xh-Qd<<1tJ7v#n>YYDBlA z+0+6TH}q~LOod1-XLCZUTvNMW1rDF(Hv*+U$DTm-ODa{5BPpxA*{YX(vL0^0-3t!Z zCu3jYo55z-MAwFNYdw-TNmA3Qw3qU5VR5?y{By7y^O{7}zIT)Q?~nDv+`U zKCXScjyozIiKdtCgkux=aoa(EUZw>sn+mk^=`x z0=i(RtoHLGb=kg}1oHE|obVLM$J8M+cw_S%z~AoV@4oTbz-izQ8oVf=35fr$zX5JU z=)6E-UMz$B9(T3z&oO{1OTlT7nAm?v1S`;{324#+u5BCb;|O#*yj92$N4K>vLkThf zx*5f~U=#ZU1=w|&N(+$9y>y!sM|X5SLP^ld{fEFutHQA(u0QEM&*iVedTnD!s-ma} z?_3r>0q}k+y|yAgfev}m=6wR!9{l3*2GzUvR7g>R zi+{W)0q6;?+Eysl7`NpkjbK)(CVg`A6JFeS%%X5MWT zs`SRE&}z9s76=JNC||ahJjb1LH?ePkV1^IdzEz7^fdN69m4`he+lje~7$qPfc%47( zf|nH+bT((iq=Ql#o`?Vr6-Kym%x3>hQ6yOekg=td_E7mMk@)s~8iJW7@Y{Wt#x+{2 zOu-vO58^P{qfh(UL@Z+x*z#cxj|NtE0iKd}ro8h)CB|XirpYE?SQ_^ls*G}r`2vU? zUpBPG{>r%!UM>L_kEMYVU&y@y+J684;bhZE@Z1#cbl9Jhb=MAHSt0+<-*a!)?S@MWLGZlne=zD`w;Yz zd%%zooSp)hvY7nz!1G%_t{h!a{vp`W74UVo0NGfmF z0iNppcD9H*cK^Bs7_&KiPT+0c&f-C&fkT}Qab~W<#bx(eK+!xPo861(t>)f+&`ZJ+@Ed8vbLU5*V(=?SaG#5hkwJ08`_Rx2x?~dj%9U0L3NENL2oeGI=;fv;GZebygArZNn+IK6J zfWm-Z6!*z1Spt^dMOxXg4G0IUQ(-6s+aIrR@PL$~ct=i9U!2Ki@tI=VAql z9bSQ2oRwJ2B6xb%J^z< zd_z3e-G}x)-Ab>kiBgS`O1{}M`;MgtUr+Wzrsb+>iVqA4-~M+UocztAqRoi@wOZj7 zI}o0hKbjpECkCqu{w>f}LXwI^-frxgul>9Y-2=&UOd zUEJWZk^pTY)2*(ZX5O+p7o?eW-rTKR)o<#E-u+Vte!uzPx>mX3$%OgE5}ekd*M4=ufUGZng7JGHw;cyM5>WkFd&JT=q1y`#@u96c>gYw!qL20_ zk)-i-76OATs5nkZcyv$ZbSvK@ZF8QgPhitUC(Px*!%L(H=oJ42_78a=*WjgN8TXzG6l z&B}*t4Xp|qPse|Ym>dcV=`#09bC7*BU=2xSda zEAizs6p4z+AQiG;On`;2x!XD!I1qekMrM?S!j!z~{uTamJY+FQ_HadX{Qp4IhwXS{ z4=9AMW8hvwp8l}|A?hnW?9jwNHLRnLJ8EeIW6flWLQfwcBqTwaH$}UYL5{)37bXU_ z1rxBkNjnj-(CWX+9K&Zms?uwR8x8D39Sr(Zkj8FfT zrwFfANqtkiQAqOA=&igzX&-UIUH5_L8Sj&hqbI>fTi47h_=mto#!(U!Ae}6Me+I13 z>+Q)m1wPtmooh!8?5n=}>A?Easp^Hkoyy|cg8ReN)at-ijta0iI()NDq{HD~UYG8V zzmPu1;_;_v%762962jjL;ya|3fcesomM2!!0>kym&L`HO56>jA4*T{z+OIlU=&>~# z0g&f@T?2cYqykFdx~A}ACjOwmbuF%~|AGj+!K7H*a$P{Kwk0rRuEN~6{om@;R2C%v zgTPDm5MiE!)lvJQOf2$tk4m!oI8q--c`ugwmT#mviZQY5*R>NJu5Xt)mtWqM@I$BO zl|Rd_qe&r?(K$|}IEH@przmlTX4M;{%Dnu`pWhfB$%XzEEPCv9A){wqhlCyOy#{r_nenE?LhS$EKE^{a`0sxv80Z%e5jwXuJ9SzJBA^ zSQa`V(sd?vj4#a3*e)IyI1t5KHX|LkuuA{HE8~QXJJg6PdSroe&2VMQ)3s&3UYBB? z{&Xy)`#)^zedYeFeDfU4Je<}IS_s|Ha}VOuWj0a*uyd6iA6o2Q+vYFhADF3@o82q_ z%>CSO9rdyhV)@Nmi;CF6{ef1A#Z-Anf=&K+p(p8;HY)QhZ_g%gR5#)@kwoKYlR^V~ z(uDHQKcfE8n~H}zRm0z%R|E^abokjZQoUzDw|SXAe)p7vwk-(B)qig2aJ`e)owWTU zCJ@fU71B?J6{are$~FJ`iYxa_dU5?G0x4us#uWq6#kffiGIG-*@u^=1s?Yh1YVZ%`h8>UlAr(KSbLd3vwC>G)t~J+S9a zjcKLx;jMwzl@SfSTTZkblA@Z)3JukHcSF7DDsUQMeclpjbbn!0l;4Lh8x{lVoQ)R4 z*I3)_ycATC$kk*G%(8gQMeS30Zy1pp5kKUlW2M|{t!Le;ZRv^e)n&`oinF-esbYKb c=q1H>%XXYC2ZLL0Q{+&TL1t6 literal 0 HcmV?d00001 diff --git a/icons/group.png b/icons/group.png new file mode 100644 index 0000000000000000000000000000000000000000..510863717246e781e945bdbeea62aa909fe111af GIT binary patch literal 12826 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 UHS}5)et8B^kWrPck~9nXU*m;Ov;Y7A literal 0 HcmV?d00001 diff --git a/icons/layer-visible-off.png b/icons/layer-visible-off.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f04a9dc0f93d75609741ef3866e72c9835a6d2 GIT binary patch literal 53079 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�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 y81O@hb{ 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 S#c{9z0000B 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 literal 0 HcmV?d00001 diff --git a/icons/object-flip-horizontal.png b/icons/object-flip-horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..2c0579e0b0080b3d3b5f6874d4f1a78fd71fbb17 GIT binary patch literal 25165 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 literal 0 HcmV?d00001 diff --git a/icons/object-flip-vertical.png b/icons/object-flip-vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..7a9ee825bbc766c7ee1fd58c5f2df47be4260058 GIT binary patch literal 22264 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 Wd*!~GJg8_3+`DsMtxUx%F#be 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 literal 0 HcmV?d00001 diff --git a/icons/qglview.png b/icons/qglview.png new file mode 100644 index 0000000000000000000000000000000000000000..21bc50b7cbab6316f05e178ebe84db8a8f246afe GIT binary patch literal 82318 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

    Q!t<|C}rxlUYes)3aq;oaHjZFQ6)* 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

    spinslider.h
    + + + GLWidget + QWidget +
    glwidget.h
    + 1 +
    + + ObjectEditor + QWidget +
    widgets/object_editor.h
    + 1 +
    + + SceneTree + QWidget +
    scene_tree.h
    + 1 +
    + + MaterialsEditor + QWidget +
    widgets/materials_editor.h
    + 1 +
    + + PrimitiveEditor + QWidget +
    primitiveeditor.h
    + 1 +
    + + ViewEditor + QWidget +
    view_editor.h
    + 1 +
    + + + + + + + + diff --git a/renderer.cpp b/renderer.cpp new file mode 100644 index 0000000..7aaec3c --- /dev/null +++ b/renderer.cpp @@ -0,0 +1,382 @@ +/* + QGL Renderer + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "renderer.h" +#include "qglview.h" +#include "glmesh.h" +#include "gltexture_manager.h" +#include + +using namespace QGLEngineShaders; + + +Renderer::Renderer(QGLView * view_): RendererBase(view_), + fbo_ds (view_, QVector() << GL_RGBA16F << GL_RGBA32F << GL_RGBA16F << GL_RGBA16F << GL_RGBA16F), + fbo_out (view_, obrBuffersCount, false, GL_RGBA16F), + rend_mat(this), rend_service(this), rend_selection(this), tone_proc(this), tex_env(view_, 512) { + quad = Primitive::plane(2., 2.); + cam_light = new Light(); + cam_light->intensity = 0.75; + cam_light->setName("Camera_Light"); + + shader_files[srSelectionFill ] = "selection.glsl"; + shader_files[srSelectionHalo ] = "selection_halo.glsl"; + shader_files[srSelectionApply] = "selection_apply.glsl"; + shader_files[srSelectionFrame] = "selection_frame.glsl"; + + shader_files[srServiceFill ] = "service_fill.glsl"; + shader_files[srServiceFrame] = "service_frame.glsl"; + shader_files[srServiceLine ] = "service_line.glsl"; + + shader_files[srGeometryPass ] = "ds_geom.glsl"; + shader_files[srLightOmniPass] = "ds_light.glsl"; + shader_files[srLightSpotPass] = "ds_light.glsl"; shader_defines[srLightSpotPass] << "SPOT"; + shader_files[srFinalPass ] = "ds_final.glsl"; + shader_files[srTonemapPass ] = "ds_tonemap.glsl"; + + /*shaders << ShaderPair("FXAA", &shader_fxaa) + << ShaderPair("dsl_pass_0", &shader_ds_0) + << ShaderPair("dsl_pass_1", &shader_ds_1) + << ShaderPair("hdr", &shader_hdr) + << ShaderPair("downscale", &shader_small) + << ShaderPair("bloom_pass_0", &shader_bloom_0) + << ShaderPair("bloom_pass_1", &shader_bloom_1) + << ShaderPair("fbo_add", &shader_fbo_add) + << ShaderPair("motion_blur", &shader_motion_blur) + << ShaderPair("shadow", &shader_shadow) + << ShaderPair("ssr", &shader_ssr) + << ShaderPair("ssr_blur", &shader_ssr_blur) + << ShaderPair("ssr_merge", &shader_ssr_merge) + << ShaderPair("ssao_blur", &shader_ssao_blur) + << ShaderPair("ssao_merge", &shader_ssao_merge) + << ShaderPair("dof", &shader_dof);*/ + shader_fxaa = 0; + gamma_ = 1.; + edit_mode = need_init_shaders = true; + camera_light_mode = QGLView::clmAuto; +} + + +Renderer::~Renderer() { + delete quad; + delete cam_light; + qDeleteAll(shaders.values()); + if (shader_fxaa) delete shader_fxaa; +} + + +void Renderer::init(int width, int height) { + resize(width, height); + rend_mat.init(width, height); + rend_service.init(width, height); + rend_selection.init(width, height); + tone_proc.init(); + initQuad(quad); + initTextureArrays(); + initCoeffTextures(); + tex_env.init(); + need_init_shaders = true; +} + + +void Renderer::resize(int width, int height) { + rend_mat.resize(width, height); + rend_service.resize(width, height); + rend_selection.resize(width, height); + fbo_ds .resize(width, height); + fbo_out .resize(width, height); + tone_proc.resize(); +} + + +void Renderer::reloadShaders() { + QMapIterator it(shader_files); + QString dir = ":shaders/"; + while (it.hasNext()) { + it.next(); + loadShadersMulti(shaders[it.key()], dir + it.value(), true, shader_defines.value(it.key())); + } + loadShadersMulti(tone_proc.shader_sum, dir + "sum.glsl", false); + QStringList fxaa_defs; + fxaa_defs << "FXAA_PC 1" << "FXAA_GLSL_130 1" << "FXAA_QUALITY__PRESET 15"; + loadShaders(shader_fxaa, QStringList() << (dir + "fxaa.vert") << (dir + "fxaa.frag"), true, fxaa_defs); + need_init_shaders = true; + view->scene()->setLightsChanged(); + view->scene()->setTreeStructChanged(); + view->scene()->setMaterialsChanged(); +} + + +bool Renderer::bindShader(Renderer::ShaderRole role, QOpenGLShaderProgram ** ret) { + QOpenGLShaderProgram * prog = shaders.value(role); + if (ret) *ret = prog; + if (!prog) return false; + if (!prog->isLinked()) return false; + prog->bind(); + return true; +} + + +bool Renderer::bindShader(QOpenGLShaderProgram * sp) { + if (!sp) return true; + if (!sp->isLinked()) return true; + if (!sp->bind()) return false; + return true; +} + + +void Renderer::initShaders() { + if (!need_init_shaders) return; + need_init_shaders = false; + initUniformBuffer(shaders.value(srGeometryPass ), &buffer_materials , bpMaterials , "QGLMaterialData" ); + initUniformBuffer(shaders.value(srLightOmniPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); + initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); + initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); + initUniformBuffer(shaders.value(srLightSpotPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); + initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); + initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); + ShaderRole roles[] = {srLightOmniPass, srLightSpotPass}; + QOpenGLShaderProgram * prog = 0; + for (int p = 0; p < 2; ++p) { + if (!bindShader(roles[p], &prog)) continue; + for (int i = 0; i < 5; ++i) + prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); + prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount); + //prog->setUniformValue("tex_coeffs[1]", (int)Renderer::dbrBuffersCount+1); + prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount+1); + } + if (bindShader(srFinalPass, &prog)) { + prog->setUniformValue("tex_g1" , 0); + prog->setUniformValue("tex_s_0", 1); + prog->setUniformValue("tex_s_1", 2); + prog->setUniformValue("tex_t_0", 3); + prog->setUniformValue("tex_t_1", 4); + } + if (bindShader(srGeometryPass, &prog)) { + setUniformMaps(prog); + } + if (bindShader(srTonemapPass, &prog)) { + prog->setUniformValue("tex_0", 0); + prog->setUniformValue("tex_sum", 1); + } +} + + +void Renderer::releaseShader() { + view->glUseProgram(0); +} + + +void Renderer::fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass) { + cur_objects_.resize(ol.size()); + for (int i = 0; i < ol.size(); ++i) { + Object & so(cur_objects_[i]); + ObjectBase * o = ol[i]; + if (o->material()) { + so.material = o->material()->_index; + so.color = QVector4D(1,1,1,1); + } else { + so.material = 0; + so.color = QColor2QVector(o->color_); + } + so.object_id = o->id_; + o->worldTransform().transposed().copyDataTo(so.modelmatrix); + //qDebug() << "load obj" << o->name() << o->worldTransform(); + } + //qDebug() << "fillObjectsBuffer" << ol.size(); + +} + + +void Renderer::renderObjects(Scene & scene, RenderPass pass) { + QOpenGLExtraFunctions * f = view; + QMapIterator it(scene.geometries_used[pass]); + bool emit_pos_change = false; + while (it.hasNext()) { + it.next(); + Mesh * mesh = it.key(); + if (mesh->isObjectsChanged(pass)) { + mesh->setObjectsChanged(pass, false); + emit_pos_change = true; + fillObjectsBuffer(it.value(), pass); + //qDebug() << "loadObjects" << pass << cur_objects_.size(); + mesh->loadObjects(f, cur_objects_, pass); + } + if (mesh->isSelectionChanged(pass) && edit_mode) { + mesh->setSelectionChanged(pass, false); + fillSelectionsBuffer(rend_selection.cur_selections_, it.value()); + //qDebug() << "fillSelectionsBuffer" << pass << rend_selection.cur_selections_.size(); + mesh->loadSelections(f, rend_selection.cur_selections_, pass); + } + //qDebug() << "draw" << pass << it.value().size(); + mesh->draw(f, it.value().size(), pass); + } + if (emit_pos_change) emit view->objectsPositionChanged(); +} + + +void Renderer::renderLight(int first_wr_buff, bool clear_only) { + QOpenGLShaderProgram * prog = 0; + Camera * cam = view->camera(); + for (int i = 0; i < 2; ++i) { + view->glActiveTexture(GL_TEXTURE0 + Renderer::dbrBuffersCount + i); + view->glBindTexture(GL_TEXTURE_2D, tex_coeff[i]); + } + fbo_ds.bindColorTextures(); + fbo_out.bind(); + tex_env.bind((int)Renderer::dbrBuffersCount+1); + //int ri = 1, wi = 0; + typedef QPair PassPair; + QVector passes; + passes << PassPair(srLightOmniPass, Light::Omni) << PassPair(srLightSpotPass, Light::Cone); + QColor back = view->fogColor_; + back.setAlpha(0); + foreach (PassPair pass, passes) { + if (bindShader(pass.first, &prog)) { + fbo_out.setWriteBuffer(first_wr_buff + pass.second); + glClearFramebuffer(back, false); + if (clear_only) continue; + setUniformCamera(prog, cam); + setUniformViewCorners(prog, cam); + prog->setUniformValue("lights_start", lights_start[pass.second]); + prog->setUniformValue("lights_count", cur_lights[pass.second].size()); + prog->setUniformValue("fog_color", view->fogColor_); + prog->setUniformValue("fog_decay", qMax(view->fogDecay_, 0.001f)); + prog->setUniformValue("fog_density", view->fogDensity_); + prog->setUniformValue("view_mat", cam->viewMatrix().inverted().toGenericMatrix<3,3>()); + renderQuad(prog, quad, cam); + } + } +} + + +void Renderer::renderScene() { + initShaders(); + tex_env.load(); + QOpenGLExtraFunctions * f = view; + Scene & scene(*(view->scene_)); + Camera * cam = view->camera(); + QOpenGLShaderProgram * prog = 0; + bool scene_changed = scene.prepare(); + scene.destroyUnused(f); + + /// reload materials on change + if (scene_changed || scene.need_reload_materials) { + //if (scene.need_reload_materials) + // maps_hash = 0; + rend_selection.generateObjectsID(scene); + reloadMaterials(scene); + if (edit_mode) + recreateMaterialThumbnails(); + emit view->materialsChanged(); + } + + /// material thumbnails + if (edit_mode && !scene_changed) { + rend_mat.procQueue(); + } + + /// lights + cur_lights = scene.lights_used; + bool use_camlight = (camera_light_mode == QGLView::clmOn); + if ((camera_light_mode == QGLView::clmAuto) && cur_lights.isEmpty()) + use_camlight = true; + if (use_camlight) { + cur_lights[Light::Omni] << cam_light; + cam_light->setPos(cam->pos()); + } + if (scene.lights_changed) { + scene.lights_changed = false; + reloadLightsParameters(cur_lights); + } + reloadLightsPositions(cam); + + /// selection + if (edit_mode) { + rend_selection.renderSelection(scene); + } + + /// solid geometry pass + fbo_ds.bind(); + glEnableDepth(); + glClearFramebuffer(); + if (bindShader(srGeometryPass, &prog)) { + setUniformCamera(prog, cam); + textures_empty.bind(f, tarEmpty); + textures_maps .bind(f, tarMaps ); + renderObjects(scene, rpSolid); + } + fbo_ds.release(); + + /// lighting passes + renderLight(obrSolidOmni, scene.geometries_used[rpSolid].isEmpty()); + + /// transparent geometry pass + fbo_ds.bind(); + glEnableDepth(); + glClearFramebuffer(Qt::black, false); + if (bindShader(srGeometryPass, &prog)) { + renderObjects(scene, rpTransparent); + } + fbo_ds.release(); + + /// lighting passes + renderLight(obrTransparentOmni, scene.geometries_used[rpTransparent].isEmpty()); + + /// blending layers + if (bindShader(srFinalPass, &prog)) { + //fbo_ds .bindColorTexture(dbrNormalZ , 0); + fbo_out.bindColorTexture(obrSolidOmni , 1); + fbo_out.bindColorTexture(obrSolidSpot , 2); + fbo_out.bindColorTexture(obrTransparentOmni, 3); + fbo_out.bindColorTexture(obrTransparentSpot, 4); + fbo_out.setWriteBuffer(obrSum); + renderQuad(prog, quad); + } + + /// tonemapping + if (tone_proc.process()) + fbo_out.bind(); + if (bindShader(srTonemapPass, &prog)) { + prog->setUniformValue("gamma", gamma_); + prog->setUniformValue("frame_max", tone_proc.frameMax()); + fbo_out.bindColorTexture(obrSum, 0); + fbo_out.setWriteBuffer(obrTonemap); + renderQuad(prog, quad); + } else + fbo_out.blit(obrSum, fbo_out.id(), obrTonemap, fbo_out.rect(), fbo_out.rect()); + fbo_out.release(); + + /// apply hovers and selection frame + if (edit_mode) { + rend_selection.drawSelection(fbo_out, obrTonemap); + rend_service.renderService(); + } else { + fbo_out.blit(obrTonemap, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size())); + } + //fbo_small_16.blit(0, 0, 0, fbo_small_16.rect(), fbo_small_16.rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR); + +} + + +void Renderer::setCameraLightMode(int m) { + camera_light_mode = m; + view->scene()->setLightsChanged(); +} diff --git a/renderer.h b/renderer.h new file mode 100644 index 0000000..d865bbb --- /dev/null +++ b/renderer.h @@ -0,0 +1,136 @@ +/* + QGL Renderer + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef RENDERER_H +#define RENDERER_H + +#include "renderer_base.h" +#include "renderer_material.h" +#include "renderer_service.h" +#include "renderer_selection.h" +#include "tonemapping_proc.h" +#include "glcubemap.h" +#include + + +class Renderer: public RendererBase { + friend class QGLView; + friend class MouseController; + friend class RendererBase; + friend class RendererMaterial; + friend class RendererService; + friend class RendererSelection; + friend class TonemappingProc; + enum ShaderRole { + // Selection + srSelectionFill, + srSelectionHalo, + srSelectionApply, + srSelectionFrame, + + // Service + srServiceFill, + srServiceFrame, + srServiceLine, + + // Deferred shading + srGeometryPass, + srLightOmniPass, + srLightSpotPass, + srFinalPass, + srTonemapPass, + }; + enum DeferredBufferRole { + dbrDiffuse, + dbrNormalZ, + dbrSpecularReflect, + dbrEmissionRough, + dbrSpeedBitangXY, + + dbrBuffersCount, + }; + enum OutBufferRole { + obrTonemap, + obrSum, + obrSolidOmni, + obrSolidSpot, + obrTransparentOmni, + obrTransparentSpot, + + obrBuffersCount, + }; + +public: + Renderer(QGLView * view_); + virtual ~Renderer(); + + void init(int width, int height); + void resize(int width, int height); + void reloadShaders(); + void renderScene(); + void setCameraLightMode(int m); + int cameraLightMode() const {return camera_light_mode;} + + QImage materialThumbnail(Material * m) {return rend_mat.materialThumbnail(m);} + void recreateMaterialThumbnails(bool force_all = false) {rend_mat.recreateMaterialThumbnails(force_all);} + +protected: + void fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass); + void reloadObjects(); + void renderObjects(Scene & scene, RenderPass pass); + void renderLight(int first_wr_buff, bool clear_only); + + bool bindShader(ShaderRole role, QOpenGLShaderProgram ** ret = 0); + bool bindShader(QOpenGLShaderProgram * sp); + void initShaders(); + void releaseShader(); + +private: + float gamma_; + int camera_light_mode; + bool edit_mode, need_init_shaders, need_render_sum; + Framebuffer fbo_ds, fbo_out; + /*QOpenGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small; + QOpenGLShaderProgram * shader_bloom_0, * shader_bloom_1, * shader_motion_blur, * shader_fbo_add; + QOpenGLShaderProgram * shader_shadow, * shader_ssr, * shader_ssr_blur, * shader_ssr_merge; + QOpenGLShaderProgram * shader_ssao_blur, * shader_ssao_merge, * shader_dof;*/ + QMap shader_files; + QMap shader_defines; + QMap shaders; + QOpenGLShaderProgram * shader_fxaa; + + RendererMaterial rend_mat; + RendererService rend_service; + RendererSelection rend_selection; + TonemappingProc tone_proc; + + Mesh * quad; + Light * cam_light; + CubeTexture tex_env; + + QPoint mouse_pos; + QRect mouse_rect; + QMatrix4x4 prev_view, prev_proj; + QMatrix3x3 nm; + QVector4D corner_dirs[4]; + QVector hcontent; + QMap> cur_lights; + +}; + +#endif // RENDERER_H diff --git a/renderer_base.cpp b/renderer_base.cpp new file mode 100644 index 0000000..f22c287 --- /dev/null +++ b/renderer_base.cpp @@ -0,0 +1,442 @@ +/* + QGL RendererBase + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "renderer_base.h" +#include "renderer.h" +#include "qglview.h" +#include "glmesh.h" +#include "gltexture_manager.h" +#include "glshaders_headers.h" + +using namespace QGLEngineShaders; + + +RendererBase::RendererBase(QGLView * view_): + view(view_), + buffer_materials (GL_UNIFORM_BUFFER, GL_STREAM_DRAW), + buffer_lights (GL_UNIFORM_BUFFER, GL_STREAM_DRAW), + buffer_lights_pos(GL_UNIFORM_BUFFER, GL_STREAM_DRAW), + textures_empty(false), + textures_maps(true) +{ + textures_manager = new TextureManager(view); + maps_size = QSize(512, 512); + maps_hash = 0; + tex_coeff[0] = tex_coeff[1] = 0; + +} + + +RendererBase::~RendererBase() { + delete textures_manager; +} + + +void RendererBase::initTextureArrays() { + QOpenGLExtraFunctions * f = view; + textures_maps.init(f); + textures_empty.init(f); + textures_empty.resize(f, QSize(1, 1), 2); + textures_empty.bind(f); + QImage im(1, 1, QImage::Format_RGBA8888); + im.fill(0xFFFFFFFF); + textures_empty.load(f, im, emrWhite); + im.fill(0xFF8080); + textures_empty.load(f, im, emrBlue); +} + + +void RendererBase::initUniformBuffer(QOpenGLShaderProgram * prog, Buffer * buffer, int bind_point, const char * blockName) { + if (!prog || !buffer) return; + if (!prog->isLinked()) return; + QOpenGLExtraFunctions * f = view; + buffer->init(f); + //glClearError(); + GLint ubo_ind = f->glGetUniformBlockIndex(prog->programId(), blockName); + f->glUniformBlockBinding(prog->programId(), ubo_ind, bind_point); + f->glBindBufferBase(GL_UNIFORM_BUFFER, bind_point, buffer->ID()); + //qDebug() << "initUBO" << QString::number(f->glGetError(), 16); +} + + +void RendererBase::setUniformHalo(QOpenGLShaderProgram * prog, const char * type, QColor color, float fill) { + prog->setUniformValue((QString(type) + "_color").toLatin1().constData(), color); + prog->setUniformValue((QString(type) + "_fill" ).toLatin1().constData(), fill); +} + + +void RendererBase::setUniformMaps(QOpenGLShaderProgram * prog) { + prog->setUniformValue("qgl_texture_array[0]", (int)tarEmpty); + prog->setUniformValue("qgl_texture_array[1]", (int)tarMaps ); +} + + +void RendererBase::setUniformCamera(QOpenGLShaderProgram * prog, Camera * cam, bool matrices, QSize viewport) { + double w = view->width(), h = view->height(); + if (viewport.isValid()) { + w = viewport.width(); + h = viewport.height(); + } + QMatrix4x4 mat_view, mat_proj; + if (cam) { + if (matrices) { + mat_view = cam->fullViewMatrix(); + mat_proj = cam->projectionMatrix(w / h); + } + prog->setUniformValue("z_near", cam->depthStart()); + } + prog->setUniformValue("dt", QVector2D(1. / w, 1. / h)); + prog->setUniformValue("qgl_ViewMatrix" , mat_view); + prog->setUniformValue("qgl_ViewProjMatrix", mat_proj * mat_view); +} + + +void RendererBase::setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * cam, QSize viewport) { + double w = view->width(), h = view->height(); + if (viewport.isValid()) { + w = viewport.width(); + h = viewport.height(); + } + QMatrix4x4 mproji = cam->projectionMatrix(w / h).inverted(); + QMatrix4x4 mviewi = cam->viewMatrix().inverted(); + QVector4D corner_dirs[4], world_dirs[4]; + corner_dirs[0] = (mproji * QVector4D(-1, -1, 0, 1)); + corner_dirs[1] = (mproji * QVector4D(-1, 1, 0, 1)); + corner_dirs[2] = (mproji * QVector4D( 1, 1, 0, 1)); + corner_dirs[3] = (mproji * QVector4D( 1, -1, 0, 1)); + for (int i = 0; i < 4; ++i) { + world_dirs[i] = mviewi.mapVector(corner_dirs[i].toVector3D()); + prog->setUniformValue(QString("view_corners[%1]").arg(i).toLatin1().constData(), corner_dirs[i]); + prog->setUniformValue(QString("world_corners[%1]").arg(i).toLatin1().constData(), world_dirs[i]); + } +} + + +void RendererBase::fillSelectionsBuffer(QVector & buffer, const ObjectBaseList & ol) { + buffer.resize(ol.size()); + for (int i = 0; i < ol.size(); ++i) { + buffer[i] = (ol[i]->isSelected(true) ? 1 : 0); + } +} + + +void RendererBase::fillSelectionsBuffer(QVector & buffer, bool yes, int size) { + buffer.resize(size); + for (int i = 0; i < size; ++i) + buffer[i] = (yes ? 1 : 0); +} + + +void RendererBase::reloadMaterials(Scene & scene) { + //qDebug() << "reloadMaterias"; + QList maps[2]; + QMap tex_layers[2]; + foreach (Material * m, scene.materials) { + if (m->map_diffuse .hasBitmap()) maps[0] << &(m->map_diffuse ); + if (m->map_normal .hasBitmap()) maps[1] << &(m->map_normal ); + if (m->map_metalness.hasBitmap()) maps[0] << &(m->map_metalness); + if (m->map_roughness.hasBitmap()) maps[0] << &(m->map_roughness); + if (m->map_emission .hasBitmap()) maps[0] << &(m->map_emission ); + if (m->map_relief .hasBitmap()) maps[0] << &(m->map_relief ); + } + for (int i = 0; i < 2; ++i) { + foreach (Map * m, maps[i]) + tex_layers[i][m->bitmap_path] = 0; + } + int layers_count = tex_layers[0].size() + tex_layers[1].size(), cl = -1; + uint cur_maps_hash = qHash(tex_layers[0].keys()) ^ (qHash(tex_layers[1].keys()) + 0xF00FF00F); + if (maps_hash != cur_maps_hash) { + maps_hash = cur_maps_hash; + textures_maps.resize(view, maps_size, layers_count); + textures_maps.bind(view); + for (int i = 0; i < 2; ++i) { + QMutableMapIterator it(tex_layers[i]); + while (it.hasNext()) { + it.next(); + QImage im = textures_manager->loadTextureImage(it.key(), i == 1); + textures_maps.load(view, im, ++cl); + it.value() = cl; + } + foreach (Map * m, maps[i]) { + m->_layer = tex_layers[i].value(m->bitmap_path); + //qDebug() << "assign" << m->bitmap_path << "layer" << m->_layer; + } + } + textures_maps.mipmaps(view); +// qDebug() << "load" << (cl+1) << "bitmaps"; + } + + QGLMaterial glm; + cur_materials_.clear(); + cur_materials_ << glm; + foreach (Material * m, scene.materials) { + if (cur_materials_.size() >= max_materials) { + qDebug() << "[QGLEngine] Warning: Too many materials! Maximum" << max_materials; + break; + } + //m->load(textures_manager); + m->_index = cur_materials_.size(); + m->_changed = false; + glm.color_diffuse = QColor2QVector(m->color_diffuse ); + glm.color_emission = QColor2QVector(m->color_emission); + glm.transparency = m->transparency; + glm.reflectivity = m->reflectivity; + glm.iof = m->iof ; + glm.dispersion = m->dispersion ; + m->map_diffuse .copyToQGLMap(glm.map[mtDiffuse ]); + m->map_normal .copyToQGLMap(glm.map[mtNormal ]); + m->map_metalness.copyToQGLMap(glm.map[mtMetalness ]); + m->map_roughness.copyToQGLMap(glm.map[mtRoughness]); + m->map_emission .copyToQGLMap(glm.map[mtEmission ]); + m->map_relief .copyToQGLMap(glm.map[mtRelief ]); + cur_materials_ << glm; + } + //qDebug() << "load" << cur_materials_.size() << "materials"; + //textures_maps.resize(maps_size, ); + //cur_materials_[0].color_diffuse = QColor2QVector(Qt::red); + buffer_materials.bind(view); + buffer_materials.resize(view, cur_materials_.size() * sizeof(QGLMaterial)); + buffer_materials.load(view, cur_materials_.constData(), cur_materials_.size() * sizeof(QGLMaterial)); + scene.need_reload_materials = false; + +} + + +void RendererBase::reloadLightsParameters(const QMap> & lights) { + lights_start.clear(); + lights_start[Light::Omni] = 0; + QMapIterator> it(lights); + current_lights.clear(); + while (it.hasNext()) { + it.next(); + lights_start[it.key()] = current_lights.size(); + current_lights.append(it.value()); + } + cur_lights_params_.resize(qMin(current_lights.size(), max_lights)); + //qDebug() << "reloadLightsParameters" << cur_lights_params_.size(); + for (int i = 0; i < cur_lights_params_.size(); ++i) { + QGLLightParameter & so(cur_lights_params_[i]); + Light * l = current_lights[i]; + double ang_start = l->angle_start / 2.f, ang_end = l->angle_end / 2.f; + if (l->light_type == Light::Omni) + ang_start = ang_end = 180.; + //qDebug() << "light" << light->name() << ulightn << pos; + so.color = QColor2QVector(l->color_); + so.angles[0] = ang_start; + so.angles[1] = cos(ang_start * deg2rad); + so.angles[2] = ang_end; + so.angles[3] = cos(ang_end * deg2rad); + so.decay_intensity[0] = l->decay_const; + so.decay_intensity[1] = l->decay_linear; + so.decay_intensity[2] = l->decay_quadratic; + so.decay_intensity[3] = l->intensity; + //so.shadow = shadow; + //so.shadowColor = shadow; + } + buffer_lights.bind(view); + buffer_lights.resize(view, cur_lights_params_.size() * sizeof(QGLLightParameter)); + buffer_lights.load(view, cur_lights_params_.constData(), cur_lights_params_.size() * sizeof(QGLLightParameter)); +} + + +void RendererBase::reloadLightsPositions(Camera * cam) { + cur_lights_pos_.resize(qMin(current_lights.size(), max_lights)); + QMatrix4x4 mat = cam->viewMatrix() * cam->offsetMatrix(); + for (int i = 0; i < cur_lights_pos_.size(); ++i) { + QGLLightPosition & so(cur_lights_pos_[i]); + Light * l = current_lights[i]; + QMatrix4x4 m = mat * l->worldTransform(); + QVector4D pos(0, 0, 0, 1.), dir(QVector3D(0,0,-1), 1);//, dir0(light->dir0), dir1(light->dir1); + pos = m * pos; + dir = (m * QVector4D(QVector3D(0,0,-1),0)).normalized();//((m * dir) - pos).normalized(); + so.position = pos; + so.direction = dir; + //so.shadowMatrix = l->shadow_matrix; + } + buffer_lights_pos.bind(view); + buffer_lights_pos.resize(view, cur_lights_pos_.size() * sizeof(QGLLightPosition)); + buffer_lights_pos.load(view, cur_lights_pos_.constData(), cur_lights_pos_.size() * sizeof(QGLLightPosition)); +} + + +void RendererBase::markReloadTextures() { + maps_hash = 0; + textures_manager->clearImageCache(); + view->scene_->need_reload_materials = true; +} + + +void RendererBase::setMapsSize(QSize sz) { + maps_size = sz; + markReloadTextures(); +} + + +void RendererBase::initQuad(Mesh * mesh, QMatrix4x4 mat) { + QGLEngineShaders::Object quab_object; + mat.transposed().copyDataTo(quab_object.modelmatrix); + mesh->init(view); + mesh->loadObject(view, quab_object); +} + + +void RendererBase::renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam, bool uniforms) { + glDisableDepth(); + if (uniforms) + setUniformCamera(prog, cam, false); + mesh->draw(view, 1); +} + + + + +float RadicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +QVector2D Hammersley(uint i, uint N) { + return QVector2D(float(i)/float(N), RadicalInverse_VdC(i)); +} +QVector3D ImportanceSampleGGX(QVector2D Xi, QVector3D N, float roughness) { + float a = roughness*roughness; + float phi = 2.0 * M_PI * Xi[0]; + float cosTheta = sqrt((1.0 - Xi[1]) / (1.0 + (a*a - 1.0) * Xi[1])); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + // преобразование из сферических в декартовы координаты + QVector3D H; + H[0] = cos(phi) * sinTheta; + H[1] = sin(phi) * sinTheta; + H[2] = cosTheta; + // преобразование из касательного пространства в мировые координаты + QVector3D up = qAbs(N[2]) < 0.999 ? QVector3D(0.0, 0.0, 1.0) : QVector3D(1.0, 0.0, 0.0); + QVector3D tangent = QVector3D::crossProduct(up, N).normalized(); + QVector3D bitangent = QVector3D::crossProduct(N, tangent); + QVector3D sampleVec = tangent * H[0] + bitangent * H[1] + N * H[2]; + return sampleVec.normalized(); +} +float GeometrySchlickGGX(float NdotV, float roughness) { + float k = (roughness * roughness) / 2.0; + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + return nom / denom; +} +float GeometrySmith(QVector3D N, QVector3D V, QVector3D L, float roughness) { + float NdotV = piMax(QVector3D::dotProduct(N, V), 0.f); + float NdotL = piMax(QVector3D::dotProduct(N, L), 0.f); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + return ggx1 * ggx2; +} +QVector2D IntegrateBRDF(float NdotV, float roughness) { + QVector3D V; + V[0] = sqrt(1.f - NdotV*NdotV); + V[1] = 0.f; + V[2] = NdotV; + float A = 0.f; + float B = 0.f; + QVector3D N = QVector3D(0.f, 0.f, 1.f); + const uint SAMPLE_COUNT = 256u; + for(uint i = 0u; i < SAMPLE_COUNT; ++i) { + QVector2D Xi = Hammersley(i, SAMPLE_COUNT); + QVector3D H = ImportanceSampleGGX(Xi, N, roughness); + QVector3D L = (2.f * QVector3D::dotProduct(V, H) * H - V).normalized(); + float NdotL = piMax(L[2], 0.f); + float NdotH = piMax(H[2], 0.f); + float VdotH = piMax(QVector3D::dotProduct(V, H), 0.f); + if(NdotL > 0.f) { + float G = GeometrySmith(N, V, L, roughness); + float G_Vis = (G * VdotH) / (NdotH * NdotV); + float Fc = pow(1.f - VdotH, 5.f); + A += (1.f - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + A /= float(SAMPLE_COUNT); + B /= float(SAMPLE_COUNT); + return QVector2D(A, B); +} + +void RendererBase::initCoeffTextures() { + QImage im = QImage(":/coeffs_brdf.png").mirrored(); + int size = im.width(); + QVector data(size*size); + int ind = -1; + for (int x = 0; x < size; ++x) { + //float c = x / double(size - 1) + 1.E-3; + for (int y = 0; y < size; ++y) { + //float r = y / double(size - 1); + QColor p = im.pixelColor(x, y); + data[++ind] = QVector2D(p.redF(), p.greenF());//IntegrateBRDF(c, 1.f - r + 1.E-3); + } + } + createCoeffTexture(tex_coeff[0], data.constData(), size, 2); + /*const int size = 512; + QVector data_diff(size*size), data_spec(size*size); + double r, c, c2; + int ind = -1; + for (int x = 0; x < size; ++x) { + c = x / double(size - 1); + c = sqrt(c); + c = piMax(1.E-16, c); + c2 = c*c; + for (int y = 0; y < size; ++y) { + r = y / double(size - 1); + double r_d = r; + double r_s = r*r*r; + r_d = piMax(1.E-16, r_d); + r_s = piMax(1.E-16, r_s); + + double ndlc = (1. - c2) / c2; + double diff = 2. / (1. + sqrt(1. + (1. - r_d) * ndlc)); + + double spec = c2 * (r_s + ndlc); + spec = r_s / (spec * spec) / M_PI; + + ++ind; + data_diff[ind] = piClamp(diff, 1.E-12, 1.E+36); + data_spec[ind] = piClamp(spec, 1.E-12, 1.E+36); + } + } + createCoeffTexture(tex_coeff[0], data_diff, size); + createCoeffTexture(tex_coeff[1], data_spec, size);*/ +} + + +void RendererBase::createCoeffTexture(GLuint & id, const void * data, int size, int channels) { + QOpenGLExtraFunctions * f = view; + deleteGLTexture(f, id); + f->glGenTextures(1, &id); + f->glBindTexture(GL_TEXTURE_2D, id); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + GLenum iformat = GL_R16F, format = GL_RED; + if (channels == 2) {iformat = GL_RG16F; format = GL_RG;} + if (channels == 3) {iformat = GL_RGB16F; format = GL_RGB;} + if (channels == 4) {iformat = GL_RGBA16F; format = GL_RGBA;} + f->glTexImage2D(GL_TEXTURE_2D, 0, iformat, size, size, 0, format, GL_FLOAT, data); +} diff --git a/renderer_base.h b/renderer_base.h new file mode 100644 index 0000000..e0f5574 --- /dev/null +++ b/renderer_base.h @@ -0,0 +1,68 @@ +/* + QGL RendererBase + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef RENDERER_BASE_H +#define RENDERER_BASE_H + +#include "glshaders_types.h" +#include "gltexturearray.h" +#include "glbuffer.h" + + +class RendererBase { +public: + RendererBase(QGLView * view_); + ~RendererBase(); + +protected: + void initTextureArrays(); + void initUniformBuffer (QOpenGLShaderProgram * prog, Buffer * buffer, int bind_point, const char * blockName); + void setUniformHalo (QOpenGLShaderProgram * prog, const char * type, QColor color, float fill); + void setUniformMaps (QOpenGLShaderProgram * prog); + void setUniformCamera (QOpenGLShaderProgram * prog, Camera * cam, bool matrices = true, QSize viewport = QSize()); + void setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * cam, QSize viewport = QSize()); + void fillSelectionsBuffer(QVector & buffer, const ObjectBaseList & ol); + void fillSelectionsBuffer(QVector & buffer, bool yes, int size); + void reloadMaterials(Scene & scene); + void reloadLightsParameters(const QMap> & lights); + void reloadLightsPositions (Camera * cam); + void markReloadTextures(); + void setMapsSize(QSize sz); + void initQuad(Mesh * mesh, QMatrix4x4 mat = QMatrix4x4()); + void renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam = 0, bool uniforms = true); + void initCoeffTextures(); + void createCoeffTexture(GLuint & id, const void * data, int size, int channels = 1); + + QGLView * view; + TextureManager * textures_manager; + QVector cur_objects_; + QVector cur_materials_; + QVector cur_lights_params_; + QVector cur_lights_pos_; + Buffer buffer_materials; + Buffer buffer_lights, buffer_lights_pos; + Texture2DArray textures_empty, textures_maps; + QSize maps_size; + uint maps_hash; + GLuint tex_coeff[2]; + QMap lights_start; + QList current_lights; + +}; + +#endif // RENDERER_BASE_H diff --git a/renderer_material.cpp b/renderer_material.cpp new file mode 100644 index 0000000..0e6c594 --- /dev/null +++ b/renderer_material.cpp @@ -0,0 +1,132 @@ +/* + QGL RendererMaterial + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "renderer_material.h" +#include "renderer.h" +#include "qglview.h" +#include "glmesh.h" +#include "gltexture_manager.h" +#include + +using namespace QGLEngineShaders; + + +RendererMaterial::RendererMaterial(Renderer * r_): r(r_), + fbo_mat_thumb(r->view, 6, true , GL_RGBA16F) { + mat_sphere = Primitive::ellipsoid(16, 16); + mat_camera = new Camera(); + mat_camera->setPos(QVector3D(2, 2, 2)); + mat_camera->setAim(QVector3D()); + mat_camera->setFOV(45.); + mat_light = new Light(); + mat_light->setPos(QVector3D(50, 100, 25)); + last_thumb_material = 0; +} + + +RendererMaterial::~RendererMaterial() { + delete mat_sphere; + delete mat_camera; + delete mat_light; +} + + +void RendererMaterial::init(int width, int height) { + resize(width, height); +} + + +void RendererMaterial::resize(int width, int height) { + fbo_mat_thumb.enablePixelBuffer(); + fbo_mat_thumb.resize(256, 256); +} + + +void RendererMaterial::renderMaterial(Material * m) { + //qDebug() << "renderMaterial" << m; + last_thumb_material = m; + QOpenGLShaderProgram * prog = 0; + QOpenGLExtraFunctions * f = r->view; + fbo_mat_thumb.bind(); + glEnableDepth(); + glClearFramebuffer(QColor(0,0,0,0)); + if (r->bindShader(Renderer::srGeometryPass, &prog)) { + r->setUniformMaps(prog); + r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size()); + //qDebug() << mat_camera->viewMatrix(); + r->textures_empty.bind(f, tarEmpty); + r->textures_maps .bind(f, tarMaps ); + Object o; + o.material = m->_index; + mat_sphere->loadObject(f, o); + mat_sphere->draw(f, 1); + } + fbo_mat_thumb.bindColorTextures(); + fbo_mat_thumb.bindDepthTexture(5); + fbo_mat_thumb.setWriteBuffer(5); + if (r->bindShader(Renderer::srLightOmniPass, &prog)) { + r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size()); + r->setUniformViewCorners(prog, mat_camera, fbo_mat_thumb.size()); + for (int i = 0; i < 5; ++i) + prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); + prog->setUniformValue("tex_d", 5); + prog->setUniformValue("lights_start", 0); + prog->setUniformValue("lights_count", 1); + QMap> mat_l; + mat_l[Light::Omni] << mat_light; + r->reloadLightsParameters(mat_l); + r->reloadLightsPositions(mat_camera); + glClearFramebuffer(r->view->backColor(), false); + r->renderQuad(prog, r->quad, mat_camera); + r->view->scene()->setLightsChanged(); + } + fbo_mat_thumb.queryImage(5); + fbo_mat_thumb.release(); +} + + +void RendererMaterial::procQueue() { + if (last_thumb_material) { + mat_thumbnails[last_thumb_material] = fbo_mat_thumb.getImage(); + emit r->view->materialThumbnailCreated(last_thumb_material); + last_thumb_material = 0; + } + if (!mat_thumb_queue.isEmpty()) + renderMaterial(mat_thumb_queue.dequeue()); +} + + +QImage RendererMaterial::materialThumbnail(Material * m) { + return mat_thumbnails.value(m); +} + + +void RendererMaterial::recreateMaterialThumbnails(bool force_all) { + if (force_all) { + mat_thumb_queue.clear(); + //qDebug() << "recreateMaterialThumbnails" << view->scene_->materials; + foreach (Material * m, r->view->scene_->materials) + mat_thumb_queue.enqueue(m); + } else { + foreach (Material * m, r->view->scene_->changed_materials) + if (!mat_thumb_queue.contains(m)) + mat_thumb_queue.enqueue(m); + } +} diff --git a/renderer_material.h b/renderer_material.h new file mode 100644 index 0000000..3c08a7b --- /dev/null +++ b/renderer_material.h @@ -0,0 +1,54 @@ +/* + QGL RendererMaterial + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef RENDERER_MATERIAL_H +#define RENDERER_MATERIAL_H + +#include "glframebuffer.h" +#include + + +class RendererMaterial { + friend class QGLView; + +public: + RendererMaterial(Renderer * r_); + virtual ~RendererMaterial(); + + void init(int width, int height); + void resize(int width, int height); + + QImage materialThumbnail(Material * m); + void recreateMaterialThumbnails(bool force_all = false); + void renderMaterial(Material * m); + void procQueue(); + +private: + Renderer * r; + + Framebuffer fbo_mat_thumb; + Mesh * mat_sphere; + Camera * mat_camera; + Light * mat_light; + QMap mat_thumbnails; + Material * last_thumb_material; + QQueue mat_thumb_queue; + +}; + +#endif // RENDERER_MATERIAL_H diff --git a/renderer_selection.cpp b/renderer_selection.cpp new file mode 100644 index 0000000..00897a7 --- /dev/null +++ b/renderer_selection.cpp @@ -0,0 +1,218 @@ +/* + QGL RendererSelection + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "renderer_selection.h" +#include "qglview.h" +#include "glmesh.h" +#include + +using namespace QGLEngineShaders; + + +RendererSelection::RendererSelection(Renderer * r_): r(r_), + fbo_selection(r->view, 6) { + sel_frame = Primitive::plane(2., 2.); + id_hover = 0; + line_thick_ = 2.; + scale_ = 0.5; +} + + +RendererSelection::~RendererSelection() { + delete sel_frame; +} + + +void RendererSelection::init(int width, int height) { + resize(width, height); +} + + +void RendererSelection::resize(int width, int height) { + line_thick_ = lineThickness() + 1.; + scale_ = 0.5 / appScale(); + fbo_selection.enablePixelBuffer(); + fbo_selection.resize(width * scale_, height * scale_); + //fbo_selection.setColorTextureFiltering(sbrSrcHover , GL_LINEAR); + //fbo_selection.setColorTextureFiltering(sbrSrcSelect, GL_LINEAR); +} + + +void RendererSelection::generateObjectsID(Scene & scene) { + ids.clear(); + aim_ids.clear(); + QList passes = scene.geometries_used.keys(); + foreach (int p, passes) { + QMapIterator it(scene.geometries_used[p]); + while (it.hasNext()) { + it.next(); + foreach (ObjectBase * o, it.value()) { + uint id = qHash(o); + ids[id] = o; + o->id_ = id; + } + } + QMapIterator> lit(scene.lights_used); + while (lit.hasNext()) { + lit.next(); + foreach (ObjectBase * o, lit.value()) { + uint id = qHash(o); + ids[id] = o; + aim_ids[id + 1] = o; + o->id_ = id; + } + } + foreach (Camera * o, scene.cameras_used) { + uint id = qHash(o); + ids[id] = o; + aim_ids[id + 1] = o; + o->id_ = id; + } + } +} + + +void RendererSelection::renderSelection(Scene & scene) { + QOpenGLShaderProgram * prog = 0; + QGLView * view = r->view; + MouseController & mc(view->mouse); + if (r->bindShader(Renderer::srSelectionFill, &prog)) { + mc.hov_objects.clear(); + mc.hov_aims.clear(); + id_hover = 0; + if (fbo_selection.queriedPoints() > 0) { + if (fbo_selection.queriedPoints() == 1) { + id_hover = fbo_selection.getPoint(); + ObjectBase * o = ids.value(id_hover); + if (o) + mc.hov_objects << o; + else { + o = aim_ids.value(id_hover); + if (o) + mc.hov_aims << o; + } + //qDebug() << id_hover; + } else { + QVector points = fbo_selection.getPointsByte(); + QSet ids_hover; + foreach (uint i, points) + ids_hover << i; + foreach (uint i, ids_hover) { + ObjectBase * o = ids.value(i); + if (o) mc.hov_objects << o; + o = aim_ids.value(i); + if (o) mc.hov_aims << o; + } + //qDebug() << ids_hover; + } + } + + fbo_selection.bind(); + + fbo_selection.setWriteBuffers(); + glEnableDepth(); + glClearFramebuffer(QColor(0,0,0,0)); + r->setUniformCamera(prog, view->camera()); + r->renderObjects(scene, rpSolid); + r->renderObjects(scene, rpTransparent); + view->glClear(GL_DEPTH_BUFFER_BIT); + + RendererService & rs(r->rend_service); + rs.drawLights(); + rs.drawCameras(); + rs.drawCurrentHandleObjects(); + + //mouse_rect = fbo_selection.rect(); + if (r->mouse_rect.isNull()) + fbo_selection.queryPoint(0, r->mouse_pos * scale_); + else + fbo_selection.queryPoints(0, QRect(r->mouse_rect.topLeft() * scale_, + r->mouse_rect.size() * scale_)); + + //qDebug() << id_hover; + fbo_selection.bindColorTexture(sbrSrcHover , sbrSrcHover ); + fbo_selection.bindColorTexture(sbrSrcSelect, sbrSrcSelect); + fbo_selection.setWriteBuffers(QVector() << sbrHovered << sbrSelected); + if (!view->hoverHalo_ && !view->selectionHalo_) + glClearFramebuffer(QColor(0,0,0,0), false); + else { + r->bindShader(Renderer::srSelectionHalo, &prog); + r->setUniformHalo(prog, "hover" , view->hoverHaloColor() , view->hoverHaloFillAlpha()); + r->setUniformHalo(prog, "selection", view->selectionHaloColor(), view->selectionHaloFillAlpha()); + prog->setUniformValue("has_hover" , view->hoverHalo_ && (id_hover > 0) ? 1.f : 0.f); + prog->setUniformValue("has_selection", view->selectionHalo_ ? 1.f : 0.f); + prog->setUniformValue("fb_hover" , (int)sbrSrcHover); + prog->setUniformValue("fb_selection", (int)sbrSrcSelect); + prog->setUniformValue("hover_id", QVector4D(float( id_hover & 0xFF) / 255.f, + float((id_hover >> 8 ) & 0xFF) / 255.f, + float((id_hover >> 16) & 0xFF) / 255.f, + float((id_hover >> 24) & 0xFF) / 255.f)); + r->renderQuad(prog, r->quad, view->camera()); + } + + prog = r->shader_fxaa; + if (r->bindShader(prog)) { + r->setUniformCamera(prog, 0, true, fbo_selection.size()); + fbo_selection.bindColorTexture(sbrHovered); + fbo_selection.setWriteBuffer(sbrHoveredFXAA); + r->renderQuad(prog, r->quad, 0, false); + fbo_selection.bindColorTexture(sbrSelected); + fbo_selection.setWriteBuffer(sbrSelectedFXAA); + r->renderQuad(prog, r->quad, 0, false); + } + + fbo_selection.release(); + } +} + + +void RendererSelection::renderSelectionFrame() { + QOpenGLShaderProgram * prog = 0; + if (r->bindShader(Renderer::srSelectionFrame, &prog)) { + QMatrix4x4 mat; + double mrx = r->mouse_rect.x(), mrw = r->mouse_rect.width() , vw = r->view->width(); + double mry = r->mouse_rect.y(), mrh = r->mouse_rect.height(), vh = r->view->height(); + mat.translate(-1. + (mrw + mrx*2) / vw, 1. - (mrh + mry*2) / vh, 0.); + mat.scale(mrw / vw, mrh / vh, 0.); + r->initQuad(sel_frame, mat); + prog->setUniformValue("size", QVector2D(mrw / vw, mrh / vh)); + prog->setUniformValue("thickness", line_thick_); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + r->renderQuad(prog, sel_frame); + glDisable(GL_BLEND); + } +} + + +void RendererSelection::drawSelection(Framebuffer & fbo_out, int index_out) { + QOpenGLShaderProgram * prog = 0; + if (r->bindShader(Renderer::srSelectionApply, &prog)) { + fbo_selection.bindColorTextures(); + fbo_out.bindColorTexture(index_out); + prog->setUniformValue("fb_out" , 0); + prog->setUniformValue("fb_hover" , (int)sbrHoveredFXAA ); + prog->setUniformValue("fb_select", (int)sbrSelectedFXAA); + r->renderQuad(prog, r->quad, r->view->camera()); + if (!r->mouse_rect.isNull()) { + renderSelectionFrame(); + } + } +} diff --git a/renderer_selection.h b/renderer_selection.h new file mode 100644 index 0000000..9062a18 --- /dev/null +++ b/renderer_selection.h @@ -0,0 +1,68 @@ +/* + QGL RendererSelection + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef RENDERER_SELECTION_H +#define RENDERER_SELECTION_H + +#include "renderer_service.h" +#include + + +class RendererSelection { + friend class QGLView; + friend class MouseController; + friend class Renderer; + friend class RendererService; + +public: + RendererSelection(Renderer * r_); + virtual ~RendererSelection(); + + void init(int width, int height); + void resize(int width, int height); + +protected: + enum SelectionBufferRole { + sbrSrcHover, + sbrSrcSelect, + sbrHovered, + sbrSelected, + sbrHoveredFXAA, + sbrSelectedFXAA, + }; + + void generateObjectsID(Scene & scene); + void renderSelection(Scene & scene); + void renderSelectionFrame(); + void drawSelection(Framebuffer & fbo_out, int index_out = 0); + +private: + Renderer * r; + + Framebuffer fbo_selection; + Mesh * sel_frame; + float line_thick_, scale_; + + QVector cur_selections_; + QHash ids; + QHash aim_ids; + uint id_hover; + +}; + +#endif // RENDERER_selection_H diff --git a/renderer_service.cpp b/renderer_service.cpp new file mode 100644 index 0000000..e71a183 --- /dev/null +++ b/renderer_service.cpp @@ -0,0 +1,490 @@ +/* + QGL RendererService + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "renderer_service.h" +#include "renderer.h" +#include "qglview.h" +#include "glmesh.h" +#include + +using namespace QGLEngineShaders; + + +RendererService::RendererService(Renderer * r_): r(r_) { + line_width = 1; + current_action = haNoAction; + current_handle = 0; + mat_xyz.resize(3); mat_ms2.resize(3); + color_xyz.resize(3); color_ms2.resize(3); + const QVector3D _rot [3] = {QVector3D(0,1,0), QVector3D(-1,0,0), QVector3D(0, 0,1)}; + const QVector3D _rot2[3] = {QVector3D(0,0,0), QVector3D( 1,0,0), QVector3D(0,-1,0)}; + for (int i = 0; i < 3; ++i) { + QMatrix4x4 m; + m.rotate(90., _rot[i]); + mat_xyz[i] = m; + m.setToIdentity(); + if (!_rot2[i].isNull()) + m.rotate(90., _rot2[i]); + mat_ms2[i] = m; + color_xyz[i] = color_ms2[i] = QVector4D(0,0,0,0.8); + color_xyz[i][i] = 1.; + } + color_ms2[0] = (color_xyz[0] + color_xyz[1]) / 2.; + color_ms2[1] = (color_xyz[0] + color_xyz[2]) / 2.; + color_ms2[2] = (color_xyz[1] + color_xyz[2]) / 2.; + axis_camera = new Camera(); + axis_camera->setAim(QVector3D()); + axis_camera->setFOV(45.); + axis_mesh = Primitive::arrow(12); + size_vp_scale = size_full_scale = 1.; + + box_mesh = Primitive::cube(0.8, 0.8, 0.8); + box_mesh_f = Primitive::cubeFrame(0.8, 0.8, 0.8); + omni_mesh = Primitive::ellipsoid(2, 1, 0.5); + omni_mesh_f = Primitive::ellipsoidFrame(2, 1, 0.5); + omni_mesh ->scalePoints(1.5); + omni_mesh_f ->scalePoints(1.5); + cone_mesh = Primitive::cone(8, 0.5, 1.); + cone_mesh_f = Primitive::coneFrame(8, 0.5, 1.); + QMatrix4x4 mat; + mat.translate(0,0,-1); + cone_mesh ->transformPoints(mat); + cone_mesh_f->transformPoints(mat); + cone_mesh_f->scalePoints(1.5); + + box_mesh ->scalePoints(1.3); + omni_mesh ->scalePoints(1.3); + cone_mesh ->translatePoints(0,0,0.5); + cone_mesh ->scalePoints(1.4); + cone_mesh ->translatePoints(0,0,-0.5); + cone_mesh ->scalePoints(1.5); + + camera_mesh = Primitive::cube(1.2, 1.2, 1.2); + mat.translate(0,0,-0.5); + Mesh * m = Primitive::cone(6, 0.6, 1.); + m->scalePoints(1.4); + m->transformPoints(mat); + camera_mesh->append(m); + camera_mesh_f = Primitive::cubeFrame(1., 1., 1.); + camera_mesh_f->append(Primitive::cubeFrame(0.5, 0.5, 0.5)); + m = Primitive::coneFrame(6, 0.6, 1.); + m->transformPoints(mat); + camera_mesh_f->append(m); + + line_spot_f = Primitive::lineFrame(QVector3D(), QVector3D(0, 0, -1)); + line_camera_f = Primitive::lineFrame(QVector3D(), QVector3D(0, 0, -1)); + + handle_move_mesh = Primitive::arrow(12, 0.06); + handle_ms_2_mesh = Primitive::torus(8, 12, 0.5, 0.02, 90); + m = Primitive::disc(8, 0.5, 90); + handle_ms_2_mesh->append(m); + m->flipNormals(); + handle_ms_2_mesh->append(m); + delete m; + + handle_rotate_mesh = Primitive::arrow(12, 0.03); + m = Primitive::torus(30, 12, 0.5, 0.06); + m->translatePoints(QVector3D(0., 0., 0.75)); + handle_rotate_mesh->append(m); + delete m; + + handle_scale_mesh = Primitive::cylinder(12, 0.03, 0.85); + m = Primitive::ellipsoid(12, 12, 0.15); + m->translatePoints(QVector3D(0., 0., 0.85)); + handle_scale_mesh->append(m); + delete m; + handle_scale_3_mesh = Primitive::ellipsoid(12, 12, 0.2); + + handle_move_mesh ->scalePoints(7.5); + handle_ms_2_mesh ->scalePoints(7.5); + handle_rotate_mesh ->scalePoints(7.5); + handle_scale_mesh ->scalePoints(7.5); + handle_scale_3_mesh->scalePoints(7.5); +} + + +RendererService::~RendererService() { + delete box_mesh; + delete box_mesh_f; + delete omni_mesh; + delete omni_mesh_f; + delete cone_mesh; + delete cone_mesh_f; + delete camera_mesh; + delete camera_mesh_f; + delete line_spot_f; + delete line_camera_f; + delete axis_camera; + delete axis_mesh; + delete handle_move_mesh; + delete handle_ms_2_mesh; + delete handle_rotate_mesh; + delete handle_scale_mesh; + delete handle_scale_3_mesh; +} + + +void RendererService::init(int width, int height) { + fillXYZObjects(); + axis_mesh->loadObjects(r->view, cur_objects); + resize(width, height); +} + + +void RendererService::resize(int width, int height) { + axis_viewport = preferredIconSize(10.); + line_width = lineThickness(); + size_vp_scale = 25. * appScale() / qMax(qMin(width, height), 1); + //qDebug() << axis_viewport; +} + + +QMatrix4x4 RendererService::invariantSizeMatrix(QVector3D p, double * ret_scale) { + QVector4D pos = QVector4D(p, 1.); + double dist = -(v_mat * pos).z(); + QMatrix4x4 m; + m.translate(pos.toVector3D()); + m.scale(dist * size_full_scale); + if (ret_scale) *ret_scale = dist * size_full_scale; + return m; +} + + +QMatrix4x4 RendererService::parentRotationMatrix(ObjectBase * o, bool self_rotation) { + QMatrix4x4 ret; + if (!o) return ret; + QMatrix4x4 pmat; + if (o->parent()) { + pmat = o->parent()->transform().matrixRotate(); + } + if (self_rotation) { + ret *= o->transform().matrixRotate(); + } + ret = pmat * ret; + return ret; +} + + +void RendererService::fillXYZObjects() { + cur_objects.resize(3); + for (int i = 0; i < 3; ++i) { + cur_objects[i].color = color_xyz[i]; + mat_xyz[i].transposed().copyDataTo(cur_objects[i].modelmatrix); + } +} + + +void RendererService::fillOmniObjects() { + QList ll = r->view->scene()->lights_used.value(Light::Omni); + Object o; + cur_objects.clear(); + foreach (Light * l, ll) { + QMatrix4x4 m = invariantSizeMatrix(l->worldPos()); + m.transposed().copyDataTo(o.modelmatrix); + o.object_id = l->id_; + cur_objects << o; + } +} + + +void RendererService::fillAimedObjects(const ObjectBaseList & objects, Mesh * line_mesh) { + Object o; + cur_objects.clear(); + cur_aims.clear(); + QVector & lv (line_mesh->vertices ()); + QVector & ln (line_mesh->normals ()); + QVector & lt (line_mesh->texcoords ()); + QVector< Vector2i> & lind(line_mesh->indicesLines()); + lv.clear(); + foreach (ObjectBase * go, objects) { + AimedObject * ao = (AimedObject *)go; + QMatrix4x4 m; + m = invariantSizeMatrix(ao->worldPos()) * parentRotationMatrix(ao); + m.transposed().copyDataTo(o.modelmatrix); + o.object_id = ao->id_; + cur_objects << o; + + lv << ao->worldPos() << ao->worldAim(); + + m = invariantSizeMatrix(ao->worldAim()); + m.transposed().copyDataTo(o.modelmatrix); + o.object_id = ao->id_ + 1; + cur_aims << o; + } + ln.resize(lv.size()); + lt.resize(lv.size()); + lind.resize(lv.size() / 2); + for (int i = 0; i < lind.size(); ++i) { + lind[i] = Vector2i(i*2, i*2 + 1); + } +} + + +void RendererService::fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count) { + QMatrix4x4 m = invariantSizeMatrix(center) * add_mat; + cur_objects.resize(count); + for (int i = 0; i < count; ++i) { + cur_objects[i].color = colors[i]; + QMatrix4x4 omat = m * mats[i]; + cur_objects[i].object_id = ids[i]; + if (current_handle.testFlag(ids[i])) { + cur_objects[i].color = QVector4D(0,1,1,1); + } + omat.transposed().copyDataTo(cur_objects[i].modelmatrix); + } +} + + +bool RendererService::calculateCenter() { + ObjectBaseList sol = r->view->scene()->selectedObjects(true); + if (sol.isEmpty()) return false; + selection_center = sol[0]->worldPos(); + if (sol.size() > 1) { + Box3D bb; + foreach (ObjectBase * o, sol) { + o->calculateBoundingBox(); + bb |= o->boundingBox(); + } + if (!bb.isEmpty()) { + selection_center = bb.center(); + } + } + axis_mat = QMatrix4x4(); + if ((sol.size() == 1)) { + if (current_action == haMove) { + if (sol[0]->selected_aim) + selection_center = ((AimedObject*)sol[0])->worldAim(); + } else { + axis_mat = parentRotationMatrix(sol[0]); + } + } + return true; +} + + +void RendererService::drawCurrentHandleObjects() { + if (current_action == haNoAction) return; + if (calculateCenter()) { + HandleMesh ids[3]; + switch (current_action) { + case haMove : ids[0] = hmMoveX ; ids[1] = hmMoveY ; ids[2] = hmMoveZ ; break; + case haRotate: ids[0] = hmRotateX; ids[1] = hmRotateY; ids[2] = hmRotateZ; break; + case haScale : ids[0] = hmScaleX ; ids[1] = hmScaleY ; ids[2] = hmScaleZ ; break; + default: break; + } + fillHandleObjects(selection_center, ids, mat_xyz, color_xyz, axis_mat); + Mesh * hm = currentHandleMesh(); + QVector sel; + sel.fill(0, 3); + if (hm) { + hm->loadObjects(r->view, cur_objects); + hm->loadSelections(r->view, sel); + hm->draw(r->view, 3); + } + if (current_action == haMove || current_action == haScale) { + switch (current_action) { + case haMove : ids[0] = hmMoveXY ; ids[1] = hmMoveXZ ; ids[2] = hmMoveYZ ; break; + case haScale : ids[0] = hmScaleXY ; ids[1] = hmScaleXZ ; ids[2] = hmScaleYZ ; break; + default: break; + } + hm = handle_ms_2_mesh; + fillHandleObjects(selection_center, ids, mat_ms2, color_ms2, axis_mat); + hm->loadObjects(r->view, cur_objects); + hm->loadSelections(r->view, sel); + hm->draw(r->view, 3); + if (current_action == haScale) { + hm = handle_scale_3_mesh; + QVector mv; mv.resize(1); + QVector cv; cv.fill(QVector4D(1, 1, 0.5, 1), 1); + ids[0] = hmMaxScale; + fillHandleObjects(selection_center, ids, mv, cv, axis_mat, 1); + hm->loadObjects(r->view, cur_objects); + hm->loadSelections(r->view, sel); + hm->draw(r->view, 1); + } + } + } +} + + +void RendererService::drawLights() { + QGLView * v = r->view; + RendererSelection & rs(r->rend_selection); + + fillOmniObjects(); + omni_mesh->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, lights2objectList(v->scene_->lights_used.value(Light::Omni))); + omni_mesh->loadSelections(v, rs.cur_selections_); + omni_mesh->draw(v, cur_objects.size()); + + ObjectBaseList ll = lights2objectList(r->view->scene()->lights_used.value(Light::Cone)); + fillAimedObjects(ll, line_spot_f); + cone_mesh->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, ll); + cone_mesh->loadSelections(v, rs.cur_selections_); + cone_mesh->draw(v, cur_objects.size()); + box_mesh->loadObjects(v, cur_aims); + box_mesh->loadSelections(v, rs.cur_selections_); + box_mesh->draw(v, cur_aims.size()); + +} + + +void RendererService::drawLightsFrame(QColor color) { + QGLView * v = r->view; + RendererSelection & rs(r->rend_selection); + + fillOmniObjects(); + setObjectsColor(cur_objects, color); + omni_mesh_f->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, lights2objectList(v->scene_->lights_used.value(Light::Omni))); + omni_mesh_f->loadSelections(v, rs.cur_selections_); + omni_mesh_f->draw(v, cur_objects.size()); + + ObjectBaseList ll = lights2objectList(r->view->scene()->lights_used.value(Light::Cone)); + fillAimedObjects(ll, line_spot_f); + setObjectsColor(cur_objects, color); + cone_mesh_f->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, ll); + cone_mesh_f->loadSelections(v, rs.cur_selections_); + cone_mesh_f->draw(v, cur_objects.size()); + + setObjectsColor(cur_aims, color); + box_mesh_f->loadObjects(v, cur_aims); + box_mesh_f->loadSelections(v, rs.cur_selections_); + box_mesh_f->draw(v, cur_aims.size()); + +} + + +void RendererService::drawCameras() { + QGLView * v = r->view; + RendererSelection & rs(r->rend_selection); + + ObjectBaseList cl = cameras2objectList(r->view->scene()->cameras_used); + cl.removeOne(r->view->camera()); + fillAimedObjects(cl, line_camera_f); + camera_mesh->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, cl); + camera_mesh->loadSelections(v, rs.cur_selections_); + camera_mesh->draw(v, cur_objects.size()); + box_mesh->loadObjects(v, cur_aims); + box_mesh->loadSelections(v, rs.cur_selections_); + box_mesh->draw(v, cur_aims.size()); + +} + + +void RendererService::drawCamerasFrame(QColor color) { + QGLView * v = r->view; + RendererSelection & rs(r->rend_selection); + + ObjectBaseList cl = cameras2objectList(r->view->scene()->cameras_used); + cl.removeOne(r->view->camera()); + fillAimedObjects(cl, line_camera_f); + setObjectsColor(cur_objects, color); + camera_mesh_f->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, cl); + camera_mesh_f->loadSelections(v, rs.cur_selections_); + camera_mesh_f->draw(v, cur_objects.size()); + + setObjectsColor(cur_aims, color); + box_mesh_f->loadObjects(v, cur_aims); + box_mesh_f->loadSelections(v, rs.cur_selections_); + box_mesh_f->draw(v, cur_aims.size()); + +} + + +void RendererService::setObjectsColor(QVector & ol, QColor col) { + QVector4D cv = QColor2QVector(col); + for (int i = 0; i < ol.size(); ++i) + ol[i].color = cv; +} + + +void RendererService::renderService() { + QOpenGLShaderProgram * prog = 0; + QOpenGLExtraFunctions * f = r->view; + size_full_scale = tan(r->view->camera()->FOV() / 2. * deg2rad) * size_vp_scale; + v_mat = r->view->camera()->fullViewMatrix(); + f->glEnable(GL_MULTISAMPLE); + glEnableDepth(); + f->glClear(GL_DEPTH_BUFFER_BIT); + glDisable(GL_CULL_FACE); + if (r->bindShader(Renderer::srServiceFrame, &prog)) { + prog->setUniformValue("qgl_ProjMatrix", r->view->camera()->projectionMatrix(r->view->aspect)); + + /// lights + r->setUniformCamera(prog, r->view->camera()); + + prog->setUniformValue("line_width", 2.f); + prog->setUniformValue("z_offset", 0.f); + drawLightsFrame(Qt::white); + drawCamerasFrame(Qt::white); + prog->setUniformValue("line_width", 1.f); + prog->setUniformValue("z_offset", -1.E-2f); + drawLightsFrame(Qt::black); + drawCamerasFrame(Qt::black); + + } + if (r->bindShader(Renderer::srServiceLine, &prog)) { + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + r->setUniformCamera(prog, r->view->camera()); + line_object.color = QColor2QVector(Qt::white); + line_spot_f ->loadObject(f, line_object); + line_camera_f->loadObject(f, line_object); + line_spot_f ->draw(f, 1); + line_camera_f->draw(f, 1); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + glEnable(GL_CULL_FACE); + if (r->bindShader(Renderer::srServiceFill, &prog)) { + r->setUniformCamera(prog, r->view->camera()); + + /// handles + f->glEnable(GL_BLEND); + f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + drawCurrentHandleObjects(); + f->glDisable(GL_BLEND); + + /// axis + f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height()); + axis_camera->setPos(-r->view->camera()->direction() * 3.); + axis_camera->setAim(QVector3D()); + axis_camera->setRotation(r->view->camera()->rotation()); + r->setUniformCamera(prog, axis_camera, true, axis_viewport); + axis_mesh->draw(f, 3); + f->glViewport(0, 0, r->view->width(), r->view->height()); + + } + f->glDisable(GL_MULTISAMPLE); +} + + +Mesh * RendererService::currentHandleMesh() { + switch (current_action) { + case haMove : return handle_move_mesh; + case haRotate: return handle_rotate_mesh; + case haScale : return handle_scale_mesh; + default: break; + } + return 0; +} diff --git a/renderer_service.h b/renderer_service.h new file mode 100644 index 0000000..c0de71f --- /dev/null +++ b/renderer_service.h @@ -0,0 +1,108 @@ +/* + QGL RendererService + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef RENDERER_SERVICE_H +#define RENDERER_SERVICE_H + +#include "glframebuffer.h" +#include "glshaders_types.h" +#include + + +class RendererService { + friend class QGLView; + friend class MouseController; + friend class Renderer; + friend class RendererSelection; + +public: + RendererService(Renderer * r_); + virtual ~RendererService(); + + enum HandleAction { + haNoAction, + haMove, + haRotate, + haScale, + }; + + enum HandleMesh { + hmMoveX = 0x01, + hmMoveY = 0x02, + hmMoveZ = 0x04, + hmMoveXY = hmMoveX | hmMoveY, + hmMoveXZ = hmMoveX | hmMoveZ, + hmMoveYZ = hmMoveY | hmMoveZ, + hmMaxMove = hmMoveX | hmMoveY | hmMoveZ, + hmRotateX = 0x08, + hmRotateY = 0x10, + hmRotateZ = 0x20, + hmMaxRotate = hmRotateX | hmRotateY | hmRotateZ, + hmScaleX = 0x40, + hmScaleY = 0x80, + hmScaleZ = 0x100, + hmScaleXY = hmScaleX | hmScaleY, + hmScaleXZ = hmScaleX | hmScaleZ, + hmScaleYZ = hmScaleY | hmScaleZ, + hmMaxScale = hmScaleX | hmScaleY | hmScaleZ, + }; + + void init(int width, int height); + void resize(int width, int height); + + QMatrix4x4 invariantSizeMatrix(QVector3D p, double * ret_scale = 0); + QMatrix4x4 parentRotationMatrix(ObjectBase * o, bool self_rotation = true); + void fillXYZObjects(); + void fillOmniObjects(); + void fillAimedObjects(const ObjectBaseList & objects, Mesh * line_mesh); + void fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count = 3); + bool calculateCenter(); + void drawCurrentHandleObjects(); + void drawLights(); + void drawLightsFrame(QColor color); + void drawCameras(); + void drawCamerasFrame(QColor color); + void setObjectsColor(QVector & ol, QColor col); + void renderService(); + void setCurrentAction(HandleAction ha) {current_action = ha;} + Mesh * currentHandleMesh(); + +private: + Renderer * r; + + Mesh * axis_mesh, * handle_move_mesh, * handle_rotate_mesh, * handle_scale_mesh; + Mesh * handle_ms_2_mesh, * handle_scale_3_mesh; + Mesh * box_mesh_f, * omni_mesh_f, * cone_mesh_f, * camera_mesh_f; + Mesh * box_mesh, * omni_mesh, * cone_mesh, * camera_mesh; + Mesh * line_spot_f, * line_camera_f; + QMatrix4x4 v_mat, axis_mat; + QVector3D selection_center; + QVector mat_xyz, mat_ms2; + QVector color_xyz, color_ms2; + QVector cur_objects, cur_aims; + QGLEngineShaders::Object line_object; + Camera * axis_camera; + QSize axis_viewport; + HandleAction current_action; + QFlags current_handle; + int line_width; + double size_vp_scale, size_full_scale; + +}; + +#endif // RENDERER_SERVICE_H diff --git a/shaders.qrc b/shaders.qrc new file mode 100644 index 0000000..97e4492 --- /dev/null +++ b/shaders.qrc @@ -0,0 +1,19 @@ + + + shaders/ds_final.glsl + shaders/ds_geom.glsl + shaders/ds_light.glsl + shaders/ds_tonemap.glsl + shaders/fxaa.frag + shaders/fxaa.vert + shaders/fxaa_v3.h + shaders/selection.glsl + shaders/selection_apply.glsl + shaders/selection_frame.glsl + shaders/selection_halo.glsl + shaders/service_fill.glsl + shaders/service_frame.glsl + shaders/service_line.glsl + shaders/sum.glsl + + diff --git a/shaders/ds_final.glsl b/shaders/ds_final.glsl new file mode 100644 index 0000000..73aecb6 --- /dev/null +++ b/shaders/ds_final.glsl @@ -0,0 +1,22 @@ +// vert // + +void main(void) { + gl_Position = qgl_ftransform(); +} + + +// frag // + +uniform sampler2D tex_g1, tex_s_0, tex_s_1, tex_t_0, tex_t_1; + +void main(void) { + ivec2 tc = ivec2(gl_FragCoord.xy); + vec4 vs0 = texelFetch(tex_s_0, tc, 0); + vec4 vs1 = texelFetch(tex_s_1, tc, 0); + vec3 sr = vs0.rgb + vs1.rgb; + vec4 vt0 = texelFetch(tex_t_0, tc, 0); + vec4 vt1 = texelFetch(tex_t_1, tc, 0); + vec3 tr = vt0.rgb + vt1.rgb; + float alpha = (vt0.a + vt1.a) / 2; + qgl_FragColor.rgb = mix(sr, tr, alpha); +} diff --git a/shaders/ds_geom.glsl b/shaders/ds_geom.glsl new file mode 100644 index 0000000..617a6ee --- /dev/null +++ b/shaders/ds_geom.glsl @@ -0,0 +1,71 @@ +// vert // + +out vec3 geom_normal; +out mat3 TBN; +out vec4 object_color; + +void main(void) { + qgl_MaterialIndex = qgl_Material; + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); + + geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix()); + TBN = qgl_getTangentMatrix() * mat3(qgl_Tangent, qgl_Bitangent, qgl_Normal); + object_color = qgl_ObjectColor; +} + + +// frag // + +in vec3 geom_normal; +in mat3 TBN; +in vec4 object_color; + +uniform vec2 dt; +uniform float z_near; + +const vec3 luma = vec3(0.299, 0.587, 0.114); +const float _pe = 2.4e-7; + +void main(void) { + vec2 tc = qgl_FragTexture.xy; + + vec4 diffuse = qgl_materialTexture(QGL_MAP_DIFFUSE, tc, vec4(0)) * object_color; + diffuse.rgb *= qgl_material[qgl_MaterialIndex].color_diffuse.rgb; + diffuse.a *= (1.f - qgl_material[qgl_MaterialIndex].transparency); + + vec3 normal, dn; + dn = qgl_materialTexture(QGL_MAP_NORMAL, tc, -vec4(0.5, 0.5, 1., 0.)).xyz; + //dn.y = -dn.y; + float dn_sl = length(dn); + dn = TBN * dn; + dn *= dn_sl / (length(dn) + 1E-6); + normal = normalize(geom_normal + dn); + + float metalness = dot(qgl_materialTexture(QGL_MAP_METALNESS, tc, vec4(0)).rgb, luma); + metalness = clamp(metalness, 0, 1); + + float roughness = dot(qgl_materialTexture(QGL_MAP_ROUGHNESS, tc, vec4(0)).rgb, luma); + roughness = clamp(roughness, 0.0001, 0.9999); + + float reflectivity = clamp(qgl_material[qgl_MaterialIndex].reflectivity, 0., 1.); + + vec4 emission = qgl_materialTexture(QGL_MAP_EMISSION, tc, vec4(0)); + emission *= qgl_material[qgl_MaterialIndex].color_emission; + + float height = dot(qgl_materialTexture(QGL_MAP_RELIEF, tc, vec4(0)).rgb, luma); + + float z = gl_FragCoord.z; + z = z + z - 1; + z = ((_pe - 2.) * z_near) / (z + _pe - 1.); // infinite depth + + qgl_FragData[0] = vec4(diffuse .rgba); + qgl_FragData[1] = vec4(normal .xyz, z); + qgl_FragData[2] = vec4(metalness, roughness, reflectivity, 0); + qgl_FragData[3] = vec4(emission.rgb, 0/*bn.x*/); + //qgl_FragData[4] = vec4(speed.xy, bn.yz); + + //ivec2 itc = ivec2(gl_FragCoord.xy); + //qgl_FragData[0].rgb = vec3(dot(n,vec3(0,0,1))); + //qgl_FragData[0].rgb = diffuse.rgb * dot(n,vec3(0,0,1)); +} diff --git a/shaders/ds_light.glsl b/shaders/ds_light.glsl new file mode 100644 index 0000000..7f8c132 --- /dev/null +++ b/shaders/ds_light.glsl @@ -0,0 +1,181 @@ +// vert // + +out vec3 view_dir, world_dir; + +uniform vec4 view_corners[4], world_corners[4]; + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); + view_dir = view_corners [gl_VertexID].xyz; + world_dir = world_corners[gl_VertexID].xyz; +} + + +// frag // + +in vec3 view_dir, world_dir; + +uniform vec2 dt; +uniform float z_near; +uniform sampler2D tex_coeffs[2]; +uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4; +uniform samplerCube tex_env; +uniform int lights_start, lights_count; + +uniform vec4 fog_color = vec4(0.5, 0.5, 0.5, 1); +uniform float fog_decay = 10, fog_density = 0; +uniform mat3 view_mat; + +const vec3 luma = vec3(0.299, 0.587, 0.114); +const float _min_rough = 1.e-8, max_lod = 8; + +vec4 pos, lpos, shp; +vec3 li, si, ldir, halfV, bn, bn2, lwdir; +//vec3 vds, vds2; +float rough_diff, rough_spec, dist, NdotL, NdotH, spot, ldist, diff, spec, sdist, shadow; + +void calcLight(in int index, in vec3 n, in vec3 v) { + lpos = qgl_light_position[index].position; + ldir = lpos.xyz - (pos.xyz * lpos.w); + ldist = length(ldir); + ldir = normalize(ldir); + //ldir = vec3(0,0,1); + halfV = normalize(ldir + v); + NdotL = max(dot(n, ldir), 1E-8); + NdotH = max(dot(n, halfV), 1E-8); + spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w; +#ifdef SPOT + float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.); + spot *= scos * step(qgl_light_parameter[index].angles.w, scos); + spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos); + /*//lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz; + //bn = normalize(cross(lwdir, vec3(1, 0, 0))); + //bn2 = normalize(cross(lwdir, bn)); + float ds = ldist/200.;//max(abs(sdist) / 5000, 0.02); + //spot *= clamp(1. - sdist, 0, 1); + vds = ds * bn.xyz; + vds2 = ds * bn2.xyz; + float shadow = getShadow(index, pos.xyz, vec3(0)) * 3.; + shadow += getShadow(index, pos.xyz, vds ) * 2.; + shadow += getShadow(index, pos.xyz, - vds ) * 2.; + shadow += getShadow(index, pos.xyz, - vds2 ) * 2.; + shadow += getShadow(index, pos.xyz, + vds2 ) * 2.; + //shadow += getShadow(index, pos.xyz, vds - vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, vds + vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, - vds - vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, - vds + vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, vds + vds ); + //shadow += getShadow(index, pos.xyz, - vds - vds ); + //shadow += getShadow(index, pos.xyz, - vds2 - vds2); + //shadow += getShadow(index, pos.xyz, + vds2 + vds2); + //shadow += getShadow(index, pos.xyz, vds + vds - vds2 ); + //shadow += getShadow(index, pos.xyz, - vds - vds - vds2 ); + //shadow += getShadow(index, pos.xyz, vds + vds + vds2 ); + //shadow += getShadow(index, pos.xyz, - vds - vds + vds2 ); + //shadow += getShadow(index, pos.xyz, vds - vds2 - vds2); + //shadow += getShadow(index, pos.xyz, vds + vds2 + vds2); + //shadow += getShadow(index, pos.xyz, - vds - vds2 - vds2); + //shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2); + //shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10; + spot *= mix(1., shadow / 11., shadow_on);*/ +#endif + vec3 dist_decay = vec3(1, ldist, ldist*ldist); + spot /= dot(qgl_light_parameter[index].decay_intensity.xyz, dist_decay); + + float NdotLs = NdotL*NdotL; + float NdotHs = NdotH*NdotH; + + float ndlc = (1. - NdotLs) / NdotLs; + diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc)); + //diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r; + li += spot * diff * qgl_light_parameter[index].color.rgb; + + ndlc = (1. - NdotHs) / NdotHs; + float der = NdotHs * (rough_spec + ndlc); + spec = rough_spec / (der*der) / 3.1416; + //spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r; + si += spot * spec * qgl_light_parameter[index].color.rgb; +} + + + +float GeometrySchlickGGX(float NdotV, float roughness) { + float a = roughness; + float k = (a * a) / 2.0; + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + return ggx1 * ggx2; +} + + + +void main(void) { + ivec2 tc = ivec2(gl_FragCoord.xy); + vec4 v1 = texelFetch(tex_1, tc, 0); + float z = v1.w; + if (z == 1.) { + discard; + } + pos.w = 1; + pos.xyz = view_dir * z; + vec3 v = normalize(-pos.xyz); + + vec4 v0 = texelFetch(tex_0, tc, 0), + v2 = texelFetch(tex_2, tc, 0), + v3 = texelFetch(tex_3, tc, 0), + v4 = texelFetch(tex_4, tc, 0); + + vec3 diffuse = v0.rgb; + vec3 normal = v1.xyz; + vec3 emission = v3.rgb; + float alpha = v0.a; + float metalness = v2.r; + float roughness = v2.g; + float reflectivity = v2.b; + float NdotV = dot(normal, v); + float roughness3 = roughness*roughness*roughness; + //bn = normalize(vec3(v3.w, v4.zw)); + //bn2 = normalize(cross(n, bn)); + rough_diff = max(roughness, _min_rough); + rough_spec = max(roughness3, _min_rough); + float shlick = clamp(metalness + (1 - metalness) * pow(1 - NdotV, 5), 0, 1); + + li = vec3(0.);//qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity; + si = vec3(0.); + for (int i = 0; i < lights_count; ++i) + calcLight(lights_start + i, normal, v); + si *= shlick; + li *= (1 - shlick); + alpha = min(1, alpha * (1 + shlick)); + + vec2 brdf = texture(tex_coeffs[0], vec2(NdotV*0.99, roughness*0.995)).rg; + float env_spec = shlick * brdf.x + brdf.y; + vec3 spec_col = mix(vec3(1), diffuse, metalness); + vec3 env_dir = view_mat * reflect(-v, normal); + vec3 env_col = textureLod(tex_env, env_dir, sqrt(roughness) * max_lod).rgb * spec_col; + + vec3 res_col = max(vec3(0), li * diffuse + si * spec_col + emission); + res_col = mix(res_col, env_col, env_spec * reflectivity); + + float plen = length(pos.xyz); + float fog = 1 - exp(-plen / fog_decay); + fog = clamp(fog * fog_color.a * fog_density, 0, 1); + res_col = mix(res_col, fog_color.rgb, fog); + + qgl_FragColor = vec4(res_col, alpha); + + //vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y); + //qgl_FragColor.rgb = vec3(shlick * brdf.x + brdf.y); + //qgl_FragColor.rgb = vec3(alpha); + //qgl_FragColor.rgb = vec3(textureLod(tex_env, world_dir, 0).rgb); + //qgl_FragColor.a = 1.; +} diff --git a/shaders/ds_tonemap.glsl b/shaders/ds_tonemap.glsl new file mode 100644 index 0000000..b9b1f8a --- /dev/null +++ b/shaders/ds_tonemap.glsl @@ -0,0 +1,25 @@ +// vert // + +void main(void) { + gl_Position = qgl_ftransform(); +} + + +// frag // + +uniform sampler2D tex_0; +uniform float gamma, frame_max; + +const vec3 luma = vec3(0.299, 0.587, 0.114); + +void main(void) { + ivec2 tc = ivec2(gl_FragCoord.xy); + vec4 src = texelFetch(tex_0, tc, 0); + vec3 res = src.rgb; + float l = dot(res, luma) * 0.75; + float g = gamma / frame_max; + res /= l; + l = 1 - exp(-l*g); + res *= l; + qgl_FragColor = vec4(res, dot(res, luma)); +} diff --git a/shaders/fxaa.frag b/shaders/fxaa.frag new file mode 100644 index 0000000..5e93037 --- /dev/null +++ b/shaders/fxaa.frag @@ -0,0 +1,2223 @@ +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY__PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + //FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return dot(rgba.rgb, FxaaFloat3(0.299, 0.587, 0.114)); } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM dot(rgbyM.rgb, FxaaFloat3(0.299, 0.587, 0.114)) + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM dot(rgbyM.rgb, FxaaFloat3(0.299, 0.587, 0.114)) + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + //return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + return FxaaFloat4(FxaaTexTop(tex, posM)); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY__PRESET 10 +Or + #define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + + + + + + + + +in vec4 pos; + +uniform sampler2D tex0; +uniform vec2 dt; + +void main() { + qgl_FragColor = FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + pos.xy, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + vec4(0), + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + tex0, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + tex0, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + tex0, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + dt, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + vec4(0), + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + vec4(0), + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + vec4(0), + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + 0.75, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + 0.125, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + 0.0625, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + 0., + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + 0., + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + 0., + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + vec4(0)); +} diff --git a/shaders/fxaa.vert b/shaders/fxaa.vert new file mode 100644 index 0000000..02c3d70 --- /dev/null +++ b/shaders/fxaa.vert @@ -0,0 +1,11 @@ +out vec4 pos; + +const float FXAA_SUBPIX_SHIFT = 1. / 4.; +uniform vec2 dt; + +void main(void) { + qgl_FragTexture = qgl_Texture; + pos.xy = qgl_Texture.xy; + pos.zw = qgl_Texture.xy - (dt * (0.5 + FXAA_SUBPIX_SHIFT)); + gl_Position = qgl_ftransform(); +} diff --git a/shaders/fxaa_v3.h b/shaders/fxaa_v3.h new file mode 100644 index 0000000..633482e --- /dev/null +++ b/shaders/fxaa_v3.h @@ -0,0 +1,2048 @@ +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY__PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + //FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return dot(rgba.rgb, FxaaFloat3(0.299, 0.587, 0.114)); } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY__PRESET 10 +Or + #define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif \ No newline at end of file diff --git a/shaders/selection.glsl b/shaders/selection.glsl new file mode 100644 index 0000000..23909ca --- /dev/null +++ b/shaders/selection.glsl @@ -0,0 +1,19 @@ +// vert // + +flat out uint id, select; + +void main(void) { + id = qgl_ObjectID; + select = qgl_ObjectSelected; + gl_Position = qgl_ftransform(); +} + + +// frag // + +flat in uint id, select; + +void main(void) { + qgl_FragData[0] = unpackUnorm4x8(id); + qgl_FragData[1] = vec4(select); +} diff --git a/shaders/selection_apply.glsl b/shaders/selection_apply.glsl new file mode 100644 index 0000000..5029eba --- /dev/null +++ b/shaders/selection_apply.glsl @@ -0,0 +1,25 @@ +// vert // + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); +} + + +// frag // + +uniform sampler2D fb_out, fb_hover, fb_select; + +void main(void) { + ivec2 tc = ivec2(gl_FragCoord.xy); + vec2 stc = qgl_FragTexture.xy; + vec4 src = texelFetch(fb_out , tc, 0); + vec4 hov = texture(fb_hover , stc); + vec4 sel = texture(fb_select, stc); + src.rgb = clamp(src.rgb, vec3(0), vec3(1)); + src.rgb = mix(src.rgb, sel.rgb, sel.a); + src.rgb = mix(src.rgb, hov.rgb, hov.a * 0.667f); + //src.rgb = src.rgb + (sel.rgb*sel.a); + qgl_FragData[0] = src; + //qgl_FragData[0] = vec4(sel.a); +} diff --git a/shaders/selection_frame.glsl b/shaders/selection_frame.glsl new file mode 100644 index 0000000..e811faa --- /dev/null +++ b/shaders/selection_frame.glsl @@ -0,0 +1,24 @@ +// vert // + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); +} + + +// frag // + +uniform vec2 dt, size; +uniform float thickness; + +void main(void) { + vec2 frame_size = size / dt; + vec2 pix_pos = qgl_FragTexture * frame_size; + vec2 frame = vec2(1) + step(pix_pos, vec2(thickness)) - step(pix_pos, frame_size - vec2(thickness)); + vec2 line = frame * step(0.5, fract(pix_pos.yx / thickness / 4.)); + float fc = max(frame.x, frame.y); + float fl = max(line.x , line.y ); + fl = mix(1, fl, fc); + qgl_FragColor = vec4(vec3(fl), fc * 0.8 + 0.2); + //qgl_FragColor = vec4(vec3(fl,0),1); +} diff --git a/shaders/selection_halo.glsl b/shaders/selection_halo.glsl new file mode 100644 index 0000000..f62f74f --- /dev/null +++ b/shaders/selection_halo.glsl @@ -0,0 +1,42 @@ +// vert // + +void main(void) { + gl_Position = qgl_ftransform(); +} + + +// frag // + +uniform sampler2D fb_hover, fb_selection; +uniform vec4 hover_id, hover_color, selection_color; +uniform float hover_fill, selection_fill, has_hover, has_selection; +ivec2 tc; + +vec4 diffVector(in sampler2D map, in vec4 id) { + vec4 ds0 = abs(texelFetchOffset(map, tc, 0, ivec2(-1, 0)) - id); + vec4 ds1 = abs(texelFetchOffset(map, tc, 0, ivec2( 1, 0)) - id); + vec4 ds2 = abs(texelFetchOffset(map, tc, 0, ivec2(0, -1)) - id); + vec4 ds3 = abs(texelFetchOffset(map, tc, 0, ivec2(0, 1)) - id); + return vec4(dot(ds0, vec4(1)), dot(ds1, vec4(1)), dot(ds2, vec4(1)), dot(ds3, vec4(1))); +} +vec2 diffPair(in vec4 dv) { + const float _c = 64; + return vec2(step(1e-6, dot(dv, vec4(1))), + step(1e-3, (dv.r * _c) * (dv.g * _c) * (dv.b * _c) * (dv.a * _c))); +} +float diffAlpha(in vec2 dp, in float fill) { + return mix(dp.x - dp.y, dp.x - dp.y - dp.y + 1, fill); +} + +void main(void) { + tc = ivec2(gl_FragCoord.xy); + float hh = clamp(dot(hover_id, vec4(1)), 0, 1); + + vec2 dp = diffPair(diffVector(fb_hover, hover_id)); + float v = diffAlpha(dp, hover_fill); + qgl_FragData[0] = has_hover*hh*v*vec4(hover_color.rgb, hover_color.a); + + dp = diffPair(diffVector(fb_selection, vec4(1))); + v = diffAlpha(dp, selection_fill); + qgl_FragData[1] = has_selection*v*vec4(selection_color.rgb, selection_color.a); +} diff --git a/shaders/service_fill.glsl b/shaders/service_fill.glsl new file mode 100644 index 0000000..bc1cc8f --- /dev/null +++ b/shaders/service_fill.glsl @@ -0,0 +1,24 @@ +// vert // + +out vec3 geom_normal; +out vec4 object_color; + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); + + geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix()); + object_color = qgl_ObjectColor; +} + + +// frag // + +in vec3 geom_normal; +in vec4 object_color; + +void main(void) { + vec3 normal = normalize(geom_normal); + float l = max(0, dot(normal, vec3(0,0,1))); + qgl_FragColor = object_color * (l * 0.6 + 0.4); +} diff --git a/shaders/service_frame.glsl b/shaders/service_frame.glsl new file mode 100644 index 0000000..65189c1 --- /dev/null +++ b/shaders/service_frame.glsl @@ -0,0 +1,51 @@ +// vert // + +out vec4 object_color_g; +out float mat_scale; + +void main(void) { + gl_Position = qgl_ftransform(); + object_color_g = qgl_ObjectColor; + //mat_scale = pow(qgl_ModelMatrix[0][0] * qgl_ModelMatrix[1][1] * qgl_ModelMatrix[2][2], 0.3333); + mat_scale = pow(determinant(mat3(qgl_ModelMatrix)), 0.333); + //mat3 mm = transpose(mat3(qgl_ModelMatrix)); + //mat_scale = min(min(dot(vec3(1), mm[0]), dot(vec3(1), mm[1])), dot(vec3(1), mm[2])); +} + + +// geom // + +layout (lines) in; +layout (triangle_strip, max_vertices = 4) out; + +in float mat_scale[]; +in vec4 object_color_g[]; +out vec4 object_color; + +uniform float line_width, z_offset; +uniform mat4 qgl_ProjMatrix; + +void main(void) { + object_color = object_color_g[0]; + vec2 dir = normalize(gl_in[0].gl_Position.xy - gl_in[1].gl_Position.xy); + vec2 side = cross(vec3(dir, 0), vec3(0, 0, 1)).xy; + vec4 vo = vec4(0, 0, z_offset, 0); + float dts = 0.05 * line_width * mat_scale[0]; + dir *= dts; + side *= dts; + gl_Position = gl_in[0].gl_Position + vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); + gl_Position = gl_in[0].gl_Position + vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); + gl_Position = gl_in[1].gl_Position - vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); + gl_Position = gl_in[1].gl_Position - vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); + EndPrimitive(); +} + + +// frag // + +in vec4 object_color; +uniform float scale; + +void main(void) { + qgl_FragColor = object_color; +} diff --git a/shaders/service_line.glsl b/shaders/service_line.glsl new file mode 100644 index 0000000..2cfec5d --- /dev/null +++ b/shaders/service_line.glsl @@ -0,0 +1,17 @@ +// vert // + +out vec4 object_color; + +void main(void) { + gl_Position = qgl_ftransform(); + object_color = qgl_ObjectColor; +} + + +// frag // + +in vec4 object_color; + +void main(void) { + qgl_FragColor = object_color; +} diff --git a/shaders/sum.glsl b/shaders/sum.glsl new file mode 100644 index 0000000..e12fd95 --- /dev/null +++ b/shaders/sum.glsl @@ -0,0 +1,25 @@ +// vert // + +layout(location = 1) in ivec2 qgl_Vertex; + +flat out vec4 color; + +uniform sampler2D tex; + +void main(void) { + color = texelFetch(tex, qgl_Vertex, 0); + gl_Position = vec4(0,0,0,1); +} + + +// frag // + +out vec4 qgl_FragData[gl_MaxDrawBuffers]; + +flat in vec4 color; + +uniform float pcnt; + +void main(void) { + qgl_FragData[0] = color;// / pcnt; +} diff --git a/tonemapping_proc.cpp b/tonemapping_proc.cpp new file mode 100644 index 0000000..b12b67c --- /dev/null +++ b/tonemapping_proc.cpp @@ -0,0 +1,186 @@ +/* + QGL TonemappingProc + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#define GL_GLEXT_PROTOTYPES +#include +#include "tonemapping_proc.h" +#include "qglview.h" +#include + +using namespace QGLEngineShaders; + + +TonemappingProc::TonemappingProc(Renderer * rend): QThread(), r(rend), + fbo_1x1(r->view, 1, false, GL_RGB32F), + fbomm(r->fbo_out, Renderer::obrSum, 3), + buffer_vbo(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW) { + shader_sum = 0; + timer_delim = 0; + frame_max = cur_max = 1.; + need_render_sum = exit_ = false; + enabled = false; + timer_tone = startTimer(10); +} + + +TonemappingProc::~TonemappingProc() { + exit_ = true; + if (!wait(1000)) + terminate(); + killTimer(timer_tone); + if (shader_sum) delete shader_sum; +} + + +void TonemappingProc::init() { + QOpenGLExtraFunctions * f = r->view; + buffer_vbo.init(f); + f->glGenVertexArrays(1, &vbo_vao); + f->glBindVertexArray(vbo_vao); + buffer_vbo.bind(f); + f->glEnableVertexAttribArray(1); + f->glVertexAttribIPointer(1, 2, GL_UNSIGNED_INT, 0, 0); + buffer_vbo.release(f); + f->glBindVertexArray(0); + fbomm.lastPlane().enablePixelBuffer(); + fbo_1x1.resize(1, 1); + resize(); + if (!isRunning()) start(); +} + + +void TonemappingProc::resize() { + QOpenGLExtraFunctions * f = r->view; + fbomm.resize(); + int pcnt = fbomm.width(fbomm.lastLevel()) * fbomm.height(fbomm.lastLevel()); + QVector _data; + _data.resize(pcnt); + pcnt = -1; + for (int x = 0; x < fbomm.width(fbomm.lastLevel()); ++x) + for (int y = 0; y < fbomm.height(fbomm.lastLevel()); ++y) + _data[++pcnt] = Vector2i(x,y); + buffer_vbo.bind(f); + buffer_vbo.resize(f, _data.size() * sizeof(Vector2i)); + buffer_vbo.load(f, _data.constData(), _data.size() * sizeof(Vector2i)); +} + + +void TonemappingProc::timerEvent(QTimerEvent * e) { + if (!fbo_1x1.isInit() || !enabled) return; + if (timer_delim == 0) + need_render_sum = true; + timer_delim = (timer_delim + 1) % 10; + mutex.lock(); + float fmax = frame_max; + mutex.unlock(); + float dt = 0.01f, a = dt * 5.f, b = 1.f - a; + cur_max = fmax * a + cur_max * b; +} + + +void TonemappingProc::renderSum(Framebuffer & fbo_src, int index) { + QOpenGLExtraFunctions * f = r->view; + int pcnt = fbo_src.width() * fbo_src.height(); + fbo_src.bindColorTexture(index); + fbo_1x1.bind(); + //glClearFramebuffer(Qt::white, false); + glClearFramebuffer(); + if (shader_sum) { + if (shader_sum->isLinked()) { + if (shader_sum->bind()) { + shader_sum->setUniformValue("tex", 0); + shader_sum->setUniformValue("pcnt", float(pcnt)); + f->glBindVertexArray(vbo_vao); + f->glEnable(GL_BLEND); + f->glBlendFunc(GL_ONE, GL_ONE); + f->glBlendEquation(GL_MAX); + f->glDrawArrays(GL_POINTS, 0, pcnt); + f->glBlendEquation(GL_FUNC_ADD); + f->glDisable(GL_BLEND); + f->glBindVertexArray(0); + } + } + } + fbo_1x1.release(); + //fbo_src.bind(); +} + + +void TonemappingProc::run() { + while (!exit_) { + if (!enabled) { + msleep(100); + continue; + } + mutex.lock(); + if (last_data.isEmpty()) { + mutex.unlock(); + msleep(10); + continue; + } + QVector data = last_data; + last_data.clear(); + mutex.unlock(); + float max = calcHistogram(data); + last_max << max; + if (last_max.size() > 5) + last_max.removeAt(0); + float cm = last_max[0]; + for (int i = 1; i < last_max.size(); ++i) + cm += last_max[i]; + cm /= last_max.size(); + mutex.lock(); + frame_max = cm; + mutex.unlock(); + } +} + + +float TonemappingProc::calcHistogram(const QVector & data) { + if (data.isEmpty()) return 1.f; + float max = 0.; + QVector3D luma(0.299, 0.587, 0.114); + foreach (const QVector4D & p, data) { + float l = QVector3D::dotProduct(p.toVector3D(), luma); + max = qMax(max, l); + } + return max; +} + + +bool TonemappingProc::process() { + if (!need_render_sum || !enabled) return false; + need_render_sum = false; + Framebuffer & fbo(fbomm.lastPlane()); + if (fbo.queriedPoints() > 0) { + QVector data = fbo.getPointsFloat(); + mutex.lock(); + last_data = data; + mutex.unlock(); + } + fbomm.create(); + fbo.queryPoints(0, fbo.rect(), GL_FLOAT); + //renderSum(fbomm.plane(fbomm.lastLevel()), 0); + return true; +} + + +float TonemappingProc::frameMax() { + if (!enabled) return 1.f; + return cur_max; +} diff --git a/tonemapping_proc.h b/tonemapping_proc.h new file mode 100644 index 0000000..b6f99d5 --- /dev/null +++ b/tonemapping_proc.h @@ -0,0 +1,66 @@ +/* + QGL TonemappingProc + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef TONEMAPPING_PROC_H +#define TONEMAPPING_PROC_H + +#include "glframebuffer_mipmap.h" +#include + + +class TonemappingProc: public QThread +{ + friend class Renderer; + friend class QGLView; +public: + TonemappingProc(Renderer * rend); + virtual ~TonemappingProc(); + + void init(); + void resize(); + void prepareSum(); + void renderSum(Framebuffer & fbo_src, int index); + + bool process(); + float frameMax(); + +protected: + void timerEvent(QTimerEvent * e); + void run() override; + float calcHistogram(const QVector & data); + +private: + Renderer * r; + QMutex mutex; + QVector last_data; + QVector last_max; + + float frame_max, cur_max; + bool need_render_sum, enabled; + std::atomic_bool exit_; + int timer_tone, timer_delim; + Framebuffer fbo_1x1; + FramebufferMipmap fbomm; + + QOpenGLShaderProgram * shader_sum; + Buffer buffer_vbo; + GLenum vbo_vao; + +}; + +#endif // RENDERER_H diff --git a/widgets/CMakeLists.txt b/widgets/CMakeLists.txt new file mode 100644 index 0000000..8055180 --- /dev/null +++ b/widgets/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.0) +project(qglengine_widgets) +if (POLICY CMP0017) + cmake_policy(SET CMP0017 NEW) +endif() +find_qt(Qt5 Core Gui Widgets) +qt_sources(SRC) +qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM) +file(GLOB PHS "*_p.h") +list(REMOVE_ITEM out_HDR "${PHS}") +import_version(${PROJECT_NAME} qglengine) +set_deploy_property(${PROJECT_NAME} SHARED + LABEL "QGLEngine widgets library" + FULLNAME "${_DOMAIN}.${PROJECT_NAME}" + COMPANY "${_COMPANY}" + INFO "QGLEngine widgets library") +make_rc(${PROJECT_NAME} _RC) +qt_add_library(${PROJECT_NAME} SHARED out_CPP ${_RC}) +qt_generate_export_header(${PROJECT_NAME}) +list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h") +qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets qglengine_core) +qt_target_include_directories(${PROJECT_NAME} PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/../" "${CMAKE_CURRENT_SOURCE_DIR}/../core") +list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME}) +copy_to_parent("") +#message(STATUS "Building ${PROJECT_NAME}") +sdk_install("qglengine" FALSE "${PROJECT_NAME}" "${out_HDR}" "${out_QM}") diff --git a/widgets/material_editor.cpp b/widgets/material_editor.cpp new file mode 100644 index 0000000..e6636fe --- /dev/null +++ b/widgets/material_editor.cpp @@ -0,0 +1,237 @@ +/* + QGL MaterialEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "material_editor.h" +#include "ui_material_editor.h" +#include "glmaterial.h" + + +MaterialEditor::MaterialEditor(QWidget * parent): QWidget(parent) { + ui = new Ui::MaterialEditor(); + ui->setupUi(this); + ui->mapDiffuse ->configure(tr("Diffuse"), true); + ui->mapNormal ->configure(tr("Normal")); + ui->mapMetalness->configure(tr("Metalness")); + ui->mapRoughness->configure(tr("Roughness")); + ui->mapEmission ->configure(tr("Emission"), true); + ui->mapRelief ->configure(tr("Relief")); + ui->checkGlass->hide(); + ui->frameReflection->hide(); + ui->label_13->hide(); + mat = 0; + active = true; + ignore_next = 0; +} + + +void MaterialEditor::changeEvent(QEvent * e) { + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +void MaterialEditor::materialChanged() { + if (!active || !mat) return; + ignore_next = 2; + mat->_changed = true; + mat->color_diffuse = ui->mapDiffuse ->color(); + mat->color_emission = ui->mapEmission->color(); + mat->transparency = ui->spinTransparent->value(); + mat->reflectivity = ui->spinReflect->value(); + mat->iof = ui->spinIOF->value(); + mat->dispersion = ui->spinDispersion->value(); + mat->glass = ui->checkGlass->isChecked(); + //emit changed(); +} + + +void MaterialEditor::setMaterial(Material * m) { + if (ignore_next > 0) { + //ignore_next = false; + return; + } + active = false; + mat = m; + setEnabled(m); + if (!mat) return; + ui->mapDiffuse ->setColor(mat->color_diffuse ); + ui->mapEmission->setColor(mat->color_emission); + ui->spinTransparent->setValue(mat->transparency); + ui->spinReflect->setValue(mat->reflectivity); + ui->spinIOF->setValue(mat->iof); + ui->spinDispersion->setValue(mat->dispersion); + ui->checkGlass->setChecked(mat->glass); + ui->mapDiffuse ->setMap(&(mat->map_diffuse )); + ui->mapNormal ->setMap(&(mat->map_normal )); + ui->mapMetalness->setMap(&(mat->map_metalness)); + ui->mapRoughness->setMap(&(mat->map_roughness)); + ui->mapEmission ->setMap(&(mat->map_emission )); + ui->mapRelief ->setMap(&(mat->map_relief )); + /*ui->lineReflFront->setProperty("GLpath", mat->map_reflection.path(0)); ui->lineReflFront->setText(QFileInfo(mat->map_reflection.path(0)).fileName()); + ui->lineReflBack->setProperty("GLpath", mat->map_reflection.path(1)); ui->lineReflBack->setText(QFileInfo(mat->map_reflection.path(1)).fileName()); + ui->lineReflLeft->setProperty("GLpath", mat->map_reflection.path(2)); ui->lineReflLeft->setText(QFileInfo(mat->map_reflection.path(2)).fileName()); + ui->lineReflRight->setProperty("GLpath", mat->map_reflection.path(3)); ui->lineReflRight->setText(QFileInfo(mat->map_reflection.path(3)).fileName()); + ui->lineReflTop->setProperty("GLpath", mat->map_reflection.path(4)); ui->lineReflTop->setText(QFileInfo(mat->map_reflection.path(4)).fileName()); + ui->lineReflBottom->setProperty("GLpath", mat->map_reflection.path(5)); ui->lineReflBottom->setText(QFileInfo(mat->map_reflection.path(5)).fileName()); + */active = true; +} + +/* +Material MaterialEditor::material() { + Material m; + mat->color_diffuse = ui->colorDiffuse ->color(); + mat->color_specular = ui->colorSpecular->color(); + mat->color_emission = ui->colorEmission->color(); + mat->transparency = ui->spinTransparent->value(); + mat->reflectivity = ui->spinReflect->value(); + mat->iof = ui->spinIOF->value(); + mat->dispersion = ui->spinDispersion->value(); + mat->glass = ui->checkGlass->isChecked(); + mat->map_diffuse = ui->mapDiffuse->map(); + mat->map_normal = ui->mapNormal->map(); + mat->map_specular = ui->mapSpecular->map(); + mat->map_roughness = ui->mapRoughness->map(); + mat->map_emission = ui->mapEmission->map(); + mat->map_relief = ui->mapRelief->map(); + mat->map_reflection.setPath(0, ui->lineReflFront->property("GLpath").toString()); + mat->map_reflection.setPath(1, ui->lineReflBack->property("GLpath").toString()); + mat->map_reflection.setPath(2, ui->lineReflLeft->property("GLpath").toString()); + mat->map_reflection.setPath(3, ui->lineReflRight->property("GLpath").toString()); + mat->map_reflection.setPath(4, ui->lineReflTop->property("GLpath").toString()); + mat->map_reflection.setPath(5, ui->lineReflBottom->property("GLpath").toString()); + return m; +} +*/ + +void MaterialEditor::on_buttonReflFrontSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflFront->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->lineReflFront->setProperty("GLpath", str); + ui->lineReflFront->setText(QFileInfo(str).fileName()); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflBackSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflBack->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->lineReflBack->setProperty("GLpath", str); + ui->lineReflBack->setText(QFileInfo(str).fileName()); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflLeftSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflLeft->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->lineReflLeft->setProperty("GLpath", str); + ui->lineReflLeft->setText(QFileInfo(str).fileName()); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflRightSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflRight->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->lineReflRight->setProperty("GLpath", str); + ui->lineReflRight->setText(QFileInfo(str).fileName()); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflTopSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflTop->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->lineReflTop->setProperty("GLpath", str); + ui->lineReflTop->setText(QFileInfo(str).fileName()); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflBottomSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflBottom->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->lineReflBottom->setProperty("GLpath", str); + ui->lineReflBottom->setText(QFileInfo(str).fileName()); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflFrontClear_clicked() { + ui->lineReflFront->setText(""); + ui->lineReflFront->setProperty("GLpath", ""); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflBackClear_clicked() { + ui->lineReflBack->setText(""); + ui->lineReflBack->setProperty("GLpath", ""); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflLeftClear_clicked() { + ui->lineReflLeft->setText(""); + ui->lineReflLeft->setProperty("GLpath", ""); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflRightClear_clicked() { + ui->lineReflRight->setText(""); + ui->lineReflRight->setProperty("GLpath", ""); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflTopClear_clicked() { + ui->lineReflTop->setText(""); + ui->lineReflTop->setProperty("GLpath", ""); + materialChanged(); +} + + +void MaterialEditor::on_buttonReflBottomClear_clicked() { + ui->lineReflBottom->setText(""); + ui->lineReflBottom->setProperty("GLpath", ""); + materialChanged(); +} + + +void MaterialEditor::on_buttonLoadCubeDir_clicked() { + QString dir = QFileDialog::getExistingDirectory(this, "Select directory", ui->lineReflFront->property("GLpath").toString()); + if (dir.isEmpty()) return; + /*CubeTexture cb(0); + cb.loadPathesFromDirectory(dir); + active = false; + ui->lineReflFront->setProperty("GLpath", cb.path(0)); ui->lineReflFront->setText(QFileInfo(cb.path(0)).fileName()); + ui->lineReflBack->setProperty("GLpath", cb.path(1)); ui->lineReflBack->setText(QFileInfo(cb.path(1)).fileName()); + ui->lineReflLeft->setProperty("GLpath", cb.path(2)); ui->lineReflLeft->setText(QFileInfo(cb.path(2)).fileName()); + ui->lineReflRight->setProperty("GLpath", cb.path(3)); ui->lineReflRight->setText(QFileInfo(cb.path(3)).fileName()); + ui->lineReflTop->setProperty("GLpath", cb.path(4)); ui->lineReflTop->setText(QFileInfo(cb.path(4)).fileName()); + ui->lineReflBottom->setProperty("GLpath", cb.path(5)); ui->lineReflBottom->setText(QFileInfo(cb.path(5)).fileName());*/ + active = true; + materialChanged(); +} diff --git a/widgets/material_editor.h b/widgets/material_editor.h new file mode 100644 index 0000000..16bc29d --- /dev/null +++ b/widgets/material_editor.h @@ -0,0 +1,67 @@ +/* + QGL MaterialEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef MATERIAL_EDITOR_H +#define MATERIAL_EDITOR_H + +#include +#include "gltypes.h" + +namespace Ui { + class MaterialEditor; +} + +class MaterialEditor: public QWidget +{ + friend class MaterialsEditor; + Q_OBJECT +public: + explicit MaterialEditor(QWidget * parent = 0); + + void setMaterial(Material * m); + +protected: + void changeEvent(QEvent * e); + + bool active; + int ignore_next; + Ui::MaterialEditor * ui; + Material * mat; + +private slots: + void materialChanged(); + void on_buttonReflFrontSelect_clicked(); + void on_buttonReflFrontClear_clicked(); + void on_buttonReflBackSelect_clicked(); + void on_buttonReflBackClear_clicked(); + void on_buttonReflLeftSelect_clicked(); + void on_buttonReflLeftClear_clicked(); + void on_buttonReflRightSelect_clicked(); + void on_buttonReflRightClear_clicked(); + void on_buttonReflTopSelect_clicked(); + void on_buttonReflTopClear_clicked(); + void on_buttonReflBottomSelect_clicked(); + void on_buttonReflBottomClear_clicked(); + void on_buttonLoadCubeDir_clicked(); + +signals: + void changed(); + +}; + +#endif // MATERIAL_EDITOR_H diff --git a/widgets/material_editor.ui b/widgets/material_editor.ui new file mode 100644 index 0000000..307d6a7 --- /dev/null +++ b/widgets/material_editor.ui @@ -0,0 +1,637 @@ + + + MaterialEditor + + + + 0 + 0 + 435 + 535 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + font:normal; + + + + + + + Qt::Horizontal + + + + + + + font:normal; + + + + + + + Qt::Horizontal + + + + + + + font:normal; + + + + + + + Qt::Horizontal + + + + + + + font:normal; + + + + + + + Qt::Horizontal + + + + + + + font:normal; + + + + + + + Qt::Horizontal + + + + + + + font:normal; + + + + + + + Qt::Horizontal + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Glass + + + + + + + Transparency + + + + + + + 1.000000000000000 + + + 2 + + + 0.010000000000000 + + + 0.100000000000000 + + + + + + + Reflectivity + + + + + + + 1.000000000000000 + + + 2 + + + 0.010000000000000 + + + 0.100000000000000 + + + + + + + IOF + + + + + + + 2.000000000000000 + + + 1.000000000000000 + + + 2 + + + 0.010000000000000 + + + 0.100000000000000 + + + + + + + Dispersion + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + 2 + + + 0.010000000000000 + + + 0.100000000000000 + + + + + + + Reflection map + + + + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + Front: + + + + + + + Back: + + + + + + + Left: + + + + + + + Right: + + + + + + + Top: + + + + + + + Bottom: + + + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + load from directory + + + + + + + + + + + + + SpinSlider + QWidget +
    spinslider.h
    +
    + + MaterialMapEditor + QWidget +
    material_map_editor.h
    + 1 + + changed() + +
    +
    + + + + spinTransparent + valueChanged(double) + MaterialEditor + materialChanged() + + + 433 + 468 + + + 283 + 149 + + + + + spinReflect + valueChanged(double) + MaterialEditor + materialChanged() + + + 433 + 497 + + + 284 + 174 + + + + + spinIOF + valueChanged(double) + MaterialEditor + materialChanged() + + + 433 + 526 + + + 284 + 236 + + + + + checkGlass + toggled(bool) + MaterialEditor + materialChanged() + + + 433 + 439 + + + 284 + 84 + + + + + spinDispersion + valueChanged(double) + MaterialEditor + materialChanged() + + + 433 + 555 + + + 326 + 288 + + + + + mapDiffuse + changed() + MaterialEditor + materialChanged() + + + 421 + 69 + + + 434 + 63 + + + + + mapMetalness + changed() + MaterialEditor + materialChanged() + + + 421 + 189 + + + 434 + 143 + + + + + mapEmission + changed() + MaterialEditor + materialChanged() + + + 421 + 338 + + + 434 + 216 + + + + + mapNormal + changed() + MaterialEditor + materialChanged() + + + 421 + 129 + + + 434 + 260 + + + + + mapRelief + changed() + MaterialEditor + materialChanged() + + + 421 + 398 + + + 434 + 304 + + + + + mapRoughness + changed() + MaterialEditor + materialChanged() + + + 421 + 249 + + + 434 + 250 + + + + + + materialChanged() + +
    diff --git a/widgets/material_map_editor.cpp b/widgets/material_map_editor.cpp new file mode 100644 index 0000000..3768d82 --- /dev/null +++ b/widgets/material_map_editor.cpp @@ -0,0 +1,150 @@ +/* + QGL MaterialMapEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "material_map_editor.h" +#include "ui_material_map_editor.h" +#include "gltexture_manager.h" +#include "glmaterial.h" + + +MaterialMapEditor::MaterialMapEditor(QWidget * parent): QWidget(parent) { + ui = new Ui::MaterialMapEditor(); + ui->setupUi(this); + ui->widgetMap->hide(); + active = true; +} + + +void MaterialMapEditor::changeEvent(QEvent * e) { + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +void MaterialMapEditor::resizeEvent(QResizeEvent * e) { + QSize sz = preferredIconSize(6, this); + ui->iconedLabel->setFixedSize(sz); + ui->iconedLabel->setIconSize(sz); +} + + +void MaterialMapEditor::updateIcon() { + ui->iconedLabel->setIcon(QIcon(TextureManager::findFile(ui->linePath->property("GLpath").toString()))); +} + + +void MaterialMapEditor::mapChanged() { + if (!active || !map) return; + active = false; + map->use_bitmap = ui->checkMap->isChecked(); + if (ui->checkMap->isChecked()) { + map->color_amount = ui->sliderAmount->value(); + map->color_offset = ui->sliderOffset->value(); + } else { + map->color_amount = ui->sliderValue->value(); + map->color_offset = 0.f; + } + map->bitmap_scale.setX(ui->spinScaleX->value()); + map->bitmap_scale.setY(ui->spinScaleY->value()); + active = true; + emit changed(); +} + + +void MaterialMapEditor::setMap(Map * m) { + active = false; + map = m; + setEnabled(m); + if (!map) return; + ui->stackedWidget->setCurrentIndex(map->use_bitmap ? 1 : 0); + ui->checkMap->setChecked(map->use_bitmap); + ui->sliderValue->setValue(map->color_amount); + ui->sliderAmount->setValue(map->color_amount); + ui->sliderOffset->setValue(map->color_offset); + ui->spinScaleX->setValue(map->bitmap_scale.x()); + ui->spinScaleY->setValue(map->bitmap_scale.y()); + ui->linePath->setProperty("GLpath", map->bitmap_path); ui->linePath->setText(QFileInfo(map->bitmap_path).fileName()); + updateIcon(); + active = true; +} + + +void MaterialMapEditor::configure(QString title, bool has_color) { + ui->labelTitle->setText(title); + ui->colorButton->setVisible(has_color); +} + + +void MaterialMapEditor::setColor(QColor c) { + active = false; + ui->colorButton->setColor(c); + active = true; +} + + +QColor MaterialMapEditor::color() const { + return ui->colorButton->color(); +} + +/* +Map MaterialMapEditor::map() { + Map m; + map->color_amount = ui->sliderAmount->value(); + map->color_offset = ui->sliderOffset->value(); + map->bitmap_scale.setX(ui->spinScaleX->value()); + map->bitmap_scale.setY(ui->spinScaleY->value()); + map->bitmap_path = ui->linePath->property("GLpath").toString(); + return m; +} +*/ + +void MaterialMapEditor::on_buttonSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->linePath->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->linePath->setProperty("GLpath", str); + ui->linePath->setText(QFileInfo(str).fileName()); + map->setBitmapPath(str); + updateIcon(); + mapChanged(); +} + + +void MaterialMapEditor::on_buttonClear_clicked() { + ui->linePath->setText(""); + ui->linePath->setProperty("GLpath", ""); + map->clearBitmap(); + updateIcon(); + mapChanged(); +} + + +void MaterialMapEditor::on_checkMap_toggled(bool checked) { + if (checked) { + ui->sliderAmount->setValue(ui->sliderValue->value()); + resizeEvent(0); + } else + ui->sliderValue->setValue(ui->sliderAmount->value()); + ui->stackedWidget->setCurrentIndex(checked ? 1 : 0); + mapChanged(); +} diff --git a/widgets/material_map_editor.h b/widgets/material_map_editor.h new file mode 100644 index 0000000..8175247 --- /dev/null +++ b/widgets/material_map_editor.h @@ -0,0 +1,60 @@ +/* + QGL MaterialMapEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef MATERIAL_MAP_EDITOR_H +#define MATERIAL_MAP_EDITOR_H + +#include +#include "gltypes.h" + +namespace Ui { + class MaterialMapEditor; +} + +class MaterialMapEditor: public QWidget +{ + Q_OBJECT +public: + explicit MaterialMapEditor(QWidget * parent = 0); + + void setMap(Map * m); + void configure(QString title, bool has_color = false); + void setColor(QColor c); + QColor color() const; + +protected: + void changeEvent(QEvent * e); + void resizeEvent(QResizeEvent * e); + void updateIcon(); + + bool active; + Ui::MaterialMapEditor * ui; + Map * map; + +private slots: + void mapChanged(); + void on_buttonSelect_clicked(); + void on_buttonClear_clicked(); + void on_checkMap_toggled(bool checked); + +signals: + void changed(); + +}; + +#endif // MATERIAL_MAP_EDITOR_H diff --git a/widgets/material_map_editor.ui b/widgets/material_map_editor.ui new file mode 100644 index 0000000..33ca383 --- /dev/null +++ b/widgets/material_map_editor.ui @@ -0,0 +1,506 @@ + + + MaterialMapEditor + + + + 0 + 0 + 725 + 218 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + font: bold; + + + title: + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + 2 + + + 0.050000000000000 + + + 0.200000000000000 + + + 0.000000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + 0 + 0 + + + + Map + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + IconedLabel::RightToLeft + + + + + + + + + 2 + + + + + + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + + :/icons/document-open.png:/icons/document-open.png + + + + + + + + + Amount: + + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + 2 + + + 0.050000000000000 + + + 0.200000000000000 + + + -99.000000000000000 + + + 99.000000000000000 + + + + + + + Offset: + + + + + + + -1.000000000000000 + + + 1.000000000000000 + + + 2 + + + 0.050000000000000 + + + 0.200000000000000 + + + -99.000000000000000 + + + 99.000000000000000 + + + + + + + + + + 0 + 0 + + + + Scale X: + + + + + + + 9999.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + Scale Y: + + + + + + + 9999.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 1 + 20 + + + + + + + + + + + + + + + + SpinSlider + QWidget +
    spinslider.h
    +
    + + ColorButton + QPushButton +
    colorbutton.h
    +
    + + IconedLabel + QFrame +
    iconedlabel.h
    +
    +
    + + + + + + + linePath + textChanged(QString) + MaterialMapEditor + mapChanged() + + + 598 + 55 + + + 99 + 73 + + + + + sliderAmount + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 655 + 87 + + + 512 + 37 + + + + + sliderOffset + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 655 + 116 + + + 511 + 65 + + + + + spinScaleX + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 491 + 146 + + + 332 + 164 + + + + + spinScaleY + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 647 + 146 + + + 493 + 164 + + + + + checkMap + toggled(bool) + sliderValue + setHidden(bool) + + + 693 + 15 + + + 626 + 14 + + + + + checkMap + toggled(bool) + widgetMap + setVisible(bool) + + + 686 + 9 + + + 695 + 62 + + + + + sliderValue + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 99 + 15 + + + 130 + 28 + + + + + colorButton + colorChanged(QColor) + MaterialMapEditor + mapChanged() + + + 60 + 11 + + + 75 + 27 + + + + + + mapChanged() + +
    diff --git a/widgets/materials_editor.cpp b/widgets/materials_editor.cpp new file mode 100644 index 0000000..467e613 --- /dev/null +++ b/widgets/materials_editor.cpp @@ -0,0 +1,207 @@ +/* + QGL MaterialsEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "materials_editor.h" +#include "ui_materials_editor.h" +#include "material_editor.h" +#include "qglview.h" +#include "glmaterial.h" +#include +#include +#include + + +MaterialsEditor::MaterialsEditor(QWidget * parent): QWidget(parent) { + ui = new Ui::MaterialsEditor(); + ui->setupUi(this); + ui->widgetMaterial->setMaterial(0); + ui->scrollArea->viewport()->setAutoFillBackground(false); + ui->scrollAreaWidgetContents->setAutoFillBackground(false); + view = 0; +} + + +void MaterialsEditor::assignQGLView(QGLView * v) { + view = v; + connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + connect(view, SIGNAL(materialsChanged()), this, SLOT(materialsChanged())); + connect(view, SIGNAL(materialThumbnailCreated(Material*)), this, SLOT(materialThumbnailCreated(Material*))); + materialsChanged(); +} + + +bool MaterialsEditor::event(QEvent * e) { + if (e->type() == QEvent::FontChange || e->type() == QEvent::Polish) { + QSize sz = preferredIconSize(1.5, this); + ui->comboMaterial->setIconSize(sz * 3); + ui->buttonRename->setIconSize(sz); + ui->buttonAdd ->setIconSize(sz); + ui->buttonClone ->setIconSize(sz); + ui->buttonDelete->setIconSize(sz); + ui->buttonAssign->setIconSize(sz); + ui->buttonUnset ->setIconSize(sz); + } + return QWidget::event(e); +} + + +void MaterialsEditor::changeEvent(QEvent * e) { + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +Material * MaterialsEditor::currentMaterial() { + if (!view) return 0; + int ind = ui->comboMaterial->currentIndex(); + QVector mats = view->scene()->getMaterials(); + if (ind < 0 || ind >= mats.size()) return 0; + return mats[ind]; +} + + +void MaterialsEditor::selectMaterial(Material * m) { + if (!m) { + ui->comboMaterial->setCurrentIndex(-1); + return; + } + for (int i = 0; i < ui->comboMaterial->count(); ++i) { + if ((Material*)(ui->comboMaterial->itemData(i, Qt::UserRole + 1).value()) == m) { + ui->comboMaterial->setCurrentIndex(i); + break; + } + } +} + + +int MaterialsEditor::indexByMaterial(Material * m) { + if (!m) return -1; + for (int i = 0; i < ui->comboMaterial->count(); ++i) { + if ((Material*)(ui->comboMaterial->itemData(i, Qt::UserRole + 1).value()) == m) + return i; + } + return -1; +} + + +void MaterialsEditor::selectionChanged() { + if (!view) return; + //qDebug() << "selectionChanged"; + ObjectBase * o = view->selectedObject(); + if (o) selectMaterial(o->material()); +} + + +void MaterialsEditor::materialsChanged() { + if (ui->widgetMaterial->ignore_next > 0) { + ui->widgetMaterial->ignore_next--; + return; + } + Material * cm = currentMaterial(); + ui->comboMaterial->clear(); + if (!view) return; + QVector mats = view->scene()->getMaterials(); + for (int i = 0; i < mats.size(); ++i) { + Material * m = mats[i]; + ui->comboMaterial->addItem(QString("[%1] " + m->name).arg(i + 1), QVariant(m->name)); + ui->comboMaterial->setItemData(i, QVariant(quintptr(m)), Qt::UserRole + 1); + ui->comboMaterial->setItemIcon(i, QIcon(QPixmap::fromImage(view->materialThumbnail(m)))); + if (cm == m) ui->comboMaterial->setCurrentIndex(i); + } + +} + + +void MaterialsEditor::materialThumbnailCreated(Material * m) { + //qDebug() << "materialThumbnailCreated" << m; + int i = indexByMaterial(m); + if (i < 0 || !view) return; + //qDebug() << "materialThumbnailCreated set to" << i; + ui->comboMaterial->setItemIcon(i, QIcon(QPixmap::fromImage(view->materialThumbnail(m)))); +} + + +void MaterialsEditor::on_comboMaterial_currentIndexChanged(int index) { + ui->widgetMaterial->setMaterial(currentMaterial()); +} + + +void MaterialsEditor::on_buttonRename_clicked() { + Material * m = currentMaterial(); + if (!m) return; + QString nn = QInputDialog::getText(this, "Materials editor", "Input new name:", QLineEdit::Normal, m->name); + if (nn.isEmpty()) return; + m->name = nn; + int ind = ui->comboMaterial->currentIndex(); + ui->comboMaterial->setItemText(ind, QString("[%1] " + nn).arg(ind + 1)); + ui->comboMaterial->setItemData(ind, nn); +} + + +void MaterialsEditor::on_buttonAdd_clicked() { + if (!view) return; + Material * m = view->scene()->newMaterial(); + materialsChanged(); + selectMaterial(m); +} + + +void MaterialsEditor::on_buttonClone_clicked() { + if (!view) return; + Material * curm = currentMaterial(); + if (!curm) return; + Material * m = view->scene()->newMaterial(curm->name); + QString nm = m->name; + *m = *curm; + m->name = nm; + m->_changed = true; + materialsChanged(); + selectMaterial(m); +} + + +void MaterialsEditor::on_buttonDelete_clicked() { + if (!view) return; + Material * m = currentMaterial(); + if (!m) return; + view->scene()->removeMaterial(m); + materialsChanged(); +} + + +void MaterialsEditor::on_buttonAssign_clicked() { + if (!view) return; + Material * m = currentMaterial(); + ObjectBaseList ol = view->selectedObjects(); + foreach (ObjectBase * o, ol) + o->setMaterial(m, true); +} + + +void MaterialsEditor::on_buttonUnset_clicked() { + if (!view) return; + ObjectBaseList ol = view->selectedObjects(); + foreach (ObjectBase * o, ol) + o->setMaterial(0, true); +} diff --git a/widgets/materials_editor.h b/widgets/materials_editor.h new file mode 100644 index 0000000..5cd704d --- /dev/null +++ b/widgets/materials_editor.h @@ -0,0 +1,66 @@ +/* + QGL MaterialsEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef MATERIALS_EDITOR_H +#define MATERIALS_EDITOR_H + +#include +#include "gltypes.h" + +namespace Ui { + class MaterialsEditor; +} + +class MaterialsEditor: public QWidget +{ + Q_OBJECT +public: + explicit MaterialsEditor(QWidget * parent = 0); + + void assignQGLView(QGLView * v); + +protected: + bool event(QEvent * e); + void changeEvent(QEvent * e); + Material * currentMaterial(); + void selectMaterial(Material * m); + int indexByMaterial(Material * m); + + Ui::MaterialsEditor * ui; + QGLView * view; + Material * mat; + +private slots: + void selectionChanged(); + void materialsChanged(); + void materialThumbnailCreated(Material * m); + + void on_comboMaterial_currentIndexChanged(int index); + void on_buttonRename_clicked(); + void on_buttonAdd_clicked(); + void on_buttonClone_clicked(); + void on_buttonDelete_clicked(); + void on_buttonAssign_clicked(); + void on_buttonUnset_clicked(); + +signals: + void changed(); + +}; + +#endif // MATERIALS_EDITOR_H diff --git a/widgets/materials_editor.ui b/widgets/materials_editor.ui new file mode 100644 index 0000000..e416569 --- /dev/null +++ b/widgets/materials_editor.ui @@ -0,0 +1,251 @@ + + + MaterialsEditor + + + + 0 + 0 + 386 + 520 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 10 + + + + + + + + Unset + + + + :/icons/dialog-cancel.png:/icons/dialog-cancel.png + + + + + + + Assign + + + + :/icons/go-jump.png:/icons/go-jump.png + + + + + + + Add + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + Delete + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + Rename ... + + + + :/icons/edit-rename.png:/icons/edit-rename.png + + + + + + + Clone + + + + :/icons/edit-copy.png:/icons/edit-copy.png + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + + + + QFrame::NoFrame + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 + 0 + 386 + 440 + + + + true + + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::Vertical + + + + 20 + 421 + + + + + + + + + + + + + EComboBox + QComboBox +
    ecombobox.h
    +
    + + MaterialEditor + QWidget +
    material_editor.h
    + 1 +
    +
    + + + + + + + + + materialChanged() + +
    diff --git a/widgets/object_editor.cpp b/widgets/object_editor.cpp new file mode 100644 index 0000000..6507ead --- /dev/null +++ b/widgets/object_editor.cpp @@ -0,0 +1,268 @@ +/* + QGL ObjectEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "object_editor.h" +#include "ui_object_editor.h" +#include "qglview.h" +#include +#include + + +ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) { + ui = new Ui::ObjectEditor(); + ui->setupUi(this); + view = 0; + active = true; + ignore_next = false; + on_comboLightType_currentIndexChanged(0); + ui->widgetMain->setEnabled(false); + ui->labelAimDist->hide(); + ui->spinAimDist->hide(); + + QObjectList ol; + ol << ui->spinPosX << ui->spinPosY << ui->spinPosZ << + ui->spinRotationX << ui->spinRotationY << ui->spinRotationZ << + ui->spinScaleX << ui->spinScaleY << ui->spinScaleZ; + foreach (QObject * o, ol) + connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinChanged(double))); + + ol.clear(); + ol << ui->spinLightIntensity << ui->spinLightDecayConst << ui->spinLightDecayLinear << + ui->spinLightDecayQuadratic << ui->spinLightAngleStart << ui->spinLightAngleEnd << + ui->spinAimDist; + foreach (QObject * o, ol) + connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinLightChanged(double))); + + ol.clear(); + ol << ui->spinCameraFOV << ui->spinCameraDepthStart << ui->spinCameraRoll << ui->spinAimDist; + foreach (QObject * o, ol) + connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinCameraChanged(double))); + + ol.clear(); + ol << ui->checkVisible << ui->checkCastShadows << ui->checkReceiveShadows << + ui->checkAcceptLight << ui->checkAcceptFog << + ui->checkCameraMirrorX << ui->checkCameraMirrorY; + foreach (QObject * o, ol) + connect(o, SIGNAL(toggled(bool)), this, SLOT(checkChanged(bool))); + +} + + +void ObjectEditor::assignQGLView(QGLView * v) { + view = v; + connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + connect(view, SIGNAL(objectsPositionChanged()), this, SLOT(selectionChanged())); + connect(view->scene(), SIGNAL(treeChanged()), this, SLOT(selectionChanged())); + selectionChanged(); +} + + +void ObjectEditor::changeEvent(QEvent * e) { + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +void ObjectEditor::selectionChanged() { + if (ignore_next) { + ignore_next = false; + return; + } + ui->widgetMain->setEnabled(false); + if (!view) return; + ObjectBaseList sol = view->selectedObjects(true); + if (sol.isEmpty()) { + ui->labelTitle->setText(tr("[No selected]")); + return; + } + ui->widgetMain->setEnabled(true); + if (sol.size() == 1) { + setObject(sol[0]); + return; + } + bool hl = !view->selectedLights().isEmpty(), hc = !view->selectedCameras().isEmpty(); + ui->groupLight ->setVisible(hl); + ui->groupCamera ->setVisible(hc); + ui->labelAimDist->setVisible(hl || hc); + ui->spinAimDist ->setVisible(hl || hc); + ui->labelTitle->setText(tr("[%1 objects]").arg(sol.size())); +} + + +void ObjectEditor::setObject(ObjectBase * o) { + active = false; + ui->labelTitle->setText(o->name()); + ui->spinPosX->setValue(o->posX()); + ui->spinPosY->setValue(o->posY()); + ui->spinPosZ->setValue(o->posZ()); + ui->spinRotationX->setValue(o->rotationX()); + ui->spinRotationY->setValue(o->rotationY()); + ui->spinRotationZ->setValue(o->rotationZ()); + ui->spinScaleX->setValue(o->scaleX()); + ui->spinScaleY->setValue(o->scaleY()); + ui->spinScaleZ->setValue(o->scaleZ()); + ui->checkVisible->setChecked(o->isVisible()); + ui->checkAcceptLight->setChecked(o->isAcceptLight()); + ui->checkAcceptFog->setChecked(o->isAcceptFog()); + ui->checkCastShadows->setChecked(o->isCastShadows()); + ui->checkReceiveShadows->setChecked(o->isReceiveShadows()); + ui->buttonColor->setColor(o->color()); + bool is_l = o->type() == ObjectBase::glLight; + bool is_c = o->type() == ObjectBase::glCamera; + ui->labelAimDist->setVisible(is_l || is_c); + ui->spinAimDist ->setVisible(is_l || is_c); + ui->groupLight ->setVisible(is_l); + ui->groupCamera ->setVisible(is_c); + if (is_l) { + Light * l = globject_cast(o); + //bool is_dir = l->light_type == Light::Directional, is_cone = l->light_type == Light::Cone; + ui->comboLightType->setCurrentIndex(l->light_type); + ui->spinLightIntensity->setValue(l->intensity); + ui->spinLightDecayConst->setValue(l->decay_const); + ui->spinLightDecayLinear->setValue(l->decay_linear); + ui->spinLightDecayQuadratic->setValue(l->decay_quadratic); + ui->spinLightAngleStart->setValue(l->angle_start); + ui->spinLightAngleEnd->setValue(l->angle_end); + ui->spinAimDist->setValue(l->distance()); + on_comboLightType_currentIndexChanged(ui->comboLightType->currentIndex()); + } + if (is_c) { + Camera * c = globject_cast(o); + ui->checkCameraMirrorX->setChecked(c->isMirrorX()); + ui->checkCameraMirrorY->setChecked(c->isMirrorY()); + ui->spinCameraFOV->setValue(c->FOV()); + ui->spinCameraRoll->setValue(c->angleRoll()); + ui->spinCameraDepthStart->setValue(c->depthStart()); + ui->spinAimDist->setValue(c->distance()); + } + active = true; +} + + +void ObjectEditor::on_spinLightAngleStart_valueChanged(double v) { + if (ui->spinLightAngleEnd->value() < v) + ui->spinLightAngleEnd->setValue(v); +} + + +void ObjectEditor::on_spinLightAngleEnd_valueChanged(double v) { + if (ui->spinLightAngleStart->value() > v) + ui->spinLightAngleStart->setValue(v); +} + + +void ObjectEditor::on_comboLightType_currentIndexChanged(int index) { + bool ang = (index == Light::Cone); + ui->labelLightAngle ->setVisible(ang); + ui->labelLightAngleDash->setVisible(ang); + ui->spinLightAngleStart->setVisible(ang); + ui->spinLightAngleEnd ->setVisible(ang); + if (!view || !active) return; + QList sll = view->selectedLights(); + foreach (Light * o, sll) { + o->light_type = (Light::Type)index; + o->apply(); + } +} + + +void ObjectEditor::on_buttonColor_colorChanged(const QColor & v) { + if (!view || !active) return; + ObjectBaseList sol = view->selectedObjects(); + foreach (ObjectBase * o, sol) + o->setColor(v); + QList sll = view->selectedLights(); + foreach (Light * o, sll) + o->apply(); +} + + +void ObjectEditor::spinChanged(double v) { + if (!view || !active) return; + ObjectBaseList sol = view->selectedObjects(true); + QObject * s = sender(); + foreach (ObjectBase * o, sol) { + if (s == ui->spinPosX ) o->setPosX (v); + if (s == ui->spinPosY ) o->setPosY (v); + if (s == ui->spinPosZ ) o->setPosZ (v); + if (s == ui->spinRotationX) o->setRotationX(v); + if (s == ui->spinRotationY) o->setRotationY(v); + if (s == ui->spinRotationZ) o->setRotationZ(v); + if (s == ui->spinScaleX ) o->setScaleX (v); + if (s == ui->spinScaleY ) o->setScaleY (v); + if (s == ui->spinScaleZ ) o->setScaleZ (v); + } + ignore_next = true; +} + + +void ObjectEditor::spinLightChanged(double v) { + if (!view || !active) return; + QList sll = view->selectedLights(); + QObject * s = sender(); + foreach (Light * o, sll) { + if (s == ui->spinLightIntensity ) o->intensity = v; + if (s == ui->spinLightDecayConst ) o->decay_const = v; + if (s == ui->spinLightDecayLinear ) o->decay_linear = v; + if (s == ui->spinLightDecayQuadratic) o->decay_quadratic = v; + if (s == ui->spinLightAngleStart ) o->angle_start = v; + if (s == ui->spinLightAngleEnd ) o->angle_end = v; + if (s == ui->spinAimDist ) o->setDistance(v); + o->apply(); + } + ignore_next = true; +} + + +void ObjectEditor::spinCameraChanged(double v) { + if (!view || !active) return; + QList scl = view->selectedCameras(); + QObject * s = sender(); + foreach (Camera * o, scl) { + if (s == ui->spinCameraFOV ) o->setFOV (v); + if (s == ui->spinCameraRoll ) o->setAngleRoll (v); + if (s == ui->spinCameraDepthStart) o->setDepthStart(v); + if (s == ui->spinAimDist ) o->setDistance (v); + } + ignore_next = true; +} + + +void ObjectEditor::checkChanged(bool v) { + if (!view || !active) return; + ObjectBaseList sol = view->selectedObjects(); + QList scl = view->selectedCameras(); + QObject * s = sender(); + foreach (ObjectBase * o, sol) { + if (s == ui->checkVisible ) o->setVisible (v); + if (s == ui->checkCastShadows ) o->setCastShadows (v); + if (s == ui->checkReceiveShadows) o->setReceiveShadows(v); + if (s == ui->checkAcceptLight ) o->setAcceptLight (v); + if (s == ui->checkAcceptFog ) o->setAcceptFog (v); + } + foreach (Camera * o, scl) { + if (s == ui->checkCameraMirrorX ) o->setMirrorX(v); + if (s == ui->checkCameraMirrorY ) o->setMirrorY(v); + } +} diff --git a/widgets/object_editor.h b/widgets/object_editor.h new file mode 100644 index 0000000..89311f1 --- /dev/null +++ b/widgets/object_editor.h @@ -0,0 +1,62 @@ +/* + QGL ObjectEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef OBJECT_EDITOR_H +#define OBJECT_EDITOR_H + +#include +#include "globject.h" + +namespace Ui { + class ObjectEditor; +} + +class ObjectEditor: public QWidget +{ + Q_OBJECT +public: + explicit ObjectEditor(QWidget * parent = 0); + + void assignQGLView(QGLView * v); + +protected: + void changeEvent(QEvent * e); + void setObject(ObjectBase * o); + + Ui::ObjectEditor * ui; + QGLView * view; + bool active, ignore_next; + +private slots: + void selectionChanged(); + void on_spinLightAngleStart_valueChanged(double v); + void on_spinLightAngleEnd_valueChanged(double v); + + void on_comboLightType_currentIndexChanged(int index); + void on_buttonColor_colorChanged(const QColor &v); + void spinChanged(double v); + void spinLightChanged(double v); + void spinCameraChanged(double v); + void checkChanged(bool v); + +signals: + void changed(); + +}; + +#endif // OBJECT_EDITOR_H diff --git a/widgets/object_editor.ui b/widgets/object_editor.ui new file mode 100644 index 0000000..58ec410 --- /dev/null +++ b/widgets/object_editor.ui @@ -0,0 +1,782 @@ + + + ObjectEditor + + + + 0 + 0 + 466 + 778 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + font: bold; + + + [No selected] + + + Qt::AlignCenter + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Position + + + + + + + 0 + 0 + + + + X: + + + + + + + + + + + 0 + 0 + + + + Y: + + + + + + + + + + + 0 + 0 + + + + Z: + + + + + + + + + + + + + Rotation + + + + + + + 0 + 0 + + + + X: + + + + + + + -360.000000000000000 + + + 360.000000000000000 + + + 1 + + + 4.500000000000000 + + + 90.000000000000000 + + + ° + + + QSlider::TicksAbove + + + 90 + + + + + + + + 0 + 0 + + + + Y: + + + + + + + -360.000000000000000 + + + 360.000000000000000 + + + 4.500000000000000 + + + 90.000000000000000 + + + ° + + + QSlider::TicksAbove + + + 90 + + + + + + + + 0 + 0 + + + + Z: + + + + + + + -360.000000000000000 + + + 360.000000000000000 + + + 4.500000000000000 + + + 90.000000000000000 + + + ° + + + QSlider::TicksAbove + + + 90 + + + + + + + + + + Scale + + + + + + + 0 + 0 + + + + X: + + + + + + + + + + + 0 + 0 + + + + Y: + + + + + + + + + + + 0 + 0 + + + + Z: + + + + + + + + + + + + + + + Accept fog + + + + + + + Accept light + + + + + + + Visible + + + + + + + Cast shadows + + + + + + + Receive shadows + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 0 + 0 + + + + Color: + + + + + + + + + + + 0 + 0 + + + + Aim distance: + + + + + + + + + + + + Light + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Type: + + + + + + + + Omni + + + + + Cone + + + + + Directional + + + + + + + + Intensity: + + + + + + + 0.000000000000000 + + + 10.000000000000000 + + + 1.000000000000000 + + + 3 + + + 0.100000000000000 + + + 1.000000000000000 + + + true + + + 999.000000000000000 + + + + + + + Decay ^0: + + + + + + + 0.000000000000000 + + + 10.000000000000000 + + + 1.000000000000000 + + + 3 + + + 0.100000000000000 + + + 1.000000000000000 + + + true + + + 999.000000000000000 + + + + + + + Decay ^1: + + + + + + + 0.000000000000000 + + + 10.000000000000000 + + + 0.000000000000000 + + + 3 + + + 0.100000000000000 + + + 1.000000000000000 + + + true + + + 999.000000000000000 + + + + + + + Decay ^2: + + + + + + + 0.000000000000000 + + + 10.000000000000000 + + + 0.000000000000000 + + + 3 + + + 0.100000000000000 + + + 1.000000000000000 + + + true + + + 999.000000000000000 + + + + + + + Angle: + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0.000000000000000 + + + 180.000000000000000 + + + 1 + + + 5.000000000000000 + + + 30.000000000000000 + + + ° + + + + + + + - + + + + + + + 0.000000000000000 + + + 180.000000000000000 + + + 1 + + + 5.000000000000000 + + + 30.000000000000000 + + + ° + + + + + + + + + + + + + Camera + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Depth start: + + + + + + + FOV: + + + + + + + 1.000000000000000 + + + 179.900000000000006 + + + 60.000000000000000 + + + 1 + + + 5.000000000000000 + + + 30.000000000000000 + + + ° + + + + + + + + + Mirror Y + + + + + + + Mirror X + + + + + + + + + 5 + + + 999999999.000000000000000 + + + 0.100000000000000 + + + + + + + -180.000000000000000 + + + 180.000000000000000 + + + 0.000000000000000 + + + 1 + + + 5.000000000000000 + + + 30.000000000000000 + + + ° + + + + + + + Roll: + + + + + + + + + + + + + + SpinSlider + QWidget +
    spinslider.h
    +
    + + ColorButton + QPushButton +
    colorbutton.h
    +
    + + ScrollSpinBox + QWidget +
    scroll_spin_box.h
    +
    +
    + + + + objectChanged() + +
    diff --git a/widgets/primitiveeditor.cpp b/widgets/primitiveeditor.cpp new file mode 100644 index 0000000..bfa3299 --- /dev/null +++ b/widgets/primitiveeditor.cpp @@ -0,0 +1,259 @@ +/* + QGL PrimitiveEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "primitiveeditor.h" +#include "ui_primitiveeditor.h" +#include +#include "glprimitives.h" +#include "glmesh.h" + + +PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui::PrimitiveEditor) { + view = 0; + can_replace = false; + ui->setupUi(this); +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) + ui->spinSegments->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); + ui->spinSegments2->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); +#endif + editors[Plane] << ui->widgetWidth; + editors[Plane] << ui->widgetLength; + editors[Cube] << ui->widgetWidth; + editors[Cube] << ui->widgetLength; + editors[Cube] << ui->widgetHeight; + editors[Ellipsoid] << ui->widgetRadius1; + editors[Ellipsoid] << ui->widgetSegments; + editors[Ellipsoid] << ui->widgetSegments2; + editors[Ellipsoid] << ui->widgetAngle; + editors[Disc] << ui->widgetRadius1; + editors[Disc] << ui->widgetSegments; + editors[Disc] << ui->widgetAngle; + editors[Cone] << ui->widgetRadius1; + editors[Cone] << ui->widgetHeight; + editors[Cone] << ui->widgetSegments; + editors[Cylinder] << ui->widgetRadius1; + editors[Cylinder] << ui->widgetHeight; + editors[Cylinder] << ui->widgetSegments; + editors[Cylinder] << ui->widgetAngle; + editors[Torus] << ui->widgetRadius1; + editors[Torus] << ui->widgetRadius2; + editors[Torus] << ui->widgetSegments; + editors[Torus] << ui->widgetSegments2; + editors[Torus] << ui->widgetAngle; + QSet all; + QMetaEnum me = metaObject()->enumerator(0); + for (int i=0; icomboPrimitives->addItem(me.key(i)); + all.unite(editors[(PrimitiveType)me.value(i)].toSet()); + } + all_editors = all.toList(); + foreach (QWidget * w, all_editors) { + if (w->layout()) w->layout()->setContentsMargins(0, layout()->spacing(), 0, 0); + } + + ui->comboPrimitives->setCurrentIndex(Plane); + on_comboPrimitives_currentIndexChanged(ui->comboPrimitives->currentIndex()); +} + + +PrimitiveEditor::~PrimitiveEditor() { + delete ui; +} + + +void PrimitiveEditor::assignQGLView(QGLView * v) { + view = v; + connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + selectionChanged(); +} + + +Mesh * PrimitiveEditor::createMesh(QVariantList & params) { + Mesh * m = 0; + PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex(); + params << pt; + switch (pt) { + case Plane: + m = Primitive::plane(ui->spinWidth->value(), + ui->spinLength->value()); + params << ui->spinWidth->value() + << ui->spinLength->value(); + break; + case Cube: + m = Primitive::cube(ui->spinWidth->value(), + ui->spinLength->value(), + ui->spinHeight->value()); + params << ui->spinWidth->value() + << ui->spinLength->value() + << ui->spinHeight->value(); + break; + case Ellipsoid: + m = Primitive::ellipsoid(ui->spinSegments->value(), + ui->spinSegments2->value(), + ui->spinRadius->value(), + ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinSegments2->value() + << ui->spinRadius->value() + << ui->spinAngle->value(); + break; + case Disc: + m = Primitive::disc(ui->spinSegments->value(), + ui->spinRadius->value(), + ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinRadius->value() + << ui->spinAngle->value(); + break; + case Cone: + m = Primitive::cone(ui->spinSegments->value(), + ui->spinRadius->value(), + ui->spinHeight->value()); + params << ui->spinSegments->value() + << ui->spinRadius->value() + << ui->spinHeight->value(); + break; + case Cylinder: + m = Primitive::cylinder(ui->spinSegments->value(), + ui->spinRadius->value(), + ui->spinHeight->value(), + ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinRadius->value() + << ui->spinHeight->value() + << ui->spinAngle->value(); + break; + case Torus: + m = Primitive::torus(ui->spinSegments->value(), + ui->spinSegments2->value(), + ui->spinRadius->value(), + ui->spinRadius2->value(), + ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinSegments2->value() + << ui->spinRadius->value() + << ui->spinRadius2->value() + << ui->spinAngle->value(); + break; + default: return 0; + } + params << ui->flipNormals->isChecked(); + params << ui->colorButton->color(); + if (ui->flipNormals->isChecked()) + m->flipNormals(); + return m; +} + + +void PrimitiveEditor::showEditors() { + foreach (QWidget * w, all_editors) w->hide(); + PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex(); + QList wds = editors[pt]; + foreach (QWidget * w, wds) w->show(); +} + + +void PrimitiveEditor::selectionChanged() { + ObjectBase * so = view->selectedObject();\ + can_replace = false; + if (so) { + QVariantList vl = so->property("primitive", &can_replace).toList(); + if (can_replace && !vl.isEmpty()) { + PrimitiveType pt = (PrimitiveType)vl.takeFirst().toInt(); + ui->comboPrimitives->setCurrentIndex(pt); + switch (pt) { + case Plane: + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + break; + case Cube: + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + break; + case Ellipsoid: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinSegments2->setValue(vl.takeFirst().toDouble()); + ui->spinRadius->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + case Disc: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinRadius->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + case Cone: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinRadius->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + break; + case Cylinder: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinRadius->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + case Torus: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinSegments2->setValue(vl.takeFirst().toDouble()); + ui->spinRadius->setValue(vl.takeFirst().toDouble()); + ui->spinRadius2->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + } + ui->flipNormals->setChecked(vl.takeFirst().toBool()); + ui->colorButton->setColor(vl.takeFirst().value()); + } + } +} + + +void PrimitiveEditor::replaceMesh() { + if (!view) return; + if (!can_replace) return; + ObjectBase * so = view->selectedObject(); + if (!so) return; + QVariantList params; + Mesh * m = createMesh(params); + if (!m) return; + so->setMesh(m); + so->setColor(ui->colorButton->color()); + so->setName(ui->comboPrimitives->currentText()); + so->setProperty("primitive", params); + delete m; +} + + +void PrimitiveEditor::on_buttonAdd_clicked() { + if (!view) return; + QVariantList params; + Mesh * m = createMesh(params); + if (!m) return; + ObjectBase * o = new ObjectBase(m); + o->setColor(ui->colorButton->color()); + o->setName(ui->comboPrimitives->currentText()); + o->setProperty("primitive", params); + view->scene()->addObject(o); + view->scene()->selectObject(o); + delete m; +} + + +void PrimitiveEditor::on_comboPrimitives_currentIndexChanged(int index) { + showEditors(); +} diff --git a/widgets/primitiveeditor.h b/widgets/primitiveeditor.h new file mode 100644 index 0000000..7d1b5a4 --- /dev/null +++ b/widgets/primitiveeditor.h @@ -0,0 +1,68 @@ +/* + QGL PrimitiveEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PRIMITIVEEDITOR_H +#define PRIMITIVEEDITOR_H + +#include +#include "qglview.h" + + +namespace Ui { +class PrimitiveEditor; +} + + +class PrimitiveEditor : public QWidget { + Q_OBJECT +public: + enum PrimitiveType { + Plane, + Cube, + Ellipsoid, + Disc, + Cone, + Cylinder, + Torus + }; + Q_ENUMS(PrimitiveType) + + explicit PrimitiveEditor(QWidget *parent = nullptr); + ~PrimitiveEditor(); + + void assignQGLView(QGLView * v); + +protected: + Mesh * createMesh(QVariantList & params); + void showEditors(); + + Ui::PrimitiveEditor *ui; + QGLView * view; + QMap > editors; + QList all_editors; + bool can_replace; + +private slots: + void selectionChanged(); + void replaceMesh(); + void on_buttonAdd_clicked(); + void on_comboPrimitives_currentIndexChanged(int index); +}; + + +#endif // PRIMITIVEEDITOR_H diff --git a/widgets/primitiveeditor.ui b/widgets/primitiveeditor.ui new file mode 100644 index 0000000..9238a84 --- /dev/null +++ b/widgets/primitiveeditor.ui @@ -0,0 +1,597 @@ + + + PrimitiveEditor + + + + 0 + 0 + 360 + 536 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + 0 + + + + + Width: + + + + + + + 1.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Length: + + + + + + + 1.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Height + + + + + + + 1.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Radius 1: + + + + + + + 1.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Radius 2: + + + + + + + 1.000000000000000 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Angle: + + + + + + + 360.000000000000000 + + + 360.000000000000000 + + + 4.500000000000000 + + + 90.000000000000000 + + + ° + + + QSlider::TicksAbove + + + 90 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Segments: + + + + + + + 1 + + + 1000 + + + 1 + + + 16 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Segments 2: + + + + + + + 1 + + + 1000 + + + 1 + + + 16 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + Color: + + + + + + + + 255 + 255 + 255 + + + + + + + + + + + + + + Flip normals + + + + + + + Qt::Vertical + + + + 20 + 176 + + + + + + + + + + Add + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + + + + SpinSlider + QWidget +
    spinslider.h
    +
    + + ColorButton + QPushButton +
    colorbutton.h
    +
    + + EComboBox + QComboBox +
    ecombobox.h
    +
    + + ScrollSpinBox + QWidget +
    scroll_spin_box.h
    +
    +
    + + + + + + spinWidth + valueChanged(double) + PrimitiveEditor + replaceMesh() + + + 331 + 51 + + + 368 + 45 + + + + + spinLength + valueChanged(double) + PrimitiveEditor + replaceMesh() + + + 330 + 84 + + + 369 + 82 + + + + + spinHeight + valueChanged(double) + PrimitiveEditor + replaceMesh() + + + 334 + 116 + + + 366 + 114 + + + + + spinRadius + valueChanged(double) + PrimitiveEditor + replaceMesh() + + + 332 + 144 + + + 370 + 145 + + + + + spinRadius2 + valueChanged(double) + PrimitiveEditor + replaceMesh() + + + 334 + 186 + + + 371 + 181 + + + + + spinAngle + valueChanged(double) + PrimitiveEditor + replaceMesh() + + + 335 + 210 + + + 372 + 213 + + + + + spinSegments + valueChanged(int) + PrimitiveEditor + replaceMesh() + + + 329 + 246 + + + 370 + 247 + + + + + spinSegments2 + valueChanged(int) + PrimitiveEditor + replaceMesh() + + + 336 + 284 + + + 372 + 279 + + + + + flipNormals + toggled(bool) + PrimitiveEditor + replaceMesh() + + + 70 + 344 + + + 370 + 341 + + + + + comboPrimitives + currentIndexChanged(int) + PrimitiveEditor + replaceMesh() + + + 348 + 9 + + + 367 + 9 + + + + + colorButton + colorChanged(QColor) + PrimitiveEditor + replaceMesh() + + + 271 + 285 + + + 179 + 267 + + + + + + replaceMesh() + +
    diff --git a/widgets/propertyeditor.cpp b/widgets/propertyeditor.cpp new file mode 100644 index 0000000..b4c568e --- /dev/null +++ b/widgets/propertyeditor.cpp @@ -0,0 +1,426 @@ +/* + QGL PropertyEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "propertyeditor.h" + + +QWidget * Delegate::widgetForProperty(QWidget * parent, const QModelIndex & index) const { + QWidget * w = 0; + int type = 0; + QVariant value = index.data(Qt::UserRole); + if (index.data(Qt::UserRole + 2).toString() == "__flags") return 0; + if (index.data(Qt::UserRole + 1).toString() == "__flag") { + qulonglong key = index.data(Qt::UserRole).toULongLong(); + value = index.parent().data(Qt::UserRole); + //QMetaProperty prop = index.parent().data(Qt::UserRole + 1).value(); + w = new QCheckBox(parent); type = 14; ((QCheckBox*)w)->setChecked(((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0)); + ((QCheckBox*)w)->setText("0x" + QString::number(key, 16).toUpper()); + connect((QCheckBox*)w, SIGNAL(clicked(bool)), this, SLOT(changedFlag())); + //qDebug() << prop.enumerator().name(); + } else { + if (value.canConvert()) { + PropertyValuePair prop = value.value(); + if (prop.first.isEnumType()) { + w = new QComboBox(parent); type = 13; ((QComboBox*)w)->setCurrentIndex(value.toInt()); + w->setProperty("__prop", QVariant::fromValue(prop.first)); + QMetaEnum menum = prop.first.enumerator(); + for (int i = 0; i < menum.keyCount(); ++i) { + ((QComboBox*)w)->addItem(QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")", menum.value(i)); + if (menum.value(i) == prop.second.toInt()) + ((QComboBox*)w)->setCurrentIndex(i); + } + connect((QComboBox*)w, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + } + } else { + switch (value.type()) { + case QVariant::Int: w = new QSpinBox(parent); type = 2; ((QSpinBox*)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; + case QVariant::UInt: w = new QSpinBox(parent); type = 3; ((QSpinBox*)w)->setRange(0, 0xFFFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; + case QVariant::LongLong: w = new QSpinBox(parent); type = 4; ((QSpinBox*)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; + case QVariant::ULongLong: w = new QSpinBox(parent); type = 5; ((QSpinBox*)w)->setRange(0, 0xFFFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; + case QVariant::Double: w = new QDoubleSpinBox(parent); type = 6; ((QDoubleSpinBox*)w)->setRange(-999999999, 999999999); ((QDoubleSpinBox*)w)->setDecimals(3); connect((QDoubleSpinBox*)w, SIGNAL(valueChanged(double)), this, SLOT(changed())); break; + case QVariant::Bool: w = new QCheckBox(parent); type = 7; ((QCheckBox*)w)->setChecked(value.toBool()); connect((QCheckBox*)w, SIGNAL(toggled(bool)), this, SLOT(changed())); break; + case QVariant::Color: w = new ColorButton(parent); type = 8; ((ColorButton*)w)->setUseAlphaChannel(true); ((ColorButton*)w)->setColor(value.value()); connect((ColorButton*)w, SIGNAL(colorChanged(QColor)), this, SLOT(changed())); break; + case QVariant::Point: w = new QPointEdit(parent); type = 9; ((QPointEdit*)w)->setDecimals(0); ((QPointEdit*)w)->setValue(QPointF(value.toPoint())); connect((QPointEdit*)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed())); break; + case QVariant::PointF: w = new QPointEdit(parent); type = 10; ((QPointEdit*)w)->setDecimals(3); ((QPointEdit*)w)->setValue(value.toPointF()); connect((QPointEdit*)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed())); break; + case QVariant::Rect: w = new QRectEdit(parent); type = 11; ((QRectEdit*)w)->setDecimals(0); ((QRectEdit*)w)->setValue(QRectF(value.toRect())); connect((QRectEdit*)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed())); break; + case QVariant::RectF: w = new QRectEdit(parent); type = 12; ((QRectEdit*)w)->setDecimals(3); ((QRectEdit*)w)->setValue(value.toRectF()); connect((QRectEdit*)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed())); break; + case QVariant::String: default: w = new CLineEdit(parent); type = 1; ((CLineEdit*)w)->setDefaultText(value.toString()); connect((CLineEdit*)w, SIGNAL(textChanged(QString)), this, SLOT(changed())); break; + } + } + } + if (w == 0) return 0; + /*QPalette pal = w->palette(); + pal.setColor(QPalette::Window, Qt::white); + w->setPalette(pal);*/ + w->setAutoFillBackground(true); + w->setProperty("__type", type); + return w; +} + + +void Delegate::setWidgetProperty(QWidget * w, const QVariant & value) const { + if (w == 0) return; + switch (w->property("__type").toInt()) { + case 1: ((CLineEdit*)w)->setText(value.toString()); break; + case 2: case 3: case 4: case 5: ((QSpinBox*)w)->setValue(value.toInt()); break; + case 6: ((QDoubleSpinBox*)w)->setValue(value.toDouble()); break; + case 7: ((QCheckBox*)w)->setChecked(value.toBool()); break; + case 8: ((ColorButton*)w)->setColor(value.value()); break; + case 9: ((QPointEdit*)w)->setValue(value.value()); break; + case 10: ((QPointEdit*)w)->setValue(value.value()); break; + case 11: ((QRectEdit*)w)->setValue(value.value()); break; + case 12: ((QRectEdit*)w)->setValue(value.value()); break; + } +} + + +const QVariant Delegate::widgetProperty(QWidget * w) const { + if (w == 0) return QVariant(); + switch (w->property("__type").toInt()) { + case 1: return QVariant::fromValue(((CLineEdit*)w)->text()); break; + case 2: return QVariant::fromValue(((QSpinBox*)w)->value()); break; + case 3: return QVariant::fromValue(((QSpinBox*)w)->value()); break; + case 4: return QVariant::fromValue(((QSpinBox*)w)->value()); break; + case 5: return QVariant::fromValue(((QSpinBox*)w)->value()); break; + case 6: return QVariant::fromValue(((QDoubleSpinBox*)w)->value()); break; + case 7: return QVariant::fromValue(((QCheckBox*)w)->isChecked()); break; + case 8: return QVariant::fromValue(((ColorButton*)w)->color()); break; + case 9: return QVariant::fromValue(((QPointEdit*)w)->value().toPoint()); break; + case 10: return QVariant::fromValue(((QPointEdit*)w)->value()); break; + case 11: return QVariant::fromValue(((QRectEdit*)w)->value().toRect()); break; + case 12: return QVariant::fromValue(((QRectEdit*)w)->value()); break; + case 13: return QVariant::fromValue(PropertyValuePair(w->property("__prop").value(), ((QComboBox*)w)->itemData(((QComboBox*)w)->currentIndex()))); break; + default: return QVariant(); break; + } + return QVariant(); +} + + +void Delegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { + if (index.data(Qt::UserRole + 1).toString() != "__flag") + model->setData(index, widgetProperty(editor), Qt::UserRole); +} + + +void Delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { + QStyledItemDelegate::paint(painter, option, index); + QVariant value = index.data(Qt::UserRole); + QStyle * style = QApplication::style(); + QStyleOption * so = 0; + QStyleOptionComplex * soc = 0; + QString text; + QRect rect; + QPalette::ColorRole role = (option.state.testFlag(QStyle::State_Selected) && option.state.testFlag(QStyle::State_Active) ? QPalette::HighlightedText : QPalette::WindowText); + if (index.data(Qt::UserRole + 2).toString() == "__flags") { + text = "0x" + QString::number(value.toInt(), 16).toUpper(); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + return; + } + if (index.data(Qt::UserRole + 1) == "__flag") { + qulonglong key = index.data(Qt::UserRole).toULongLong(); + value = index.parent().data(Qt::UserRole); + so = new QStyleOptionButton(); + so->rect = option.rect; + so->palette = option.palette; + so->fontMetrics = option.fontMetrics; + ((QStyleOptionButton*)so)->state = (((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0) ? QStyle::State_On : QStyle::State_Off) | option.state; + ((QStyleOptionButton*)so)->text = "0x" + QString::number(key, 16).toUpper(); + if (option.state.testFlag(QStyle::State_Selected)) + so->palette.setColor(QPalette::WindowText, so->palette.color(QPalette::HighlightedText)); + style->drawControl(QStyle::CE_CheckBox, so, painter); + } else { + if (value.canConvert()) { + PropertyValuePair prop = value.value(); + if (prop.first.isEnumType()) { + QMetaEnum menum = prop.first.enumerator(); + for (int i = 0; i < menum.keyCount(); ++i) { + if (menum.value(i) == prop.second.toInt()) { + text = QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")"; + break; + } + } + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + } + } else { + switch (value.type()) { + case QVariant::Int: + text.setNum(value.toInt()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::UInt: + text.setNum(value.toUInt()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::LongLong: + text.setNum(value.toLongLong()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::ULongLong: + text.setNum(value.toULongLong()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::Double: + text.setNum(value.toDouble(), 'f', 3); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::Bool: + so = new QStyleOptionButton(); + so->rect = option.rect; + so->state = option.state; + so->palette = option.palette; + so->fontMetrics = option.fontMetrics; + ((QStyleOptionButton*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off) | option.state; + style->drawControl(QStyle::CE_CheckBox, so, painter); + break; + case QVariant::Color: + rect = option.rect;//style->subElementRect(QStyle::QStyle::SE_FrameContents, so); + rect.setRect(rect.x() + 3, rect.y() + 3, rect.width() - 6, rect.height() - 6); + painter->fillRect(rect, ab); + painter->fillRect(rect, value.value()); + break; + case QVariant::Point: + text = pointString(value.toPoint()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::PointF: + text = pointString(value.toPointF()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::Rect: + text = rectString(value.toRect()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::RectF: + text = rectString(value.toRectF()); + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); + break; + case QVariant::String: default: + style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, value.toString()), + Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, value.toString(), role); + break; + } + } + } + /*so = new QStyleOptionFrame(); + so->rect = option.rect; + so->state = option.state; + so->palette = option.palette; + so->fontMetrics = option.fontMetrics; + ((QStyleOptionFrame*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off); + style->drawPrimitive(QStyle::PE_PanelLineEdit, so, painter); + style->drawPrimitive(QStyle::PE_FrameLineEdit, so, painter); + break;*/ + if (so != 0) delete so; + if (soc != 0) delete soc; + +} + + +void Delegate::changedFlag() { + QAbstractItemModel * model = const_cast(cmi.model()); + model->setData(cmi, qobject_cast(sender())->isChecked(), Qt::UserRole + 3); + QModelIndex p = cmi.parent(), mi; + int row = 0; + qulonglong val = 0; + QList chldr; + mi = p.child(row, 1); + while (mi.isValid()) { + chldr << mi; + model->setData(mi, !mi.data(Qt::UserRole + 4).toBool(), Qt::UserRole + 4); + mi = p.child(++row, 1); + } + bool cc = cmi.data(Qt::UserRole + 3).toBool(); + qulonglong cv = cmi.data(Qt::UserRole).toULongLong(); + //qDebug() << "*****"; + if (cc && cv == 0) { + val = 0; + //qDebug() << "null" << cv; + } else { + if (!cc && cv != 0) { + //qDebug() << "uncheck" << cv; + for (int i = 0; i < chldr.size(); ++i) { + if (chldr[i] == cmi) continue; + //qDebug() << (chldr[i].data(Qt::UserRole).toULongLong() & cv); + if (chldr[i].data(Qt::UserRole).toULongLong() & cv) + model->setData(chldr[i], false, Qt::UserRole + 3); + } + } + for (int i = 0; i < chldr.size(); ++i) { + //qDebug() << chldr[i].data(Qt::UserRole + 3).toBool(); + if (chldr[i].data(Qt::UserRole + 3).toBool()) + val |= chldr[i].data(Qt::UserRole).toULongLong(); + } + } + for (int i = 0; i < chldr.size(); ++i) { + if (chldr[i] == cmi) continue; + cv = chldr[i].data(Qt::UserRole).toULongLong(); + model->setData(chldr[i], ((val & cv) == cv && cv != 0) || (val == 0 && cv == 0), Qt::UserRole + 3); + } + //qDebug() << val; + model->setData(p, val, Qt::UserRole); + model->setData(p.sibling(p.row(), 1), val, Qt::UserRole); +} + + + +PropertyEditor::PropertyEditor(QWidget * parent): QTreeWidget(parent) { + object = 0; + active_ = false; + configTree(); + connect(this, SIGNAL(itemClicked(QTreeWidgetItem * , int)), this, SLOT(itemClicked(QTreeWidgetItem * , int))); + connect(this, SIGNAL(itemChanged(QTreeWidgetItem * , int)), this, SLOT(itemChanged(QTreeWidgetItem * , int))); +} + + +PropertyEditor::~PropertyEditor() { + +} + + +void PropertyEditor::changeEvent(QEvent * e) { + QTreeWidget::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + configTree(); + return; + } +} + + +void PropertyEditor::configTree() { + setColumnCount(2); + setRootIsDecorated(false); + setColumnWidth(0, 170); + setColumnWidth(1, 10); + header()->setStretchLastSection(true); + QStringList lbls; + lbls << tr("Property") << tr("Value"); + setHeaderLabels(lbls); + setAlternatingRowColors(true); + setItemDelegateForColumn(1, new Delegate()); + +} + + +void PropertyEditor::itemClicked(QTreeWidgetItem * item, int column) { + if (column == 0) + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + else { + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); + editItem(item, 1); + } +} + + +void PropertyEditor::itemChanged(QTreeWidgetItem * item, int column) { + if (!active_) return; + if (column != 1) return; + QVariant value = item->data(1, Qt::UserRole); + if (value.canConvert()) { + value = value.value().second; + } + object->setProperty(item->text(0).toLatin1(), value); +} + + +void PropertyEditor::rebuild() { + clear(); + configTree(); + if (object == 0) return; + active_ = false; + const QMetaObject * mo = object->metaObject(); + QList mol; + while (mo != 0) { + mol.push_front(mo); + mo = mo->superClass(); + } + int ps, pe; + QTreeWidgetItem * ti, * tli, * tfi; + QVariant value; +// QWidget * pw = 0; + int chue = 0; + QColor bc; + font_b = font(); + font_b.setBold(true); + foreach (const QMetaObject * o, mol) { + ps = o->propertyOffset(); + pe = o->propertyCount();// - ps; + //qDebug() << i->className() << ps << pe; + tli = new QTreeWidgetItem(); + tli->setText(0, o->className()); + tli->setFont(0, font_b); + setItemBackColor(tli, Qt::darkGray); + setItemForeColor(tli, Qt::white); + addTopLevelItem(tli); + setFirstItemColumnSpanned(tli, true); + tli->setExpanded(true); + for (int i = ps; i < pe; ++i) { + props << o->property(i); + value = o->property(i).read(object); + ti = new QTreeWidgetItem(); + ti->setSizeHint(1, QSize(20, 20)); + bc.setHsv(chue, 60, 245 + (i % 2) * 20 - 10); + setItemBackColor(ti, bc); + ti->setText(0, o->property(i).name()); + if (props.back().isFlagType()) { + QMetaEnum menum = props.back().enumerator(); + for (int j = 0; j < menum.keyCount(); ++j) { + tfi = new QTreeWidgetItem(); + tfi->setText(0, menum.key(j)); + tfi->setData(1, Qt::UserRole, menum.value(j)); + tfi->setData(1, Qt::UserRole + 1, "__flag"); + tfi->setData(1, Qt::UserRole + 2, value.toULongLong()); + tfi->setData(1, Qt::UserRole + 3, (value.toULongLong() & menum.value(j)) > 0); + tfi->setSizeHint(1, QSize(20, 20)); + bc.setHsv(chue, 60, 245 + ((i + j + 1) % 2) * 20 - 10); + setItemBackColor(tfi, bc); + ti->addChild(tfi); + } + ti->setData(0, Qt::UserRole, value); + ti->setData(1, Qt::UserRole, value); + ti->setData(1, Qt::UserRole + 2, "__flags"); + ti->setData(0, Qt::UserRole + 1, QVariant::fromValue(props.back())); + } + else if (props.back().isEnumType()) + value.setValue(PropertyValuePair(props.back(), value)); + //ti->setText(1, value.toString()); + ti->setData(1, Qt::UserRole, value); + tli->addChild(ti); + //const_cast(indexFromItem(ti, 1)).; + //if (pw != 0) setItemWidget(ti, 1, pw); + } + chue += 60; + chue %= 360; + } + active_ = true; +} + + +void PropertyEditor::refresh() { + +} diff --git a/widgets/propertyeditor.h b/widgets/propertyeditor.h new file mode 100644 index 0000000..143e32c --- /dev/null +++ b/widgets/propertyeditor.h @@ -0,0 +1,95 @@ +/* + QGL PropertyEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef PROPERTYEDITOR_H +#define PROPERTYEDITOR_H + +#include +#include +#include +#include +#include +#include +#include + + +class Delegate: public QStyledItemDelegate { + Q_OBJECT +public: + Delegate(QObject * parent = 0): QStyledItemDelegate() {ab = QBrush(QImage(":/icons/alpha.png"));} + + QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {cmi = const_cast(index); return widgetForProperty(parent, index);} + void setEditorData(QWidget * editor, const QModelIndex & index) const {setWidgetProperty(editor, index.data(Qt::UserRole));} + void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; + void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const {editor->setGeometry(option.rect);} + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + +private: + QWidget * widgetForProperty(QWidget * parent, const QModelIndex & index) const; + void setWidgetProperty(QWidget * w, const QVariant & value) const; + const QVariant widgetProperty(QWidget * w) const; + QString pointString(const QPoint & p) const {return QString::number(p.x()) + " x " + QString::number(p.y());} + QString pointString(const QPointF & p) const {return QString::number(p.x()) + " x " + QString::number(p.y());} + QString rectString(const QRect & r) const {return QString::number(r.x()) + " x " + QString::number(r.y()) + " : " + + QString::number(r.width()) + " x " + QString::number(r.height());} + QString rectString(const QRectF & r) const {return QString::number(r.x()) + " x " + QString::number(r.y()) + " : " + + QString::number(r.width()) + " x " + QString::number(r.height());} + + QBrush ab; + mutable QModelIndex cmi; + +private slots: + void changed() {setModelData((QWidget * )sender(), const_cast(cmi.model()), cmi);} + void changedFlag(); + +}; + +typedef QPair PropertyValuePair; +Q_DECLARE_METATYPE (PropertyValuePair) +Q_DECLARE_METATYPE (QMetaProperty) + +class PropertyEditor: public QTreeWidget { + Q_OBJECT +public: + explicit PropertyEditor(QWidget * parent = 0); + virtual ~PropertyEditor(); + + void assignObject(QObject * o) {object = o; rebuild();} + +protected: + void changeEvent(QEvent * e); + +private: + void configTree(); + void setItemBackColor(QTreeWidgetItem * i, const QColor & c) {i->setBackgroundColor(0, c); i->setBackgroundColor(1, c);} + void setItemForeColor(QTreeWidgetItem * i, const QColor & c) {i->setForeground(0, c); i->setForeground(1, c);} + void rebuild(); + void refresh(); + + QObject * object; + QFont font_b; + QList props; + bool active_; + +private slots: + void itemClicked(QTreeWidgetItem * item, int column); + void itemChanged(QTreeWidgetItem * item, int column); + +}; + +#endif // PROPERTYEDITOR_H diff --git a/widgets/scene_tree.cpp b/widgets/scene_tree.cpp new file mode 100644 index 0000000..b137d53 --- /dev/null +++ b/widgets/scene_tree.cpp @@ -0,0 +1,504 @@ +/* + QGL SceneTree + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "scene_tree.h" +#include "ui_scene_tree.h" +#include "glcamera.h" +#include "qglview.h" +#include +#include +#include +#include + +enum Column { + cName, + cVis, + cMaterial +}; +enum ItemRole { + irObject = Qt::UserRole, + irType = Qt::UserRole + 1, +}; + +enum ObjectType { + otNode = 1, + otMesh = 2, + otLight = 4, + otCamera = 8, +}; + + +QAction * newSeparator() { + QAction * s = new QAction(); + s->setSeparator(true); + return s; +} + + +SceneTree::SceneTree(QWidget * parent): QWidget(parent) { + ui = new Ui::SceneTree(); + ui->setupUi(this); + ui->treeObjects->header()->setSectionResizeMode(cVis, QHeaderView::ResizeToContents); + ui->treeObjects->header()->setSectionsMovable(false); + ui->treeObjects->header()->swapSections(cName, cVis); + icon_empty = QIcon(":/icons/type-empty.png"); + icon_geo = QIcon(":/icons/type-geo.png"); + icon_camera = QIcon(":/icons/type-camera.png"); + icon_light = QIcon(":/icons/type-light.png"); + icon_vis[0] = QIcon(":/icons/layer-visible-off.png"); + icon_vis[1] = QIcon(":/icons/layer-visible-on.png"); + ui->treeObjects->addActions(actionsSelection()); + ui->treeObjects->addAction (newSeparator()); + ui->treeObjects->addActions(actionsAdd()); + ui->buttonFilter->addActions(QList() << ui->actionFilter_node << ui->actionFilter_mesh << ui->actionFilter_light << ui->actionFilter_camera); + view = 0; + hidden_by_filter = obj_count = 0; + block_tree = false; + connect(ui->treeObjects->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(treeObjects_selectionCnahged())); +} + + +SceneTree::~SceneTree() { + delete ui; +} + + +void SceneTree::assignQGLView(QGLView * v) { + view = v; + objectsTreeChanged(); + if (!view) return; + connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + connect(view, SIGNAL(materialsChanged()), this, SLOT(materialsChanged())); + connect(view->scene(), SIGNAL(treeChanged()), this, SLOT(objectsTreeChanged())); + connect(view->scene(), SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*))); + view->setContextActions(actionsSelection()); + checkActions(); +} + + +QList SceneTree::actionsAdd() { + QList ret; + ret << ui->actionAdd_node << ui->actionAdd_light << ui->actionAdd_camera; + return ret; +} + + +QList SceneTree::actionsSelection() { + QList ret; + ret << ui->actionFocus << newSeparator() + << ui->actionGroup << ui->actionClone << newSeparator() + << ui->actionSelect_parent << ui->actionSelect_by_mesh << ui->actionSelect_by_material << newSeparator() + << ui->actionTransfer_transform_to_children << newSeparator() + << ui->actionActive_camera << ui->actionDefault_camera << newSeparator() + << ui->actionRemove; + return ret; +} + + +void SceneTree::changeEvent(QEvent * e) { + QWidget::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + return; + } +} + + +void SceneTree::rememberExpanded(QTreeWidgetItem * ti) { + for (int i = 0; i < ti->childCount(); ++i) { + QTreeWidgetItem * ci = ti->child(i); + if (ci->isExpanded()) + expanded_ << itemObject(ci); + rememberExpanded(ci); + } +} + + +void SceneTree::restoreExpanded(QTreeWidgetItem * ti) { + for (int i = 0; i < ti->childCount(); ++i) { + QTreeWidgetItem * ci = ti->child(i); + ci->setExpanded(expanded_.contains(itemObject(ci))); + restoreExpanded(ci); + } +} + + +void SceneTree::makeObjetTree(ObjectBase * o, QTreeWidgetItem * ti) { + ++obj_count; + for (int i = 0; i < o->childCount(); ++i) { + ObjectBase * co = o->child(i); + QTreeWidgetItem * ci = new QTreeWidgetItem(ti); + ci->setText(cName, co->name()); + ci->setCheckState(cVis, co->isVisible() ? Qt::Checked : Qt::Unchecked); + ci->setIcon(cVis, icon_vis[co->isVisible(true)]); + if (co->material()) + ci->setText(cMaterial, co->material()->name); + ci->setFlags(ci->flags() | Qt::ItemIsEditable); + ObjectType t = otNode; + switch (co->type()) { + case ObjectBase::glMesh: + if (co->mesh()) { + t = otMesh; + ci->setIcon(cName, icon_geo); + geo_items << ci; + } else { + ci->setIcon(cName, icon_empty); + } + break; + case ObjectBase::glLight: + t = otLight; + ci->setIcon(cName, icon_light); + break; + case ObjectBase::glCamera: + t = otCamera; + ci->setIcon(cName, icon_camera); + ci->setText(cVis, (co == view->camera()) ? "*" : ""); + cam_items << ci; + break; + default: break; + } + ci->setData(cName, irObject, quintptr(co)); + ci->setData(cName, irType, int(t)); + ci->setSelected(co->isSelected()); + makeObjetTree(co, ci); + } +} + + +ObjectBase * SceneTree::itemObject(QTreeWidgetItem * item) const { + if (!item) return 0; + return (ObjectBase*)(item->data(cName, irObject).toULongLong()); +} + + +int SceneTree::itemType(QTreeWidgetItem * item) const { + if (!item) return otNode; + return item->data(cName, irType).toInt(); +} + + +void SceneTree::selectionChanged() { + if (block_tree) return; + block_tree = true; + QList il = ui->treeObjects->findItems("", Qt::MatchContains | Qt::MatchRecursive); + const ObjectBase * fo = 0; + if (view->selectedObjects().size() == 1) + fo = view->selectedObject(); + foreach (QTreeWidgetItem * i, il) { + ObjectBase * o = itemObject(i); + i->setSelected(o->isSelected()); + if (fo && (fo == o)) { + ui->treeObjects->setCurrentItem(i); + } + } + block_tree = false; + checkActions(); +} + + +void SceneTree::materialsChanged() { + foreach (QTreeWidgetItem * i, geo_items) { + ObjectBase * o = itemObject(i); + if (!o) continue; + if (o->material()) + i->setText(cMaterial, o->material()->name); + } +} + + +void SceneTree::cameraChanged() { + if (!view) return; + foreach (QTreeWidgetItem * i, cam_items) { + ObjectBase * o = itemObject(i); + if (!o) continue; + i->setText(cVis, (o == view->camera()) ? "*" : ""); + } +} + + +bool SceneTree::filterTree(QTreeWidgetItem * ti, const QString & filter, int types) { + bool ret = false; + for (int i = 0; i < ti->childCount(); ++i) { + QTreeWidgetItem * ci = ti->child(i); + QString cit = ci->text(cName); + int t = itemType(ci); + if (ci->childCount() > 0) { + if (!filterTree(ci, filter, types)) { + ci->setHidden(true); + ++hidden_by_filter; + continue; + } + ci->setHidden(false); + ret = true; + } else { + bool f = false; + if (filter.isEmpty()) { + f = true; + } else { + f = f || cit.contains(filter, Qt::CaseInsensitive); + } + if ((types & t) != t) + f = false; + ci->setHidden(!f); + if (f) ret = true; + else ++hidden_by_filter; + } + } + return ret; +} + + +void SceneTree::checkActions() { + bool has_1 = false, has_m = false; + if (view) { + has_1 = !view->selectedObjects().isEmpty(); + has_m = view->selectedObjects().size() > 1; + } + ui->actionFocus ->setEnabled(has_1); + ui->actionRemove->setEnabled(has_1); + ui->actionClone ->setEnabled(has_1); + ui->actionGroup->setEnabled(has_m); + ui->actionTransfer_transform_to_children->setEnabled(has_1); + ui->actionSelect_parent->setEnabled(has_1); + ui->actionSelect_by_mesh->setEnabled(has_1); + ui->actionSelect_by_material->setEnabled(has_1); + ui->actionActive_camera->setEnabled(has_1); +} + + +void SceneTree::treeObjects_selectionCnahged() { + if (block_tree || !view) return; + block_tree = true; + view->scene()->clearSelection(); + ObjectBaseList sol; + QList til = ui->treeObjects->selectedItems(); + foreach (QTreeWidgetItem * i, til) + sol << itemObject(i); + view->scene()->selectObjects(sol); + block_tree = false; + checkActions(); +} + + +void SceneTree::filter() { + int types = 0; + if (ui->actionFilter_node ->isChecked()) types |= otNode ; + if (ui->actionFilter_mesh ->isChecked()) types |= otMesh ; + if (ui->actionFilter_light ->isChecked()) types |= otLight ; + if (ui->actionFilter_camera->isChecked()) types |= otCamera; + if (types == 0) types = 0xFF; + hidden_by_filter = 0; + filterTree(ui->treeObjects->invisibleRootItem(), ui->lineFilter->text(), types); + ui->treeObjects->invisibleRootItem()->setHidden(false); + ui->labelCounts->setText(tr("%1 objects, %2 hide by filter").arg(obj_count).arg(hidden_by_filter)); +} + + +void SceneTree::__objectDeleted(ObjectBase * o) { + for (int i = 0; i < geo_items.size(); ++i) + if (itemObject(geo_items[i]) == o) { + geo_items.removeAt(i); + --i; + } + for (int i = 0; i < cam_items.size(); ++i) + if (itemObject(cam_items[i]) == o) { + cam_items.removeAt(i); + --i; + } +} + + +void SceneTree::on_treeObjects_itemChanged(QTreeWidgetItem * item, int column) { + if (block_tree) return; + if (column == cName) { + ObjectBase * o = itemObject(item); + if (o) o->setName(item->text(cName)); + } + if (column == cVis) { + bool vis = item->checkState(cVis) == Qt::Checked; + QList til = ui->treeObjects->selectedItems(); + if (!til.contains(item)) { + til.clear(); + til << item; + } + foreach (QTreeWidgetItem * ti, til) { + //itemObject(ti)->setVisible(vis); + itemObject(ti)->setVisible(vis); + } + } +} + + +void SceneTree::on_treeObjects_itemMoved(QTreeWidgetItem * item, QTreeWidgetItem * new_parent) { + ObjectBase * co = itemObject(item); + if (!co->hasParent()) return; + //co->parent()->removeChild(co); + if (new_parent == ui->treeObjects->invisibleRootItem()) { + view->scene()->rootObject()->addChild(co); + } else { + ObjectBase * po = itemObject(new_parent); + if (po) + po->addChild(co); + } +} + + +void SceneTree::on_actionAdd_node_triggered() { + if (!view) return; + ObjectBase * no = new ObjectBase(); + view->scene()->addObject(no); + view->scene()->selectObject(no); +} + + +void SceneTree::on_actionAdd_light_triggered() { + if (!view) return; + ObjectBase * no = new Light(); + view->scene()->addObject(no); + view->scene()->selectObject(no); +} + + +void SceneTree::on_actionAdd_camera_triggered() { + if (!view) return; + ObjectBase * no = new Camera(); + view->scene()->addObject(no); + view->scene()->selectObject(no); +} + + +void SceneTree::on_actionClone_triggered() { + if (!view) return; + QList sil = ui->treeObjects->selectedItems(); + ObjectBaseList col; + foreach (QTreeWidgetItem * i, sil) { + ObjectBase * o = itemObject(i); + if (!o) continue; + ObjectBase * no = o->clone(); + o->parent()->addChild(no); + col << no; + } + view->scene()->selectObjects(col); +} + + +void SceneTree::on_actionGroup_triggered() { + if (!view) return; + ObjectBaseList sol = view->scene()->selectedObjects(true); + ObjectBase * cp = sol[0]->parent(); + ObjectBase * nr = new ObjectBase(); + cp->addChild(nr); + foreach (ObjectBase * o, sol) + nr->addChild(o); + view->scene()->selectObject(nr); +} + + +void SceneTree::on_actionTransfer_transform_to_children_triggered() { + if (!view) return; + ObjectBaseList sol = view->scene()->selectedObjects(true); + foreach (ObjectBase * o, sol) + o->transferTransformToChildren(); +} + + +void SceneTree::on_actionActive_camera_triggered() { + if (!view) return; + ObjectBase * o = view->scene()->selectedObject(); + if (!o) return; + if (o->type() != ObjectBase::glCamera) return; + view->setCamera((Camera *)o); + cameraChanged(); +} + + +void SceneTree::on_actionDefault_camera_triggered() { + if (!view) return; + view->setDefaultCamera(); + cameraChanged(); +} + + +void SceneTree::on_actionSelect_parent_triggered() { + if (!view) return; + ObjectBaseList sol = view->scene()->selectedObjects(true); + QSet nsl; + foreach (ObjectBase * o, sol) { + ObjectBase * po = o->parent(); + if (po != view->scene()->rootObject()) + o = po; + nsl << o; + } + view->scene()->selectObjects(nsl.toList()); +} + + +void SceneTree::on_actionSelect_by_mesh_triggered() { + view->scene()->selectObjectsByMesh(); +} + + +void SceneTree::on_actionSelect_by_material_triggered() { + view->scene()->selectObjectsByMaterial(); +} + + +void SceneTree::removeObjects() { + if (!view) return; + QList sil = ui->treeObjects->selectedItems(); + foreach (QTreeWidgetItem * i, sil) { + ObjectBase * o = itemObject(i); + if (o) delete o; + } + qDeleteAll(sil); +} + + +void SceneTree::focusObjects() { + if (!view) return; + if (!view->camera()) return; + Box3D bb; + ObjectBaseList ol = view->selectedObjects(); + foreach (ObjectBase * o, ol) { + o->calculateBoundingBox(); + bb |= o->boundingBox(); + } + view->focusOn(bb); +} + + +void SceneTree::objectsTreeChanged() { + int vpos = ui->treeObjects->verticalScrollBar()->value(); + expanded_.clear(); + geo_items.clear(); + cam_items.clear(); + rememberExpanded(ui->treeObjects->invisibleRootItem()); + block_tree = true; + ui->treeObjects->clear(); + block_tree = false; + if (!view) return; + block_tree = true; + obj_count = 0; + makeObjetTree(view->scene()->rootObject(), ui->treeObjects->invisibleRootItem()); + --obj_count; + restoreExpanded(ui->treeObjects->invisibleRootItem()); + block_tree = false; + filter(); + QApplication::processEvents(); + ui->treeObjects->verticalScrollBar()->setValue(vpos); +} diff --git a/widgets/scene_tree.h b/widgets/scene_tree.h new file mode 100644 index 0000000..bf16a55 --- /dev/null +++ b/widgets/scene_tree.h @@ -0,0 +1,100 @@ +/* + QGL SceneTree + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef SCENE_TREE_H +#define SCENE_TREE_H + +#include +#include +#include "glscene.h" + +class QTreeWidgetItem; + +namespace Ui { + class SceneTree; +} + +class SceneTree: public QWidget +{ + Q_OBJECT +public: + SceneTree(QWidget * parent = 0); + ~SceneTree(); + + void assignQGLView(QGLView * v); + QList actionsAdd(); + QList actionsSelection(); + +private: + void changeEvent(QEvent * e); + void rememberExpanded(QTreeWidgetItem * ti); + void restoreExpanded(QTreeWidgetItem * ti); + void makeObjetTree(ObjectBase * o, QTreeWidgetItem * ti); + ObjectBase * itemObject(QTreeWidgetItem * item) const; + int itemType(QTreeWidgetItem * item) const; + bool filterTree(QTreeWidgetItem * ti, const QString & filter, int types); + void checkActions(); + + Ui::SceneTree * ui; + bool block_tree; + int hidden_by_filter, obj_count; + QIcon icon_empty, icon_geo, icon_camera, icon_light, icon_vis[2]; + QSet expanded_; + QList geo_items, cam_items; + QGLView * view; + +private slots: + void treeObjects_selectionCnahged(); + void on_treeObjects_itemChanged(QTreeWidgetItem * item, int column); + void on_treeObjects_itemMoved (QTreeWidgetItem * item, QTreeWidgetItem * new_parent); + + void on_actionAdd_node_triggered(); + void on_actionAdd_light_triggered(); + void on_actionAdd_camera_triggered(); + + void on_actionFocus_triggered() {focusObjects();} + void on_actionRemove_triggered() {removeObjects();} + void on_actionClone_triggered(); + void on_actionGroup_triggered(); + void on_actionTransfer_transform_to_children_triggered(); + + void on_actionActive_camera_triggered(); + void on_actionDefault_camera_triggered(); + + void on_actionSelect_parent_triggered(); + void on_actionSelect_by_mesh_triggered(); + void on_actionSelect_by_material_triggered(); + + void removeObjects(); + void focusObjects(); + void objectsTreeChanged(); + void selectionChanged(); + void materialsChanged(); + void cameraChanged(); + void filter(); + void __objectDeleted(ObjectBase * o); + +public slots: + +signals: + +private: + +}; + +#endif // SCENE_TREE_H diff --git a/widgets/scene_tree.ui b/widgets/scene_tree.ui new file mode 100644 index 0000000..ec57188 --- /dev/null +++ b/widgets/scene_tree.ui @@ -0,0 +1,425 @@ + + + SceneTree + + + + 0 + 0 + 442 + 606 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Filter: + + + + + + + + + + + :/icons/configure.png:/icons/configure.png + + + QToolButton::InstantPopup + + + + + + + Qt::Vertical + + + + + + + Expand tree + + + + :/icons/expand.png:/icons/expand.png + + + + + + + Collapse tree + + + + :/icons/collapse.png:/icons/collapse.png + + + + + + + + + + + + + + + + Qt::ActionsContextMenu + + + QAbstractItemView::InternalMove + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::ScrollPerPixel + + + true + + + false + + + + Name + + + + + Vis + + + + + Material + + + + + + + + + :/icons/type-camera.png:/icons/type-camera.png + + + Focus + + + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + Remove + + + + + + :/icons/edit-copy.png:/icons/edit-copy.png + + + Clone + + + + + + :/icons/group.png:/icons/group.png + + + Group + + + + + + :/icons/go-top.png:/icons/go-top.png + + + Select parent + + + + + + :/icons/type-geo.png:/icons/type-geo.png + + + Select by mesh + + + + + + :/icons/format-fill-color.png:/icons/format-fill-color.png + + + Select by material + + + + + + :/icons/add-type-empty.png:/icons/add-type-empty.png + + + Add node + + + + + + :/icons/add-type-light.png:/icons/add-type-light.png + + + Add light + + + + + + :/icons/add-type-camera.png:/icons/add-type-camera.png + + + Add camera + + + + + true + + + + :/icons/type-empty.png:/icons/type-empty.png + + + Nodes + + + + + true + + + + :/icons/type-geo.png:/icons/type-geo.png + + + Meshes + + + + + true + + + + :/icons/type-light.png:/icons/type-light.png + + + Lights + + + + + true + + + + :/icons/type-camera.png:/icons/type-camera.png + + + Cameras + + + + + Transfer transform to children + + + + + + :/icons/type-camera.png:/icons/type-camera.png + + + Active camera + + + + + + :/icons/type-camera.png:/icons/type-camera.png + + + Default camera + + + + + + CLineEdit + QLineEdit +
    clineedit.h
    +
    + + InternalMoveTreeWidget + QTreeWidget +
    treewidget_p.h
    +
    +
    + + + + + + + + + + buttonExpand + clicked() + treeObjects + expandAll() + + + 395 + 164 + + + 299 + 359 + + + + + buttonCollapse + clicked() + treeObjects + collapseAll() + + + 427 + 164 + + + 332 + 369 + + + + + lineFilter + textChanged(QString) + SceneTree + filter() + + + 273 + 130 + + + 355 + 37 + + + + + actionFilter_camera + toggled(bool) + SceneTree + filter() + + + -1 + -1 + + + 414 + 302 + + + + + actionFilter_mesh + toggled(bool) + SceneTree + filter() + + + -1 + -1 + + + 414 + 302 + + + + + actionFilter_light + toggled(bool) + SceneTree + filter() + + + -1 + -1 + + + 414 + 302 + + + + + actionFilter_node + toggled(bool) + SceneTree + filter() + + + -1 + -1 + + + 414 + 302 + + + + + + removeObjects() + focusObjects() + filter() + +
    diff --git a/widgets/treewidget_p.h b/widgets/treewidget_p.h new file mode 100644 index 0000000..18cce4b --- /dev/null +++ b/widgets/treewidget_p.h @@ -0,0 +1,51 @@ +/* + QGL SceneTree + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef TREEWIDGET_H +#define TREEWIDGET_H + +#include +#include +#include +#include + +class InternalMoveTreeWidget: public QTreeWidget +{ + Q_OBJECT +public: + InternalMoveTreeWidget(QWidget * parent = 0): QTreeWidget(parent) {} + +protected: + virtual void dropEvent(QDropEvent * e) { + QList sil = selectedItems(); + if (sil.isEmpty()) return; + QTreeWidget::dropEvent(e); + foreach (QTreeWidgetItem * ti, sil) { + QTreeWidgetItem * ti_p = ti->parent(); + if (!ti_p) ti_p = invisibleRootItem(); + int ti_ppos = ti_p->indexOfChild(ti); + emit itemMoved(ti, ti_p, ti_ppos); + } + } + +signals: + void itemMoved(QTreeWidgetItem * item, QTreeWidgetItem * new_parent, int new_index); + +}; + +#endif // TREEWIDGET_H diff --git a/widgets/view_editor.cpp b/widgets/view_editor.cpp new file mode 100644 index 0000000..ab48597 --- /dev/null +++ b/widgets/view_editor.cpp @@ -0,0 +1,179 @@ +/* + QGL ViewEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "view_editor.h" +#include "ui_view_editor.h" +#include +#include +#include + + +ViewEditor::ViewEditor(QWidget * parent): QWidget(parent) { + ui = new Ui::ViewEditor(); + ui->setupUi(this); + view = 0; + active = true; + ui->checkCameraLight->setCheckState(Qt::PartiallyChecked); +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) + ui->spinDepthStart->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); +#endif +} + + +void ViewEditor::assignQGLView(QGLView * v) { + view = v; + if (!view) return; + active = false; + ui->spinFOV->setValue(view->FOV()); + ui->spinDepthStart->setValue(view->depthStart()); + ui->groupHoverHalo->setChecked(view->isHoverHaloEnabled()); + ui->groupSelectionHalo->setChecked(view->isSelectionHaloEnabled()); + ui->spinHoverHaloFill->setValue(view->hoverHaloFillAlpha()); + ui->spinSelectionHaloFill->setValue(view->selectionHaloFillAlpha()); + ui->colorHoverHalo->setColor(view->hoverHaloColor()); + ui->colorSelectionHalo->setColor(view->selectionHaloColor()); + ui->checkFXAA->setChecked(view->isFeatureEnabled(QGLView::qglFXAA)); + ui->checkCameraOrbit->setChecked(view->isCameraOrbit()); + ui->checkCameraLight->setCheckState((Qt::CheckState)view->cameraLightMode()); + ui->checkService->setChecked(view->isServiceMode()); + ui->lineHDR->setProperty("GLpath", view->environmentMapFile()); + ui->lineHDR->setText(QFileInfo(view->environmentMapFile()).fileName()); + active = true; +} + + +void ViewEditor::changeEvent(QEvent * e) { + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +void ViewEditor::on_spinFOV_valueChanged(double val) { + if (!view || !active) return; + view->setFOV(val); +} + + +void ViewEditor::on_spinDepthStart_valueChanged(double val) { + if (!view || !active) return; + view->setDepthStart(val); +} + + +void ViewEditor::on_spinViewGamma_valueChanged(double val) { + if (!view || !active) return; + view->setGamma(val); +} + + +void ViewEditor::on_comboViewRenderMode_currentIndexChanged(int val) { + if (!view || !active) return; + static int modes[] = {GL_POINT, GL_LINE, GL_FILL}; + view->setRenderMode((ObjectBase::RenderMode)modes[val]); +} + + +void ViewEditor::on_groupHoverHalo_clicked(bool val) { + if (!view || !active) return; + view->setHoverHaloEnabled(val); +} + + +void ViewEditor::on_groupSelectionHalo_clicked(bool val) { + if (!view || !active) return; + view->setSelectionHaloEnabled(val); +} + + +void ViewEditor::on_spinHoverHaloFill_valueChanged(double val) { + if (!view || !active) return; + view->setHoverHaloFillAlpha(val); +} + + +void ViewEditor::on_spinSelectionHaloFill_valueChanged(double val) { + if (!view || !active) return; + view->setSelectionHaloFillAlpha(val); +} + + +void ViewEditor::on_colorHoverHalo_colorChanged(QColor color) { + if (!view || !active) return; + view->setHoverHaloColor(color); +} + + +void ViewEditor::on_colorSelectionHalo_colorChanged(QColor color) { + if (!view || !active) return; + view->setSelectionHaloColor(color); +} + + +void ViewEditor::on_checkAutoExposure_toggled(bool val) { + if (!view || !active) return; + view->setAutoExposure(val); +} + + +void ViewEditor::on_checkFXAA_clicked(bool val) { + if (!view || !active) return; + view->setFeature(QGLView::qglFXAA, val); +} + + +void ViewEditor::on_checkCameraOrbit_clicked(bool val) { + if (!view || !active) return; + view->setCameraOrbit(val); +} + + +void ViewEditor::on_checkService_clicked(bool val) { + if (!view || !active) return; + view->setServiceMode(val); +} + + +void ViewEditor::on_checkCameraLight_stateChanged(int s) { + if (!view || !active) return; + view->setCameraLightMode((QGLView::CameraLightMode)s); + +} + + +void ViewEditor::on_buttonHDRClear_clicked() { + if (!view || !active) return; + ui->lineHDR->setText(""); + ui->lineHDR->setProperty("GLpath", ""); + view->setEnvironmentMapFile(""); +} + + +void ViewEditor::on_buttonHDRSelect_clicked() { + if (!view || !active) return; + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineHDR->property("GLpath").toString(), "Radiance HDR(*.hdr)"); + if (str.isEmpty()) return; + ui->lineHDR->setText(QFileInfo(str).fileName()); + ui->lineHDR->setProperty("GLpath", str); + view->setEnvironmentMapFile(str); +} diff --git a/widgets/view_editor.h b/widgets/view_editor.h new file mode 100644 index 0000000..405fa4b --- /dev/null +++ b/widgets/view_editor.h @@ -0,0 +1,67 @@ +/* + QGL ViewEditor + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef VIEW_EDITOR_H +#define VIEW_EDITOR_H + +#include +#include "qglview.h" + +namespace Ui { + class ViewEditor; +} + +class ViewEditor: public QWidget +{ + Q_OBJECT +public: + explicit ViewEditor(QWidget * parent = 0); + + void assignQGLView(QGLView * v); + +protected: + void changeEvent(QEvent * e); + + Ui::ViewEditor * ui; + QGLView * view; + bool active; + +private slots: + void on_spinFOV_valueChanged(double val); + void on_spinDepthStart_valueChanged(double val); + void on_spinViewGamma_valueChanged(double val); + void on_comboViewRenderMode_currentIndexChanged(int val); + void on_groupHoverHalo_clicked(bool val); + void on_groupSelectionHalo_clicked(bool val); + void on_spinHoverHaloFill_valueChanged(double val); + void on_spinSelectionHaloFill_valueChanged(double val); + void on_colorHoverHalo_colorChanged(QColor color); + void on_colorSelectionHalo_colorChanged(QColor color); + void on_checkAutoExposure_toggled(bool val); + void on_checkFXAA_clicked(bool val); + void on_checkCameraOrbit_clicked(bool val); + void on_checkService_clicked(bool val); + void on_checkCameraLight_stateChanged(int s); + void on_buttonHDRClear_clicked(); + void on_buttonHDRSelect_clicked(); + +signals: + +}; + +#endif // VIEW_EDITOR_H diff --git a/widgets/view_editor.ui b/widgets/view_editor.ui new file mode 100644 index 0000000..744b0a5 --- /dev/null +++ b/widgets/view_editor.ui @@ -0,0 +1,511 @@ + + + ViewEditor + + + + 0 + 0 + 328 + 538 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Draw mode: + + + + + + + 2 + + + + Point + + + + + Wireframe + + + + + Solid + + + + + + + + Gamma: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.010000000000000 + + + 5.000000000000000 + + + 1.000000000000000 + + + 2 + + + + + + + Env HDR: + + + + + + + 2 + + + + + + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + + :/icons/document-open.png:/icons/document-open.png + + + + + + + + + + + + + + FXAA + + + + + + + Auto exposure + + + + + + + Service mode + + + true + + + + + + + Camera light + + + true + + + + + + + + + Camera + + + + + + + + Orbit + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 1 + + + + + + + + FOV: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0.100000000000000 + + + 179.900000000000006 + + + 60.000000000000000 + + + + + + + + + + + Depth start: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 3 + + + 999999999.000000000000000 + + + 1.000000000000000 + + + + + + + + + + + + Hover halo + + + true + + + + + + Fill: + + + + + + + 0.000000000000000 + + + 1.000000000000000 + + + 0.300000000000000 + + + 2 + + + 0.050000000000000 + + + 0.100000000000000 + + + + + + + + 255 + 0 + 251 + + + + true + + + + + + + + + + Selection halo + + + true + + + + + + Fill: + + + + + + + 0.000000000000000 + + + 1.000000000000000 + + + 0.300000000000000 + + + 2 + + + 0.050000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 143 + 239 + + + + true + + + + + + + + + + + + + 0 + 0 + + + + Fog + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Density: + + + + + + + + + 0.000000000000000 + + + 10.000000000000000 + + + 0.000000000000000 + + + 3 + + + 0.050000000000000 + + + 0.100000000000000 + + + + + + + + 128 + 128 + 128 + + + + + + + + + + Decay: + + + + + + + 0.000000000000000 + + + 9999.000000000000000 + + + 10.000000000000000 + + + 2 + + + 0.050000000000000 + + + 0.100000000000000 + + + true + + + 9999.000000000000000 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + SpinSlider + QWidget +
    spinslider.h
    +
    + + ColorButton + QPushButton +
    colorbutton.h
    +
    +
    + + + + + +
    diff --git a/widgets/widgets.qrc b/widgets/widgets.qrc new file mode 100644 index 0000000..c83819f --- /dev/null +++ b/widgets/widgets.qrc @@ -0,0 +1,18 @@ + + + ../icons/go-jump.png + ../icons/dialog-close.png + ../icons/dialog-cancel.png + ../icons/edit-clear.png + ../icons/configure.png + ../icons/document-save.png + ../icons/edit-find.png + ../icons/list-add.png + ../icons/edit-delete.png + ../icons/edit-copy.png + ../icons/edit-paste.png + ../icons/document-edit.png + ../icons/group.png + ../icons/format-fill-color.png + +

    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 Ag8%>k literal 0 HcmV?d00001 diff --git a/icons/transform-move.png b/icons/transform-move.png new file mode 100644 index 0000000000000000000000000000000000000000..b20fc4482967538ec7b1cfacd6c9af1884fb78d8 GIT binary patch literal 24712 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 literal 0 HcmV?d00001 diff --git a/icons/transform-rotate.png b/icons/transform-rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..50631586fc018fb27a37f45fb1c5cf94e9c2b234 GIT binary patch literal 20621 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 YEi!afq-Av(#0&yw&)8rq&ApQT2Lyk6+5i9m literal 0 HcmV?d00001 diff --git a/icons/transform-scale.png b/icons/transform-scale.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff1d443b084bc2d22ea8687e94e0afbb02d9fce GIT binary patch literal 8092 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 UNR*#30pO43MLo5=^929@0rbsTIRF3v literal 0 HcmV?d00001 diff --git a/icons/type-camera.png b/icons/type-camera.png new file mode 100644 index 0000000000000000000000000000000000000000..e7fcde0b3f98aa9add014848aad1b6a46f0c20d5 GIT binary patch literal 33163 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 VBc=Sg2vDX$m-Vme6<%}*|3B}Wpxpof literal 0 HcmV?d00001 diff --git a/icons/type-empty.png b/icons/type-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..337f0dec34d2ebebd19f4a0047cd574584d706f1 GIT binary patch literal 2071 zcmV+y2qkIJ-^$KNKzAHxM zdB*!Ldp}oP`GIFjUmpDMEw`OmH-JC<{;8=wd#?MtbD7PYJtLtki7_tgW47812DbW~ zX7A`X$S75cR>7s0UT%WP$rq0A*?-{XXb}RPwyYpWgvi8UVMq|mt9V* z!i7TRf7pypyTd!2m4beTkq$7nr(s zFW2mzTJ}Hh{fad2g9pGl$N2a-*X*7mrO5GP$A->d`4K6UQleZean224nX%*QodEpn z^;7)zH@_xU6|Gi_&=}lL$%hYpA9cz{Zn=#suDpsJJ9cv9uYVa_V+=~~M+0C6J_NEM zgUu3SV`BjP>DgznlyJ^bRjX$%RmGC==Vzbc6L($3*!VahctmtybcNta$wu*j5xgf2 z@jz+}2AG?jC8o6%ytij(dvq#GUkCLd19Lw*g+lNo%Z38zal8toH3EpbG%i$OC4fdw zO-@WQbLPxY88bWvydO%TE`ToBwMq`>94RGK74MfkU}lVuZz9IX!omVCz4%YEETbs$ z5j{`_YzY4*CntK(|DHQfUKDEr(Dw7a=kc*|M1-;|DNE1HnU@KrN1WoE!^}pD0keb; zVMP(CCrnICOmNf99|EA$USM%?u`Xz=EMWaLV{&qWs;cO8+DuGLa^R*9^5aK;$in?+zXti1ttua)j;iB-32fo>xxZPgh@t^;UiOESs6th%=H0vDz zQc9#0i7|5a>xJSoLKI5N79QdF=3E05)&lf;b&K<{d9_%I3{m0C?>1PneyX1%zaS$E@1}(b7;A z2rxZ!x|bI7EGOF9(rBLLy#hFM_RNLr#z<;3CQ=*@pnFzORSdge|1OI((_Xy9P$4>8 zFeVuVz#2SYeUj5<4j+6Iu(I;b!@4EbaM_YPNf>g0bw)l9tj@h|Fbg6|2!TA$*|zNx zf}if~rbs`6I)l~rCobN0Nl$jGDAv@ST0+>mve24?*peX#P6ek9=Nwt)m_2t6fZOl* z7)5KWQKT7}I-DxbY5nXn%o44l;MUvk0AO}@7MEo>SI?)a2wJD>WdB_d_ly=noI@3y zD58prB3gUk=+Ps5^w!(BVgHTXu)n^#`O5wGp?TIjG8$l^;yd4caM>DvJNg`%b0jm& zq)wrlkR;9eu~+#=01#_qRdFhaI#i`Gz6PM8Jo&`05D~7s{(3ID=pypGAj>l{m-WSf z^}vMSnR|PVBS)U&$tRw`Ifo=8H2@?DkyO)Enq)Gh5)ag=_k8v}_JB$AKTx_^v3t@ojQR-R8j+Srsd*QJ1SUYNLs%Qhq8Nx07e~}W zBHHY#_IAEYD|NN;+KUTWdKU$SS``S0)pDZQVKYTF5tASdz3Nn1VJIw6tlMa7}n5-8Vz5Rv*eqw5K)(`Yh78;V%0=ZliCSaV;@AsSH=%xYPk ziFR}H`T*ql7)6%jeFO+HtrOEJ(5 z&PGDV7^z}KY%)w0BdMz2W31}$tBS?NMfUC8VXwA3Pp`X>&Cf3!EK4tYrlu^<3#wRA zdXEnkA%teJxK!u>QR>X(99foA6a__5kma>_Q&(RprY@yYs^_U9z6ylk@jg(63g>dJ z*|po+osOKJKYwtfpP26a_?^45+&y&et+x)md3J`E@u0s+n)x$@c1u&d2-{|z>T)iHroGZ`w!j%jH{#X+-Cp)002ovPDHLkV1l&% B>KXt5 literal 0 HcmV?d00001 diff --git a/icons/type-geo.png b/icons/type-geo.png new file mode 100644 index 0000000000000000000000000000000000000000..d6b825ca09cf86103dc4d334e5fdd26b6e8162de GIT binary patch literal 5538 zcmV;T6 zaB^>EX>4U6ba`-PAZ2)IW&i+q+O?W%b{jhmg#U9Dvjo0LEC+m@Gdq~&&j(8Kjh)!e zy_1nn)N-rECQ(3Dfr{Jz`S)@E;*pb7mrLtaYV|y_WQod~?jH}mufga0dLQZe5r4ls z@7_L$oJxOP+3WNC=6vM(_&h(K<0$9L4+F`5elXsDpwEF~f8OAE{&k}i9yjpMft@}F zO7VH;{P=r3mgTGT_Tv)f^ZN7r{Dy&l&R%kAv6dQI<~2v(S{2^+=yM}(%O;xIz5m;d zKK|`qmqz9kcM8e#+HHo3=_g6bYq+ms*YLFWiPvJ+*-SwzI^TFNueg5w_-f|vHT5Ut z?;w497d|=v1JdpW^z}jdfKYuq{_=b%f1P*lvdnP%;m)l5I^tM{6fwCowNEm z`>{IBl_l5bqFzh6@3?MQwC=Ym&&I#vy9L{x!n0En6F3*Q96V=`5P|W899Gb9!oJ5D zCR5CD$Hp^!lN~T5&I@<8XE?C|{7N0LC+Uzl8{g&e*w-{Xufk1WuQl=hLjssXiDRD8$ zm{Y2NLltmuzSF|JG?w@{4G{uFN!6tWHk2k{QTCgsB%+fWaZn+1*#*CH1a5;jyC#` zp)-euR_cHgq~kZLELe9Eb(oqog}eM9XD z>rc#$6`9;xh|C#ni)C5*AcUi$zZ3prGLX!T6ZR0o54-=@>mLT%Ba zO<@;Sd!s-2TdAaDde&w-E7q0r={xtm&-trwrC;G6QjiIz(a~Ap;8YpTJmMt@Er!Flt-7A5ZuS8Fof#Qlr!|a67n{Wy^(( z;Gtol5!+5eB?i@6dP0u;l$7Ft|E9F+^M>jUNnL%u+JT(#vu`v&vb;}Z7C>Fh~XIr8c3pkuD6dx8Egj3xpf z#6EMM)$sOBOIs;5@)VOS$j;7{si(S+kXl9~o@%8)%0hiMDo!woWSrC>e4hO1+#B|l z*bad|WWh-aP^iJyR^<4-)S1+%As~q;h>vIPNhqopxV`Fbgc61`3ym4HG|o^68i-{5 zGd_YVp+rGv(Ynd}ltIg0Gy-sgTeTjmqXjXT6wX2N)0|z8K787vz?s0t!a-|jo!C#R z^Bmpj%u3QwK+wn{HluZ8?BQ45ne;*NP&?Fp9J&`;ok3MEv6Y@UN1na%DW(l_At@H2 za}}9~&c_1vaOxrp{3LG3sn3-N!=_Csh;O>nJ=WilkDTW z`KJe2J$aG|?6Pn-B6V>W+*hc3tgW6@W%^-QU?`&(Htx;(~tx)K4)LrIPZ|=l&qhLLO4aSBiC>3IA!QD_VZD^*0v-E!@*hKe~?17;i zT9oqguq)Ys-<#=H>jZl8?@_J=o+5G)O(MDlXK3yKkZSE6YrtKz!zVDELb(<~!+f<2 z#1>`@MoqgiPtorkiTnBj_{{bYkTNAwYEsyMc&|!9q20_vab#$>g9xY=L>wqHQcN^O z%-P~(H|lPY*{0hAvXE2Es~=QNke|LuOqjry;Q9nYli+ZgurfwkLc&3X3B|^Y;>HPD z0}jv;ON)-*vEw2u%@Jkh@4iwSx>)7r6UUM>h&$ewFzj{$y@Fj0r)C3mC%Xy0Ck=uv3oUsBGB@~wTuFMlAGd(f zP~<334oZ?zgJ>De0L87pRFUuWv?Fg~o<0t{$y(hK3Fo#Pg{Ka@;uFb76 zXI7IrJ@JgN8}%56c0;@XDCkM|cF8HS9<=1ZMGY5=jd;^!qN+qg;d;yJuRbT7K0S)l z`Om7h^pW@yNUfy^Gg8jiW1P4EgT4`K+5#_S$5k5wIr^mxY7kQheV?6+3?p}_o&JIj zpJW;Bl@s(UND4tGbRgFkJ#`p(NSLYQYyB2nO?6MJ3RaJMqz}g`VkV{7_sqsqvL2h; zjGiglS53KJ7g;9L86B#?$SrIw)c`jmN~j_wq9nJc1Sl!2%nHPa_sDnv0`iF-juva; z9r>7Q8-3e`qwh)q)@+?A2&B34M=5FU&tT?*`!krG?fxcaAG1Erj27p*T^7jnDryU+ z6SM#xoj^A7v9|W^Y8Ghk)ke0~>Lvl{yv>VVp7Z|lVyMIY z9>|mfbpDmGarP!jp&0YJbDJI3&CSRqY@0XSHDvKdNK?R?p>_hE@f;uUThz$KJUw_R1zQu=@B&^D%RW7+(|OJ1~Mi(?sy z9xpn&`A#2*C8oorRi{*}g~oYH!roe+g=A7*`EHir-*UF!7U)mY>gFo&VKg(2xhgHz z@NRq;sf^=9~nuLsH)qy1eBsljc z8psX!S<$GN{$)Kxpg*QBvA&2x5#7a90d!%`BN2?u=m}n?&FL{Oav^}DF~WV$8k?j=7U~v~DEQAr&Bw(uf54OEfAOk7~BifML$+@MVO{TcIg{O%v7%hsfXD zBBMm^m-x2g*|lfeoTV|$9kCA?mlch>9w-jFLYnWz1r&zu4dW=rh?!o*5-yj6`WtZ| z(XH3W66x++#21%hyUH>lU~A<7z2GAGw&YuaoisB8=dQOPVJ5c2ej%mnOEC4yYagn( zM+A5kZbJiR2k1|UUcrUTZJX1`nM#Om*e3aY{7ORIu16oB;iIhR)sVYaV+Q)g$|RXm zC}=;9{BZN#>wpc(q#fRoHJ%4YLsy|y@zS;bahp~B_7p89erq2lIt3ZJR0Gu+b|9uGu-JCTP*}8P zW6?ockyW(gjhu%v`Z~qQnAUT(7@$zwEGuP_RfHdtXTNFeKtdYP zZBX6t9K9t~ZPb2!bXXMkO`TWbNV*wf$+OG}yycFIhVR0L*ssnSj5%;b-ZK5MJCP`T zoLB4l(FWZv$fR5vShrO%-Q3n(EiF_@zS|xIB8ASpI7Y}E9KfEZ5O=zT%4#9#@^CA5 z2~0*~3EMadQnT4SnlSp!Y^6N6f!K@-=)L@>eb0|a_uU0w9W$H@iP1^;<1%HuVk=Z1 zoLlHp=)y5bg^HYt7uAQL?G^=iuAm`!t&fvw2)F%^L<($IiWHh2R&3v5LDhCiB;Fk( zhOOSDmh0)FyzQxt*-u^wW5K5_bSDuo`^Ar&kTMHtM_1ELq(YcyS$H_Qa?9$9=fnX% zs06I+|5j|**V7D{w_%34ZpNIPYHxNW=8eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00r(zL_t(&-tC!9Y*bYkhM)V>J3nQHb{cI%NElK@G!hXgVFAQwh&2$SNduA?T!=es zB5YXbqA^5W7&jy?bcM2jjgnvtsS9HWO-PU*XRry=q|9`fsSNG>-1c^6?wsRdW~4$( z@66m5Nc@u7+?+G_eb4uv_niBE@Pvo9O#izISO=79zbB5s%fN@g4&Ww`eUh@e6(|4_ zuz>{dIS_slz`p`aYMLfhRh6o$${LY5;0o||O8hOiWCuLI|&v z@}efxHFT_=@FQ7)Ht zpj%4W--@iXR>1rH{6%h3M{Tw}dl!1W(y1KetJCN>| zRW6s)oXARZ;_<4gex&PqAP@*VV3TgfVzQD__9%*S0C*nwc|HlnfyeI!+Pb^D85$a5 zf0r=ME^SxylMq6)h?}~#jm&>G5DfaBy zgWvD3Kh6QE`Q!9O=6?h1E|<&f*s-H&r)f4U%i`L#Yg8%~JRT2Tub0``S%4|PbV8sH zKnTI1LxVkc(fGwAl&w2MFc>72N-;Atv+UqgsT7e-4XWnc!t zGI${bqobot zPfs^BUvGAkS(ZgdM+bhtA4O4`cA983+LAo=R#q>Y&63aO357!ck(<*+h(sckO05+w zbT=fB$zb;g+c+-Gzo=5c)i~LI87pvAdyJ8`aahQ)WP1pdl$nn2!%ob#9}crnT+f2S{4HJ zD3wa2(`ho945n!=%R5w7AZquRmM(U+@I4X&t;E>a*!=9RUQr4C`_a+FL02pmiAJNG zJ$tt9YBunx69TJ%_PT~G%fjdLt>~&3i$yM7y2SACaQ&dmQmw20=H#1r9o5pfr&KCo znkH-4uBE-by(MdP>ibhuQw$FeGcq!QZQDpG{{{vY0>2o667UqT8PMYKI2SKoB%jaI z-QC?3k$gVyh``j;6z9&JBN~lj+crXovD(UyG*VV60T+Njfain|opW<@dMp+r8jTVR z2I=bRqOGmX)eO|Z$6_%QMZvc1%fNfUmKd{gyHx}FE^9hWNjdAkiNoHnds8lM`z-Pdhwb~~uMPQ*#zNoCE zl+4b~a{c;s&YU@eWm!lmO{%@M@2IwAA9)07ht3tMZB?mhnhb}-a&T}^?%lgr8irAC zyJmrRYjYmE2m@bGZE#zvs!GE!q+uBKzVRg0M#*CzVX8G&lY3qJ7}XY)YoRS8fx278 kfFcmDT@o+zf82|I0H5$6;madKxBvhE07*qoM6N<$g69a1zW@LL literal 0 HcmV?d00001 diff --git a/icons/type-light.png b/icons/type-light.png new file mode 100644 index 0000000000000000000000000000000000000000..53011730f14d49e03853ff037e4893d588770d8e GIT binary patch literal 2899 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 literal 0 HcmV?d00001 diff --git a/icons/view-refresh.png b/icons/view-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..66f0cebe10de3813d2c7d752637bd45151e56756 GIT binary patch literal 40505 zcmV)xK$E|TP)S%cYE6;%{MbDE9tcDZtwPN@3VE1MrBpz_j_gDj2OsEUh=Zr3X|&#$V*=G zk~_&0Kwk2)8%v%5b|XOurTxAchC#W$-n5KTi}px8w<6Cz2#U zXA;b{WhOzH>GU>pYgw}L_{sC6u+vDM0EV$70K65@WX`I~tYI5#*_TaFu8C}zBg5Rf zY`1Ql0BndMPYT0R@&qu9#0Kz*z^=_Xb#7edEX$_tQHb)Zwyi4M*uJr_sk6x+Lou$z zS<*AAa#UbW^_)PNrz{Ezz$L?6Tb3OdBM49!F?d2KL?(RRATI00#{`@XXKkscbp711b5~!!=<;p&3^A}L z1>g(HM`8iK74$|;&egWmI`4S*j!7FkHqPh`^-hV((Fw97kHs(=iJ@HN z;2eyDcL1J)zzL>_XL)7L;W?|UlVyAyB>*yEz|%>TL`noPDMpuLvN|X0vNDf}F^Ec0 zeZt!bQPeXmvkjkjv)kd`Q0^`N;lw>p{O;sEPVR!l)`I3r#2-SQ42E3t1Te&61AMDV z&z<(vX%p6LUvqeGw0AMq$TL`pt-;_DG*ADT-QR*sv|E}eC zeX`exy&_wA5X~=&qD}&dz^^TnNdrG!j>QRpZWrTLf=UPw zL$O|LDXio;?mwm8(s$mx=FKlEp;Cl65$F~{o(P6U@&qtMVgNro_nx^W+ncr@E=8n6 zu$J7HmD%waoQx5`eSmM!>UP^TvJm(<;I(oJe2oZr#VQ~cfQbNPB?h3G`5N#wcR&NO zkqk7T8%cozpGawocrI^+HSJo2{gnn*yBE&;24yXY-UmXE~l ziM^jEfWenM0Su;`4K65xlNgyf3mdryV6R(XSr#EEa$f=vHgMWEDte($Go5jw}rO8v~A*hDb{UAO>w?1m<~6 zP7lF7urAlHa#xi+0St!x6qaBk_Izy29)%}A14^`=Xk6lZ8zb@*lxzZkvx2=(&&I)= zk`VB*dLU3W|H)e?L_`GpRSM;5dk3%JHY$Bekd(0g{tBzs4T360#^aJ1Q)n?mnlFtMN2bnDC$x6ALQ_W*w05;ZTTdH=qv1HH4X%Q5-Re$Q$v|sypsoN?2!OaHlmIj@ zKxrh6ViI@{Pme>q% z0LD0=eV3>@l4PWV0i0qS#IHHJ$5z3Jclf42Q+0j?|aIhLD=t-V$F-F^DwIY0ik z)LEK-Z_Zrb$WA58u+FK0b8y|f22Yb{nO)yGFfZ#afRzAvUN`T@l#YR=GnT@_$qQjt z^(-iHmzaKk9Z} z{U`9*y3e2|)}s)BWFY{Qzy*l^aNjut5&U+Z#_qxI;cnQRlLs;c^1#Xm*pGI6bhJnC zJUG@rwxY^g1%9WWKCi}LBW&;5{?5pPk*8iU|BAMB&X*^EbmT%1pa3prqHq-k{uo-8 zLhBpnMgky_cLMqfe+3*r{{+~7+G3bJat>5@D@;Eb6ob$Z!X|ZZ9i0=f>`X%LvC>ru zHJ%!%c2`50tIQO8AVA;Px)I)4^A0@s`LnR0X@edFB-)=603>w*63t`ShSnsD(OQy~oS3Dl7z12|SDgm$HrO&M++yOg!cEE=gbp8GPwfW_zC@ti7`LJ^{|GPB?5jDBG3rHDLCPb{my{X7M=$4M$S_r@~VWz zFw}?Y6~Om4P|dz82_b}PPc@8ikDzmGrs}nifPG`zMtF6_tMHEx{sDEJb+jpvY)_j2 zwB>lYj4gs!kbrK4Kf=mf-~T|R`o8MX<(~2t^DE|;Oe~oQm7Yopexm(Jus0M7K}Vzm zT0^bS(A@xAyS6^|_z{nvo9euI0S#G=cvMX)v3_uU`i@8S=0^RCyi=4Thy>&4Dd2vwUX3)eEjpYC7f#z#_s`u(u>K4`BTJ(0UYz z1gHf-2%sa>0d+lf*lp}S@%f`)d@0%a^8}#DHBih&**{^$d=`+7I<}xk<}%B663Hi^ zKYiipFr|Eo9w8?$WqsFr*wnQNdd1#c-|4Ux^2|nhM^Z8v?HjFUD>et4;khrLgS+1N zBeVxqYbjwIfQhg7?R&X_W#r4myW#Cz-)k!2?__Vs-s3gox=Gy{Q#b|=9djtms@Q|N z0Mz{F91v8^e+vF^2PS}aXzXpoQ`4hwo%q&y$$leG09e?o*oznuYX%ugX+b*RH_S=W z%~e181)R6&eA+Hggaq+61~yV{zq^_D*%IO=5Q|{4e==0MD`^=a&{tQz3b*|Gcd)f} zYm!(%5)vS9jYls@F7#8l4H|NNpLRmP51@cw%iOH-)xbfc4~Bhe_QA^|pb(q?M7m== z3h-4IpdAxHOK&r5?cV;MPfq=0|75?jTN8kA4a`MR=6;Zwy^;=vX#~GvTcNuUu0G;g zIAh_NQ0OeANj0_IweWrC_fQ|KkDIJ{8L*HT!6g4Am|irU2E9nGz(*TDg4CNh1n^7z>?H0^B%=$6F6aaL6l36) zdQ0KDqkj!2?Rhc{>d`26*G5>;x?-1$-VZk+Ehkfpro!yf+2G}sfai0-U{!o zc{_0oK%3hwv#=Tj_7d?<@snKNpW}8OoBimTK0!`QW`)?~->Z5795eA)m|Q#sx`JKc z^?0FEHUA0ln|hjPQ($e^7O3m4gQiPcl45+fBLL^s+>ufYJ5}3-+G-Y0T5Sn5A6S+JY_kIaE^k-V;94hjsK-C zCNcT9ckO`9flYYYOp}6wxK8$79?25`m1V#=#$vxpf}dkBvnU1ljaC3@YPs#CJK%)5 zC(v|Ql9jineGRN`Urke9^O8FuLBk3D2{5;8F3m(FNkkuP_yDec?iaAFZEIpHz=i}E zWxk4W$jc(P!}_7T59e+C9k|k6Z95LMIuYw-flR!6i3@?q|DLpw9*Y3KN z@8k2^kpPJU95?m^xcjibKwG2@sytQj_?pLHZTk4{-N;z(k!TDQbu-n0&xC< zI|{|%F?^?`rVX~izWDN_iYajS>3@NFBj(ZE^lw|gg_W%|+BwJQD4dE`@s`WlC*-#d!MY!O}#B+QfM zhp&o)o=3n)QAK?pqvpAY%4gev`2wfrCdL3J)Bug1`24s^u@3aRKc4nt8@$ixqI>tfS#~$NwHGeU&t*_i4kYP}^0T>)Xl8 z0EAcp`_=46lZr_C^^>3f6K?pw-zt_|BG6lwNsnt*U@i;a9(z1n*X8~l20vr)`HjEJ z7)SuiK_d?71AZds&p00@Jv@%yS0V{rzMBz%=L+svImSGKUs{QFhqig*L{#vPC>jNS zT>dB6Z~T6gMTxn;qIpH$+~0+S#0U1R*_SrkZtvI*S3Q3ve7@;3v$h3DZWXZ1Kf}@3 z#c($aDDq3dZwmMsf6uT?u5IavgW-Mx{wN0jme)<`r&!7az%3Lb}t=1+f8_X%`HI&*z1c^L#DQS^D0^I&$_Y)bS` z{`U#E>E#LJc-hO5fx^HsyjrQARF5+p)h@}|(57O};UfcXypS~mK z%s2;TJ~lN40YrBX0&ra>JO~oHkZN_K%1@9gN-D#hC;t%>z=^ag<)`(Z(k7I=?D|sV zEP}-&7Sq()washc(kCv4O|2W1jW#BDUrPXLWu84Wa!X`GCco{7IjfV%$ zdk7|$O{77-_qV?f;aE7=caoPOmf01vVXvyaASOlO&NuIbM?ZVWUi%w^bNV*a3_NpW z@2#<~()lg#jgC99=Kp2F^J^w5{=ff-12Om?RKUOGH9DNSot!n}ELia5Y>3E-8!38r zX#%(ed~U?QiEX(365f&Vfn)1n*I}}mId#KB<)#PaHI218L8m6S{N2WSX6T${Qa2w zX{!_Q`4fSk$Qd)vfW4oZ2T?)*36Sh$B5dnri94n2v;^S&8C0SO{|=IvS$*!rh6G5H z-tDLU0gjn-ECgdgcz5f&G;caDc_Dr6myBLQyW4JU-wNkFeiokB+QbFSB%oRZWGupS zgSSSXu{*aHgC7X^0s2}KmTBLb{o(#&AEe+XW`8p96FF`AX|V6pdqEV1cP|2P{=zwd z?UdhRkUBn}D#&<8hM3BPstNG7^B#op*z~Ur)WU~bKcs_H<|Qvi*`sm~*t>df=#BQm zH81`G-d+2ajh5~ktON2{6`uKd@RrD5jOX+I#(5_L2F-6h&d^6;Va+1=`*AAxH@%it zrYRwS1D;t3VH8S;WXG;X0Gg5-WX#EF4tZVUb{d>twB-hja`gT2phSSN=O z@c->tZ1%@6_&25pej=w#KLwUPyEsk&HfR=HVYcmpU4#Iu}9WKUbRC5@~X} z&ZvM!j{wJXV4L8oWF337Y44hSvF3k(eqiO*jjv|Z$7K2R<#6Z=2SP~dO-KOzu0jC5 zOI%Cjkn|e9V7FElzbmZ?MJXZg;-^Rc94w!)A-Zcy1-sA44Bl^6yA$`rS$w|{rg2P{03SqIgFCnSI zId=g9@Lnd&hHm%>A;zy=w8`J6qTM3{H=lM3EZh4e*wncRKG^a>&OV%xmz`fGmrjNQ zMjrr8T}^PoQ|G|ew%Wvb0tu~xzWXhx-W%>c{(hQr{_2LzG`}XxrY(b`UOEh00KtR= zz=|QZ{qmid0E#Ymjg586pJS7%N-INJvJazL{i^9tl6(Gq(Y>%_>QdT0^0RH9<%i|U z%YbEc(P%hi+#wJQ2jQY8&x7xq*O;>dlahfsXh>G~tlkUmJwY}5`w4y`Cr&#Nj{Db- zpjRURJhk|9=QLqhhg5BdGKZZm$0H?MXoPD zFT0SC;NXuY{D^+N=x5Je3SaN|QrTb^)wc!*4Q2Cd7Qj8n-$&z8udeSu_=y}p^>{e( z<)a`Z2kk8oBC(y704@ZNS9E+1QP{(DwKlg>hrP- z3K@t0$jL|2uEy8=zpLQm%^xQB_W?}X=MnH9_jfvC^gzK+GI z;&b@mh)GA#UWK>5@q2h>^-H!f0IT1>aP%U$}lF*KvawMGn`YDtE5(Oe9 zr-SW0uXE=i0N;7ee?SQIh6|*re=Xprio@Z6M}GMPjH?(AudIEAei$JyyRZzino0uB zOUEyTvHr0T2nFDSweP{IhVNiy{Wo+x!nq^o!_4YEVE;)6Ky_g?H1;&YTN~cWY6j{N zlaGM&-#i_f>ER)M7!@eW;rF~88gfu~aRsR)y*Yq77rB|0MG*10!@{i!hZ=MC+ zQg`1Vq&kU?orD02&UG!3Lg+1!K`>t}>T{vLyWkEuWcH!(=7u+6N7s&AUwU3Lk-@5Q zLtT>%m6XH-CY4Qsa&I}5d&+5$u(`Kc`ATow=ImRi>Te%5=`gtT?Q@_j2?0bUo(=pY zFuVz%@QT6`)D-z1B;{irrcZAhzX*#LuRP^yIA!sv@cx$fVN=_tTwi)#1}d4>z+q8i zlSnqwPSQNbA(IY)pS^nl1jO!y!N;h~4SxdgpXvNa4#WQXy{m(D(wjj@2mcvIoC`lW z>ZkDOwohSA)0$jg_OKS>Ciz`{8nt!`PMY6Nf>)$d6q#I{izZ3Mq!=A-hRjK`l(wv| ztIMRkC)z{5$v0rhMy(qbH5al2_64qNCy0r~VecZTuF#+L6{EEW3pepclD|Xd88rr-**Qq{vkSEMlR( zryZI*o1w9z5$ap(VMogjXbrSNC=!BjBn+Wwh%S>U7K?$v3*htkpwL^WPX*orsPI=n zWpO1`6jy-Y5P)^C^dl)PJuT1~PB4CAe{0rowg`q$yQd=uO*jaC`N1X7DF(ngV2MTo zJjb$i7j_L#0`Q;jS}F(NEv)5v{o!a=gyQQ9X6yxjxae-!(7pjasm=NK8*?h;3pnH} zvE)02H3cYu3g3cVwgE@CQKYP5&Q*y zDDoG9+v|pw-WEE>qUEAf-Bh|aKYXRX!0yj+>M=_uEP-Erd^sk7&OTX(THhp|V}>UI z_%HSs%N>y)m>8LE-(~)}L-}JsYlDeCSNASS7(s2sl3#y-Az()U>YN*{1WR5j_3ENOa8Sv;*TsA z0Kf&yE`gH|Tn_(Q{V(W_bm!tyhg66^Khi%ECX`KpG5#^Iv2i23{=e7Z^-o`ij;>*t z=)|PCj^{qN4`xlB1(U~527j@i1{Q6PNp!AEuVo-I5U{3mY?g>)@wmls(`VNhECA?Z z1u#xDya=H5eAj`oc6bNh7;pYQpZOZ+W5557OYVaAHoXU1JBFFY%d!w{Keb{i%&43J zk|e>q-@FS?z4H`oYaGV?8j^vZNm7QTrlJOBPn``D$4&&172{pDhbnNGO0wx?raD); zzh$%Eeq;B8TfVp+6F__XIrQm)h`5G}yX8cu9a;jwR=xie*9M5d1QX_s766|7{$hCe zH~*wx>iJ^p7eji9Ln&lv@)=b#U|PjA*xtGwUijz*c;!E@KunAc{N#fvOa{wI%811? zZ~8o#H*FsHihK}^2JO$4&UIv4hQhobAUW(iW?#7D%Nw8rYgBUrP@Dh|l7|lgl$_=H zozx{?k4(S^CE#bc*}H!ESE$BX;8_L zo)vds7r>4HfEI|nn0o>!I@fayYLj0kF#zi7+xY%Yrwbms`Jd1bY=Hl5``=Jp){qEk zx8G;%KHy*-@Wi`Mz|(I%z4N&>slb~K0i@bDLD~Fi^I`V1*}(8gs%n30aW*u3y65Td zIg%W==g2+b?<@a^Er8Ypoq-sLN+Q>MX)Xz18E{45-V6~mS_8gb{|yB2>t}m&7k`DO$OA2XP0LJC2vMN|O zXCV|97N>X3nhYS_wqM)P0LoHrGnCJ*nF|lCxf|M47r>qXqPZi0it}CL@U?x9L~v0> zuU-bS1pn^1`cEJVGJL(`>%qL7K^M}jMg08f)zfJL&)v`6J^Y*W5=pw?&lK$aApyfW ziKk4TIGr{fax9nq`_8t{o(}N)NhY(aXTxJ_?uB--&GbHuB)~E`v;ay^aepZFpaXQj z-x&B)ErJ6V9|9Mga1p%x-OC`#;$U9Rph}^u5cZ$AKR6f%-1Wj;@bQX|bA3qzlXSFs zDsZO*{zU5l2}yuRX;CR0xaWbi_u_zLApZM6KyO!;;qUBGwFf-$!+n?lS`!igM0sxO zWvxR`0A=U+mWi#>3-sb;&`p12NcnX+J#gR6|A24mzk%(Y+Xw4X23<(L{@!EvhPB() z!p)D}3~hn7TwhWjVaXV4cw*@A3S`cx{Vo{V0Yg^DT|{`9PApP}Wm9)a8{p}bL6R~^ zQf66qI-Ia*&LS95F(Nw;X|OcBUD-h01YAC|Y9>6h_Cb>i(1!$KTy6-U^d!&sQZJfj zA^>B;4+;F8c_~brG7~;n|G{8g#-PjmQS)J1)iikagJSHEgb0o_T2_@9d=ETaAK?|lBwoVDu{pmQP%T#N-?Bw$xxDN_7p zYIF6Ilj0v=W=zB;x?~WYGDuEL3V5C|@Y5v()5X|bV0^K%v=SE0UIcE38`6?&HOpno z0zet;tCo=z@)tKgMqL2A?*foADHjA#a*}5S3Zgkk)Bd{ekMtIRTdw^B1mrGQ)41~u z?L~&xS~7VF2&@1%K6)dptzA2$zfV9fL^B?DX?mnZ{|#;a`!8AoryYA1)&4u%03RgSw{*%<=<4o*U;pFR(A3^E zB)?01b^&X7A;w{i&zOO3SE;OopqHodyj8R_`X8;_ey&wMgk6JZfe0}lb{SkKd+`9f z^#nr3KRj^Wflyjln%)6}3HWrid_Rd~a`|LB*ii zjqG{1Tycis3`_^x>sGi{j~s+2+#3wz?=i1yr?|! zPMP@q*)r)`^h06Ywsmmh!#8GUXzT>SVU6#M3K;mTQeXhTT}z6|0!ZKrSo&N+ayEz~ zpRp9BX8|y_U&xglm9@w0jEA?ky#yUn3uxVctt7w-z;8Hb2ne9&f}%O$`pDNH0jp^x-Sx3Sx5+b;gM1Y47!!o^iSwb>$({9=%V^ao)97A4+A*Y!Izywex0dN^ROTe&Q^vDpZ ziGk!s_7;KN91^T25(7v`@N>bG1u&*!jP3S>Wr^0a;n!zM1a{l-G_GVEe6ZvHpj~QC zNC3=G5kT1~-nZpWbcojMrxAc&F|h^k+iQLg8v~o@c=9`gICuv&`#S<1aNUE~(XsRg z<#!|wTrq+A`&2Zb+kxDsMa4=KtQ)#GKfjW3p!E#TuH-oO%ci=n74Q+H?YC5);~phN zxqYQ5nvcm~niNE{q%N7LQawUwCV@EUb+^Id4jA_fW49nuEdklw{|5MF;Q_YtZ<} zYykk6-2e;twQ{zAZQ=^q4;c^lSnE?=Zw|&YsXDc2j3~w~k%Q<+u|t}QuYm^(3D}wc zb^}$A8A&V(j*f!pm(9n3;hX^WwNxuh)2}CFzI66d@VdN-_f2=%=KLA$o9S^0mPh+X z!zYbzVghKkO#)I9fe^px$L)hl02QbEo)+7rQ)#8tBL5~LKydZXuZJC>x}7HSf54;z z0DIza{e#!jUVYgXLFO>{1z=>x0B~gX=WSg9q?IAAh~2{bn70Hk^I-ks!6EH(SbSlz zpAU)`$X(KjVnCjYV#vi%-=49rj9^?h?-QLQ;Dtl~00e|8XrewPwGa-z^DrLI!Q$SK}iy_|=K?u?=hq`-syo z-BpfNOMn4u?<$d*>Tv8czP&0|mR1zET%Fr_*8qXiFN}7Scgyrg- zeCBN5srxF4Q3C;Ox@GASN z2K>}WKlS|$ZouU~y$YJeR%q;M9O%ytx|I3KsOkUb7yb*f!j9TR}@IT}fpA8Z1sSnmBm>O==p zZ6<+UVUg+%R8&{MPcQk!PNDsYpLqE6!{Nh~AHoxFJdxFNbNEpgN-nim9@uMtqbr~; zGdzU&O8!xgv*)UNCs<^n&Z6&C)Mr>>}Ek{)s+o9UKvb@K`au8k$Lyn>r`` zBlnrS50n*@4H$?SmqUj8B)AXq$++)2KEW6p z2YkFDYfXUH{_3~z`PR>eea`=s$|>{%oTRNkn`8G0n1c&tXCE`)YU&$ELFP-j4~1gp zlKO|b*XR1VWJAWB4X$v^cbC{CohwV=HiO;1{hCan3K4pzL=)H2{zTgia|h>uMN=1n z*XfOK%S5{;n`d|}rhU?MBPzTVuqN;s4FV=20A?@=pyEXDYN;E|&{BPo>H_G&zsZx~ z@S~4}@9MrA$j=PAkTl;VQzCHw)dGZWJx0NO%OE<$j6H1)|-0XIPzX&G2NWiiba=(C@7|3v3Z z_FL(mGn4bH>*d~Z_@V2+dNZK@3|RvKaDzkuBQNw%2yGWPfP@%5<4=y00IATYopBCy z@SV^V?&|N)42dkAx)i=x^##1}{tH<>fJTYL$*KI{(Y{W$6(6z z8^F=}z3)}ARX)Tv9$@1Z1g3@|R-K>@r>kj`EKjbU43jD+B|g@AT(WXG#XkMDDr}A^ zb(g}%p0CwRKqCQwZUx8=R#7LIpFY%PX=AISMDYnFkRC|W16(9+NL;&T-dF$j}sG&`N62zPR)I5MW3-*K=d(VbV zEt~rL6N4_K+bD_p-}|q7;fF0hWaXS3egj3U+cw&7jr5bbP|5$Z@u{w}bNwuGAvNa} zo*AhZ9{^E_3y?}{pC`aT*TgVH#*3Nz{VBA+HdPc>!2B`u&F4th4ahVm&|mAqvR>pW zf~~>t^h6*n=Yr8J06gafMp&6`0;svjzcf-Sz6V;;4^f<296+@Q&i(O4urat9qGB5U zTaIMbh*=N_1mMA!AI!@6Nd8L+N5Iea0l$d=$a7y8hA5yL0^-%`Jr!*hPtyp1S^(PEe|U2Hd~oi?KZgI+4&P6F`J6sj zG;t9f*rO|$9m~6jbAbc+J|;i1kO1poI)!R(S^a~7ougyKAWP+CzH(@Ucf~HW2V)s< zRBI|E!;Q5s=`|mi2uRx84)Dfpmi`nThX?kZurF;QG@UnH?QJE2RL5uHw%DAHj83(q z_Xh}waRSiY0E~XR&Ld&f+0EG{fXWjJHihD7{R78gJxfO9Xs1Xi`K8n$i!#LOF4JPvMu;`Xduqkx}u z5$9EhK?40HnMr^aN}iFz$=e?6d@0w@U^vN$GYX#yH%q56Hkw~s4pqgVdtoFqz*xy3 z5fRAobrKLcs~s=%u*XPnJm?cQ{?J{Ksd)n)=~8+V4K&_kkDRdlA-cT{qx!5x>6_`~94u9ogEA zSF-?IRl?2NAL+ay*Y`i1WCYgyk!I;s``&DE3!rOy7{b%V^Z{tyCPQ)}FifO~p#YwUPE@F%N*KS{9w zrp}%Tqvwo=)}Ge>)`>xt0#^Zy^^b+SpU+P0t&nwsn{k->r`!4ejuQ6Ybx(F3m+Si< zPEviE|LJJ6cxs|7HvO4$0Bwf{K`um@0Y8Pdw~Ym;+vkj&1Et>5tI@(BV4m;?`avD4+!i8Lc!l)2YxV& z7=-9@q)LRq;bHZ`swXhcHNY9?nG%6I6$scmEE$_z^QRMJ>`z&;?O?yZlXF6Mq)u-I zFlJRUstdqzl4He%t=S=fQRkIh9;%DpP5piHAjCNE2?=;S9ys*$V_;MB@J#-hT0Ip$ zTk#pJ-Zbz4yoV8>fK^h{jAKj034r$K3-eWu{de5gHhkMdhgfP(RW!fdP+_z(s-YCJ zEmAH)*O4JW*uzR{-fQJn@Fz0&E$cpq4@MV_hB9wia!qd~n{+@v7*>F~>|h-bj5c5k zpf#QZq&EX9E&%J~9N(T-mmLBaahm`2NQ?NRc;p}HS%8E9repuVWO@|@LV@hnm@Eky zC!Tyw^{+4db-?E$I=_td>Y88c>aL5%&^6o@Tkq@qORn#IxX8#;{m+IP#O1chJ^&^Q zAXdge<9aSMi!5RbsN{gH|xF`@VR`9 z6I%cdGw_-Cj937?huKv3OxMI*-}i74tofgf)W??F`S|96K^TbDV6*@DFzHUINPmED zT(`_UoQL-RDEE{ncM-sHu4LP(#z0`OLGCv1M8bC>Mao2k?+_dgeDh@EU6L0DZh5(1X!2(0-}R>5zlS&1a__pRFA z0(>{;hEcvz6!^xDS_wg#2%yQfrAsL3kV1-OlCuzrwbB@X)(WjBQjttRLI4iV@!duB zSs;M({MUqbh_`F)|C$ScRCmDR^TGiq9Rl0hh93bCQ^_s6;f>GV7}$yM)AHh)>D5#d z1F9Q!P{6aCmH8T=1sW-6mfM#0BlehiIm{Y*_ZXsc4$ zqx4_ZP1rsJfSfhLe%t=u{&}wNJJ&+MAFjjTCt~#b)pg@&!O_tYbf2Mu-x~Q&N8?*f zeOUqi2=54}a91R6EwEco_Pgm!*5ko)?ko@hv0|iH2Mq$6%zpqq4}fuT&eaz;BB`xaKEfr)`bPcHmdb zocLdjw+1R*m2r)qBpBESpy>kNjw}+LH_<-n1_CYXq)FSsIG{1G4#Fs?1pF*x0njpm zbFR6pao_|{ajdUi>XEB;(2Jl)|4BSxpQ9E-fE|7WKpvFXE5fJWW-u^`ouFR6pVGaAS5c7_7&DiqS)(yG7?_3H7|MTIx*h!`kiKU%ivk0PNG59aQ;3qAri7LJo zya2YKcHn%sos{`tq>tI{+HW)Rs z2wWac?Fq=ln*db>#W}M<05v*?uQ4fwpk_VAiXC$;gtC@b)Kf zr}t^E1i+``tII4DM?HPE8(RW|67HG0#{#G2`kr$sRm%!qh}4P8=t>`=WWd3Z*M=61O1XHoG#g90!ovdH_gmK>+k6lLY$+tN=yM zA_#N`puV*pwlr=5S(5erMvcG(;N}d`f1>$W-5OxMtn>Rzng&JyBQGkR8QL6KMG}8B zz{|2?1&|lQ@jUE((qd@s9)9`%Wv()s`kPb|fZkZ{i#fn0s-KjiNh?UL%!+x-a!lAa z0!DATcjq0#d!SNDz`uilADPp7H8GH8bfN@3mqp`EeMC}eQQ15Ri~v>6DyVcAO#O7g zp9=UW&Fyw(ej?L9k(B_@=RSFcr{n#RA?lmjn_xrz28hLCwnQljYLt3K+G|Sm=%RrgOR>6Jipf5Q4A1|0>B&kQDgZ zRNCuN%u1urZwO*>h0KSIPj)ZK^*!fGjNn(Ek4=)4`YdAv{Fg_QoBfF*`~)C~r=YJA zs^Y*0NUhHTDw|dL)``lN5d)4Ra1=#z{49d z0L|&Zd_finpytfNyCe1DXr86{HFnWZE}bl z6oy>p?O^Dhx8&}pYG`CfGtg1puVlX z&oFXHNd`+zr9uG4L?Gknz#PlD)?VElN%Zd0B7n-}g>Q(hvBN3w4Q_x&0+aWi0dnbJ zRt;P0*Xn|F8p`QJ$_acKfgp^N(_t?M|cmYEpi@?}aGw`I&g12(#8# zdhyVJ-&7fbzeoUnA_)LTfM3B?Km}hxms9%ciGV66*e@N|AyEt>89>!?VmXr0dy1XK zG>{kQ3BdNY?XbCNGlZg{0a+9^RfXWfE`V_i0KJ8Z3<}C+fdI;m_x&ITq^U~eAOEV> z0-#z1GnUSQh&z_fsfJV-k%6z*d~LqlRFlnqMO|*-B;DpWbyy+76)@j4J<~HEb~Dkz zuZdlNR9%lv!{EQh0)8S%Onw6Pa<&{Q`AP-&iTrRaxib;yjr*n2^4c+AIBzec`>}-V1Et{davpIEKAx-U1381nNoG#wb1=!FWh$lhF0s)jB;p;>p z$*(8>7+L@b5zIMa0dzyp;MKH#N-z+F4O=(#3-sE=$_x~Dc$8!x;|D7Y$2iNl8|xnJ zx+&N9JCss$a`8_?+amWMTmg`-_TzKo5DBsA5(KZq3c_PJL6S&1Cv#BBl|m&~X*Tr- zI=5N?=^m3}AL6_F1wRxDSQ|4g2!sPr-(C;fI<`^3BN-(I^#J1u)s+R<0#Jj~TJxX5 z4dC6JYu!}?Ab_$<%6#(rU>6w!KpXVK>ITd^aUpbuI)|w0r6=TjZ>xS-1>K?U)TVwC zLU2ZS@O3*Z`)IYCL~t0{F~T{v;lB3mxxVM2lDR(_yKmQ)(5Epm2EDy8kR*||3hB>H zozrOl3<-LFlK}ig3_xOK7E0Mts9-CAS4US)X|mgaR7$WtT?-%y2@wCifGeP2_w#<* z644%PrysxFj;jC(;OT%*$1TZ3>)T9Kl|F0%2zvkjcuRm%O$9eUFaoGNzv#eNZS(^Q zdaVI3z#Bd|kh`j#x$Vn;N|fS;(zGZg_~ zsj5&2fHwVU;5P&T1qb6;e{Ea;`vO#-=Q}05Renav0YK(H0JyAdbR`tdD9P&QvW z&C4+v)@)ppe!wrmRNU;QZh$=jU=yo^ySM3|T|dqBZ4ZSU_lLdQZJUEz$BeElFDmvx zG#Y`HR&4Ipw?R`=C-ej&Ac+#S26XWIAYLgg6`XuPr5OJsz$d^;mh6+142&8-(Xr`( z9+81wJc@=VfaeNnRKB6R0UEj*psuTqYI_~vR?8yMlq~{)zGb8tkQbEfR94La(A`uH z+PD0+J!yD8B>_~O?YlU#UAj**{dG4$jRlm9Du;q;#ks4M*1J*fsH>|Bwl!?a81PmT zwzxsf{-e3sucR+3)95ZW~one(lIHW#IEU0C6%z!q^IE>w+EI zT4Bf5c4%qtg`SaN2>v#TD+dr28h>7zmw*YiL{>DuLw3-1a8gF1<-{7$myx9$&*?hY z?5A!sp38O{GHe6$HYekR2qv|LU<1|i1n|_gO$2NssaV&oRzZLKe&aUiyPZ6Tkt6+m zzXhPV037pF?Qh!8NcK)s5~BHUNJjK<%{%+@ZVM2;Qwt|0ipv}kP&$MJUq=-PoVkWi9l-y z>}0?<9%r{L8K{k*Om%EFi6B(~FooGqW6t;=hwHb;?Eo*f!n6)RW&!}}3h)k?yZJXA zNv+e=LBP{|e~Z*hmy!S=BB2C}3s5$>65L~aLs%6pS8t=)$p9d$)~y0Wo9@7VVj-nv z;0o~I4hV+4cIA!G6k}o`6teHOJkxVXZf<^PW$~{jTsn1Z)!!!1C#FyK7{ex0#u2hKMKbzk zq*@@1<$T8GTx9qS^EIpIva=)s64W84ud*=2jr47ny2u!hvwkB{9q-Q^kh$3g-*wRN@0wSF40fr17n@L^VGWkg?6 zJR!(Y&R){^XwUsack{WEWe?3M<=UCnX|rmepuht%0l!E_q`}%BPhso=Y^!aB@4l^t z`Wwq4Q6va4t~Z|Pno34j2`W`=Kd@00Q2#V+d2hgfU@U;@B( zp{F|x+jlg<=FK~xv!feCH7UqAQnJ<1Ln|Zr*F>(6qjhG>pT6W6zXxFo$fvE%08t?=&?5 z9Pjxy)-LZ6_x&Mm0T2S1TMa_7knZpGPfW}S$-#^FX=!VLKrk?13!re53s}kUumMaj zS{TjEZ2Ei8@cj((Ajm;C%-9P$`OnHqi#WH7wDED+9l!(-3_)Fe3!WOGySrCO4AV?_ zfTUJ{zMDn)>e`>g#}zX^9xG=+w$=WMu$FVN`cMw0sAGIhH}x3C(z`?{O^tQ_F>datpNW9CruL36D%w*nW<)K+WyhoFnBjV zJY~OYrcRHvOHaC4_gshIpoj^DqtMHRpB)(cxB+81v-*2>A3crNO(uSf z(fqf5>dV*>&5-wxf#1bA*vpWQd%EGKj*LHgk&*yPj&$!3yU_^U_cx>h(`LX0Rls_< zepI70B#D`y5Wx7D#+F8N4l@33H-> z=m}y3&4>h}vqIgm39)E|6=k(;&?u>DTHozR!LR~+ycs(iK$;dJxSXzo+Ip{tWf`OX zM9SM@46*Szz&X(HO_BxGIm9h`)^I(XMh}c;Cg?-}amr!h-hiP#(l2%CTMgEMscy#s z&h`PnkpMUdu`II%aj=Eq;XT%YUKM$?spYm{zw_`@5+tFY zm6yC^AgKx9821lSr#uxIngFR;tY&r<&nW}GQ0PPW1G=JgfuA6mhm4*Y6{G#s{@Q?w z4ETO<03%wq>;4-8M-7Z?dLUdo)GsYBdC8WfCV=DIUrX)sJY`Edj(7h@YLyouLjX|eoyAb^Osc|;nxCPc-)6Duu0$`~NpnO=tvyKPoVfDOqV}OP*0AIqL)cRP@i@AP@dC5zEB{cyobH5O4l9y>; z1y-W}O1P5zix!FyDG(`0`sD>!fXQe8V%;!lR4Se*xHEsN=gZM zdjcS2q_hFKHekXEkOpUDI*-<@!xgjFwmlxaBiAo6FL~*&q$YrqJ&(j1q;pLKfGq$H zsRU3ULBua&3qa1C0Fr5CJJ6=HPdb24Y5^z&z+!+qwqZ-9iKUrmS{wiw37`<3XnQhr zR<2)SUh>jkNlgH!y6=wGNtc7x1Sl&L>6c7KTZ#EZ2o?2%05Sn~f5;)j=0Bqgz|j~6 zc3GP7R7+d{S(vhdMa=H~@O0hQRFTd@(dC*DrB*mck>QjMR$ML=ND4etG+&J|vP+UfN&+Z4(|vrbR(c84uK+P>CZIsu`B{)T1U(fI z5Jfp@Qy`W806rV>fef}A34mk-3afaK0)*VuIDp!hTkE93`IvvTKM^`1*DrE+70&{} z+84b~Eo98}VBU{_T_*&lFG0lT$~lOe=wKAffpmh!)?(MoJ8!%pB>@zl?VT0f9Q#iB z3J}ojKavRKz$P-!a`Z8Fjfg-jmOK|AZIBNJ_%k2{V&+o<5I7|cP>VNi$HtH9253V! z>2Uy#Y3q0)RF>-(xjRbHu`VWBFS#K;${5oBn7j1H2N2K-QQR7^3>StB%L&WWmLQ!J zv^nEss5`-ssDyyY;l<%i4k-x$ZUEN%p(BDs#8Vf5WY`h{pv`4G?Ml^C9f61}QUb8$ zfLwsTpTR-e$p-`9i7fzu=YRk}Xms%dBXY?dt-NE!#ThN{61p>8jsTyg0dsBZ(&l2K~Q23q#JPH z+1$q*QWF3c-{H;%xm&K%hF~THAmBR|h?$I+Nf0o^#S|@RV}E4~`hf%k`(p)Iwvi@4 zVgV2mAXR|>i~}i3Qj3s2CZIkXGhSy4*vHx)?L9ZwFLQSj-~LXI+$*btQQ%sse7gbB zgfK?wz>k#@t&&tX$vXCt!DK+X-M|>aSd3cE=-@|vh=Ea;^>W5Q1m^9gK|Hi$w7SPB zaR$13d;sm%#W)iwhhF@|NsNI%Fx9LB*u zkpAf|BAhZ(iF%9)BZ_rN2n9jlxxouSrbPgS%UsWj4bpO?TL9#n5X4LtsJR?-iO^FR zg_vlG1M~;<*$5O4&=SxBfrJ2PbKo{yzL}u|UCP?G0aRB&8+yV~=GvqAZyl=!>qX_o zEdHaNLaagdD3smAen$1uJuj<`^g*+q98$cNf@HWKwy7>KA7OofF!gy03iS;zCY3< zkpCY?hq@+KfD#0Z=LFCMqC)QO)(3m8%=Qb)i@o^vbCk*vtcO(PtdKT`+-`w1QOn|N zY_Uy{Xxj~=jxI#M1E>Z7nO?lmjpt-ImmoulfguDD1jQmytps|otdfQ57a&>vQH3DX zG%@lUC{7NBU?DP^{L~5nt)3xk-Djvz8ILcSEdopePiL0|(sKb$_Z%Z_js4r03&5!s z03iVx|LdvDNc-N)t_j&ug%c}xNhy3DS`7C?ur#5vSP z+xBR1S~g!!UhJj#csCc>E>lbb=xGKm>5 z3J8%p*Mf&ZhLQo(gZIINz;v^~^y2bfmRbn1hI&S^Ayfj;od^UPVJP6&JPYb^aE6u$ z4r!(X(zLz#!yl@PV8RMRUC^$7W+zUN76EwA_g2d5qm7__6hyTE2tb?;fihxubr`~` zhNO}X=!Y^MkV&fmc{do;#Jcfdk|Q|}OalY*daPB{)(+!9p=xjkaaF=$Eq@BUGYEA) zF9s=G;w%-r5cwV*B>)zKS|CANfyZ+mN!2oh_KBgWB;x8StJow*G72Uc#rbDcjjQDh zssy2wse_WTs#+&lr+fA?)M_9W1k+3Bh$YrUSVS=07V zaOR-Z{JcQfGA|R_5*rWdXuWNsD0Mu^q+DFF~(x9Ih$MZ0Y2q|!c93uE=ObRR+P$r`M zsuChc%239P?qb9(1eGL|tW)*USe3n425J3JkkMrzZown{CxY||;75*4D1gS(A;DzD zSaM+v>2fM2a;P8*J~1%I*}0QyAYL&x$Qxkm@M1?pD<^F0I6W>IPF z0MMHO=`oz*T=JF7*-d{8{&Ucgu$xNZVXhLXRW1hw{8Y&b95(;m0&+WeBs&2@hsRJv zjv+z-N<1$k81xn#`yeR7n6)f}s6l^>S?sfU*{5 zXe^11;^in_#&eboTPZ5Of-=meN)T+^f>b@WwNCCyc&T8(3 z%;+S+f?5vR*ySookn@R{IwBa;*vcdmBjGLBb0Ks3GfJR>+SW0wd_)XFQI@G&VT=(3 z9?CpGm^K0UPIBHa)=L+upJ$+U2=R?Q4kZvM3Nmz+h9E=&fk;lR?Xwvq97u2wKp)UO z4t`~c>_VCY2?2NnCmke&S&iMjc8SIU^!_6Tzl?H0G5f3LKXu$<@@(C9#I6^uvy=yj-0 zy-p5VoS1-I2HjOqhSAep2;HS1?u0VLo*I~BH8R1Pl#^LHCmrxeH~d&khDZcc046wD z8K(m23KiGGt_L!+0@AktPII3oZH+xe`vj15U>Rs%02j6ZJlOXl<$;`n znN(Uo+m=8EE`XiZ*B*(s$g5U>7ZU&>I_N+keh-SJgS27Cn0QkSIj@6hYjO9Cg1aH< zx7qWOzLYNav60&7Y+Uz9mOX_Wi~VBk`y;nYKu&=}QmKr3_ZQ`eh|Pc69Hr;-n6y1P z-eL`a$r?~f)NdPE*3BdkcP?ZLF{tYbA*hK;>NZB%q68X|W+lX946LjY0VNGOI1O^L zJaI!&6kDHSrwlQX1~|3PpCHW=?Rs#K2mr1Cx9c0e3u3_2K);A+cVIWR06a7fz(IFu z7<#w}3BD-Y)L#M^f>we=;I~^R$w0&f@L>`l@ebk!ggR9#0L7a<8NH(r{^N&xn(ykl zd{9xb8%e=|uBmdjTm(v}g#bq8dD8SJAg^1|{?Yv^WRz-LZYbW1;qOXsI3D$3UZZ&V;gR2XdMcG z?8;Jdtg9qiC(qJAi65^-+Wj3^>w7&8a5`B@tOf`zh+$xea!jIQIB8!elr`HP6fJJG z29U`bFvbC_E`r{zAf7~+CJAWekc1pS-$(lZGI0Sg%1E%?>vWQ&G$aQRiUdW7VoO_M z^gID2(TLbac;0<~B<)XyWkdj;;~kGkP4c-~*I*KebYM5Y>vGcOKr%Q;XL+yU2FUWj z2w;#p4=I<*3LB^c;)II&xRpZr>E1$0OdrRl-4@?zDGHtNTE;jN}W_Z&Xx z2-$_D{B$oD+8A4m>l^7Rqj=jaBMVB_AM&_)85^G{atJp61*-jJCH4pE%og-k7r;sa za)P)3GLe8GMqmPQ9PDx*_nLUI)4S~j7< z0_Yhm0w_4uacp#({IWheFe06oI2r@+VJm>#M_@!R^oUV%fq(`Q2+Vdoz!v;{!EU=w zTLc(zV=KUe3Bc>XR2u|{eUG3w5(CMU`=EaZl0F}{7~RouNATJ~#>p-#{w1yjQjc7w zr}E&M$FiL4bn&RbEy#kvB54X%j8jAu#@b(!XeyclDIM5aYXF6r)+dm*z5z0kfO3po zD}jLoR9cWNF$1%~t$gunG z(ZL}AxDW*ATD}K69}cZw0O=Iu#@gTKanZK&?y?AU^I^cISiCtfT>==aAYmrp*IEWF z>m)eClO{m{v$5cyaRGU|4AFWS!lKghp%I?`ZFeOEB(bH;nGLsgJu`?n*(Ig)I8Sw? zPTU6|4jD|uGRgMCroZfQaWc3O)&4<=w)@LkrY>lG0CgfTn(veZWW#zQmq50X0Dv7S z!~=ykpif2y$e{WA1Qc0i;2ngmPDI>K6hSE3CZkY{Cfq4|6SH4S87B44$w=LQ9i$il z5$BJD?@*^aOZz%IxkwTqE5HQc!kRJc6QQGkGzVhM2y%J^(BC*fntp#e;5Re?*pq=C z3*ZSOV=F+Q?Yt7P0QY|=Hd%Ywa(2J^n>tqxB3^bWDLvi8M>k2w z;pfRJP2dc|`bFY+7P*`bxxgbJo?}pKPg(A*lH@QZ0IdFr<7oi40pyC=FB_}@q^*OE z_E*8K^%GRAh14VvH~izkmy^T;l9q9b)rkt6E=1Dq#cqT`9W>5Cutg&OS}#L=9(*7w zX7ZdfCII*G!r!Du`BI$#K*V|64je2ZNV1#>_^rU#N{mFn zb4n+uLd?i6JSWY9(JdnMM%7jU&HmRSx|#?~qu+~WuDiXvZ4mIXOG(Aqg=}O?^cbx1 z3b3M+l~E`eM2s$n0|Ub2kX$Yn$wf$x?2ic`MwvK1mbZ3UHj`q zVRZ>K68Qh^eF?N>Sy|qHraRv^zZ$w50vHFD#yBi97>DRGPD=yQ4KxZE1O+uwmS%|( z5l8}}E6dPAw}MkhRH8zHi33TDl0=M)s4EKThOVw2YOYsrzVp3j@16hO!#R7Od(Iu+ zdsVNh>+M>n&OPT2?+)kt{_h|5zipLZCcHYN;N0ihddO7;9BgIaK2D3t(DOw-EQy6m zh5B!x^=G2j8j`w}t8jSQ`a?3^*dqd%t3&nN1Wxo6(Cm(^0g~~pP6opi>LxNhR}BjRJoWBkLC<_&c?js{R=91WzTq z0VX-Bi5hTS0{Ix51Pm!~=QuY*AguFaBw(fo=D7l51~Sl90w79$D4Hn$7b<0{y%EE! zTy*<=7@GNrsqe3*J4e7fkBn}v0-zp&rH=(|7(!Kjg(?m}fxtyn0j0=?*2)m}%IF5f zGo}NNiU_RRhX%iwemVBB%(futDJwv+fCef7S|5R(W6*1lU@&4bKdTEzlewRszFNGd z_u(r)z4yQ^z|tKzR$jN_i}T%=vL37(Ni9=;r~txJ$m`XJ*Xt3FkPPB47QB1Uh*RKi z$e95+vt+skvsMME_2utX($9%x+b|@(GL;FJ0Qw$`&NG=680h){;K?6J z-2u8J7rmdl`mVhnyP06R)5hxSRz3c7@0F~}&w!AYUv}-HYQHE5SQV{)vtFWBZA^R? z@ZJk!-Wd%k@W;sfn_?dgP;LRzxCBmYAVUhuRdBNgMhTe5*(5Ms3Al9vyujDzd1Qc> ziwKbd>ZOucDpz<3-Oj-cA=9*??IHU=H~|4u179j|%+eOOwl;<5olBTP#tTu!;u^ zF2&G65|H%)x=E_41P6-<@c)MQk;|3c2jJ~6bIRt~I!^y!#Tz~9znXXWa|wuYZoCjE z`#nar{?$r}H_`G}$`Kdqf{p$*6YbH64`TBB<+sc&;2UesEPtKZv4JcpfT|hDQwj#` z388=+6UYVztsbO_`p8;*K0yV@J(UI{o=EzO#d2Am>tAHh?)Jry>s2^y=}$Go0kGcB zkNWd|_Xi??+H2sR(G$T17*Sh8Q0YKKN3B|drAAd&2X>Z5u-)iDXIPL8IEdVz_E=EX z{_x` z-nwh61@HU*n%6xKui-8J0+HHACWC&V$EehIp&l`GF&Wf7PJVwIVLb^DLi?`l-VCH4m1gZn`D%OEi0_sRp`=jBSk zDB|C!mV_61jDMvNt!-mWwDF|K)nw7SGd^U?uowaa3oCn&)(3O_^s}o{y&Wa6F~W; z(GT#;{2>)~Q5Q7Lnrqg}u#75znriOe*F#m@gB}~HHd;qb00j~M!t&lZ!SAK{K<7BC z0>~Yx21o+s5)wgKPLdj-Wb5uC3G}If2vb)Hx7VPs7O(WYKCFm0TzuQ^2aXb8xAR#0 z_QvNkHN8BN)>(rJzfO*%%1fmXeSX|(6@g^H_?L0sT^aID925AZ_=gmzwgSkI!Z-oO0CyxYdq7Wh_7Cz<%xb6T={-v3J==)d261o6nJ3Hq`qSZ(F z&vd3k)%;s7fZ)CN$NLBQ9S%$Y@SUjip9;3oyrO{w?j%`%I*z?B0N%S# z2L0GT#{3fhJl4QxIyz?pdAfD2Fv@^|r3@^oPq@^NO)RxKR@K5>ry^|QTo>4_xYCiMioC**?>wZl5v2gMj2QjVDouh*z5OXtFYW);IxSU6attO@y~Sw z4g-G2#mEv1P1{t>Lr4kGq@jR&FucSi3H183Zh}zFQq;v|N`=9*eg;t!|I06pUiQq} zJJ$~L+uV-h^y?a@;*0#PFobpOV<*y``ryd6-j#r(5n;7jiH9MA{|iC%Psgl195TFy z=n0Ig;vS~ylxYy_q8~RNAd~_~EVPLQi1c>i5@bj~6NwNu31nOYLjufJ0y!jLElrXD zKkE+2Lef$Y@@A<5tJNx}b+>vKVzIZ=6TJ~t)d=JFb5Jt@l>(@H+r4*>4pdumC;}+I zJoty~qWEnS2$cQ{NnvyYRu^m1D(;>cz;@J;GX&=<4W2RY?;RTa+2<95KUEWU>99R* zST=8fS`^C6K%Gbc?}#rkXz!vD=u?Uie|e_sM1}Qt>@PMzm!Jk8jF+n4cln1eABfp+ zw{iLv&2Nb}`0I854JG;2f*x|MsUY%MovQrm5vx{9+()0^|5Bg#76-gN9I+Al{3QKF zlJA$6T=u52q&m~DZIgge23!N$C;?`HlN&;@+yV2P#2v^K4{=+4fCj#mF0>T~fJ-pO z32*{{f$(VNA78H2_+q&NywCamlOwU;?a2(;)G3KbfXaob zlMr9%y z2k?A=q%p4U9E-=kPg8r*>W6%xUSics$Z3UL|8IG$QyH-?$$pvZV=+&Cc3T0&Di~<| z_e9b&17r)hX_g=*0UbAx7CO#J6Y{+0Td@b*HLxwe6%R;)g2wI02!GWxDDncT{Nt;Y zs;Gn|(Z4nlyH}9_QT}TOk|(~uuSmzM!cPA^@!+7p&!GvR^kV;)`3Afu%?5ZfD!$yT z!O~(y0%q&^UDz3Qp+8HbkQq~e2LZpEA($2X`LFA`4esLuxhW+;*#Qa+$`zD0Pzh{| zq&q;p6Ju4trh}-i7EtR{s6e5J#HMJnw>e2EZnumjo9x0Z5U=2dtU|;RXnuV4+O`RP9*x(S5E|`AVfC z&$T`?5_>I*{*P2eNgDXmMBwqkFT__5^E(}$0A5-80{&F|Ni(mCUXUyx6$Py=)u395 zptC%L&4muM29y$2J#Ve17U(YtZAAx~5 ztwE!}r7m_(DL#+ddC6v;X!*+#tJh1SQVKaNc?`Ztur>^NFCOusn%_fB*ez)o;$!Z?tmcy+lsS1RbVOxtqg;CU7<+}GK7#$SQ4tKXsA+u ze6?B=jVR)S8?o5AFyIvZ9|_go9It(4W_=w4KxhpfVcUoK%??cfG@@_tKOqIX>i~pl&dza+AoW#%9)>HM>m-+oDL~B=xc)e0)B>ltC=iXUQ@Xr&x#R&XE zwEQyB&!n|iQaaX_I+ggT<&IsyJ-N-2I6-QunI+emn;sN8n~+-n93^1a2(a|Eo%A5n zF&-wy;{izq!n`hZ0Y>8>mdiCx!9QvW+WO3p@9y>lsvs^`H}bW5@(cl>xu}UN!-v>h zv;VT=NC+T&N%#}uI)8f-3iF_q!<7`j_AlE47^!7h%B6@0HJ|%01Tk2ODcHyRDEnj1C{CJKeOJ!QV@m-DW?5dAoEN5b ztpz$o0_Js#NPvs9YS07*jS`5#E*nlsAe$cK`n{!@gv2ed;{l2o$oe;;l2}9Qzfh`( z;ZDrApXl?wUSCdhl8-YHf8zoK5D(wSo;mFAcq9Y>4?ro{_O8RgTQac#=>wzur(odn zQdO>Ga^nSE*zV`3fEkHkn)EMp1Lgt0eR~G*+wMZqYtf#v12loC8kJ;RK)D0~Fmeg5 zkD%M3%E2KFkO)R*3JMtsu4fYJITwat)pRfcsvV)H_8~mRtKtJ9;J@|EJ9eKulHXR3 z=ltkuU35lY1s(sTyv@HEFYCJTV}+i)145)g;4-x*CBN@`yc`9xgAakfRxNR=@eiKs zb9e#p4qoQn5la3zriNZjclEIXetFVA&G8F4Sr&{NVB~eIffkE2Rj7l44k4r@kj^Mf zq`K|KSb;#6k^jsh1Um)k%u%pn07hw`?~j5Gtv~tx>y;Xh{DAL&W+1jV(fW^u9KR16 z{M`8eqU_xmy*EB^^xur5ApjiV{o%ht74XA`0O+zUg@K$Lw7y)Gt;6@%`>;{(LTix8 z2+SJz%UI?VWa`#Det%w7pQ|qB1OF`X2$>;}%Z)`y0Fj(ZTnkmv&~O{o0F@8-htMA} zxd!1#&nT3}UoJ!>%ol-A{E$NC=O5k@y5E%Kzh);V)5HTolaf`kp`V z_+Z4=L-x!M?TY99_;MMqs-_sSH81u~qfNdCue|%b816#{^toaHpN~J-3)C!U6Xa4L zPa@-7N4DifZ-9?-pGtbk>Lcjuiq`Coq)+NZ+3^2=jGfN>P?tm2-G{r*6`$!atTO(i! zg&d_|TYN}^j`s6a*)u+<9E5zaTHz@FIh6pn&JX$4wJxRpREI;$>KpJw33f&gvnxjd z+oK}@9KpBwkH8K1-lW`>dg%E9ETS85YNakS0(+iVQiGjbPmHv}} z>LpLi5BSXl{(|77c@4xrAXuQ{M>1gAKr)~h0mV*42Z>-)H5ifo1qMU}OwB2XlaR8G zfm>vt0WOjSuL11rjIaqKsYbNViv;+>A_h~#rjOMlxTXoYd<9xFv}7TIA5|X$K0@G! zl-9%Jkol3v!?Wn5+~@ILIO4t0P|$>)k&N?k8~Aq0EgOJ~(_mYo1}svr1B4<@{BSoQ zXp=ymJ1~|aOw`DDP*4W|6U%QLH$x~%AyJ+yK=*}6l+^KewN~fLl`z_vbQ|n)5j}G1g?6xBScm*s6*St%p0&2$C$lB&g3EhA?tSl)Na2-{^R<8qn zt{s6X0l=xinwAxq8uS}~e9_;S75roGC+9u*pwfj@C{&g$$3qz)q)dS%g06txW(>X7 z2>L_7(|(NeVFXw&O<*AN;#H1b`!Wk^d{OE&h?Q zEOO3#6i64~G^v0xs(`aSxK`=F{;)6oTsa4_AOJW|;BOwke=OqfyvF$J9u)kAO2o51 zu1puIAR$euu7;uPGDI^BB@s}!A&L>~DgvNDA;k!WLJtd?ROdl6AU#2|KjrdVQ7Ebe`X~^T-!H8MJh%rbX&HErjnLZ1 zvU$gl$9fts{b!ZTCcd*{Ar1Jl)qi$PfSW1MB%p(Z+))MNB#>Bp;mUlgW^iVgp~R0KdvVIeZ8XmHNA> z1ON}hY5%(S4C?!`xu7TlP78;uuhw8~p$@E!D&YA_1$1LIM?g$S``MP-2JkfLe^9?a zO9u^r5F8s?v|?d2&}|7J~pEc+?M3ptJ|F`cXvl9|93X zo`}|Qe~-^c6}3o5e}sFq_A$OO^7H9k=^j1Y1<%;A5Kf9NA%Zw#v9ly#5reR0eU=26 zPUXd}?=I{>A-9OdjyV`LlFENOHjtMI$Ycd*x^pE8*-E7*)=~bG>$LOf9^csL2=e_U zNow$WRsoPe>(3rx=Z+GtM^6BB!Mxc2px71SfU65_*z5NJ z1rH?MgJ%f*6&L(Wmi~n?fP$c3-s8-}3N8OcWdemN!oHuHjF2KAu$BB!RuIzKi{u*6 zx&%ZJl#yop9EL4a0&OPe7mTDT;Ia=R#R^Cn&?33Cajq*4HTb!nl_;wWJ-sTe-kZ;a ze?FPuL>ZmPY(z%Xt8W3{<03wG(HEj2!~lgoN_+ypT%rr#hYs-BEw|Eofei4S+;}4Y z4L~88x~q$Wk|=)?7_=<9O#-n6+H6d~b^($p#fcA}wfcsXrWXm>Rfu*FP!b2F`W8w0 zBlw%867O!ueB)f3?~w1WtiSa2y-WbmFN;4Pz6XZ4JpsV0;JN-K?+N_4k#X_qBBCAv zlo2?!(f~j7VB-aCxDj`uH5#Zj1g50@j#m0l3i^%9{ah6=0sL+}VKVq95rOBa2Be`E z%7!Zh#HuC)YDrG3710`vyo+e)pb}`IThK)kkVGJ)Dv%S8Gzsv;3so+FZ$7i0zd+m~ zm#Nm^r)owDRuUP63n2te4f=)$v_Lw_dKfUdMk3xG$)**tGV~^=XBOYE0Fk!sDo_Af zpE(Oglef2W|3)2X7r>7AyY4_53`}3cw%|;-&k3v@JHaJG|W=$f`g2noi9>?nBsOkBG;P8mc#k0O*BZ zbVh(K;Du%d&aO6OeZZg|!_|A+u#K(&6$de^U%gqRp3$Rs%1M70~1&N+l8rkV=pi8gB=lvg882L`EH=aEtqR730R!)P*q;}q&AWw0g-gTv7C)e8LZ_a zyTl+eBw&hwthoSIU{3+o1OjvN{kCf`<_yQ%?vn2Le6V}l`Y6C5W?Su;cq3a z|CxH7*Q2s%T_5nPPqg?>x66kyQ_h>01pZWlm#lwPd}8zv9QoAnn??Yn0=&!Kr}68o zCUpVSI;#@NUIAy21j?llcJAxKwFq5-AuV{oR6y{s*58_xlf8c)zkf^x6sd>IxvAjK zD`Lt8e|npSwAQ}*2FOCo&cvSTP8`YGfo#PVN!hNZB`fRg%g3vw%RTAbC#ok6m1{>e zN$$($C9=wfD-}U4DPpcN5KK={<+?&q=J88^ph5%I+3&{E-=+D$^e5F=n zd?@&}Pqp~QZijaUL#|uM3UH(Uv;q)W|G&B!Fui#MKo{)&{=3AMc#~Zh5QaW9t7SN| z){wIW8CsX?pVfkmeg``7P&Ey4z>)%F7VCc$(m#(RvVp$5-2VLFF9v&I0MU9+pozfK z08a?QQ*{Oed=*%PggDf5Me>JCEw7oI%5+MA8$tk;VUR7|wCQs)3Fh;Oma_%>Oiunfp!J_#@RKY3Cs_Qv z=TCG2rhtD8#1pN)=e$-nreLQ>lLz`Dx$XHvKSzC^X*SROR;oO_9KeC_E?Ku*=+MxuTS$JxMTe_0ib~E@KfS{!rOCxoFf`H zp8)8Oyx99au`j+U$vf+SAaxHui>?5vfk8EfYtL!JCItkkf1q?OkI?$(fOcH^&!7Sd zfIO9UEp zxoW^JssXpopJl*kNI-Q8a{c;j9KZs;UDzXXp6A33>`6mTsc`0Xk`yM9fk!$2Fyd<@ z{TmCc8bo~iQkP$TW}k0&lC+20_7ioweL zX99!H1R~*pcb0g78)UT9g6S*B#Dst#etznA$d+W(zsYEwzg}y^FFv*_Q2H|~@MjZ% zneTr^JPe<>+0eW-1VH1Z@K)G{wV)m<` zKn2*O;3bm8Rt8=wP*UKhK|)OgCQz7(rYGHZGM3pU0hS>F9p%@+P22#b612+^XQ~A= z^8#E&kexm(|EA?8Sin!}|D(WXwW!2T*Bk6qwJwS6%A@=I^5#C<@AlPXC?)+_0)7?z zi(v^q3O@-4ZuU9rxOD_TIQ~}n4D{i%%_$QQTxyal(1cZV3E~Qe8_(&$b#w*Vw4exA zog`l+$L;ZNk$~y($BLAI>(l4C0(R^`pG%vG zIMb5F_}=O%m=H*!8mI$OIgF^w4?EjvaBBB`<3g8TcxI1ncREV?3&-zIw-Ejc-h)`V z1>@Ec0F76`*T5G1f#f)Vq}q*KfmL(`?nPICmKg6Xj^O%A3pUXep!Eb~ZTk^g|1lXq zgTFtSJTi*Gd5v-PGEdsl2LD_{0PeZ$d40xJ1+!c*!g_&e3c&0$MBpX40rM7&4oHZ= zQ3E-XZJY=_fR_7ihaUstI70%wARdsm5lbrj+<>6%e1CK>hto2>vEt zELVAVf5@MHbcb#1IXQom@=GiK0@#J?X#GEQ^8$a)?|Cc!h%;USABGnGZ{7gD19AoG zRdfZA1kSE6Km}F7{@FfUjXJQS;{j$?>r4Qe%lhXN$u#Mo{9WsP6bBIJ0l$774PG1U zLa%^4Mg&C)z&fXHyZ*mCH|v#@U{X-Q-cX9I4Q|Y?*PxEnSN}sR3_<9jXoHm{o?=IL+QUq zeg2s0gOFH%mPmg(F2jGl*?~WM++ zs0Dk2o-92zSJt%1|1|6GJhwpl&!z&3{r*`BhqB5cPx9x2T}$`mc9HbA6@Yb4jr4Wq zzGyNkzy*E!$GpizVB7%kToM3V34l%)I@TYOF27DQ5DnNQE$9H)QUpS{v4o7vU_XDn zWY}^6tbkyWod`UiCit-RdR?5VHW;-;yZS_%UA(-95OuA%aiBd*RP-B^+-( z0nm65{x0mm$7FLO{VwbRp?lYxu(nu-xXj_kJ#DzA;{h=@Rf5wk=secHFz`1;`WI&p z#vgxJ@aGXhkt>i$dk6Fxxo<0gd9DKCatOc-3Lx)T5rGvPRJy=Ra|1G8p2h_dCEzsj zNTd8|Ko6|6plkgT1(6K|nkav4&HZONH36v_7*7i_-w${#3~8bdKT~h8S`_llOI>#1 z$vrNk{==c3mIdQ!KOe54-T&QNCH*s(!7+^c;mzm@yd!xdL;}=0yBxv#as%!=wIDMD zy@e56UuwffrwctQ71k|j)N_)s;M8E=Jl4NRLF7vRqM)C7to6M4z^_5=Yk>O&R^L9( z0sbTfFy{XkT@7PFKkEteC;&G-sCy2iYG8~6lrz9B5)c^|z@!LcD;Sr=19F0bwkr^) zWFTL7JS#A!2FCjg7!vS&k5___mi1z18cpc}w6=%rsZVe7>*)8l`UBbFSGfs}<)^KW z(*MKovvAAWx=;JbZ_RiS`a6C22g#e!sljHw1ZP&8aL?KTR4XC0PY>Z**n-V&ANoiF zssZg}>km^ccm|LYB>yDoU+iv7FC3Z#els;%6j^=8@3+s(vl-vtI%oarb6bD&bgS?u zJkg#Lb7ftCv2%$ca7Z8lw3$ulNPB0dpW{+Eu7Q3|K>7YK zWGm$gKhtQi<#Lq|dNF_cQ#8@|u66}Jir_!eHtsY3mdEi& zlkx4a0Q)i?aIbkcG9FM0V6jnwd)Jz98i|0q&g|bifa|OUThu@#9w{M}jRPE!^&fk! zF>9~CyczypZsAadG!6p(yqJKSApnOc#uR|<|NArkUa1FGTnVWENNVlD`1zI!u#fe3 z#S1?H(V*)S5-OR^LSaL-hL}fj>Gf2p%s1(0Dm~Ig-F1;a8Ew186EM z#RF)8(R)ud;S?1K;k~{-tYx|kwu@JvC9Qm)`yM2zkgx~-ja)1wz0^cHmL=EsHDQHLlvhILR5ju@L ztU3VG5Y#Lf!ZRdbj_n=-%F??T0IOZtSPVcOdot)3u!VBOPt}_IbiK|ZJihe!E`R#c z9@}blcyBb4K|h`HGuGdv{WjnXd=TD#G#!2qGLD}BXxtA!23>e(@}@l1GF$czSg5O@ z;8Gn#8DQ^B53coFuuTh%k`hRsfR7QtEY?4l3}C9-n7wewn+kp#)WWxJXNdry zKoLNC+s^=gEG97H7z+Y=P788xDiIU_KXY4tES@0&og477>+HFf-tG!)%X>9@&~56O zoiG$z1R};<11pG#m!}}`H%cK}uQnK^{3_@MY+P*fC(i*}9i-xKr}=)tlV%~{=KO~c z!M}xv;aJypygdkj#X*!jn|#P!`a+o$H9a*0EcT79sBe-Zp1O8=YEDW|ZNJ&H9KHwFQng2fq_Aw$zK%L%~0H04FfkXi$=S)D*5QANy zV@h{T7QiNhIFl7{3WV~@gfmlxt$0I-K7T#b;IB6rwf5S*(Pif!+h$jHTWr5OptTQJ z67*ArJ}kNI!(YJr;CGK3atHkRZ{m0vdkF{hsKThm zU~9Pt*E>i8)Krwo$zmFWIevLzRbM`cXSe>vF@PcxaxJ{bkU{DW^MEYoH5I=6hTH_=!ii_|=^@+w1kHw;$tf#6PwE zK0J=1|JQGIzQ1VPUIaknrSNsoga0g(BZ)gez36>t*2=P%;C-hS<Bi|PQz2q1f@=E;6= z0iGVaYG7^>;OYI^1%RYtkdL_nV~c`}rvsB#;mnfxCIFaMBCL-+7I>bhm!f#BQs<`| zO}0=fvHhI^JNKzgeg$R!UPnj#Q}EkeiHa?tDhGfw2x^NHVd(ajrV*NFj)cQ1^MK2*tkoOKE_rHDG3-AU@3y6UO>kK zRA#_c0coR9D;|*SGc*3QpKoUYGNrx{Q;9G7{PAkFD(ChumMg5aJCxwRytU7Ex(NP} zO!wshpSDf>ogP8yf6I$~CXL&Z0BF1n{t1%6L!huE->F$?nSoRp$mF0%I}0h9pRwR>T2SPH-Bbq(i!7+0 zUmPO%t6>1}OnqDAcS<61aD5L3SA)H8|`x)4(7tRw0BTf!S0*z8?=0pO3tn4H z0=;F$UH@Ms@;(c05kTVWkNf@Ou7En9{_=SWAnO)*E+6OzX<{&dH|Gk0Uu5Ygk$~+w z(3(ri!d@k&y5Fg&vprtvSG^=;I3tNk0G;cnB6Hz=pvse@OeXm zU#9vb`1jD~f8xzN?nq!iGP8Hx1 zLKgfv@q)Y{;g|w&(}T`^c^697=Lg%r2iM9&#{ahfpGyLk3K)A_4jJU!&rQnE4hUvu z2#%%n?Ae0mSijqt+ITON%hbw?QM#{=M6kWlW#=A4pMSeWvY+*a68y;mreoGWfZu>$ zfd78n@R>C33B7v2KDtKjp&gu}Z_uH`5??R7O z&eb)8(}3@QdP?wb`jp|U^|$1Fo(jkXz3l>wgFl-(Ol||@6G5Q@u&lp1Z(Drxf7aj6 z5J4{RGq=;Ao<8RU2fd7?2diEn-xbh%ZYC0CRDk94JM{r+7a?8j1G31+k4r(o7s{3R zH2VDOwMJYCL%wmT&CWf(#jfnM*lwps^ZN6^pOSzNA4c2%JI4*3Y2(fy02<#7HQ0iW z;}85r$vY>INfJ=24V_x9BMB_Q+F}j-k_Wxj5o`>J1bWb+R^w)!${FQ&GA7gl-FCd+>#J0sn$xdLx_)z?tPHlq(^yWe&T34>r2A2M8zS?JJC6X&cscwW{tRz$NdV;PxV1_NRu*b-@9F}aU1>t2 zTmsP)&}j@|gMx#-9`xcEoj?v|5N7Z$9q6rkflTp_ zTP$Sd^*t@QQvHoHP7a$M(1*t&*jk5GA7z+TJAu^{0q|A{6d?&b9qxEB`ZUA?NwCfIle+$`S!g zP61jE8&d%Gac=QW4hf`+z{>~wyehzbzU>AWC7>7XRC*%}d|sE5zs9L^?_#CQVdSx= z&uz1(F77b&_hqENN2~U7p?V1@@W&bO@8I^M=<|R2xM6V6apw~NjR)by_;dUkewv!? z63F=j6dXjCV0Ezu_mE4l+?2;&9iZEYwM#$^M`<2`NP=W@`TrB;e*yTXx&|seruwxEmm} z)yJ=fR_h5wGpbVaPD=5yMybR*djodv(M^6~V~<_mYx7ojzy>s<54dSBCg%!hzuy%6 zTtt)eCiunMv%+uI@$4V~8ZVbM0>6#hayB>^1RhjNk*pj%yV`(zR~BHUQG=k2bdG9Z zYh+x4p{gDPF_tcbLg3FJ|FgkAe?IGPK+SD%7pQ@;n1JtEem6A;`3k_?&ej2pS$uG$ z|3ng))%x>UNkDx7KcfV6OhF`Fh3MmY9*=xqRKrLtl`CwuS{Exw03|=<*Dkf#xyLuf za z`o1qG5;g0_C0K;h=n_!xL2nVD6AfVtmB3EF2i@4D3n5<(93=XmYx!pb|D?Sm{rx=f zTarJoMnGQ$HW}nyCT_(axJ1AUNWh-hlV8T0yB~`M%n}65xB)~AK1v?seo+o0u}~@@ z=xZEhzi32d&IXJ>b#7NYd4Y<1+G1B#_961QY98uYmOm}B|n$NJ?VrV`Xs3W z@S%lg$m-t_1wONmXCDEW@$K*i{Qqb06ISzFf=U@(f_g=&0V095W?e2)>eoFORT*pz zy0DFkpp7IjOq!1>NiehjKNaW&`x&i&zH4Av_kzkor$|U&1tLLs=BltO{Qwe6pF7FN zQUcbDy}7Lam{m7hfg4~y7J&}|o-cU;)O?itr7EmeYGnCEHHt)Uf5e|Yw<9iG-xb$( z+I*+o6`jF|jTqI4>e+m5VUHpKAN~9gUXT9%x#Pa9k9s_N34q3Tz~99Ge*-_|=jOQt zkq!`2itzMO1I{cpVWm-p2;Bm|iEe>Egd3y=$Sq)&TVNA`LjYR-&kFQhH$W4>0aA$e z9_$Q+MGSeafExtN872sr0luB{A0vSoEIdpL>doi|klYXO!$$aj#SdX2D8p*0Cf2HT zSSnRyz2B9m_r>|Aw#C(*eQ{&I%UivH7>r`B*ZDGFH+}ofG41~l%JBX03#b5|h2z;x z05o0+b^QPRK$;-q5+rH>0bj3`VSS+nXORR>FEpWn#1K^j5DVlM^rRZtAE_!r*)tk) ziioE8|9mEQV7dZGQ;Wr~k7B>@}UFbUj~eR!7y3S_@e zk{>^0}&<@h!Nxu_vzWw)tMCFM5L^1^T$G8rCZg zfxTXzN%{Hc>wf@#D*YCoedF0r0A{=jUWflbluZ?q8jy`gQ4Np_uvkMiuvmwCmKM-0 zsLAX>*z_T;ao8F3U~kxi_HZPp8Pj5=)*Lz~|341$3BWH@0F#tMae#4L`e(?%i5t*6 zPtQA7h8_4bdoeEaize?(B!E00K5svk4Nw-}$A2X}uJ{o&{4%UWRahxkVL7TnJ&a(` zW^m#Bo_OZs4qQR2zt!rAc8?U$!@U+&u(9NvsR7w&M7AL>!78N;Q4P?xRIfs%9743P;ss5KlQ5vY=4 zwd#~Kh|_^T3Dg11pc1CX1@b2q6;uxU z!LKC$`%q5&bCmqOo2LFHTxhnXVS8WK>f`?Y& z(HIfPFF~W;oG`!#ueheaD5WS;G@M~E!ANqtU&`U zKI;kCc)AT2FYF=k+i(Mck8&TnO77EwvZ^G=0Nxt||2aJOeemz#PmlW&y_MtcBLFjA zBLjpFYq5iB4Plu!|r7XsjQo+^UTPzDQ!=sw13 zfqO{=JP*XVRe~@^8oV%An6DsU3VGzsA;<;e5xAn0*J>?ceG`T2>PJC4tA#*Z&^$^*?dk7vgb^yPW{kcm*uu)%Fg&^?JxzEZY!4D2X7H-G^2zMPOnC z)kUf*^q|cLiVTnl+H3$luE>B?K}?DO6iC^G0-!Mhn9(hmIQeMWKH~~Fz|ThgbNBhy z9dcy8pG5L~c{|V+pHg{Mvi4pH!LC5RjQb{9dr|_!?HD!@_}4BI=-YB5;CK3H@ndQ6 zL5w#y&5}SLKj*t)3H}AVSI*Q3gXPK5#yz^7#ZrU2je|M^6+ z$iHuF0ufj#zo|a^WFi13XRm{KxDO@h11Jls+KVLc7rY8AqSRkO&@cKF*o(j)c+k2s zfE&-C#NX<|=6(mZ+FkAAqsv7-A9Y5iAYW%r(~Q7>k1X@!X!V~t?#u0V7$*df9dAVl zJqh0}8$1B4}$12Vo7>=#SwyL~cPn?;$A>puZZ1vb>n)6_64j7hwg-V5x?xpoAB6 zJ%nJ%2eHJV?F~^845X{j5vU6I5c-0tm;sUjLj=X14k9LMK;#4yr-OOE$6B``U$Re> z`&>orO|ITEfjq9#EhS{Pibnyx5-iXrL5~~mYbf!{_;|ht(A^lq_T?UI-smW6-y&;2 zkpBIEvMp%sWvllh;M>E8Kf^!$CiqqO!{ffBZpU##0MiB$K?rZeYwaK7(PG|1%-n!L z_9YBt3Xxoa#VY!-jhZ3@+|%5HYNS*_xS}Q>b-frmNCYiDlKT$syGR2)B!(f#J{1sy ziWiuy0s)sNptjV)Gy*8hM&y?g+jI170`LtQ<57vvyV{4{-5%_;da&KbJ#PDG?fZ$f=b#(?P5<3IcmlV7 zh8F)fkNXn3oyQ3Q%sL)G@RuYByb-sxyoZ>z0gNh$hzw+`0Lh?Mmaf5yb`fYz!xE~7 zQX_zP2epAfKtgCsLeT0!jF1ds=zA19AVP?>LJ)G#D1Knnf(7caf+R~xOm8$| zeI^a?Y?Pj?dLXow$NM6b^(DMr5upS-S$W#i)Jz5Zk~~KWz#k##H#u~#jbQ%@g1)7| zPQkqWZXa4b{LEzSsqC7mh`yM`+N*I1-~YSdGQ1D|hn&rKGA4`@0+@GDAyJHOfd~H- zkIoi7ESWLrtDs>?lR*PrgariuLai+8320AQ1u8i%qdFim2o@-AfZ%R2=-?ldBp_8m zENct~=qB`Ok7O{Qa~^Fdi)r)a+?S+&AkU3ZD#EQBkZ)MuR&yJK%u7np>zaF0j8m4@ zol0?0(u+v$s|ft6vGP!sdpeFhAH0qSVo$(`Ed3UOesh45UV(lO0l(Kpcc_nU&_G%G z5n1|qti2k4DkJ-s;ln4upM9JVz(L11;#Iy3--THF5j=X{q=ywBtU`0J`n;Q(|L*=#GZ;Hq#H}s z0>0tcSH(%P^O3J7GSLi4J*kN@9lrcWfTw1QK1z9fF9>q7@D!jc5(l{!)VzfH7SKk-05wlmB*xU+63Kuv3zT4#iU1S=D3`$;tNVnPrZ#=h zdwn}F1R(3B$elr*a&or)RR@G{Co%HJf-Wp z15_*{mA0cQJqdblQg<_hp2jB70vrM!f!}~D$9)Oh$>W3oj&i&lo`bl1C4Q@~#*6dw zrae4aPY_hMB3mKQMubo+hf*m}0TQ_gL;y8 z0=U`ZyV1_>z&8O%Rq!piFVFf^n-J8o$}spEz`mZsOm2j9C5Rw`lrVhlX83`AoFo%3 zd9IxDFXYM@N$tG!!+Cm)Se8JR!MT`#%`~{xW7K-w!U@_P0_oL8AWW$}|%=lXsFQWbmC z(p;ZZmRlqwA(G8{j=m+_69*Z8A+5Y8E&a2u_ulO~P6*)mh6gW!zkwJ1*W&H3#r;>~ znT12XV&(_+@*Yw+#FTpuVbSx(1>F7^w~s>rzmKqg>PTPxWXv>92;g=Z4xc%;dHN(M!2dBGeH{K1Ts-bKbuvx};PxF4KnVu$cTm?;F!6J7|G9Dx zaQe94+6?0=Q1A}mPw+keF}gkf8$JsA$Ni>G#`riPfIDqaNpc@P2lWDxf!Y)?d^X%V z#XuJQlB~DqxPh#@S9=cU;df+pz{$7+#t8vDdxi(!0?$FEK;_9zV7P(aJnOc*Edcf4 z5LC(|*SS-BI`)!%2ls8g-^Klt5Tn2T(Yw2m#. +*/ + +#include "mouse_controller.h" +#include "glmesh.h" +#include "qglview.h" +#include +#include +#include + +using namespace QGLEngineShaders; + + +MouseController::MouseController(QGLView * view_): view(view_) { + app_scale = 1; + lastPos = QPoint(-1, -1); + cur_action = RendererService::haNoAction; + sel_button = Qt::LeftButton; + sel_mod = Qt::ControlModifier; + mouse_first = mouseSelect_ = mouseRotate_ = cameraOrbit_ = canSelect_ = true; + grabMouse_ = mouse_sec = selecting_ = customMouseMove_ = false; +} + + +MouseController::~MouseController() { +} + + +void MouseController::resize() { + mouse_first = true; + app_scale = appScale(); +} + + +void MouseController::mouseReleaseEvent(QMouseEvent * e) { + if (cur_action != RendererService::haNoAction) { + mouseMoveEvent(e); + return; + } + bool add_ts = e->modifiers().testFlag(sel_mod); + if (selecting_) { + selecting_ = false; + canSelect_ = true; + view->renderer_.mouse_rect = QRect(); + view->scene_->selectObjects(hov_objects.toList(), add_ts); + return; + } + if (canSelect_ && mouseSelect_) { + if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance()) { + if (e->button() == Qt::LeftButton) { + //qDebug() << hov_objects << hov_aims; + if (hov_objects.isEmpty() && hov_aims.isEmpty()) { + view->scene()->clearSelection(); + } else { + if (!hov_objects.isEmpty()) + view->scene_->selectObject(hov_objects[0], add_ts); + if (!hov_aims.isEmpty()) { + view->scene_->selectObject(hov_aims[0], add_ts); + hov_aims[0]->selected_aim = true; + } + } + } + if (e->button() == Qt::RightButton) { + if (view->renderer_.edit_mode && !view->scene()->selectedObjects().isEmpty()) + view->context_menu.popup(e->globalPos()); + } + } + } + canSelect_ = e->buttons() == 0; + emit view->glMouseReleaseEvent(e); +} + + +void MouseController::mousePressEvent(QMouseEvent * e) { + downPos = e->pos(); + if (cur_action != RendererService::haNoAction && e->buttons() == Qt::LeftButton) { + return; + } + if (selecting_) { + selecting_ = false; + view->renderer_.mouse_rect = QRect(); + return; + } + if (!QRect(QPoint(), view->size()).contains(e->pos())) return; + lastPos = e->pos(); + downPos = e->pos(); + emit view->glMousePressEvent(e); +} + + +void MouseController::mouseMoveEvent(QMouseEvent * e) { + QPoint cpos = e->pos(); + if (cur_action != RendererService::haNoAction && (e->buttons() == Qt::LeftButton)) { + RendererService & rs(view->renderer_.rend_service); + ObjectBaseList objects = view->scene_->selectedObjects(true); + QVector axis; + switch (cur_action) { + case RendererService::haMove: + if (cur_handle.testFlag(RendererService::hmMoveX)) axis << 0; + if (cur_handle.testFlag(RendererService::hmMoveY)) axis << 1; + if (cur_handle.testFlag(RendererService::hmMoveZ)) axis << 2; + break; + case RendererService::haRotate: + if (cur_handle.testFlag(RendererService::hmRotateX)) axis << 0; + if (cur_handle.testFlag(RendererService::hmRotateY)) axis << 1; + if (cur_handle.testFlag(RendererService::hmRotateZ)) axis << 2; + break; + case RendererService::haScale: + if (cur_handle.testFlag(RendererService::hmScaleX)) axis << 0; + if (cur_handle.testFlag(RendererService::hmScaleY)) axis << 1; + if (cur_handle.testFlag(RendererService::hmScaleZ)) axis << 2; + break; + default: break; + } + QVector scales; + foreach (int a, axis) { + QVector3D axe_vector; axe_vector[a] = 1.; + QMatrix4x4 axis_mat = view->camera()->fullViewMatrix() * rs.axis_mat; + QVector3D center_screen = axis_mat * rs.selection_center; + QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized(); + QVector3D mouse_vector(cpos - lastPos); + mouse_vector[1] *= -1.; + if (cur_action == RendererService::haMove) { + double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length(); + mouse_vector /= QVector3D(view->width(), view->height(), 1); + mouse_vector *= -center_screen.z() * len_scl; + axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); + QMatrix4x4 pmat; + foreach (ObjectBase * o, objects) { + pmat.setToIdentity(); + if (o->parent()) + pmat = o->parent()->worldTransform().inverted(); + QVector3D dv = pmat.mapVector(axe_vector); + if (o->selected_aim) { + AimedObject * ao = (AimedObject*)o; + ao->setAim(ao->aim() + dv); + } else + o->move(dv); + } + } + if (cur_action == RendererService::haRotate) { + axe_screen.setZ(0.); + axe_screen.normalize(); + QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.); + axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale; + foreach (ObjectBase * o, objects) + o->setRotation(o->rotation() + axe_vector); + } + if (cur_action == RendererService::haScale) { + mouse_vector /= QVector3D(view->width(), view->height(), 1); + mouse_vector *= 3. / app_scale; + axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); + scales << axe_vector; + } + } + //if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor; + if (cur_action == RendererService::haScale) { + double sc = 0., max = 0.; + foreach (const QVector3D & s, scales) { + double v = QVector3D::dotProduct(s, QVector3D(1,1,1)); + sc += v; + max = qMax(max, qAbs(v)); + } + sc = max * (sc > 0. ? 1. : -1); + QVector3D axe_vector; + foreach (int a, axis) + axe_vector[a] = 1.; + foreach (ObjectBase * o, objects) + o->scale(QVector3D(1,1,1) + (axe_vector * sc)); + QCursor::setPos(view->mapToGlobal(downPos)); + } else + lastPos = e->pos(); + emit view->objectsPositionChanged(); + return; + } + if (selecting_) { + view->renderer_.mouse_rect = QRect(downPos, cpos).normalized(); + return; + } + if (e->buttons().testFlag(Qt::LeftButton)) { + if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) { + selecting_ = true; + canSelect_ = false; + } + return; + } + QRect g_rect(QPoint(), view->size()); + if (mouseRotate_) { + float dx = e->x() - lastPos.x(); + float dy = e->y() - lastPos.y(); + if (e->buttons().testFlag(Qt::MidButton)) { + if (cameraOrbit_) { + view->camera()->orbitZ (dx / 4.f); + view->camera()->orbitXY(dy / 4.f); + } else { + view->camera()->rotateZ(-dx / 4.f); + view->camera()->rotateX(-dy / 4.f); + } + emit view->cameraPosChanged(view->camera()->pos()); + } else if (e->buttons().testFlag(Qt::RightButton)) { + float ad = view->camera()->distance(); + view->camera()->moveLeft(dx / 1000.f * ad); + view->camera()->moveUp (dy / 1000.f * ad); + emit view->cameraPosChanged(view->camera()->pos()); + } + } + if (customMouseMove_) emit view->customMouseMoveEvent(e->pos(), lastPos, e->buttons()); + lastPos = e->pos(); + if (e->buttons() == 0) { + cur_handle = 0; + cur_action = RendererService::haNoAction; + Qt::CursorShape cs = Qt::CrossCursor; + if (view->renderer_.edit_mode) { + uint hid = view->renderer_.rend_selection.id_hover; + cur_handle = (RendererService::HandleMesh)hid; + if (hid >= RendererService::hmMoveX && hid <= RendererService::hmMaxMove ) { + cur_action = RendererService::haMove; + cs = Qt::SizeAllCursor; + } + if (hid >= RendererService::hmRotateX && hid <= RendererService::hmMaxRotate) { + cur_action = RendererService::haRotate; + cs = Qt::PointingHandCursor; + } + if (hid >= RendererService::hmScaleX && hid <= RendererService::hmMaxScale ) { + cur_action = RendererService::haScale; + cs = Qt::SplitHCursor; + } + } + if (cur_action == RendererService::haNoAction) + cur_handle = 0; + view->setCursor(cs); + view->renderer_.rend_service.current_handle = cur_handle; + } + if (grabMouse_) { + QCursor::setPos(view->mapToGlobal(QRect(QPoint(), view->size()).center())); + if (mouse_sec) { + mouse_sec = false; + return; + } + if (mouse_first) { + mouse_first = false; + mouse_sec = true; + return; + } + lastPos = g_rect.center(); + int dx = e->x() - lastPos.x(); + int dy = e->y() - lastPos.y(); + emit view->glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers())); + return; + } + emit view->glMouseMoveEvent(e); +} + + +void MouseController::wheelEvent(QWheelEvent * e) { + if (mouseRotate_) { + if (e->delta() > 0) view->camera()->flyCloser(0.1f); + if (e->delta() < 0) view->camera()->flyFarer(0.1f); + emit view->cameraPosChanged(view->camera()->pos()); + } + emit view->glWheelEvent(e); +} + + +void MouseController::leaveEvent(QEvent * ) { + lastPos = QPoint(-1, -1); + //qDebug() << lastPos; +} + + +void MouseController::mouseDoubleClickEvent(QMouseEvent * e) { + if (e->buttons().testFlag(Qt::MidButton)) + emit view->doubleClick(); +} diff --git a/mouse_controller.h b/mouse_controller.h new file mode 100644 index 0000000..310fe45 --- /dev/null +++ b/mouse_controller.h @@ -0,0 +1,84 @@ +/* + QGL MouseController + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef MOUSE_CONTROLLER_H +#define MOUSE_CONTROLLER_H + +#include "glprimitives.h" +#include "glcamera.h" +#include "renderer_service.h" +#include +#include + + +class MouseController: public QObject +{ + friend class QGLView; + friend class RendererSelection; + Q_OBJECT +public: + MouseController(QGLView * view_); + virtual ~MouseController(); + + bool isGrabMouseEnabled() const {return grabMouse_;} + bool isMouseRotateEnabled() const {return mouseRotate_;} + bool isMouseSelectionEnabled() const {return mouseSelect_;} + bool isCameraOrbit() const {return cameraOrbit_;} + + Qt::MouseButton selectionButton() const {return sel_button;} + Qt::KeyboardModifier selectionModifier() const {return sel_mod;} + + void setSelectionButton(Qt::MouseButton v) {sel_button = v;} + void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;} + +protected: + void resize(); + void mousePressEvent(QMouseEvent * e); + void mouseMoveEvent(QMouseEvent * e); + void mouseReleaseEvent(QMouseEvent * e); + void wheelEvent(QWheelEvent * e); + void leaveEvent(QEvent * ); + void mouseDoubleClickEvent(QMouseEvent * e); + +private: + QGLView * view; + QPoint lastPos, downPos; + QSet keys_; + QVector hov_objects, hov_aims; + Qt::MouseButton sel_button; + Qt::KeyboardModifier sel_mod; + RendererService::HandleAction cur_action; + QFlags cur_handle; + float app_scale; + bool grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_; + bool cameraOrbit_, selecting_, mouse_sec; + +private slots: + +public slots: + void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;} + void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;} + void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;} + void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;} + void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;} + +signals: + +}; + +#endif // QGLVIEW_H diff --git a/openglwindow.cpp b/openglwindow.cpp new file mode 100644 index 0000000..96c0b4b --- /dev/null +++ b/openglwindow.cpp @@ -0,0 +1,113 @@ +/* + QGL OpenGLWindow + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "openglwindow.h" +#include +#include +#include +#include + + +OpenGLWindow::OpenGLWindow(QWindow *parent) + : QWindow(parent) + , m_context(nullptr) + , m_device(nullptr) +{ + setFlags(flags() | Qt::FramelessWindowHint); + setSurfaceType(QWindow::OpenGLSurface); + QSurfaceFormat format = QSurfaceFormat::defaultFormat(); +// qDebug() << format; +#ifdef QT_OPENGL_ES_2 + format.setRenderableType(QSurfaceFormat::OpenGLES); +#else + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(4, 0); + format.setProfile(QSurfaceFormat::CoreProfile); + } +#endif + format.setDepthBufferSize(24); + format.setSamples(8); +// format.setStencilBufferSize(8); + setFormat(format); + QSurfaceFormat::setDefaultFormat(format); +} + + +OpenGLWindow::~OpenGLWindow() { + delete m_device; +} + + +void OpenGLWindow::render(QPainter *painter) { +} + + +void OpenGLWindow::initialize() { +} + + +void OpenGLWindow::render() { +// if (!m_device) m_device = new QOpenGLPaintDevice; +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +// m_device->setSize(size() * devicePixelRatio()); +// m_device->setDevicePixelRatio(devicePixelRatio()); +// QPainter painter(m_device); +// render(&painter); +} + + +void OpenGLWindow::renderLater() { + requestUpdate(); +} + + +bool OpenGLWindow::event(QEvent *event) { + switch (event->type()) { + case QEvent::UpdateRequest: + renderNow(); + return true; + default: + return QWindow::event(event); + } +} + + +void OpenGLWindow::exposeEvent(QExposeEvent *event) { + if (isExposed()) renderNow(); +} + + +void OpenGLWindow::renderNow() { + if (!isExposed()) + return; + bool needsInitialize = false; + if (!m_context) { + m_context = new QOpenGLContext(this); + m_context->setFormat(requestedFormat()); + m_context->create(); + needsInitialize = true; + } + m_context->makeCurrent(this); + if (needsInitialize) { + initializeOpenGLFunctions(); + initialize(); + } + render(); + m_context->swapBuffers(this); +} + diff --git a/openglwindow.h b/openglwindow.h new file mode 100644 index 0000000..47501f7 --- /dev/null +++ b/openglwindow.h @@ -0,0 +1,54 @@ +/* + QGL OpenGLWindow + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include +#include + +class QPainter; +class QOpenGLContext; +class QOpenGLPaintDevice; + + +class OpenGLWindow: public QWindow, protected QOpenGLExtraFunctions +{ + Q_OBJECT +public: + explicit OpenGLWindow(QWindow *parent = nullptr); + ~OpenGLWindow(); + + virtual void render(QPainter *painter); + virtual void render(); + + virtual void initialize(); + + QOpenGLContext * context() {return m_context;} + +public slots: + void renderLater(); + void renderNow(); + +protected: + bool event(QEvent *event) override; + + void exposeEvent(QExposeEvent *event) override; + +private: + QOpenGLContext *m_context; + QOpenGLPaintDevice *m_device; +}; + diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt new file mode 100644 index 0000000..355566a --- /dev/null +++ b/plugin/CMakeLists.txt @@ -0,0 +1,18 @@ +if (DESIGNER_PLUGINS) + if (NOT Qt5) + message(WARNING "Building ${PROJECT_NAME} available only on Qt5!") + else() + project(qglengine_plugin) + include_directories("..") + add_definitions(-DQT_PLUGIN) + add_definitions(-DQT_NO_DEBUG) + add_definitions(-DQT_SHARED) + add_definitions(-DQDESIGNER_EXPORT_WIDGETS) + find_qt(Qt5 Core Designer Gui Widgets OpenGL) + qt_sources(SRC) + qt_wrap(${SRC} CPPS out_CPP QMS out_QM) + qt_add_library(${PROJECT_NAME} SHARED out_CPP) + qt_target_link_libraries(${PROJECT_NAME} qglengine) + qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtPlugins/designer) + endif() +endif() diff --git a/plugin/qglview_designerplugin.cpp b/plugin/qglview_designerplugin.cpp new file mode 100644 index 0000000..708776b --- /dev/null +++ b/plugin/qglview_designerplugin.cpp @@ -0,0 +1,14 @@ +#include "qglview_designerplugin.h" +#include "qglviewplugin.h" + + +QGLViewDesignerPlugin::QGLViewDesignerPlugin(QObject * parent): QObject(parent) +{ + m_widgets.append(new QGLViewPlugin(this)); +} + + +QList QGLViewDesignerPlugin::customWidgets() const { + return m_widgets; +} + diff --git a/plugin/qglview_designerplugin.h b/plugin/qglview_designerplugin.h new file mode 100644 index 0000000..db6fc67 --- /dev/null +++ b/plugin/qglview_designerplugin.h @@ -0,0 +1,22 @@ +#ifndef QGLVIEW_DESIGNERPLUGIN_H +#define QGLVIEW_DESIGNERPLUGIN_H + +#include +#include + + +class QGLViewDesignerPlugin: public QObject, public QDesignerCustomWidgetCollectionInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "qad.qglview") + Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) +public: + QGLViewDesignerPlugin(QObject * parent = 0); + virtual QList customWidgets() const; + +private: + QList m_widgets; + +}; + +#endif // QGLVIEW_DESIGNERPLUGIN_H diff --git a/plugin/qglviewplugin.cpp b/plugin/qglviewplugin.cpp new file mode 100644 index 0000000..97db1e4 --- /dev/null +++ b/plugin/qglviewplugin.cpp @@ -0,0 +1,95 @@ +#include "../glwidget.h" +#include "qglviewplugin.h" +#include +#include "glprimitives.h" +#include "qglview.h" + + +QGLViewPlugin::QGLViewPlugin(QObject * parent): QObject(parent) { + m_initialized = false; +} + + +void QGLViewPlugin::initialize(QDesignerFormEditorInterface * /* core */) { + if (m_initialized) + return; + + // Add extension registrations, etc. here + + m_initialized = true; +} + + +bool QGLViewPlugin::isInitialized() const { + return m_initialized; +} + + +QWidget * QGLViewPlugin::createWidget(QWidget * parent) { + GLWidget * w = new GLWidget(parent); + if (m_initialized) { + auto axis = new GLObjectBase(); + GLObjectBase * obj; + float al = 1.; + obj = new GLPrimitiveLine(QVector3D(0, 0, -al), QVector3D(0, 0, al)); + obj->material().color_diffuse = Qt::darkBlue; obj->setAcceptLight(false); + obj->setSelectable(false); + axis->addChild(obj); + obj = new GLPrimitiveLine(QVector3D(-al, 0, 0), QVector3D(al, 0, 0)); + obj->material().color_diffuse = Qt::darkRed; obj->setAcceptLight(false); + obj->setSelectable(false); + axis->addChild(obj); + obj = new GLPrimitiveLine(QVector3D(0, -al, 0), QVector3D(0, al, 0)); + obj->material().color_diffuse = Qt::darkGreen; obj->setAcceptLight(false); + obj->setSelectable(false); + axis->addChild(obj); + w->view()->addObject(axis); + auto cam_light = new Light(); + cam_light->intensity = 0.5; + cam_light->setName("Camera_Light"); + w->view()->camera()->addChild(cam_light); + w->start(); + } + return w; +} + + +QString QGLViewPlugin::name() const { + return QLatin1String("GLWidget"); +} + + +QString QGLViewPlugin::group() const { + return QLatin1String("Display Widgets"); +} + + +QIcon QGLViewPlugin::icon() const { + return QIcon("://icons/qglview.png"); +} + + +QString QGLViewPlugin::toolTip() const { + return QLatin1String(""); +} + + +QString QGLViewPlugin::whatsThis() const { + return QLatin1String(""); +} + + +bool QGLViewPlugin::isContainer() const { + return false; +} + + +QString QGLViewPlugin::domXml() const { + return QLatin1String("\n\n"); +} + + +QString QGLViewPlugin::includeFile() const { + return QLatin1String("glwidget.h"); +} + diff --git a/plugin/qglviewplugin.h b/plugin/qglviewplugin.h new file mode 100644 index 0000000..6516afb --- /dev/null +++ b/plugin/qglviewplugin.h @@ -0,0 +1,33 @@ +#ifndef QGLVIEWPLUGIN_H +#define QGLVIEWPLUGIN_H + +#include +#include + + +class QGLViewPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + explicit QGLViewPlugin(QObject * parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget * createWidget(QWidget * parent); + void initialize(QDesignerFormEditorInterface * core); + +private: + bool m_initialized; + +}; + +#endif //QGLVIEWPLUGIN_H diff --git a/qglview.cpp b/qglview.cpp new file mode 100644 index 0000000..d48d666 --- /dev/null +++ b/qglview.cpp @@ -0,0 +1,299 @@ +/* + QGLView + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "qglview.h" +#include "glmesh.h" +#include "gltexture_manager.h" +#include +#include +#include +#include +#include + +using namespace QGLEngineShaders; + + +QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { + setIcon(QIcon(":/icons/qglview.png")); + deleting_ = false; + timer = 0; + need_init_ = is_first_draw = true; + backColor_ = Qt::darkGray; + hoverHaloColor_ = QColor(195, 140, 255); + selectionHaloColor_ = QColor(175, 255, 140); + ambientColor_ = QColor(10, 10, 10); + lineWidth_ = 1.; + max_anisotropic = 1; + max_texture_chanels = 8; + lightEnabled_ = true; + shaders_supported = false; + fps_cnt = 0; + fps_tm = fps_ = 0.; + fogColor_ = Qt::darkGray; + fogDensity_ = 0.; + fogDecay_ = 10.; + hoverHaloFill_ = selectionHaloFill_ = 0.15f; + //lmode = Simple; + setFeature(qglFXAA, false); + setFeature(qglAnisotropicLevel, 8); + setFeature(qglEyeAccomodationEnabled, false); + setFeature(qglEyeAccomodationTime, 16.); + setFeature(qglEyeAccomodationMaxSpeed, 0.2); + setFeature(qglBloomEnabled, false); + setFeature(qglBloomThreshold, 0.9); + setFeature(qglBloomFactor, 1.); + setFeature(qglBloomRadius, 8); + setFeature(qglMotionBlurEnabled, false); + setFeature(qglMotionBlurFactor, 1.); + setFeature(qglMotionBlurSteps, 8); + setFeature(qglShadowsEnabled, false); + setFeature(qglShadowsMapSize, 512); + setFeature(qglShadowsSoftEnabled, true); + setFeature(qglReflectionsEnabled, false); + setFeature(qglReflectionsBlur, true); + setFeature(qglSSAOEnabled, false); + setFeature(qglSSAORadius, 5); + setFeature(qglDepthOfFieldEnabled, false); + setFeature(qglDepthOfFieldAutoFocusEnabled, true); + setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1); + setFeature(qglDepthOfFieldFocus, 1.); + setFeature(qglDepthOfFieldDiaphragm, 8.); + hoverHalo_ = selectionHalo_ = true; + fogEnabled_ = is_init = shaders_bind = changed_ = false; + rmode = ObjectBase::Fill; +// sel_pen = QPen(Qt::black, 1, Qt::DashLine); +// sel_brush = QBrush(QColor(170, 100, 255, 120)); + scene_ = new Scene(); + connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); + connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed())); + connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*))); + default_camera = new Camera(); + default_camera->setPos(QVector3D(2, 2, 2)); + default_camera->setAim(QVector3D()); + camera_ = default_camera; +// qDebug() << camera_->aim(); + default_camera->setName("Camera"); + emit cameraPosChanged(default_camera->pos()); + //camera().aim_ = camera().pos_; + ktm_.restart(); + + //Mesh * m = Primitive::torus(100, 40, 1., 0.4, 360); + Mesh * m = Primitive::cube(10, 10, 10); + m->flipNormals(); + //QMatrix4x4 mat; + //mat.rotate(90, 0,1,0); + //mat.translate(0, 0, 2); + //mat.rotate(180, 1,0,0); + //m->transformPoints(mat); + ObjectBase * o = new ObjectBase(m); + o->setColor(Qt::cyan); + scene()->addObject(o); + delete m; + +} + + +QGLView::~QGLView() { + deleting_ = true; + stop(); + scene_->clear(); + delete scene_; + delete default_camera; +} + + +void QGLView::stop() { + if (timer) killTimer(timer); +} + + +void QGLView::start(float freq) { + timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq)); +} + + +QList QGLView::selectedLights() const { + QList ret; + ObjectBaseList sol = scene_->selectedObjects(); + foreach (ObjectBase * o, sol) + if (o->type() == ObjectBase::glLight) + ret << (Light*)o; + return ret; +} + + +QList QGLView::selectedCameras() const { + QList ret; + ObjectBaseList sol = scene_->selectedObjects(); + foreach (ObjectBase * o, sol) + if (o->type() == ObjectBase::glCamera) + ret << (Camera*)o; + return ret; +} + + + +void QGLView::resizeEvent(QResizeEvent * e) { + renderLater(); + mouse.resize(); +} + + +void QGLView::timerEvent(QTimerEvent *) { + renderNow(); + //if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return; + Qt::KeyboardModifiers km = QApplication::keyboardModifiers(); + foreach (int i, keys_) + emit keyEvent((Qt::Key)i, km); +} + + +void QGLView::render() { + resizeGL(width(), height()); + emit glBeginPaint(); + renderer_.mouse_pos = mapFromGlobal(QCursor::pos()); + renderer_.renderScene(); + emit glEndPaint(); + fps_tm += time.elapsed(); + time.restart(); + fps_cnt++; + if (fps_tm < 1000.) return; + fps_ = fps_cnt / fps_tm * 1000.; + fps_tm = 0.; + fps_cnt = 0; +} + + +void QGLView::initialize() { + checkCaps(); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDisable(GL_MULTISAMPLE); + glDisable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT); + glEnable(GL_CULL_FACE); + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + glCullFace(GL_BACK); + renderer_.reloadShaders(); + renderer_.init(width(), height()); + is_init = true; + need_init_ = false; + emit glInitializeDone(); +} + + +void QGLView::checkCaps() { + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic); + shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms(); +} + + +void QGLView::__destroyed() { + renderer_.rend_mat.mat_thumbnails.clear(); + mouse.hov_objects.clear(); +} + + +void QGLView::__objectDeleted(ObjectBase * o) { + if (o == camera_) + setDefaultCamera(); +} + + +void QGLView::resizeGL(int width, int height) { + if (!is_init) return; + if (width <= 0 || height <= 0) return; + if (prev_size == QSize(width, height)) return; + prev_size = QSize(width, height); + aspect = float(width) / float(height); + renderer_.resize(width, height); + //qDebug() << "resize" << width << height; + iaspect = (aspect == 0.f) ? 0. : 1 / aspect; + glViewport(0, 0, width, height); + emit glResize(width, height); +} + + +void QGLView::keyPressEvent(QKeyEvent * e) { + emit glKeyPressEvent(e); + if (e->key() > 0) keys_.insert(e->key()); + if (e->key() == Qt::Key_F11) { + emit doubleClick(); + } +} + + +void QGLView::keyReleaseEvent(QKeyEvent * e) { + emit glKeyReleaseEvent(e); + keys_.remove(e->key()); +} + + +void QGLView::focusOutEvent(QFocusEvent *) { + keys_.clear(); +} + + +void QGLView::focusOn(const Box3D & bb) { + if (bb.isEmpty() || !camera()) return; + double size = qMax(qMax(bb.width, bb.length), bb.height); + camera()->setAim(bb.center()); + camera()->flyToDistance(size * 1.25); +} + + +QByteArray QGLView::saveCamera() { + ChunkStream cs; + const Camera * c = camera(); + cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV()); + return cs.data(); +} + + +void QGLView::restoreCamera(const QByteArray & ba) { + if (ba.isEmpty()) return; + Camera * c = camera(); + QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation()); + float fov(c->FOV()); + ChunkStream cs(ba); + cs.readAll(); + cs.get(1, pos).get(2, aim).get(3, ang).get(4, fov); + camera()->setPos(pos); + camera()->setAim(aim); + camera()->setAngles(ang); + camera()->setFOV(fov); +} + + +QByteArray QGLView::saveFeatures() { + QByteArray ba; + QDataStream ds(&ba, QIODevice::WriteOnly); + ds << features_; + return ba; +} + + +void QGLView::restoreFeatures(const QByteArray & ba) { + QHash f; + QDataStream ds(ba); + ds >> f; + features_ = f; +} diff --git a/qglview.h b/qglview.h new file mode 100644 index 0000000..66a64a5 --- /dev/null +++ b/qglview.h @@ -0,0 +1,293 @@ +/* + QGLView + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef QGLVIEW_H +#define QGLVIEW_H + +#include "openglwindow.h" +#include "glframebuffer.h" +#include "glprimitives.h" +#include "glcamera.h" +#include "glrendererbase.h" +#include "glscene.h" +#include "renderer.h" +#include "mouse_controller.h" +#include +#include + + +class QGLView: public OpenGLWindow +{ + friend class MouseController; + friend class GLRendererBase; + friend class TextureManager; + friend class ObjectBase; + friend class Scene; + friend class RendererBase; + friend class Renderer; + friend class RendererMaterial; + friend class RendererService; + friend class RendererSelection; + friend class TonemappingProc; + Q_OBJECT + Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) + Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth) + Q_PROPERTY (float FOV READ FOV WRITE setFOV) + Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart) + Q_PROPERTY (float gamma READ gamma WRITE setGamma) + Q_PROPERTY (bool autoExposure READ autoExposure WRITE setAutoExposure) + Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) + Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor) + Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled) + Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity) + Q_PROPERTY (float fogDecay READ fogDecay WRITE setFogDecay) + Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode) + Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) + Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) + Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) + Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) + Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) + Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) + Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) + Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) + Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) + Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) + Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton) + Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier) + Q_PROPERTY (Scene::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + +public: + QGLView(); + virtual ~QGLView(); + + enum CameraLightMode { + clmOff, + clmAuto, + clmOn, + }; + + enum Feature { + qglFXAA, + qglAnisotropicLevel, + qglEyeAccomodationEnabled, + qglEyeAccomodationTime, + qglEyeAccomodationMaxSpeed, + qglBloomEnabled, + qglBloomThreshold, + qglBloomFactor, + qglBloomRadius, + qglMotionBlurEnabled, + qglMotionBlurFactor, + qglMotionBlurSteps, + qglShadowsEnabled, + qglShadowsMapSize, + qglShadowsSoftEnabled, + qglReflectionsEnabled, + qglReflectionsBlur, + qglSSAOEnabled, + qglSSAORadius, + qglDepthOfFieldEnabled, + qglDepthOfFieldAutoFocusEnabled, + qglDepthOfFieldAutoFocusSpeed, + qglDepthOfFieldFocus, + qglDepthOfFieldDiaphragm + }; + + Q_ENUM(CameraLightMode) + + void stop(); + void start(float freq = 60.); + + QColor backColor() const {return backColor_;} + float lineWidth() const {return lineWidth_;} + float FOV() const {return camera()->fov_;} + float depthStart() const {return camera()->depth_start;} + float currentFPS() const {return fps_;} + float gamma() const {return renderer_.gamma_;} + bool autoExposure() const {return renderer_.tone_proc.enabled;} + int maxAnisotropicLevel() const {return max_anisotropic;} + QString environmentMapFile() const {return renderer_.tex_env.fileHDR();} + + QColor ambientColor() const {return ambientColor_;} + QColor fogColor() const {return fogColor_;} + float fogDensity() const {return fogDensity_;} + float fogDecay() const {return fogDecay_;} + bool isFogEnabled() const {return fogEnabled_;} + bool isLightEnabled() const {return lightEnabled_;} + bool isGrabMouseEnabled() const {return mouse.isGrabMouseEnabled();} + bool isMouseRotateEnabled() const {return mouse.isMouseRotateEnabled();} + bool isMouseSelectionEnabled() const {return mouse.isMouseSelectionEnabled();} + bool isCameraOrbit() const {return mouse.isCameraOrbit();} + bool isHoverHaloEnabled() const {return hoverHalo_;} + QColor hoverHaloColor() const {return hoverHaloColor_;} + float hoverHaloFillAlpha() const {return hoverHaloFill_;} + bool isSelectionHaloEnabled() const {return selectionHalo_;} + QColor selectionHaloColor() const {return selectionHaloColor_;} + float selectionHaloFillAlpha() const {return selectionHaloFill_;} + + QVariant feature(Feature f) const {return features_.value(int(f));} + QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;} + bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();} + + int renderMode() const {return (int)rmode;} + void setRenderMode(int mode) {rmode = (ObjectBase::RenderMode)mode;} + + bool isServiceMode() const {return renderer_.edit_mode;} + void setServiceMode(bool yes) {renderer_.edit_mode = yes;} + + + Scene::SelectionMode selectionMode() const {return scene_->selectionMode();} + Qt::MouseButton selectionButton() const {return mouse.selectionButton();} + Qt::KeyboardModifier selectionModifier() const {return mouse.selectionModifier();} + + void setSelectionMode(Scene::SelectionMode m) {scene_->setSelectionMode(m);} + void setSelectionButton(Qt::MouseButton v) {mouse.setSelectionButton(v);} + void setSelectionModifier(Qt::KeyboardModifier v) {mouse.setSelectionModifier(v);} + + void selectObject(ObjectBase * o, bool add_to_selection = false) {scene_->selectObject(o, add_to_selection);} + void clearSelection() {scene_->clearSelection();} + ObjectBaseList selectedObjects(bool top_only = false) const {return scene_->selectedObjects(top_only);} + QList selectedLights() const; + QList selectedCameras() const; + ObjectBase * selectedObject() const {return scene_->selectedObject();} + + TextureManager * textureManager() {return renderer_.textures_manager;} + void reloadTextures() {renderer_.markReloadTextures();} + + Scene * scene() {return scene_;} + void focusOn(const Box3D & bb); + void setCameraLightMode(CameraLightMode m) {renderer_.setCameraLightMode(m);} + CameraLightMode cameraLightMode() const {return (CameraLightMode)renderer_.cameraLightMode();} + + Camera * camera() {return camera_;} + const Camera * camera() const {return camera_;} + void setCamera(Camera * camera) {camera_ = camera;} + void setDefaultCamera() {camera_ = default_camera;} + QByteArray saveCamera(); + void restoreCamera(const QByteArray & ba); + QByteArray saveFeatures(); + void restoreFeatures(const QByteArray & ba); + + QImage materialThumbnail(Material * m) {return renderer_.materialThumbnail(m);} + void setCurrentAction(RendererService::HandleAction ha) {renderer_.rend_service.setCurrentAction(ha);} + void setContextActions(QList al) {context_menu.clear(); context_menu.addActions(al);} + + GLfloat aspect, iaspect; + Renderer renderer_; + +protected: + void render(); + void resizeEvent(QResizeEvent * e); + + void timerEvent(QTimerEvent * ); + void initialize(); + void resizeGL(int width, int height); + void mousePressEvent(QMouseEvent * e) {mouse.mousePressEvent(e);} + void mouseMoveEvent(QMouseEvent * e) {mouse.mouseMoveEvent(e);} + void mouseReleaseEvent(QMouseEvent * e) {mouse.mouseReleaseEvent(e);} + void wheelEvent(QWheelEvent * e) {mouse.wheelEvent(e);} + void mouseDoubleClickEvent(QMouseEvent * e) {mouse.mouseDoubleClickEvent(e);} + void leaveEvent(QEvent * ); + + void keyPressEvent(QKeyEvent * e); + void keyReleaseEvent(QKeyEvent * e); + void focusOutEvent(QFocusEvent *); + + void checkCaps(); + +private: + void processKeys(); + bool setupViewport(); + + Scene * scene_; + Camera * camera_, * default_camera; + MouseController mouse; + QMenu context_menu; + QSet keys_; + QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_; + QTime time, ktm_; + GLint max_anisotropic, max_texture_chanels; + ObjectBase::RenderMode rmode; + GLRendererBase::RenderingParameters start_rp; + QHash features_; + QSize prev_size; + float lineWidth_; + float fps_, fps_tm, fogDensity_, fogDecay_; + float hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor; + int timer, fps_cnt, sh_id_loc, deleting_; + bool is_first_draw, is_init, fogEnabled_, lightEnabled_; + bool shaders_supported, changed_, need_init_; + bool hoverHalo_, selectionHalo_, shaders_bind; + +private slots: + void __destroyed(); + void __objectDeleted(ObjectBase * o); + +public slots: + void setBackColor(const QColor & arg) {backColor_ = arg;} + void setLineWidth(const float & arg) {lineWidth_ = arg;} + void setFOV(const float & arg) {camera()->fov_ = arg;} + void setDepthStart(const float & arg) {camera()->depth_start = arg;} + void setGamma(const float & arg) {renderer_.gamma_ = arg;} + void setAutoExposure(bool arg) {renderer_.tone_proc.enabled = arg;} + void setAmbientColor(const QColor & arg) {ambientColor_ = arg;} + void setEnvironmentMapFile(QString file) {renderer_.tex_env.setFileHDR(file); renderer_.recreateMaterialThumbnails(true);} + void setFogColor(const QColor & arg) {fogColor_ = arg;} + void setFogDensity(const float & arg) {fogDensity_ = arg;} + void setFogDecay(const float & arg) {fogDecay_ = arg;} + void setFogEnabled(const bool & arg) {fogEnabled_ = arg;} + void setLightEnabled(const bool & arg) {lightEnabled_ = arg;} + void setGrabMouseEnabled(const bool & arg) {mouse.setGrabMouseEnabled(arg);} + void setMouseRotateEnabled(const bool & arg) {mouse.setMouseRotateEnabled(arg);} + void setMouseSelectionEnabled(const bool & arg) {mouse.setMouseSelectionEnabled(arg);} + void setCustomMouseMove(const bool & arg) {mouse.setCustomMouseMove(arg);} + void setCameraOrbit(const bool & arg) {mouse.setCameraOrbit(arg);} + void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;} + void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;} + void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;} + void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;} + void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;} + void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;} + + void reloadShaders() {renderer_.reloadShaders();} + +signals: + void glBeginPaint(); + void glEndPaint(); + void glKeyPressEvent(QKeyEvent * e); + void glKeyReleaseEvent(QKeyEvent * e); + void glMousePressEvent(QMouseEvent * e); + void glMouseMoveEvent(QMouseEvent * e); + void glMouseReleaseEvent(QMouseEvent * e); + void glWheelEvent(QWheelEvent * e); + void glResize(int, int); + void glInitializeDone(); + void cameraPosChanged(QVector3D pos); + void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod); + void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons); + + void hoverChanged(ObjectBase * cur, ObjectBase * prev); + void selectionChanged(); + void objectsPositionChanged(); + void materialsChanged(); + void materialThumbnailCreated(Material*); + void doubleClick(); + +}; + +#endif // QGLVIEW_H diff --git a/qglview.qrc b/qglview.qrc new file mode 100644 index 0000000..e67f617 --- /dev/null +++ b/qglview.qrc @@ -0,0 +1,46 @@ + + + coeffs_brdf.png + icons/add-type-camera.png + icons/add-type-geo.png + icons/add-type-light.png + icons/add-type-empty.png + icons/collapse.png + icons/expand.png + icons/edit-rename.png + icons/alpha.png + icons/application-exit.png + icons/configure.png + icons/dialog-close.png + icons/document-edit.png + icons/document-import.png + icons/document-new.png + icons/document-open.png + icons/document-save.png + icons/document-save-all.png + icons/edit-clear.png + icons/edit-clear-locationbar-rtl.png + icons/edit-copy.png + icons/edit-delete.png + icons/edit-find.png + icons/edit-paste.png + icons/go-jump.png + icons/go-top.png + icons/layer-visible-on.png + icons/layer-visible-off.png + icons/light-+.png + icons/list-add.png + icons/object-flip-horizontal.png + icons/object-flip-vertical.png + icons/picker.png + icons/qglview.png + icons/transform-move.png + icons/transform-rotate.png + icons/transform-scale.png + icons/type-camera.png + icons/type-geo.png + icons/type-light.png + icons/type-empty.png + icons/view-refresh.png + + diff --git a/qglview_test/main.cpp b/qglview_test/main.cpp new file mode 100644 index 0000000..eb43d61 --- /dev/null +++ b/qglview_test/main.cpp @@ -0,0 +1,34 @@ +/* + QGLViewWindow + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include "qglview_window.h" + +int main(int argc, char ** argv) { + QApplication a(argc, argv); + a.setAttribute(Qt::AA_UseHighDpiPixmaps, true); + QGLViewWindow w; + w.show(); + QStringList al(a.arguments()); + al.pop_front(); + foreach (QString s, al) + w.loadFile(s); + return a.exec(); +} diff --git a/qglview_test/qglview_window.cpp b/qglview_test/qglview_window.cpp new file mode 100644 index 0000000..a6ac505 --- /dev/null +++ b/qglview_test/qglview_window.cpp @@ -0,0 +1,251 @@ +/* + QGLViewWindow + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "qglview_window.h" +#include "renderer.h" +#include "glwidget.h" +#include "gltexture_manager.h" +#include +#include +#include +#include "qad_types.h" + + +QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLViewWindow() { + setupUi(this); + session.setFile("session_qglview_test.conf"); + session.addEntry(this); + + extensions = "All(" + supportedFormats().join(" ") + " *.qgl)"; + extensions += ";;QGLEngine(*.qgl)"; + + //view->view()->camera()->setPos(QVector3D(2, 2, 2)); + //view->view()->camera()->setAim(QVector3D()); + //view->view()->camera()->flyToDistance(2.); +// view->setFrameShape(QFrame::NoFrame); + view->view()->setMouseRotateEnabled(true); + view->view()->setMouseSelectionEnabled(true); + view->view()->setSelectionHaloEnabled(true); + view->view()->setHoverHaloEnabled(true); + view->view()->setBackColor(Qt::lightGray); + view->view()->setDepthStart(0.1); + view->view()->setSelectionMode(Scene::smMultiSelection); + + + groupShadows->setChecked(view->view()->isFeatureEnabled(QGLView::qglShadowsEnabled)); + groupEyeAccomodation->setChecked(view->view()->isFeatureEnabled(QGLView::qglEyeAccomodationEnabled)); + groupBloom->setChecked(view->view()->isFeatureEnabled(QGLView::qglBloomEnabled)); + groupMotionBlur->setChecked(view->view()->isFeatureEnabled(QGLView::qglMotionBlurEnabled)); + groupReflections->setChecked(view->view()->isFeatureEnabled(QGLView::qglReflectionsEnabled)); + checkSoftShadows->setChecked(view->view()->isFeatureEnabled(QGLView::qglShadowsSoftEnabled)); + groupSSAO->setChecked(view->view()->isFeatureEnabled(QGLView::qglSSAOEnabled)); + spinAccom->setValue(view->view()->feature(QGLView::qglEyeAccomodationTime).toDouble()); + spinAccomMS->setValue(view->view()->feature(QGLView::qglEyeAccomodationMaxSpeed).toDouble()); + checkReflectionsBlur->setChecked(view->view()->isFeatureEnabled(QGLView::qglReflectionsBlur)); + spinShadowmapSize->setValue(view->view()->feature(QGLView::qglShadowsMapSize).toInt()); + spinMotionBlurFactor->setValue(view->view()->feature(QGLView::qglMotionBlurFactor).toDouble()); + spinMotionBlurSteps->setValue(view->view()->feature(QGLView::qglMotionBlurSteps).toInt()); + spinBloomFactor->setValue(view->view()->feature(QGLView::qglBloomFactor).toDouble()); + spinBloomRadius->setValue(view->view()->feature(QGLView::qglBloomRadius).toInt()); + spinBloomThreshold->setValue(view->view()->feature(QGLView::qglBloomThreshold).toDouble()); + spinSSAORadius->setValue(view->view()->feature(QGLView::qglSSAORadius).toInt()); + groupDOF->setChecked(view->view()->isFeatureEnabled(QGLView::qglDepthOfFieldEnabled)); + checkDOFAutoFocus->setChecked(view->view()->isFeatureEnabled(QGLView::qglDepthOfFieldAutoFocusEnabled)); + spinDOFFocus->setValue(view->view()->feature(QGLView::qglDepthOfFieldFocus).toDouble()); + spinDOFDiaphragm->setValue(view->view()->feature(QGLView::qglDepthOfFieldDiaphragm).toDouble()); + spinDOFSpeed->setValue(view->view()->feature(QGLView::qglDepthOfFieldAutoFocusSpeed).toDouble()); + + view->view()->start(-1); + startTimer(1000/60); + + connect(view->view(), SIGNAL(keyEvent(Qt::Key, Qt::KeyboardModifiers)), this, SLOT(view_keyEvent(Qt::Key, Qt::KeyboardModifiers))); + //connect(matEditor, SIGNAL(changed()), this, SLOT(materialChanged())); + sceneTree->assignQGLView(view->view()); + matEditor->assignQGLView(view->view()); + objectEditor->assignQGLView(view->view()); + primitiveEditor->assignQGLView(view->view()); + viewEditor->assignQGLView(view->view()); + + session.load(); + + //loadFile("axis.DAE.qgl"); + //matEditor->setMaterial(const_cast(view->view()->scene()->rootObject()->child(0))->material()); + /*Scene * sc = loadScene("truck.obj"); + //view->view()->scene()->addScene(sc); + sc->rootObject()->moveY(-8); + for (int i = 0; i < 7; ++i) { + sc->rootObject()->moveY(2); + view->view()->scene()->addScene(sc); + } + //view->view()->scene()->dump(); + delete sc;*/ +} + + +QGLViewWindow::~QGLViewWindow() { + session.save(); + //delete ps; +} + + +void QGLViewWindow::changeEvent(QEvent * e) { + QMainWindow::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + retranslateUi(this); + return; + } +} + + +void QGLViewWindow::timerEvent(QTimerEvent * ) { + //static double t = 0.; + //((RendererSimple*)(view->view()->renderer()))->mpos = view->view()->mapFromGlobal(QCursor::pos()); + statusBar()->showMessage(QString("FPS: %1").arg(QString::number(view->view()->currentFPS(), 'f', 2))); +} + + +void QGLViewWindow::loadFile(const QString & path, bool import) { + prev_path = path; + QApplication::setOverrideCursor(Qt::WaitCursor); + QFileInfo fi(path); + Scene * s = nullptr; + if (fi.suffix().toLower() == "qgl") s = loadFromQGLFile(path); + else s = loadScene(path); + QApplication::restoreOverrideCursor(); + if (!s) { + QMessageBox::critical(this, "Import", "Can`t load " + path + "!"); + return; + } + s->setName(fi.baseName()); + if (import) view->scene()->addScene(s); + else { + TextureManager::clearSearchPathes(); + view->scene()->assignFrom(s); + view->view()->focusOn(view->scene()->boundingBox()); + } + TextureManager::addSearchPath(fi.absoluteDir().path()); + delete s; +} + + +void QGLViewWindow::on_actionReset_triggered() { + ///view->view()->removeObject(axis, false); + view->view()->scene()->clear(); + ///view->view()->addObject(axis); +} + + +void QGLViewWindow::on_actionImport_triggered() { + QStringList fl = QFileDialog::getOpenFileNames(this, "Select files", prev_path, extensions); + if (fl.isEmpty()) return; + prev_path = fl.back(); + foreach (QString f, fl) + loadFile(f, true); +} + + +void QGLViewWindow::on_actionSave_triggered() { + QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)"); + if (f.isEmpty()) return; + if (f.right(4).toLower() != ".qgl") + f += ".qgl"; + prev_path = f; + QApplication::setOverrideCursor(Qt::WaitCursor); + saveToQGLFile(f, view->scene()); + QApplication::restoreOverrideCursor(); +} + + +void QGLViewWindow::on_actionSaveSelected_triggered() { + ObjectBase * sel_obj = view->view()->selectedObject(); + if (!sel_obj) return; + QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)"); + if (f.isEmpty()) return; + if (f.right(4).toLower() != ".qgl") + f += ".qgl"; + prev_path = f; + QApplication::setOverrideCursor(Qt::WaitCursor); + ///saveToQGLFile(f, sel_obj); + QApplication::restoreOverrideCursor(); +} + + +void QGLViewWindow::on_actionOpen_triggered() { + QString f = QFileDialog::getOpenFileName(this, "Select file", prev_path, extensions); + if (f.isEmpty()) return; + prev_path = f; + loadFile(f); +} + + +void QGLViewWindow::view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m) { + //qDebug() << k; + double spd = 0.2; + if (m.testFlag(Qt::ShiftModifier)) + spd = 0.5; + switch (k) { + case Qt::Key_W: view->view()->camera()->moveForward(spd); break; + case Qt::Key_S: view->view()->camera()->moveBackward(spd); break; + case Qt::Key_A: view->view()->camera()->moveLeft(spd); break; + case Qt::Key_D: view->view()->camera()->moveRight(spd); break; + default: break; + } +} + + +void QGLViewWindow::on_actionArrow_triggered(bool on) { + actionArrow ->setChecked(true); + actionMove ->setChecked(false); + actionRotate->setChecked(false); + actionScale ->setChecked(false); + view->view()->setCurrentAction(RendererService::haNoAction); +} + + +void QGLViewWindow::on_actionMove_triggered(bool on) { + actionArrow ->setChecked(false); + actionMove ->setChecked(true); + actionRotate->setChecked(false); + actionScale ->setChecked(false); + view->view()->setCurrentAction(RendererService::haMove); +} + + +void QGLViewWindow::on_actionRotate_triggered(bool on) { + actionArrow ->setChecked(false); + actionMove ->setChecked(false); + actionRotate->setChecked(true); + actionScale ->setChecked(false); + view->view()->setCurrentAction(RendererService::haRotate); +} + + +void QGLViewWindow::on_actionScale_triggered(bool on) { + actionArrow ->setChecked(false); + actionMove ->setChecked(false); + actionRotate->setChecked(false); + actionScale ->setChecked(true); + view->view()->setCurrentAction(RendererService::haScale); +} + + +#include "glcubemap.h" +void QGLViewWindow::on_pushButton_3_clicked() { + QString f = QFileDialog::getOpenFileName(this, "Select file", "", "*"); + if (f.isEmpty()) return; +} diff --git a/qglview_test/qglview_window.h b/qglview_test/qglview_window.h new file mode 100644 index 0000000..304353f --- /dev/null +++ b/qglview_test/qglview_window.h @@ -0,0 +1,119 @@ +/* + QGLViewWindow + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef QGLVIEWWINDOW_H +#define QGLVIEWWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ui_qglview_window.h" +#include "formats/loader_qgl.h" +#include "formats/loader_assimp.h" +#include "session_manager.h" +//#include "renderer_rt.h" +#include "qglview.h" +#include "ui_qglview_window.h" + + +class QGLViewWindow: public QMainWindow, public Ui::QGLViewWindow +{ + Q_OBJECT +public: + QGLViewWindow(QWidget * parent = 0); + ~QGLViewWindow(); + + void loadFile(const QString & path, bool import = false); + +private: + // Qt`s overloaded + void changeEvent(QEvent * e); + void timerEvent(QTimerEvent * ); + + QString extensions; + QTranslator translator; + QString prev_path; + //GLPrimitiveCube * box; + Material m; + SessionManager session; + bool isChanged; + +private slots: + void on_groupShadows_clicked(bool val) {view->view()->setFeature(QGLView::qglShadowsEnabled, val);} + void on_groupEyeAccomodation_clicked(bool val) {view->view()->setFeature(QGLView::qglEyeAccomodationEnabled, val);} + void on_groupBloom_clicked(bool val) {view->view()->setFeature(QGLView::qglBloomEnabled, val);} + void on_groupMotionBlur_clicked(bool val) {view->view()->setFeature(QGLView::qglMotionBlurEnabled, val);} + void on_groupReflections_clicked(bool val) {view->view()->setFeature(QGLView::qglReflectionsEnabled, val);} + void on_checkSoftShadows_clicked(bool val) {view->view()->setFeature(QGLView::qglShadowsSoftEnabled, val);} + void on_groupSSAO_clicked(bool val) {view->view()->setFeature(QGLView::qglSSAOEnabled, val);} + void on_groupDOF_clicked(bool val) {view->view()->setFeature(QGLView::qglDepthOfFieldEnabled, val);} + void on_checkDOFAutoFocus_clicked(bool val) {view->view()->setFeature(QGLView::qglDepthOfFieldAutoFocusEnabled, val);} + void on_spinDOFFocus_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldFocus, val);} + void on_spinDOFDiaphragm_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldDiaphragm, val);} + void on_spinDOFSpeed_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldAutoFocusSpeed, val);} + void on_spinAccom_valueChanged(double val) {view->view()->setFeature(QGLView::qglEyeAccomodationTime, val);} + void on_spinAccomMS_valueChanged(double val) {view->view()->setFeature(QGLView::qglEyeAccomodationMaxSpeed, val);} + void on_checkReflectionsBlur_clicked(bool val) {view->view()->setFeature(QGLView::qglReflectionsBlur, val);} + void on_spinShadowmapSize_valueChanged(double val) {view->view()->setFeature(QGLView::qglShadowsMapSize, val);} + void on_spinMotionBlurFactor_valueChanged(double val) {view->view()->setFeature(QGLView::qglMotionBlurFactor, val);} + void on_spinMotionBlurSteps_valueChanged(int val) {view->view()->setFeature(QGLView::qglMotionBlurSteps, val);} + void on_spinBloomFactor_valueChanged(double val) {view->view()->setFeature(QGLView::qglBloomFactor, val);} + void on_spinBloomRadius_valueChanged(int val) {view->view()->setFeature(QGLView::qglBloomRadius, val);} + void on_spinBloomThreshold_valueChanged(double val) {view->view()->setFeature(QGLView::qglBloomThreshold, val);} + void on_spinSSAORadius_valueChanged(int val) {view->view()->setFeature(QGLView::qglSSAORadius, val);} + + void on_actionExit_triggered() {close();} + void on_actionReset_triggered(); + void on_actionImport_triggered(); + void on_actionSave_triggered(); + void on_actionSaveSelected_triggered(); + void on_actionOpen_triggered(); + + void view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m); + + void on_pushButton_2_clicked() {view->view()->reloadShaders();} + + void on_actionArrow_triggered(bool on); + void on_actionMove_triggered(bool on); + void on_actionRotate_triggered(bool on); + void on_actionScale_triggered(bool on); + + void on_colorFogBack_colorChanged(const QColor & v) {view->view()->setFogColor(v);} + void on_spinFogDensity_valueChanged(double v) {view->view()->setFogDensity(v);} + void on_spinFogDecay_valueChanged(double v) {view->view()->setFogDecay(v);} + + void on_pushButton_3_clicked(); + +public slots: + +signals: + +private: + QMatrix4x4 cam_mat; + +}; + +#endif // QGLVIEWWINDOW_H diff --git a/qglview_test/qglview_window.ui b/qglview_test/qglview_window.ui new file mode 100644 index 0000000..a9bde08 --- /dev/null +++ b/qglview_test/qglview_window.ui @@ -0,0 +1,978 @@ + + + QGLViewWindow + + + + 0 + 0 + 1107 + 878 + + + + QGLView converter + + + + + + + Qt::Horizontal + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + View + + + + + + 0 + + + + Common + + + + + + + + + + Features + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 934 + 737 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Shadows + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Shadowmap size + + + + + + + 16.000000000000000 + + + 2048.000000000000000 + + + 512.000000000000000 + + + 0 + + + 16.000000000000000 + + + 512.000000000000000 + + + true + + + + + + + Soft + + + true + + + + + + + + + + Bloom + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Factror + + + + + + + 0.000000000000000 + + + 100.000000000000000 + + + 1.000000000000000 + + + 1 + + + 0.100000000000000 + + + 1.000000000000000 + + + false + + + + + + + 1.000000000000000 + + + 128.000000000000000 + + + 8.000000000000000 + + + 0 + + + 1.000000000000000 + + + 4.000000000000000 + + + false + + + + + + + Radius + + + + + + + Threshold + + + + + + + 0.000000000000000 + + + 1.000000000000000 + + + 0.900000000000000 + + + 2 + + + 0.050000000000000 + + + 0.100000000000000 + + + false + + + + + + + + + + Motion blur + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Factror + + + + + + + Steps + + + + + + + 0.000000000000000 + + + 10000.000000000000000 + + + 1.000000000000000 + + + 1 + + + 0.100000000000000 + + + 1.000000000000000 + + + false + + + + + + + 1.000000000000000 + + + 128.000000000000000 + + + 8.000000000000000 + + + 0 + + + 1.000000000000000 + + + 4.000000000000000 + + + false + + + + + + + + + + Eye accomodation + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Time + + + + + + + Max speed + + + + + + + 0.000000000000000 + + + 256.000000000000000 + + + 32.000000000000000 + + + true + + + + + + + 0.010000000000000 + + + 1.000000000000000 + + + 0.100000000000000 + + + 3 + + + 0.100000000000000 + + + 1.000000000000000 + + + true + + + + + + + + + + Depth of field + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Diaphragm + + + + + + + Max speed + + + + + + + 0.100000000000000 + + + 1024.000000000000000 + + + 8.000000000000000 + + + true + + + + + + + 0.010000000000000 + + + 10.000000000000000 + + + 0.100000000000000 + + + 2 + + + 0.100000000000000 + + + 1.000000000000000 + + + true + + + + + + + Focus + + + + + + + 0.100000000000000 + + + 1000.000000000000000 + + + 1.000000000000000 + + + true + + + 999999.000000000000000 + + + + + + + Auto focus + + + + + + + + + + Reflections + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Blur + + + + + + + + + + SSAO + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Time + + + + + + + 0.000000000000000 + + + 16.000000000000000 + + + 5.000000000000000 + + + 0 + + + 1.000000000000000 + + + 4.000000000000000 + + + false + + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + + + + + + + reload shaders + + + + + + + load HDR + + + + + + + Qt::Vertical + + + + 20 + 107 + + + + + + + + + Object + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + Material + + + + + + + + + + Primitives + + + + + + + + + + + + + + + 0 + 0 + + + + + + Scene + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + 0 + 0 + 1107 + 24 + + + + + File + + + + + + + + + + + + + Scene + + + + + Mode + + + + + + + + + + + + + + toolBar_2 + + + TopToolBarArea + + + false + + + + + + :/icons/application-exit.png:/icons/application-exit.png + + + Exit + + + + + + :/icons/document-import.png:/icons/document-import.png + + + Import ... + + + Ctrl+I + + + + + + :/icons/document-open.png:/icons/document-open.png + + + Open ... + + + Ctrl+O + + + + + + :/icons/document-save-all.png:/icons/document-save-all.png + + + Save ... + + + Ctrl+S + + + + + + :/icons/document-new.png:/icons/document-new.png + + + Reset + + + Ctrl+N + + + + + + :/icons/document-save.png:/icons/document-save.png + + + Save selected ... + + + Save selected + + + Ctrl+Shift+S + + + + + true + + + true + + + Arrow + + + Ctrl+1 + + + + + true + + + + :/icons/transform-move.png:/icons/transform-move.png + + + Move + + + Ctrl+2 + + + + + true + + + + :/icons/transform-rotate.png:/icons/transform-rotate.png + + + Rotate + + + Ctrl+3 + + + + + true + + + + :/icons/transform-scale.png:/icons/transform-scale.png + + + Scale + + + Ctrl+4 + + + + + + SpinSlider + QWidget +