Initial Commit
This commit is contained in:
commit
a1f998f581
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/build/
|
||||
/docs/
|
||||
/Doxyfile
|
87
CMakeLists.txt
Executable file
87
CMakeLists.txt
Executable file
@ -0,0 +1,87 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_PATCH 1)
|
||||
set(PROJECT_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
||||
|
||||
project(glw VERSION ${PROJECT_VERSION})
|
||||
|
||||
set(GLW_HEADERS
|
||||
buffer.h
|
||||
common.h
|
||||
shader.h
|
||||
vertex_descriptor.h
|
||||
texture.h
|
||||
framebuffer.h
|
||||
texture_array.h
|
||||
debug.h
|
||||
timer.h
|
||||
)
|
||||
|
||||
# Set CPP Standard
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
|
||||
# Find Dependencies
|
||||
find_package(glm REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
find_package(OpenGL REQUIRED COMPONENTS OpenGL)
|
||||
|
||||
add_library(glw INTERFACE
|
||||
${GLW_HEADERS}
|
||||
)
|
||||
|
||||
target_link_libraries(glw INTERFACE
|
||||
Freetype::Freetype
|
||||
GLEW::GLEW
|
||||
OpenGL::GL
|
||||
open-cpp-utils
|
||||
)
|
||||
|
||||
# Testing Framework ----------------------------------------------------------------------------------------------------
|
||||
|
||||
if (GTest_FOUND)
|
||||
|
||||
find_package(GTest)
|
||||
|
||||
add_executable(glw-test)
|
||||
|
||||
target_link_libraries(glw-test PRIVATE
|
||||
GTest::gtest
|
||||
glw
|
||||
)
|
||||
|
||||
endif ()
|
||||
|
||||
# DOXYGEN ==============================================================================================================
|
||||
# https://vicrucann.github.io/tutorials/quick-cmake-doxygen/
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
get_filename_component(DOXYGEN_PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
set(DOXYGEN_CONFIG_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
|
||||
set(DOXYGEN_CONFIG_OUT ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
|
||||
|
||||
configure_file(${DOXYGEN_CONFIG_IN} ${DOXYGEN_CONFIG_OUT} @ONLY)
|
||||
message("Doxygen Build Started.")
|
||||
|
||||
if(WIN32)
|
||||
add_custom_target(glw-documentation ALL
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT}
|
||||
COMMAND start firefox "${CMAKE_CURRENT_SOURCE_DIR}/Documentation/html/index.html"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating Doxygen Documentation"
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_target(glw-documentation ALL
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT}
|
||||
COMMAND firefox "${CMAKE_CURRENT_SOURCE_DIR}/Documentation/html/index.html"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating Doxygen Documentation"
|
||||
VERBATIM)
|
||||
endif()
|
||||
else()
|
||||
message("Doxygen not found.")
|
||||
endif()
|
5
Doxyfile.in
Executable file
5
Doxyfile.in
Executable file
@ -0,0 +1,5 @@
|
||||
OUTPUT_DIRECTORY = "@CMAKE_CURRENT_SOURCE_DIR@/docs/"
|
||||
INPUT = "@CMAKE_CURRENT_SOURCE_DIR@/README.md" "@CMAKE_CURRENT_SOURCE_DIR@/"
|
||||
RECURSIVE = YES
|
||||
PROJECT_NAME = "@DOXYGEN_PROJECT_NAME@"
|
||||
PROJECT_NUMBER = "@CMAKE_PROJECT_VERSION@"
|
674
LICENSE
Executable file
674
LICENSE
Executable file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
glw, an open-source library that wraps OpenGL structures into classes.
|
||||
Copyright (C) 2024 Medusa Slockbower
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
glw Copyright (C) 2024 Medusa Slockbower
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
412
buffer.h
Executable file
412
buffer.h
Executable file
@ -0,0 +1,412 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_BUFFER_H
|
||||
#define GLW_BUFFER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <glm/common.hpp>
|
||||
#include <open-cpp-utils/dynarray.h>
|
||||
|
||||
namespace ocu = open_cpp_utils;
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Definitions
|
||||
// =====================================================================================================================
|
||||
|
||||
|
||||
// Typedefs ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using buffer_t = GLenum;
|
||||
|
||||
template<buffer_t T, flags_t Fs>
|
||||
class buffer;
|
||||
|
||||
|
||||
// Enums ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
enum buffer_type
|
||||
{
|
||||
buf_vertex = GL_ARRAY_BUFFER
|
||||
, buf_element = GL_ELEMENT_ARRAY_BUFFER
|
||||
, buf_copy_read = GL_COPY_READ_BUFFER
|
||||
, buf_copy_write = GL_COPY_WRITE_BUFFER
|
||||
, buf_pixel_pack = GL_PIXEL_PACK_BUFFER
|
||||
, buf_pixel_unpack = GL_PIXEL_UNPACK_BUFFER
|
||||
, buf_query = GL_QUERY_BUFFER
|
||||
, buf_texture = GL_TEXTURE_BUFFER
|
||||
, buf_transform_feedback = GL_TRANSFORM_FEEDBACK_BUFFER
|
||||
, buf_uniform = GL_UNIFORM_BUFFER
|
||||
, buf_indirect_draw = GL_DRAW_INDIRECT_BUFFER
|
||||
, buf_atomic_counter = GL_ATOMIC_COUNTER_BUFFER
|
||||
, buf_indirect_dispatch = GL_DISPATCH_INDIRECT_BUFFER
|
||||
, buf_shader_storage = GL_SHADER_STORAGE_BUFFER
|
||||
, buf_parameter = GL_PARAMETER_BUFFER
|
||||
};
|
||||
|
||||
enum buffer_flags
|
||||
{
|
||||
buf_flags_read = GL_MAP_READ_BIT
|
||||
, buf_flags_write = GL_MAP_WRITE_BIT
|
||||
, buf_flags_read_write = buf_flags_read | buf_flags_write
|
||||
, buf_flags_dynamic = GL_DYNAMIC_STORAGE_BIT
|
||||
, buf_flags_persistent = GL_MAP_PERSISTENT_BIT
|
||||
, buf_flags_coherent = GL_MAP_COHERENT_BIT | bf_persistent
|
||||
, buf_flags_client = GL_CLIENT_STORAGE_BIT
|
||||
};
|
||||
|
||||
enum mapping_flags
|
||||
{
|
||||
buf_map_read = GL_MAP_READ_BIT
|
||||
, buf_map_write = GL_MAP_WRITE_BIT
|
||||
, buf_map_read_write = buf_map_read | buf_map_write
|
||||
, buf_map_persistent = GL_MAP_PERSISTENT_BIT
|
||||
, buf_map_coherent = GL_MAP_COHERENT_BIT | buf_map_persistent
|
||||
, buf_map_invalidate_range = GL_MAP_INVALIDATE_RANGE_BIT
|
||||
, buf_map_invalidate_buffer = GL_MAP_INVALIDATE_BUFFER_BIT
|
||||
, buf_map_flush_explicity = GL_MAP_FLUSH_EXPLICIT_BIT | buf_map_write
|
||||
, buf_map_unsynchronized = GL_MAP_UNSYNCHRONIZED_BIT
|
||||
|
||||
, buf_map_optional = buf_map_invalidate_range
|
||||
| buf_map_invalidate_buffer
|
||||
| buf_map_flush_explicity
|
||||
| buf_map_unsynchronized
|
||||
};
|
||||
|
||||
|
||||
// Buffer Aliases
|
||||
|
||||
template<flags_t Fs> using vertex_buffer = buffer<buf_vertex, Fs>;
|
||||
template<flags_t Fs> using element_buffer = buffer<buf_element, Fs>;
|
||||
template<flags_t Fs> using copy_read_buffer = buffer<buf_copy_read, Fs>;
|
||||
template<flags_t Fs> using copy_write_buffer = buffer<buf_copy_write, Fs>;
|
||||
template<flags_t Fs> using pixel_pack_buffer = buffer<buf_pixel_pack, Fs>;
|
||||
template<flags_t Fs> using pixel_unpack_buffer = buffer<buf_pixel_unpack, Fs>;
|
||||
template<flags_t Fs> using query_buffer = buffer<buf_query, Fs>;
|
||||
template<flags_t Fs> using texture_buffer = buffer<buf_texture, Fs>;
|
||||
template<flags_t Fs> using transform_feedback_buffer = buffer<buf_transform_feedback, Fs>;
|
||||
template<flags_t Fs> using uniform_buffer = buffer<buf_uniform, Fs>;
|
||||
template<flags_t Fs> using indirect_draw_buffer = buffer<buf_indirect_draw, Fs>;
|
||||
template<flags_t Fs> using atomic_counter_buffer = buffer<buf_atomic_counter, Fs>;
|
||||
template<flags_t Fs> using indirect_dispatch_buffer = buffer<buf_indirect_dispatch, Fs>;
|
||||
template<flags_t Fs> using shader_storage_buffer = buffer<buf_shader_storage, Fs>;
|
||||
template<flags_t Fs> using parameter_buffer = buffer<buf_parameter, Fs>;
|
||||
|
||||
|
||||
// Buffer Definition ---------------------------------------------------------------------------------------------------
|
||||
|
||||
template<buffer_t T_, flags_t Fs_>
|
||||
class buffer
|
||||
{
|
||||
// Constants ===========================================================================================================
|
||||
|
||||
public:
|
||||
static constexpr buffer_t type = T_;
|
||||
static constexpr flags_t flags = Fs_;
|
||||
|
||||
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
public:
|
||||
|
||||
// Constructors --------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* \brief Construct a buffer filled with the provided data
|
||||
* \param size Size of the buffer in bytes
|
||||
* \param data Pointer to the data to initialize the buffer with, if null, initialized with 0
|
||||
*/
|
||||
buffer(size_t size, const void* data = nullptr);
|
||||
|
||||
buffer(const buffer&);
|
||||
buffer(buffer&&) = default;
|
||||
~buffer();
|
||||
|
||||
|
||||
// Access --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* \brief Map the buffer to the CPU
|
||||
* \param size Size of the region to map
|
||||
* \param offset Offset into the buffer to map
|
||||
* \param map_flags Flags to map the buffer with
|
||||
* \return Whether the buffer was successfully mapped
|
||||
*/
|
||||
bool map(size_t size = -1, offset_t offset = 0, flags_t map_flags = mapping_flags::read);
|
||||
|
||||
void unmap();
|
||||
|
||||
template<typename T>
|
||||
T* data() { static_assert(flags | buffer_flags::write); return map_; }
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* \tparam T
|
||||
* \return
|
||||
*/
|
||||
template<typename T>
|
||||
const T* data() const { static_assert(flags | buffer_flags::read); return map_; }
|
||||
|
||||
/**
|
||||
* \brief Bind the buffer for usage with gl functions
|
||||
*/
|
||||
void bind();
|
||||
|
||||
/**
|
||||
* \brief Attach the buffer to a specific base location for usage in a shader program
|
||||
* \param location Location to bind the buffer to
|
||||
*/
|
||||
void attach(location_t location);
|
||||
|
||||
|
||||
// Status --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
[[nodiscard]] bool mapped() const { return map_ != nullptr; }
|
||||
|
||||
[[nodiscard]] bool valid() const { return handle_ != NULL; }
|
||||
|
||||
|
||||
// Capacity ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
[[nodiscard]] size_t size() const { return size_; }
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] size_t capacity() const { return size_ / sizeof(T); }
|
||||
|
||||
|
||||
// Modifiers -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* \brief Read a section of the buffer from the gpu into a location on the cpu
|
||||
* \param buffer Pointer to the buffer to read into
|
||||
* \param size Size of the buffer
|
||||
* \param offset Offset into the gpu memory
|
||||
*/
|
||||
void read(void* buffer, size_t size, offset_t offset = 0);
|
||||
|
||||
/**
|
||||
* \brief Write a section to the buffer on the gpu from the cpu
|
||||
* \param buffer Pointer to the buffer to write from
|
||||
* \param size Size of the buffer
|
||||
* \param offset Offset into the gpu memory
|
||||
*/
|
||||
void write(const void* buffer, size_t size, offset_t offset = 0);
|
||||
|
||||
/**
|
||||
* \brief Clear a portion of the buffer
|
||||
* \param size Size of the section to clear, if negative, size will be automatically calculated using the offset.
|
||||
* \param offset Offset into the buffer
|
||||
* \param data Value to clear the buffer with
|
||||
* \param layout Layout of the provided data
|
||||
* \param type Type of the provided data
|
||||
* \param format Format of the provided data
|
||||
*/
|
||||
void clear(size_t size = -1, offset_t offset = 0, const void* data = nullptr,
|
||||
enum_t layout = r_i, enum_t type = uint8, enum_t format = r8_ui);
|
||||
|
||||
/**
|
||||
* \brief Copy data from another buffer
|
||||
* \tparam oType Type of the other buffer
|
||||
* \tparam oFlags Flags of the other buffer
|
||||
* \param src Source buffer to copy from
|
||||
* \param size Size of the section of data to copy
|
||||
* \param src_offset Offset into the source buffer
|
||||
* \param dst_offset Offset into the destination buffer
|
||||
*/
|
||||
template<enum_t oType, flags_t oFlags>
|
||||
void copy(const buffer<oType, oFlags>& src, size_t size = -1, offset_t src_offset = 0, offset_t dst_offset = 0);
|
||||
|
||||
/**
|
||||
* \brief Resize the buffer
|
||||
* \param size New size of the data in bytes
|
||||
*/
|
||||
void resize(size_t size);
|
||||
|
||||
|
||||
// Variables ===========================================================================================================
|
||||
|
||||
private:
|
||||
handle_t handle_;
|
||||
size_t size_;
|
||||
|
||||
void* map_;
|
||||
offset_t map_start_, map_end_;
|
||||
flags_t map_flags_;
|
||||
};
|
||||
|
||||
|
||||
// =====================================================================================================================
|
||||
// Implementations
|
||||
// =====================================================================================================================
|
||||
|
||||
|
||||
// Constructors --------------------------------------------------------------------------------------------------------
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
buffer<Type, Flags>::buffer(size_t size, const void *data)
|
||||
: handle_(NULL)
|
||||
, size_(size)
|
||||
, map_(nullptr)
|
||||
, map_start_(0), map_end_(0)
|
||||
, map_flags_(0)
|
||||
{
|
||||
glCreateBuffers(1, &handle_);
|
||||
glNamedBufferStorage(handle_, size_, data, flags);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
buffer<Type, Flags>::buffer(const buffer& other)
|
||||
: handle_(NULL)
|
||||
, size_(other.size_)
|
||||
, map_(nullptr)
|
||||
, map_start_(0), map_end_(0)
|
||||
, map_flags_(0)
|
||||
{
|
||||
glCreateBuffers(1, &handle_);
|
||||
glNamedBufferData(handle_, size_, nullptr, flags);
|
||||
copy(other, size_, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// Access --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
buffer<Type, Flags>::~buffer()
|
||||
{
|
||||
glDeleteBuffers(1, &handle_);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
bool buffer<Type, Flags>::map(size_t size, offset_t offset, flags_t map_flags)
|
||||
{
|
||||
static_assert(flags & read_write);
|
||||
|
||||
if(map_) return false;
|
||||
|
||||
map_flags &= flags | optional;
|
||||
if(size < 0) size = size_ - offset;
|
||||
|
||||
map_flags_ = map_flags;
|
||||
map_start_ = offset; map_end_ = map_start_ + size;
|
||||
return map_ = glMapNamedBufferRange(handle_, offset, size, map_flags_);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::unmap()
|
||||
{
|
||||
glUnmapNamedBuffer(handle_);
|
||||
map_ = nullptr;
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::bind()
|
||||
{
|
||||
glBindBuffer(type, handle_);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::attach(location_t location)
|
||||
{
|
||||
glBindBufferBase(type, location, handle_);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::read(void* buffer, size_t size, offset_t offset)
|
||||
{
|
||||
// If not mapped, use glGetBufferSubData to avoid mapping the buffer
|
||||
if(map_ == nullptr)
|
||||
{
|
||||
glGetNamedBufferSubData(handle_, offset, size, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we need to remap the buffer
|
||||
offset_t start = offset, end = offset + size;
|
||||
if(start < map_start_ || end > map_end_ || !(map_flags_ & mapping_flags::read))
|
||||
{
|
||||
flags_t map_flags = map_flags_ | mapping_flags::read;
|
||||
start = glm::min(start, map_start_); end = glm::max(end, map_end_);
|
||||
unmap();
|
||||
map(end - start, start, map_flags);
|
||||
}
|
||||
|
||||
// Copy from the mapping
|
||||
offset = offset - map_start_;
|
||||
memcpy(buffer, map_ + offset, size);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::write(const void *buffer, size_t size, offset_t offset)
|
||||
{
|
||||
// if the buffer isn't mapped and is dynamic, use glBufferSubData to avoid mapping the buffer
|
||||
if(map_ == nullptr && flags | dynamic)
|
||||
{
|
||||
glNamedBufferSubData(handle_, offset, size, buffer);
|
||||
}
|
||||
|
||||
// Check if we need to remap the buffer
|
||||
offset_t start = offset, end = offset + size;
|
||||
if(start < map_start_ || end > map_end_ || !(map_flags_ & mapping_flags::write))
|
||||
{
|
||||
flags_t map_flags = map_flags_ | mapping_flags::write;
|
||||
start = glm::min(start, map_start_); end = glm::max(end, map_end_);
|
||||
unmap();
|
||||
map(end - start, start, map_flags);
|
||||
}
|
||||
|
||||
// Copy to the mapping
|
||||
offset = offset - map_start_;
|
||||
memcpy(map_ + offset, buffer, size);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::clear(size_t size, offset_t offset, const void* data,
|
||||
layout_t layout, type_t type, format_t format)
|
||||
{
|
||||
glClearNamedBufferSubData(handle_, format, offset, size, format, type, data);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
template<buffer_t oType, flags_t oFlags>
|
||||
void buffer<Type, Flags>::copy(const buffer<oType, oFlags>& src, size_t size,
|
||||
offset_t src_offset, offset_t dst_offset)
|
||||
{
|
||||
glCopyNamedBufferSubData(src.handle_, handle_, src_offset, dst_offset, size);
|
||||
}
|
||||
|
||||
template<buffer_t Type, flags_t Flags>
|
||||
void buffer<Type, Flags>::resize(size_t size)
|
||||
{
|
||||
if(map_) unmap();
|
||||
|
||||
handle_t handle;
|
||||
glCreateBuffers(1, &handle);
|
||||
glNamedBufferStorage(handle, size, nullptr, flags);
|
||||
glCopyNamedBufferSubData(handle_, handle, 0, 0, glm::min(size_, size));
|
||||
glDeleteBuffers(1, &handle_);
|
||||
handle_ = handle;
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BUFFER_H
|
421
common.h
Executable file
421
common.h
Executable file
@ -0,0 +1,421 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_COMMON_H
|
||||
#define GLW_COMMON_H
|
||||
|
||||
#define GLW_STRINGIFY_(X) #X
|
||||
#define GLW_STRINGIFY(X) GLW_STRINGIFY_(X)
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <gl/glew.h>
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
// Typedefs ============================================================================================================
|
||||
|
||||
using handle_t = GLuint;
|
||||
using size_t = GLsizei;
|
||||
using offset_t = GLintptr;
|
||||
using flags_t = GLbitfield;
|
||||
using index_t = GLint;
|
||||
using location_t = GLuint;
|
||||
using enum_t = GLenum;
|
||||
using int_t = GLint;
|
||||
using int64_t = GLint64;
|
||||
using float_t = GLfloat;
|
||||
using uint_t = GLuint;
|
||||
using char_t = GLchar;
|
||||
|
||||
|
||||
// Template Pack Contains Value
|
||||
|
||||
template<class...Ts> struct contains;
|
||||
template<enum_t...Ts> struct contains_enum;
|
||||
|
||||
template<class T> struct contains<T> { static constexpr bool value = std::false_type{}; };
|
||||
template<enum_t T> struct contains_enum<T> { static constexpr bool value = std::false_type{}; };
|
||||
|
||||
template<class T, class T0, class...Ts>
|
||||
struct contains<T, T0, Ts...>
|
||||
{
|
||||
static constexpr bool value = std::is_same<T, T0>::value || (sizeof...(Ts) > 0 && contains<T, Ts...>::value);
|
||||
constexpr operator bool() const { return value; }
|
||||
};
|
||||
|
||||
template<enum_t T, enum_t T0, enum_t...Ts>
|
||||
struct contains_enum<T, T0, Ts...>
|
||||
{
|
||||
static constexpr bool value = T == T0 || (sizeof...(Ts) > 0 && contains_enum<T, Ts...>::value);
|
||||
constexpr operator bool() const { return value; }
|
||||
};
|
||||
|
||||
|
||||
// Math Functions
|
||||
template<typename genType>
|
||||
inline genType min(genType&& v) { return std::forward<genType>(v); }
|
||||
|
||||
template<typename genType>
|
||||
inline genType min(genType&& a, genType&& b) { return std::forward<genType&&>(a < b ? a : b); }
|
||||
|
||||
template<typename genType>
|
||||
inline genType min(genType&& a, genType&& b, genType&& rest...)
|
||||
{
|
||||
return max(std::forward<genType&&>(a < b ? a : b), std::forward<genType>(rest)...);
|
||||
}
|
||||
|
||||
|
||||
template<typename genType>
|
||||
inline genType&& max(genType&& v) { return std::forward<genType>(v); }
|
||||
|
||||
template<typename genType>
|
||||
inline genType&& max(genType&& a, genType&& b) { return std::forward<genType&&>(a > b ? a : b); }
|
||||
|
||||
template<typename genType>
|
||||
inline genType&& max(genType&& a, genType&& b, genType&& rest...)
|
||||
{
|
||||
return max(std::forward<genType&&>(a > b ? a : b), std::forward<genType>(rest)...);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
inline genType ceil_div(const genType& a, const genType& b)
|
||||
{
|
||||
return 1 + ((a - 1) / b);
|
||||
}
|
||||
|
||||
|
||||
// Enums ===============================================================================================================
|
||||
|
||||
enum access : enum_t
|
||||
{
|
||||
access_read = GL_READ_ONLY
|
||||
, access_write = GL_WRITE_ONLY
|
||||
, access_read_write = GL_READ_WRITE
|
||||
};
|
||||
|
||||
enum layout : enum_t
|
||||
{
|
||||
|
||||
// Floating Point Layouts ==============================================================================================
|
||||
|
||||
r = GL_RED
|
||||
, rg = GL_RG
|
||||
, rgb = GL_RGB
|
||||
, bgr = GL_BGR
|
||||
, rgba = GL_RGBA
|
||||
, bgra = GL_BGRA
|
||||
|
||||
|
||||
// Integer Layouts =====================================================================================================
|
||||
|
||||
, r_i = GL_RED_INTEGER
|
||||
, rg_i = GL_RG_INTEGER
|
||||
, rgb_i = GL_RGB_INTEGER
|
||||
, bgr_i = GL_BGR_INTEGER
|
||||
, rgba_i = GL_RGBA_INTEGER
|
||||
, bgra_i = GL_BGRA_INTEGER
|
||||
|
||||
|
||||
// Special Layouts =====================================================================================================
|
||||
|
||||
, depth = GL_DEPTH_COMPONENT
|
||||
, stencil = GL_STENCIL_INDEX
|
||||
, depth_stencil = GL_DEPTH_STENCIL
|
||||
|
||||
};
|
||||
|
||||
|
||||
enum format : enum_t
|
||||
{
|
||||
|
||||
// Fixed & Floating Points Formats =====================================================================================
|
||||
|
||||
r8 = GL_R8
|
||||
, r8_snorm = GL_R8_SNORM
|
||||
, r16 = GL_R16
|
||||
, r16f = GL_R16F
|
||||
, r16_snorm = GL_R16_SNORM
|
||||
, r32 = GL_R32F
|
||||
|
||||
, rg8 = GL_RG8
|
||||
, rg8_snorm = GL_RG8_SNORM
|
||||
, rg16 = GL_RG16
|
||||
, rg16f = GL_RG16F
|
||||
, rg16_snorm = GL_RG16_SNORM
|
||||
, rg32 = GL_RG32F
|
||||
|
||||
, rgb332 = GL_R3_G3_B2
|
||||
, rgb4 = GL_RGB4
|
||||
, rgb5 = GL_RGB5
|
||||
, rbg8 = GL_RGB8
|
||||
, srgb8 = GL_SRGB8
|
||||
, rbg8_snorm = GL_RGB8_SNORM
|
||||
, rgb9e5 = GL_RGB9_E5
|
||||
, rgb10 = GL_RGB10
|
||||
, rgb11_11_10f = GL_R11F_G11F_B10F
|
||||
, rgb12 = GL_RGB12
|
||||
, rgb16 = GL_RGB16
|
||||
, rgb16f = GL_RGB16F
|
||||
, rgb16_snorm = GL_RGB16_SNORM
|
||||
, rgb32f = GL_RGB32F
|
||||
|
||||
, rgba2 = GL_RGBA2
|
||||
, rgba4 = GL_RGBA4
|
||||
, rgb5_a1 = GL_RGB5_A1
|
||||
, rgba8 = GL_RGBA8
|
||||
, srgba8 = GL_SRGB8_ALPHA8
|
||||
, rbga8_snorm = GL_RGBA8_SNORM
|
||||
, rgb10_a2 = GL_RGB10_A2
|
||||
, rgba12 = GL_RGBA12
|
||||
, rgba16 = GL_RGBA16
|
||||
, rgba16f = GL_RGBA16F
|
||||
, rgba16_snorm = GL_RGBA16_SNORM
|
||||
, rgba32f = GL_RGBA32F
|
||||
|
||||
|
||||
// Integer Formats =====================================================================================================
|
||||
|
||||
, r8_i = GL_R8I
|
||||
, r8_ui = GL_R8UI
|
||||
, r16_i = GL_R16I
|
||||
, r16_ui = GL_R16UI
|
||||
, r32_i = GL_R32I
|
||||
, r32_ui = GL_R32UI
|
||||
|
||||
, rg8_i = GL_RG8I
|
||||
, rg8_ui = GL_RG8UI
|
||||
, rg16_i = GL_RG16I
|
||||
, rg16_ui = GL_RG16UI
|
||||
, rg32_i = GL_RG32I
|
||||
, rg32_ui = GL_RG32UI
|
||||
|
||||
, rgb8_i = GL_RGB8I
|
||||
, rgb8_ui = GL_RGB8UI
|
||||
, rgb16_i = GL_RGB16I
|
||||
, rgb16_ui = GL_RGB16UI
|
||||
, rgb32_i = GL_RGB32I
|
||||
, rgb32_ui = GL_RGB32UI
|
||||
|
||||
, rgba8_i = GL_RGBA8I
|
||||
, rgba8_ui = GL_RGBA8UI
|
||||
, rgb10_a2_ui = GL_RGB10_A2UI
|
||||
, rgba16_i = GL_RGBA16I
|
||||
, rgba16_ui = GL_RGBA16UI
|
||||
, rgba32_i = GL_RGBA32I
|
||||
, rgba32_ui = GL_RGBA32UI
|
||||
|
||||
|
||||
// Depth / Stencil Formats =============================================================================================
|
||||
|
||||
, depth16 = GL_DEPTH_COMPONENT16
|
||||
, depth24 = GL_DEPTH_COMPONENT24
|
||||
, depth32 = GL_DEPTH_COMPONENT32
|
||||
, depth32_f = GL_DEPTH_COMPONENT32F
|
||||
|
||||
, stencil1 = GL_STENCIL_INDEX1
|
||||
, stencil4 = GL_STENCIL_INDEX4
|
||||
, stencil8 = GL_STENCIL_INDEX8
|
||||
, stencil16 = GL_STENCIL_INDEX16
|
||||
|
||||
, depth24_stencil = GL_DEPTH24_STENCIL8
|
||||
, depth32_f_stencil = GL_DEPTH32F_STENCIL8
|
||||
|
||||
|
||||
// Compressed Formats ==================================================================================================
|
||||
|
||||
|
||||
// Generic Formats
|
||||
, r_compressed = GL_COMPRESSED_RED
|
||||
, rg_compressed = GL_COMPRESSED_RG
|
||||
, rgb_compressed = GL_COMPRESSED_RGB
|
||||
, srgb_compressed = GL_COMPRESSED_SRGB
|
||||
, rgba_compressed = GL_COMPRESSED_RGBA
|
||||
, srgba_compressed = GL_COMPRESSED_SRGB_ALPHA
|
||||
|
||||
// BPTC
|
||||
, rgb_bptc = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
|
||||
, rgb_bptc_signed = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT
|
||||
, rgba_bptc_unorm = GL_COMPRESSED_RGBA_BPTC_UNORM
|
||||
, srgba_bptc = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM
|
||||
|
||||
// RGTC
|
||||
, r_rgtc = GL_COMPRESSED_RED_RGTC1
|
||||
, r_rgtc_signed = GL_COMPRESSED_SIGNED_RED_RGTC1
|
||||
, rg_rgtc = GL_COMPRESSED_RG_RGTC2
|
||||
, rg_rgtc_signed = GL_COMPRESSED_SIGNED_RG_RGTC2
|
||||
|
||||
// EAC
|
||||
, r_eac = GL_COMPRESSED_R11_EAC
|
||||
, rg_eac = GL_COMPRESSED_RG11_EAC
|
||||
, r_eac_signed = GL_COMPRESSED_SIGNED_R11_EAC
|
||||
, rg_eac_signed = GL_COMPRESSED_SIGNED_RG11_EAC
|
||||
, rgba_eac = GL_COMPRESSED_RGBA8_ETC2_EAC
|
||||
, srgba_eac = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
|
||||
|
||||
// ASTC
|
||||
, rgba_astc4x4 = GL_COMPRESSED_RGBA_ASTC_4x4_KHR
|
||||
, rgba_astc5x4 = GL_COMPRESSED_RGBA_ASTC_5x4_KHR
|
||||
, rgba_astc5x5 = GL_COMPRESSED_RGBA_ASTC_5x5_KHR
|
||||
, rgba_astc6x5 = GL_COMPRESSED_RGBA_ASTC_6x5_KHR
|
||||
, rgba_astc6x6 = GL_COMPRESSED_RGBA_ASTC_6x6_KHR
|
||||
, rgba_astc8x5 = GL_COMPRESSED_RGBA_ASTC_8x5_KHR
|
||||
, rgba_astc8x6 = GL_COMPRESSED_RGBA_ASTC_8x6_KHR
|
||||
, rgba_astc8x8 = GL_COMPRESSED_RGBA_ASTC_8x8_KHR
|
||||
, rgba_astc10x5 = GL_COMPRESSED_RGBA_ASTC_10x5_KHR
|
||||
, rgba_astc10x6 = GL_COMPRESSED_RGBA_ASTC_10x6_KHR
|
||||
, rgba_astc10x8 = GL_COMPRESSED_RGBA_ASTC_10x8_KHR
|
||||
, rgba_astc10x10 = GL_COMPRESSED_RGBA_ASTC_10x10_KHR
|
||||
, rgba_astc12x10 = GL_COMPRESSED_RGBA_ASTC_12x10_KHR
|
||||
, rgba_astc12x12 = GL_COMPRESSED_RGBA_ASTC_12x12_KHR
|
||||
|
||||
, srgba_astc4x4 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
|
||||
, srgba_astc5x4 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
|
||||
, srgba_astc5x5 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
|
||||
, srgba_astc6x5 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
|
||||
, srgba_astc6x6 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
|
||||
, srgba_astc8x5 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
|
||||
, srgba_astc8x6 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
|
||||
, srgba_astc8x8 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
|
||||
, srgba_astc10x5 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
|
||||
, srgba_astc10x6 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
|
||||
, srgba_astc10x8 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
|
||||
, srgba_astc10x10 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
|
||||
, srgba_astc12x10 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
|
||||
, srgba_astc12x12 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
|
||||
|
||||
};
|
||||
|
||||
inline constexpr bool is_depth(enum_t fmt)
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
case(depth16): case(depth24):
|
||||
case(depth32): case(depth32_f):
|
||||
case(depth24_stencil): case(depth32_f_stencil):
|
||||
return true;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline constexpr bool is_stencil(enum_t fmt)
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
case(stencil1): case(stencil4):
|
||||
case(stencil8): case(stencil16):
|
||||
case(depth24_stencil): case(depth32_f_stencil):
|
||||
return true;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<enum_t F_>
|
||||
struct format_traits
|
||||
{
|
||||
static constexpr enum_t format = F_;
|
||||
static constexpr bool is_depth = glw::is_depth(format);
|
||||
static constexpr bool is_stencil = glw::is_stencil(format);
|
||||
static constexpr bool is_depth_stencil = std::is_same<std::bool_constant<is_depth>, std::bool_constant<is_stencil>>{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
enum type : enum_t
|
||||
{
|
||||
int8 = GL_BYTE
|
||||
, uint8 = GL_UNSIGNED_BYTE
|
||||
, int16 = GL_SHORT
|
||||
, uint16 = GL_UNSIGNED_SHORT
|
||||
, int32 = GL_INT
|
||||
, uint32 = GL_UNSIGNED_INT
|
||||
|
||||
, float16 = GL_HALF_FLOAT
|
||||
, float32 = GL_FLOAT
|
||||
, float64 = GL_DOUBLE
|
||||
|
||||
, uint8_332 = GL_UNSIGNED_BYTE_3_3_2
|
||||
, uint8_233r = GL_UNSIGNED_BYTE_2_3_3_REV
|
||||
, uint16_565 = GL_UNSIGNED_SHORT_5_6_5
|
||||
, uint16_565r = GL_UNSIGNED_SHORT_5_6_5_REV
|
||||
, uint32_10_11_11 = GL_UNSIGNED_INT_10F_11F_11F_REV
|
||||
|
||||
, uint16_4444 = GL_UNSIGNED_SHORT_4_4_4_4
|
||||
, uint16_4444r = GL_UNSIGNED_SHORT_4_4_4_4_REV
|
||||
, uint16_5551 = GL_UNSIGNED_SHORT_5_5_5_1
|
||||
, uint16_1555r = GL_UNSIGNED_SHORT_1_5_5_5_REV
|
||||
, uint32_8888 = GL_UNSIGNED_INT_8_8_8_8
|
||||
, uint32_8888r = GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
, uint32_rgb10_a2 = GL_UNSIGNED_INT_10_10_10_2
|
||||
, uint32_a2_bgr10 = GL_UNSIGNED_INT_2_10_10_10_REV
|
||||
, uint32_9995r = GL_UNSIGNED_INT_5_9_9_9_REV
|
||||
|
||||
};
|
||||
|
||||
inline constexpr enum_t size_of(enum_t type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
// 1 byte
|
||||
case(int8): case(uint8):
|
||||
case(uint8_332): case(uint8_233r):
|
||||
return 1;
|
||||
|
||||
// 2 byte
|
||||
case(int16): case(uint16):
|
||||
case(uint16_565): case(uint16_565r):
|
||||
case(uint16_4444): case(uint16_4444r):
|
||||
case(uint16_5551): case(uint16_1555r):
|
||||
case(float16):
|
||||
return 2;
|
||||
|
||||
// 4 byte
|
||||
case(int32): case(uint32):
|
||||
case(uint32_10_11_11):
|
||||
case(uint32_8888): case(uint32_8888r):
|
||||
case(uint32_rgb10_a2): case(uint32_a2_bgr10):
|
||||
case(uint32_9995r):
|
||||
case(float32):
|
||||
return 4;
|
||||
|
||||
// 8 byte
|
||||
case(float64):
|
||||
return 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum compare : enum_t
|
||||
{
|
||||
never = GL_NEVER
|
||||
, always = GL_ALWAYS
|
||||
, less = GL_LESS
|
||||
, greater = GL_GREATER
|
||||
, equal = GL_EQUAL
|
||||
, lequal = GL_LEQUAL
|
||||
, gequal = GL_GEQUAL
|
||||
, nequal = GL_NOTEQUAL
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //COMMON_H
|
183
debug.h
Executable file
183
debug.h
Executable file
@ -0,0 +1,183 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_DEBUG_H
|
||||
#define GLW_DEBUG_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace glw::debug
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief OpenGL error codes
|
||||
*/
|
||||
enum error
|
||||
{
|
||||
error_invalid_enum = GL_INVALID_ENUM
|
||||
, error_invalid_value = GL_INVALID_VALUE
|
||||
, error_invalid_operation = GL_INVALID_OPERATION
|
||||
, error_stack_overflow = GL_STACK_OVERFLOW
|
||||
, error_stack_underflow = GL_STACK_UNDERFLOW
|
||||
, error_out_of_memory = GL_OUT_OF_MEMORY
|
||||
, error_invalid_framebuffer_operation = GL_INVALID_FRAMEBUFFER_OPERATION
|
||||
, error_context_lost = GL_CONTEXT_LOST
|
||||
, error_table_too_large = GL_TABLE_TOO_LARGE
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Converts an error code into a string representation
|
||||
* \param error The error code to translate
|
||||
* \return C string containing the string representation
|
||||
*/
|
||||
inline const char_t* translate_error(enum_t error)
|
||||
{
|
||||
switch(error)
|
||||
{
|
||||
case error_invalid_enum: return GLW_STRINGIFY(error_invalid_enum);
|
||||
case error_invalid_value: return GLW_STRINGIFY(error_invalid_value);
|
||||
case error_invalid_operation: return GLW_STRINGIFY(error_invalid_operation);
|
||||
case error_stack_overflow: return GLW_STRINGIFY(error_stack_overflow);
|
||||
case error_stack_underflow: return GLW_STRINGIFY(error_stack_underflow);
|
||||
case error_out_of_memory: return GLW_STRINGIFY(error_out_of_memory);
|
||||
case error_invalid_framebuffer_operation: return GLW_STRINGIFY(error_invalid_framebuffer_operation);
|
||||
case error_context_lost: return GLW_STRINGIFY(error_context_lost);
|
||||
case error_table_too_large: return GLW_STRINGIFY(error_table_too_large);
|
||||
default: return GLW_STRINGIFY(error_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the last error thrown by OpenGL, it is preferable to use the callback handler for performance
|
||||
* \return Error code of the last error
|
||||
*/
|
||||
inline enum_t get_error() { return glGetError(); }
|
||||
|
||||
/**
|
||||
* \brief Source ids of a debug message
|
||||
*/
|
||||
enum debug_source
|
||||
{
|
||||
source_api = GL_DEBUG_SOURCE_API
|
||||
, source_window_system = GL_DEBUG_SOURCE_WINDOW_SYSTEM
|
||||
, source_shader_compiler = GL_DEBUG_SOURCE_SHADER_COMPILER
|
||||
, source_third_party = GL_DEBUG_SOURCE_THIRD_PARTY
|
||||
, source_application = GL_DEBUG_SOURCE_APPLICATION
|
||||
, source_other = GL_DEBUG_SOURCE_OTHER
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Translate a debug message source into a string representation
|
||||
* \param source ID of the debug message source
|
||||
* \return C string containing the string representation
|
||||
*/
|
||||
inline const char_t* translate_source(enum_t source)
|
||||
{
|
||||
switch(source)
|
||||
{
|
||||
case source_api: return GLW_STRINGIFY(source_api);
|
||||
case source_window_system: return GLW_STRINGIFY(source_window_system);
|
||||
case source_shader_compiler: return GLW_STRINGIFY(source_shader_compiler);
|
||||
case source_third_party: return GLW_STRINGIFY(source_third_party);
|
||||
case source_application: return GLW_STRINGIFY(source_application);
|
||||
case source_other: return GLW_STRINGIFY(source_other);
|
||||
default: return GLW_STRINGIFY(source_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Types of debug messages
|
||||
*/
|
||||
enum debug_type
|
||||
{
|
||||
type_error = GL_DEBUG_TYPE_ERROR
|
||||
, type_deprecated_behavior = GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
|
||||
, type_undefined_behavior = GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
|
||||
, type_portability = GL_DEBUG_TYPE_PORTABILITY
|
||||
, type_performance = GL_DEBUG_TYPE_PERFORMANCE
|
||||
, type_marker = GL_DEBUG_TYPE_MARKER
|
||||
, type_push_group = GL_DEBUG_TYPE_PUSH_GROUP
|
||||
, type_pop_group = GL_DEBUG_TYPE_POP_GROUP
|
||||
, type_other = GL_DEBUG_TYPE_OTHER
|
||||
};
|
||||
|
||||
inline void push_group(enum_t src, uint_t id, size_t len, const char_t* msg) { glPushDebugGroup(src, id, len, msg); }
|
||||
inline void pop_group() { glPopDebugGroup(); }
|
||||
|
||||
inline void set_label(enum_t id, handle_t name, size_t len, const char_t* label) { glObjectLabel(id, name, len, label); }
|
||||
inline void set_label(void* ptr, size_t len, const char_t* label) { glObjectPtrLabel(ptr, len, label); }
|
||||
|
||||
inline void get_label(enum_t id, handle_t name, size_t buf_size, size_t& length, char_t* buf)
|
||||
{ glGetObjectLabel(id, name, buf_size, &length, buf); }
|
||||
|
||||
inline void get_label(void* ptr, size_t buf_size, size_t& length, char_t* buf)
|
||||
{ glGetObjectPtrLabel(ptr, buf_size, &length, buf); }
|
||||
|
||||
inline const char_t* translate_type(enum_t source)
|
||||
{
|
||||
switch(source)
|
||||
{
|
||||
case type_error: return GLW_STRINGIFY(type_error);
|
||||
case type_deprecated_behavior: return GLW_STRINGIFY(type_deprecated_behavior);
|
||||
case type_undefined_behavior: return GLW_STRINGIFY(type_undefined_behavior);
|
||||
case type_portability: return GLW_STRINGIFY(type_portability);
|
||||
case type_performance: return GLW_STRINGIFY(type_performance);
|
||||
case type_marker: return GLW_STRINGIFY(type_marker);
|
||||
case type_push_group: return GLW_STRINGIFY(type_push_group);
|
||||
case type_pop_group: return GLW_STRINGIFY(type_pop_group);
|
||||
case type_other: return GLW_STRINGIFY(type_other);
|
||||
default: return GLW_STRINGIFY(type_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
enum debug_severity
|
||||
{
|
||||
severity_low = GL_DEBUG_SEVERITY_LOW
|
||||
, severity_medium = GL_DEBUG_SEVERITY_MEDIUM
|
||||
, severity_high = GL_DEBUG_SEVERITY_HIGH
|
||||
, severity_notification = GL_DEBUG_SEVERITY_NOTIFICATION
|
||||
};
|
||||
|
||||
inline const char_t* translate_severity(enum_t severity)
|
||||
{
|
||||
switch(severity)
|
||||
{
|
||||
case severity_low: return GLW_STRINGIFY(severity_low);
|
||||
case severity_medium: return GLW_STRINGIFY(severity_medium);
|
||||
case severity_high: return GLW_STRINGIFY(severity_high);
|
||||
case severity_notification: return GLW_STRINGIFY(severity_notification);
|
||||
default: return GLW_STRINGIFY(severity_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
inline void insert_message(enum_t source, enum_t type, uint_t id, enum_t severity, size_t length, const char_t* message)
|
||||
{
|
||||
glDebugMessageInsert(source, type, id, severity, length, message);
|
||||
}
|
||||
|
||||
using debug_callback = GLDEBUGPROC;
|
||||
|
||||
inline void set_debug_callback(debug_callback callback, void* user_data)
|
||||
{
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(callback, user_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //DEBUG_H
|
375
framebuffer.h
Executable file
375
framebuffer.h
Executable file
@ -0,0 +1,375 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_FRAMEBUFFER_H
|
||||
#define GLW_FRAMEBUFFER_H
|
||||
|
||||
#include "texture.h"
|
||||
#include "texture_array.h"
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
namespace glw
|
||||
{
|
||||
enum framebuffer_usage : enum_t
|
||||
{
|
||||
fb_usage_read = GL_READ_FRAMEBUFFER
|
||||
, fb_usage_draw = GL_DRAW_FRAMEBUFFER
|
||||
, fb_usage_any = GL_FRAMEBUFFER
|
||||
};
|
||||
|
||||
enum framebuffer_status : enum_t
|
||||
{
|
||||
fb_status_complete = GL_FRAMEBUFFER_COMPLETE
|
||||
, fb_status_undefined = GL_FRAMEBUFFER_UNDEFINED
|
||||
, fb_status_incomplete_attachment = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
|
||||
, fb_status_missing_attachment = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
|
||||
, fb_status_incomplete_draw = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
|
||||
, fb_status_incomplete_read = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
|
||||
, fb_status_incomplete_multisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
|
||||
, fb_status_incomplete_layers = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
|
||||
, fb_status_unsupported = GL_FRAMEBUFFER_UNSUPPORTED
|
||||
, fb_status_unknown = 0
|
||||
};
|
||||
|
||||
static const char* translate_framebuffer_status(enum_t status)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
case(fb_status_complete): return "Complete";
|
||||
case(fb_status_undefined): return "Undefined";
|
||||
case(fb_status_incomplete_attachment): return "Incomplete Attachment";
|
||||
case(fb_status_missing_attachment): return "Missing Attachment";
|
||||
case(fb_status_incomplete_draw): return "Incomplete Draw";
|
||||
case(fb_status_incomplete_read): return "Incomplete Read";
|
||||
case(fb_status_incomplete_multisample): return "Incomplete Multisample";
|
||||
case(fb_status_incomplete_layers): return "Incomplete Layers";
|
||||
case(fb_status_unsupported): return "Unsupported";
|
||||
|
||||
case(fb_status_unknown):
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
enum attachment_bit
|
||||
{
|
||||
fb_depth_bit = GL_DEPTH_BUFFER_BIT
|
||||
, fb_stencil_bit = GL_STENCIL_BUFFER_BIT
|
||||
, fb_color_bit = GL_COLOR_BUFFER_BIT
|
||||
};
|
||||
|
||||
enum attachment
|
||||
{
|
||||
no_attachment = GL_NONE
|
||||
|
||||
, depth_attachment = GL_DEPTH_ATTACHMENT
|
||||
, stencil_attachment = GL_STENCIL_ATTACHMENT
|
||||
, depth_stencil_attachment = GL_DEPTH_STENCIL_ATTACHMENT
|
||||
|
||||
, color_attachment0 = GL_COLOR_ATTACHMENT0
|
||||
, color_attachment1 = GL_COLOR_ATTACHMENT1
|
||||
, color_attachment2 = GL_COLOR_ATTACHMENT2
|
||||
, color_attachment3 = GL_COLOR_ATTACHMENT3
|
||||
, color_attachment4 = GL_COLOR_ATTACHMENT4
|
||||
, color_attachment5 = GL_COLOR_ATTACHMENT5
|
||||
, color_attachment6 = GL_COLOR_ATTACHMENT6
|
||||
, color_attachment7 = GL_COLOR_ATTACHMENT7
|
||||
, color_attachment8 = GL_COLOR_ATTACHMENT8
|
||||
, color_attachment9 = GL_COLOR_ATTACHMENT9
|
||||
, color_attachment10 = GL_COLOR_ATTACHMENT10
|
||||
, color_attachment11 = GL_COLOR_ATTACHMENT11
|
||||
, color_attachment12 = GL_COLOR_ATTACHMENT12
|
||||
, color_attachment13 = GL_COLOR_ATTACHMENT13
|
||||
, color_attachment14 = GL_COLOR_ATTACHMENT14
|
||||
, color_attachment15 = GL_COLOR_ATTACHMENT15
|
||||
|
||||
, front_buffer = GL_FRONT
|
||||
, back_buffer = GL_BACK
|
||||
, front_and_back_buffer = GL_FRONT_AND_BACK
|
||||
, left_buffer = GL_LEFT
|
||||
, right_buffer = GL_RIGHT
|
||||
, front_left_buffer = GL_FRONT_LEFT
|
||||
, front_right_buffer = GL_FRONT_RIGHT
|
||||
, back_left_buffer = GL_BACK_LEFT
|
||||
, back_right_buffer = GL_BACK_RIGHT
|
||||
};
|
||||
|
||||
inline constexpr handle_t default_framebuffer = 0;
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t...Fs_>
|
||||
class framebuffer
|
||||
{
|
||||
// Constants ===========================================================================================================
|
||||
|
||||
static_assert(!contains_enum<depth16, Fs_...>::value);
|
||||
static_assert(!contains_enum<depth24, Fs_...>::value);
|
||||
static_assert(!contains_enum<depth32, Fs_...>::value);
|
||||
static_assert(!contains_enum<depth32_f, Fs_...>::value);
|
||||
|
||||
static_assert(!contains_enum<stencil1, Fs_...>::value);
|
||||
static_assert(!contains_enum<stencil4, Fs_...>::value);
|
||||
static_assert(!contains_enum<stencil8, Fs_...>::value);
|
||||
static_assert(!contains_enum<stencil16, Fs_...>::value);
|
||||
|
||||
static_assert(!contains_enum<depth24_stencil, Fs_...>::value);
|
||||
static_assert(!contains_enum<depth32_f_stencil, Fs_...>::value);
|
||||
|
||||
using array_type = texarray<T_, F_, Fs_...>;
|
||||
|
||||
public:
|
||||
|
||||
inline static constexpr enum_t type = T_;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
// Helpers -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
template<int I = 0, int C = 0>
|
||||
void bind_textures_()
|
||||
{
|
||||
auto& tex = textures_.template get<I>();
|
||||
bool color = false;
|
||||
|
||||
switch(tex.get_format())
|
||||
{;
|
||||
case depth16:
|
||||
case depth24:
|
||||
case depth32_f:
|
||||
glNamedFramebufferTexture(handle_, depth_attachment, tex.handle(), 0);
|
||||
break;
|
||||
|
||||
case stencil1:
|
||||
case stencil4:
|
||||
case stencil8:
|
||||
case stencil16:
|
||||
glNamedFramebufferTexture(handle_, stencil_attachment, tex.handle(), 0);
|
||||
break;
|
||||
|
||||
case depth24_stencil:
|
||||
case depth32_f_stencil:
|
||||
glNamedFramebufferTexture(handle_, depth_stencil_attachment, tex.handle(), 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
glNamedFramebufferTexture(handle_, color_attachment0 + C, tex.handle(), 0);
|
||||
colors_.push_back(color_attachment0 + C);
|
||||
color = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if constexpr(I + 1 < array_type::length)
|
||||
{
|
||||
if(color) bind_textures_<I + 1, C + 1>();
|
||||
else bind_textures_<I + 1, C>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Constructors --------------------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
framebuffer(size_t size)
|
||||
: handle_(NULL), size_(size, 1, 1), samples_(1), textures_(size)
|
||||
{ static_assert(contains_enum<type, texture1D>::value); glCreateFramebuffers(1, &handle_); }
|
||||
|
||||
framebuffer(glm::ivec2 size)
|
||||
: handle_(NULL), size_(size, 1), samples_(1), textures_(size)
|
||||
{ static_assert(contains_enum<type, texture1DArray, texture2D, textureCubemap>::value); glCreateFramebuffers(1, &handle_); }
|
||||
|
||||
framebuffer(glm::ivec2 size, size_t samples = 1) requires(type == texture2DMS)
|
||||
: handle_(NULL), size_(size, 1), samples_(samples), textures_(size, samples)
|
||||
{ glCreateFramebuffers(1, &handle_); }
|
||||
|
||||
framebuffer(glm::ivec3 size)
|
||||
: handle_(NULL), size_(size), samples_(1), textures_(size)
|
||||
{ static_assert(contains_enum<type, texture2DArray, textureCubemapArray, texture3D>::value); glCreateFramebuffers(1, &handle_); }
|
||||
|
||||
framebuffer(glm::ivec3 size, size_t samples = 1) requires(type == texture2DMSArray)
|
||||
: handle_(NULL), size_(size), samples_(samples), textures_(size, samples)
|
||||
{ glCreateFramebuffers(1, &handle_); }
|
||||
|
||||
~framebuffer() { glDeleteFramebuffers(1, &handle_); }
|
||||
|
||||
|
||||
// Attachments ---------------------------------------------------------------------------------------------------------
|
||||
|
||||
void rebuild();
|
||||
void build() { rebuild(); };
|
||||
|
||||
template<class FB>
|
||||
void blit(
|
||||
enum_t src_att
|
||||
, FB& dst, enum_t dst_att
|
||||
, glm::ivec2 src_off, glm::ivec2 src_size
|
||||
, glm::ivec2 dst_off, glm::ivec2 dst_size
|
||||
, enum_t filter
|
||||
) { blit(src_att, dst.handle_, dst_att, src_off, src_size, dst_off, dst_size, filter); }
|
||||
|
||||
void blit(
|
||||
enum_t src_att
|
||||
, handle_t dst, enum_t dst_att
|
||||
, glm::ivec2 src_off, glm::ivec2 src_size
|
||||
, glm::ivec2 dst_off, glm::ivec2 dst_size
|
||||
, enum_t filter
|
||||
);
|
||||
|
||||
template<int I>
|
||||
auto& get() { return textures_.template get<I>(); }
|
||||
|
||||
template<int I>
|
||||
const auto& get() const { return textures_.template get<I>(); }
|
||||
|
||||
|
||||
// Status --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
enum_t get_status() const { return glCheckNamedFramebufferStatus(handle_, GL_FRAMEBUFFER); }
|
||||
bool is_complete() const { return get_status() == fb_status_complete; }
|
||||
|
||||
void bind(enum_t usage = fb_usage_any) { glBindFramebuffer(usage, handle_); }
|
||||
|
||||
|
||||
// Capacity ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
const glm::ivec3& size() const { return size_; }
|
||||
|
||||
void resize(size_t size);
|
||||
void resize(const glm::ivec2& size);
|
||||
void resize(const glm::ivec2& size, size_t samples);
|
||||
void resize(const glm::ivec3& size);
|
||||
void resize(const glm::ivec3& size, size_t samples);
|
||||
|
||||
size_t sample_count() const { return samples_; }
|
||||
|
||||
// Variables ===========================================================================================================
|
||||
|
||||
private:
|
||||
handle_t handle_;
|
||||
glm::ivec3 size_;
|
||||
size_t samples_;
|
||||
array_type textures_;
|
||||
std::vector<enum_t> colors_;
|
||||
};
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::rebuild()
|
||||
{
|
||||
colors_.clear(); colors_.reserve(textures_.length);
|
||||
bind_textures_();
|
||||
|
||||
glNamedFramebufferDrawBuffers(handle_, colors_.size(), colors_.data());
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::blit(uint32_t src_att, handle_t dst, uint32_t dst_att, glm::ivec2 src_off,
|
||||
glm::ivec2 src_size, glm::ivec2 dst_off, glm::ivec2 dst_size, enum_t filter)
|
||||
{
|
||||
flags_t mask;
|
||||
bool src_color = (src_att >= color_attachment0 && src_att <= color_attachment15)
|
||||
|| (src_att >= front_left_buffer && src_att <= front_and_back_buffer);
|
||||
bool dst_color = (dst_att >= color_attachment0 && dst_att <= color_attachment15)
|
||||
|| (dst_att >= front_left_buffer && dst_att <= front_and_back_buffer);
|
||||
|
||||
if(src_att != dst_att && src_color != dst_color) return;
|
||||
|
||||
switch(src_att)
|
||||
{
|
||||
case depth_attachment: mask = fb_depth_bit; break;
|
||||
case stencil_attachment: mask = fb_stencil_bit; break;
|
||||
case depth_stencil_attachment: mask = fb_depth_bit | fb_stencil_bit; break;
|
||||
default:
|
||||
mask = fb_color_bit;
|
||||
glNamedFramebufferReadBuffer(handle_, src_att);
|
||||
glNamedFramebufferDrawBuffer(dst, dst_att);
|
||||
break;
|
||||
}
|
||||
|
||||
glBlitNamedFramebuffer(
|
||||
handle_, dst
|
||||
, src_off.x, src_off.y, src_off.x + src_size.x, src_off.y + src_size.y
|
||||
, dst_off.x, dst_off.y, dst_off.x + dst_size.x, dst_off.y + dst_size.y
|
||||
, mask, filter
|
||||
);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::resize(size_t size)
|
||||
{
|
||||
const auto& sample = textures_.template get<0>();
|
||||
if(sample.size() == size) return;
|
||||
|
||||
glDeleteFramebuffers(1, &handle_);
|
||||
glCreateFramebuffers(1, &handle_);
|
||||
textures_.resize(size);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::resize(const glm::ivec2 &size)
|
||||
{
|
||||
const auto& sample = textures_.template get<0>();
|
||||
if(sample.size() == size) return;
|
||||
|
||||
glDeleteFramebuffers(1, &handle_);
|
||||
glCreateFramebuffers(1, &handle_);
|
||||
textures_.resize(size);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::resize(const glm::ivec2 &size, size_t samples)
|
||||
{
|
||||
const auto& sample = textures_.template get<0>();
|
||||
if(sample.size() == size && sample.samples() == samples) return;
|
||||
|
||||
glDeleteFramebuffers(1, &handle_);
|
||||
glCreateFramebuffers(1, &handle_);
|
||||
textures_.resize(size, samples);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::resize(const glm::ivec3 &size)
|
||||
{
|
||||
const auto& sample = textures_.template get<0>();
|
||||
if(sample.size() == size) return;
|
||||
|
||||
glDeleteFramebuffers(1, &handle_);
|
||||
glCreateFramebuffers(1, &handle_);
|
||||
textures_.resize(size);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t F_, enum_t... Fs_>
|
||||
void framebuffer<T_, F_, Fs_...>::resize(const glm::ivec3 &size, size_t samples)
|
||||
{
|
||||
const auto& sample = textures_.template get<0>();
|
||||
if(sample.size() == size && sample.samples() == samples) return;
|
||||
|
||||
glDeleteFramebuffers(1, &handle_);
|
||||
glCreateFramebuffers(1, &handle_);
|
||||
textures_.resize(size, samples);
|
||||
rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLW_FRAMEBUFFER_H
|
502
shader.h
Executable file
502
shader.h
Executable file
@ -0,0 +1,502 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_SHADER_H
|
||||
#define GLW_SHADER_H
|
||||
|
||||
#include <string>
|
||||
#include <format>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <glm/mat2x2.hpp>
|
||||
#include <glm/mat2x3.hpp>
|
||||
#include <glm/mat2x4.hpp>
|
||||
#include <glm/mat3x2.hpp>
|
||||
#include <glm/mat3x3.hpp>
|
||||
#include <glm/mat3x4.hpp>
|
||||
#include <glm/mat4x2.hpp>
|
||||
#include <glm/mat4x3.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace ocu = open_cpp_utils;
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Definitions
|
||||
// =====================================================================================================================
|
||||
|
||||
|
||||
// Typedefs ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Enums ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
enum source_type
|
||||
{
|
||||
vertex = GL_VERTEX_SHADER
|
||||
, tess_ctrl = GL_TESS_CONTROL_SHADER
|
||||
, tess_eval = GL_TESS_EVALUATION_SHADER
|
||||
, geometry = GL_GEOMETRY_SHADER
|
||||
, fragment = GL_FRAGMENT_SHADER
|
||||
, compute = GL_COMPUTE_SHADER
|
||||
};
|
||||
|
||||
enum uniform_type
|
||||
{
|
||||
// bool ----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
b = GL_BOOL
|
||||
, bvec2 = GL_BOOL_VEC2
|
||||
, bvec3 = GL_BOOL_VEC3
|
||||
, bvec4 = GL_BOOL_VEC4
|
||||
|
||||
|
||||
// int -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, i = GL_INT
|
||||
, ivec2 = GL_INT_VEC2
|
||||
, ivec3 = GL_INT_VEC3
|
||||
, ivec4 = GL_INT_VEC4
|
||||
|
||||
|
||||
// unsigned int --------------------------------------------------------------------------------------------------------
|
||||
|
||||
, u = GL_UNSIGNED_INT
|
||||
, uvec2 = GL_UNSIGNED_INT_VEC2
|
||||
, uvec3 = GL_UNSIGNED_INT_VEC3
|
||||
, uvec4 = GL_UNSIGNED_INT_VEC4
|
||||
|
||||
|
||||
// float ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, f = GL_FLOAT
|
||||
, vec2 = GL_FLOAT_VEC2
|
||||
, vec3 = GL_FLOAT_VEC3
|
||||
, vec4 = GL_FLOAT_VEC4
|
||||
, mat2 = GL_FLOAT_MAT2
|
||||
, mat3 = GL_FLOAT_MAT3
|
||||
, mat4 = GL_FLOAT_MAT4
|
||||
, mat2x3 = GL_FLOAT_MAT2x3
|
||||
, mat2x4 = GL_FLOAT_MAT2x4
|
||||
, mat3x2 = GL_FLOAT_MAT3x2
|
||||
, mat3x4 = GL_FLOAT_MAT3x4
|
||||
, mat4x2 = GL_FLOAT_MAT4x2
|
||||
, mat4x3 = GL_FLOAT_MAT4x3
|
||||
|
||||
|
||||
// double --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, d = GL_DOUBLE
|
||||
, dvec2 = GL_DOUBLE_VEC2
|
||||
, dvec3 = GL_DOUBLE_VEC3
|
||||
, dvec4 = GL_DOUBLE_VEC4
|
||||
, dmat2 = GL_DOUBLE_MAT2
|
||||
, dmat3 = GL_DOUBLE_MAT3
|
||||
, dmat4 = GL_DOUBLE_MAT4
|
||||
, dmat2x3 = GL_DOUBLE_MAT2x3
|
||||
, dmat2x4 = GL_DOUBLE_MAT2x4
|
||||
, dmat3x2 = GL_DOUBLE_MAT3x2
|
||||
, dmat3x4 = GL_DOUBLE_MAT3x4
|
||||
, dmat4x2 = GL_DOUBLE_MAT4x2
|
||||
, dmat4x3 = GL_DOUBLE_MAT4x3
|
||||
|
||||
|
||||
// sampler -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, sampler1D = GL_SAMPLER_1D
|
||||
, sampler1DShadow = GL_SAMPLER_1D_SHADOW
|
||||
, sampler1DArray = GL_SAMPLER_1D_ARRAY
|
||||
, sampler1DArrayShadow = GL_SAMPLER_1D_ARRAY_SHADOW
|
||||
|
||||
, sampler2D = GL_SAMPLER_2D
|
||||
, sampler2DShadow = GL_SAMPLER_2D_SHADOW
|
||||
, sampler2DRect = GL_SAMPLER_2D_RECT
|
||||
, sampler2DRectShadow = GL_SAMPLER_2D_RECT_SHADOW
|
||||
, sampler2DArray = GL_SAMPLER_2D_ARRAY
|
||||
, sampler2DArrayShadow = GL_SAMPLER_2D_ARRAY_SHADOW
|
||||
, sampler2DMS = GL_SAMPLER_2D_MULTISAMPLE
|
||||
, sampler2DMSArray = GL_SAMPLER_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, samplerCube = GL_SAMPLER_CUBE
|
||||
, samplerCubeShadow = GL_SAMPLER_CUBE_SHADOW
|
||||
, samplerCubeArray = GL_SAMPLER_CUBE_MAP_ARRAY
|
||||
|
||||
, sampler3D = GL_SAMPLER_3D
|
||||
|
||||
|
||||
// isampler ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, isampler1D = GL_INT_SAMPLER_1D
|
||||
, isampler1DArray = GL_INT_SAMPLER_1D_ARRAY
|
||||
|
||||
, isampler2D = GL_INT_SAMPLER_2D
|
||||
, isampler2DRect = GL_INT_SAMPLER_2D_RECT
|
||||
, isampler2DArray = GL_INT_SAMPLER_2D_ARRAY
|
||||
, isampler2DMS = GL_INT_SAMPLER_2D_MULTISAMPLE
|
||||
, isampler2DMSArray = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, isamplerCube = GL_INT_SAMPLER_CUBE
|
||||
, isamplerCubeArray = GL_INT_SAMPLER_CUBE_MAP_ARRAY
|
||||
|
||||
, isampler3D = GL_INT_SAMPLER_3D
|
||||
|
||||
|
||||
// usampler ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, usampler1D = GL_UNSIGNED_INT_SAMPLER_1D
|
||||
, usampler1DArray = GL_UNSIGNED_INT_SAMPLER_1D_ARRAY
|
||||
|
||||
, usampler2D = GL_UNSIGNED_INT_SAMPLER_2D
|
||||
, usampler2DRect = GL_UNSIGNED_INT_SAMPLER_2D_RECT
|
||||
, usampler2DArray = GL_UNSIGNED_INT_SAMPLER_2D_ARRAY
|
||||
, usampler2DMS = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE
|
||||
, usampler2DMSArray = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, usamplerCube = GL_UNSIGNED_INT_SAMPLER_CUBE
|
||||
, usamplerCubeArray = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY
|
||||
|
||||
, usampler3D = GL_UNSIGNED_INT_SAMPLER_3D
|
||||
|
||||
|
||||
// image ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, image1D = GL_IMAGE_1D
|
||||
, image1DArray = GL_IMAGE_1D_ARRAY
|
||||
|
||||
, image2D = GL_IMAGE_2D
|
||||
, image2DRect = GL_IMAGE_2D_RECT
|
||||
, image2DArray = GL_IMAGE_2D_ARRAY
|
||||
, image2DMS = GL_IMAGE_2D_MULTISAMPLE
|
||||
, image2DMSArray = GL_IMAGE_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, imageCube = GL_IMAGE_CUBE
|
||||
, imageCubeArray = GL_IMAGE_CUBE_MAP_ARRAY
|
||||
|
||||
, image3D = GL_IMAGE_3D
|
||||
|
||||
|
||||
// iimage --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, iimage1D = GL_INT_IMAGE_1D
|
||||
, iimage1DArray = GL_INT_IMAGE_1D_ARRAY
|
||||
|
||||
, iimage2D = GL_INT_IMAGE_2D
|
||||
, iimage2DRect = GL_INT_IMAGE_2D_RECT
|
||||
, iimage2DArray = GL_INT_IMAGE_2D_ARRAY
|
||||
, iimage2DMS = GL_INT_IMAGE_2D_MULTISAMPLE
|
||||
, iimage2DMSArray = GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, iimageCube = GL_INT_IMAGE_CUBE
|
||||
, iimageCubeArray = GL_INT_IMAGE_CUBE_MAP_ARRAY
|
||||
|
||||
, iimage3D = GL_INT_IMAGE_3D
|
||||
|
||||
|
||||
// uimage --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, uimage1D = GL_UNSIGNED_INT_IMAGE_1D
|
||||
, uimage1DArray = GL_UNSIGNED_INT_IMAGE_1D_ARRAY
|
||||
|
||||
, uimage2D = GL_UNSIGNED_INT_IMAGE_2D
|
||||
, uimage2DRect = GL_UNSIGNED_INT_IMAGE_2D_RECT
|
||||
, uimage2DArray = GL_UNSIGNED_INT_IMAGE_2D_ARRAY
|
||||
, uimage2DMS = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE
|
||||
, uimage2DMSArray = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, uimageCube = GL_UNSIGNED_INT_IMAGE_CUBE
|
||||
, uimageCubeArray = GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
|
||||
|
||||
, uimage3D = GL_UNSIGNED_INT_IMAGE_3D
|
||||
|
||||
|
||||
// atomic --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
, atomic_uint = GL_UNSIGNED_INT_ATOMIC_COUNTER
|
||||
};
|
||||
|
||||
|
||||
// Buffer Definition ---------------------------------------------------------------------------------------------------
|
||||
|
||||
class shader
|
||||
{
|
||||
// Typedefs ============================================================================================================
|
||||
|
||||
public:
|
||||
struct uniform
|
||||
{
|
||||
public:
|
||||
uniform() : shader_(0), name_(""), type_(int8), location_(-1) { }
|
||||
uniform(const std::string& str) : shader_(0), name_(str), type_(int8), location_(-1) { }
|
||||
uniform(shader& shader, const std::string& name, enum_t type);
|
||||
uniform(const uniform& u) : shader_(u.shader_), name_(u.name_), type_(u.type_), location_(u.location_) { }
|
||||
~uniform() = default;
|
||||
|
||||
template<typename T>
|
||||
inline uniform& operator=(T v) { assert(false); return *this; }
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
enum_t type() const { return type_; }
|
||||
index_t location() const { return location_; }
|
||||
|
||||
private:
|
||||
handle_t shader_;
|
||||
std::string name_;
|
||||
enum_t type_;
|
||||
index_t location_;
|
||||
};
|
||||
|
||||
// OpenGL Built Ins
|
||||
static constexpr char gl_NumWorkGroups[] = "gl_NumWorkGroups";
|
||||
static constexpr char gl_WorkGroupID[] = "gl_WorkGroupID";
|
||||
static constexpr char gl_LocalInvocationID[] = "gl_LocalInvocationID";
|
||||
static constexpr char gl_GlobalInvocationID[] = "gl_GlobalInvocationID";
|
||||
static constexpr char gl_LocalInvocationIndex[] = "gl_LocalInvocationIndex";
|
||||
|
||||
// GLW Built Ins
|
||||
static constexpr char glw_RequestedInvocations[] = "glw_RequestedInvocations";
|
||||
static inline const std::string built_ins_compute = std::format("uniform ivec3 {};", glw_RequestedInvocations);
|
||||
|
||||
private:
|
||||
using uniform_map = std::unordered_map<std::string, uniform>;
|
||||
|
||||
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
public:
|
||||
|
||||
shader();
|
||||
~shader();
|
||||
|
||||
bool attach_source(enum_t type, size_t count, const char** source, const size_t* lengths);
|
||||
bool attach_source(enum_t type, const std::vector<std::string>& source);
|
||||
bool link();
|
||||
|
||||
void bind() const;
|
||||
|
||||
void dispatch(int x = 1, int y = 1, int z = 1);
|
||||
|
||||
uniform operator[](const std::string& str);
|
||||
|
||||
const std::string& get_error_string() const { return error_; }
|
||||
|
||||
inline static std::string group_size(int x, int y, int z)
|
||||
{ return std::format("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;", x, y, z); }
|
||||
|
||||
private:
|
||||
handle_t handle_;
|
||||
std::string error_;
|
||||
int work_group_size_[3];
|
||||
bool pass_requested_invocations_;
|
||||
uniform_map uniforms_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// =====================================================================================================================
|
||||
// Implementation
|
||||
// =====================================================================================================================
|
||||
|
||||
|
||||
// uniform -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
inline shader::uniform::uniform(shader& shader, const std::string& name, enum_t type)
|
||||
: shader_(shader.handle_)
|
||||
, name_(name)
|
||||
, type_(type)
|
||||
, location_(0)
|
||||
{
|
||||
location_ = glGetUniformLocation(shader_, name_.c_str());
|
||||
}
|
||||
|
||||
#define validate(handle, type) if(handle == 0) return *this; assert(type_ == type);
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<bool>(bool v) { validate(shader_, uniform_type::b); glProgramUniform1i(shader_, location_, v); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::bvec2>(glm::bvec2 v) { validate(shader_, uniform_type::bvec2); glProgramUniform2i(shader_, location_, v.x, v.y); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::bvec3>(glm::bvec3 v) { validate(shader_, uniform_type::bvec3); glProgramUniform3i(shader_, location_, v.x, v.y, v.z); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::bvec4>(glm::bvec4 v) { validate(shader_, uniform_type::bvec4); glProgramUniform4i(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<int>(int v) { validate(shader_, uniform_type::i); glProgramUniform1i(shader_, location_, v); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::ivec2>(glm::ivec2 v) { validate(shader_, uniform_type::ivec2); glProgramUniform2i(shader_, location_, v.x, v.y); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::ivec3>(glm::ivec3 v) { validate(shader_, uniform_type::ivec3); glProgramUniform3i(shader_, location_, v.x, v.y, v.z); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::ivec4>(glm::ivec4 v) { validate(shader_, uniform_type::ivec4); glProgramUniform4i(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::uint>(glm::uint v) { validate(shader_, uniform_type::u); glProgramUniform1ui(shader_, location_, v); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::uvec2>(glm::uvec2 v) { validate(shader_, uniform_type::uvec2); glProgramUniform2ui(shader_, location_, v.x, v.y); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::uvec3>(glm::uvec3 v) { validate(shader_, uniform_type::uvec3); glProgramUniform3ui(shader_, location_, v.x, v.y, v.z); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::uvec4>(glm::uvec4 v) { validate(shader_, uniform_type::uvec4); glProgramUniform4ui(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<float>(float v) { validate(shader_, uniform_type::f); glProgramUniform1f(shader_, location_, v); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::vec2>(glm::vec2 v) { validate(shader_, uniform_type::vec2); glProgramUniform2f(shader_, location_, v.x, v.y); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::vec3>(glm::vec3 v) { validate(shader_, uniform_type::vec3); glProgramUniform3f(shader_, location_, v.x, v.y, v.z); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::vec4>(glm::vec4 v) { validate(shader_, uniform_type::vec4); glProgramUniform4f(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<double>(double v) { validate(shader_, uniform_type::d); glProgramUniform1d(shader_, location_, v); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dvec2>(glm::dvec2 v) { validate(shader_, uniform_type::dvec2); glProgramUniform2d(shader_, location_, v.x, v.y); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dvec3>(glm::dvec3 v) { validate(shader_, uniform_type::dvec3); glProgramUniform3d(shader_, location_, v.x, v.y, v.z); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dvec4>(glm::dvec4 v) { validate(shader_, uniform_type::dvec4); glProgramUniform4d(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat2> (glm::mat2 v) { validate(shader_, uniform_type::mat2); glProgramUniformMatrix2fv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat2x3>(glm::mat2x3 v) { validate(shader_, uniform_type::mat2x3); glProgramUniformMatrix2x3fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat2x4>(glm::mat2x4 v) { validate(shader_, uniform_type::mat2x4); glProgramUniformMatrix2x4fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat3x2>(glm::mat3x2 v) { validate(shader_, uniform_type::mat3x2); glProgramUniformMatrix3x2fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat3> (glm::mat3 v) { validate(shader_, uniform_type::mat3); glProgramUniformMatrix3fv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat3x4>(glm::mat3x4 v) { validate(shader_, uniform_type::mat3x4); glProgramUniformMatrix3x4fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat4x2>(glm::mat4x2 v) { validate(shader_, uniform_type::mat4x2); glProgramUniformMatrix4x2fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat4x3>(glm::mat4x3 v) { validate(shader_, uniform_type::mat4x3); glProgramUniformMatrix4x3fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::mat4> (glm::mat4 v) { validate(shader_, uniform_type::mat4); glProgramUniformMatrix4fv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat2> (glm::dmat2 v) { validate(shader_, uniform_type::dmat2); glProgramUniformMatrix2dv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat2x3>(glm::dmat2x3 v) { validate(shader_, uniform_type::dmat2x3); glProgramUniformMatrix2x3dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat2x4>(glm::dmat2x4 v) { validate(shader_, uniform_type::dmat2x4); glProgramUniformMatrix2x4dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat3x2>(glm::dmat3x2 v) { validate(shader_, uniform_type::dmat3x2); glProgramUniformMatrix3x2dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat3> (glm::dmat3 v) { validate(shader_, uniform_type::dmat3); glProgramUniformMatrix3dv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat3x4>(glm::dmat3x4 v) { validate(shader_, uniform_type::dmat3x4); glProgramUniformMatrix3x4dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat4x2>(glm::dmat4x2 v) { validate(shader_, uniform_type::dmat4x2); glProgramUniformMatrix4x2dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat4x3>(glm::dmat4x3 v) { validate(shader_, uniform_type::dmat4x3); glProgramUniformMatrix4x3dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat4> (glm::dmat4 v) { validate(shader_, uniform_type::dmat4); glProgramUniformMatrix4dv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
||||
|
||||
|
||||
// shader --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
inline shader::shader()
|
||||
: handle_(glCreateProgram())
|
||||
, work_group_size_{ 1 }
|
||||
, pass_requested_invocations_(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
inline shader::~shader()
|
||||
{
|
||||
glDeleteProgram(handle_);
|
||||
}
|
||||
|
||||
inline bool shader::attach_source(enum_t type, size_t count, const char** source, const size_t* lengths)
|
||||
{
|
||||
handle_t shader = glCreateShader(type);
|
||||
glShaderSource(shader, count, source, lengths);
|
||||
glCompileShader(shader);
|
||||
|
||||
int result; glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
|
||||
|
||||
if(result) glAttachShader(handle_, shader);
|
||||
else
|
||||
{
|
||||
int res; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &res);
|
||||
error_.resize(res);
|
||||
glGetShaderInfoLog(shader, res, &res, error_.data());
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool shader::attach_source(enum_t type, const std::vector<std::string>& source)
|
||||
{
|
||||
std::vector<const char*> src; src.reserve(source.size());
|
||||
std::vector<size_t> len; len.reserve(source.size());
|
||||
|
||||
for(const std::string& str : source)
|
||||
{
|
||||
src.push_back(str.c_str());
|
||||
len.push_back(static_cast<int>(str.length()));
|
||||
}
|
||||
|
||||
return attach_source(type, static_cast<int>(source.size()), src.data(), len.data());
|
||||
}
|
||||
|
||||
inline bool shader::link()
|
||||
{
|
||||
glLinkProgram(handle_);
|
||||
|
||||
int result; glGetProgramiv(handle_, GL_LINK_STATUS, &result);
|
||||
|
||||
if(!result)
|
||||
{
|
||||
int res; glGetProgramiv(handle_, GL_INFO_LOG_LENGTH, &res);
|
||||
error_.resize(res);
|
||||
glGetProgramInfoLog(handle_, res, &res, error_.data());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
glGetProgramiv(handle_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &result);
|
||||
std::string buffer(result + 1, '\0');
|
||||
size_t max_length = static_cast<int>(buffer.capacity());
|
||||
char* str = buffer.data();
|
||||
glGetProgramiv(handle_, GL_ACTIVE_UNIFORMS, &result);
|
||||
|
||||
for(int i = 0; i < result; ++i)
|
||||
{
|
||||
enum_t type; size_t length, size;
|
||||
glGetActiveUniform(handle_, i, max_length, &length, &size, &type, str);
|
||||
std::string res = buffer.substr(0, length).c_str();
|
||||
uniforms_[res] = uniform(*this, res, type);
|
||||
|
||||
const bool len = length == sizeof(glw_RequestedInvocations) - 1;
|
||||
const bool cmp = (strncmp(buffer.c_str(), glw_RequestedInvocations, length) == 0);
|
||||
pass_requested_invocations_ |= (len && cmp);
|
||||
}
|
||||
|
||||
glGetProgramiv(handle_, GL_COMPUTE_WORK_GROUP_SIZE, work_group_size_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void shader::bind() const
|
||||
{
|
||||
glUseProgram(handle_);
|
||||
}
|
||||
|
||||
inline void shader::dispatch(int x, int y, int z)
|
||||
{
|
||||
int num_groups_x = ceil_div(x, work_group_size_[0]);
|
||||
int num_groups_y = ceil_div(y, work_group_size_[1]);
|
||||
int num_groups_z = ceil_div(z, work_group_size_[2]);
|
||||
|
||||
bind();
|
||||
|
||||
if(pass_requested_invocations_)
|
||||
this->operator[](glw_RequestedInvocations) = glm::ivec3(x, y, z);
|
||||
|
||||
glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
|
||||
}
|
||||
|
||||
inline shader::uniform shader::operator[](const std::string &str)
|
||||
{
|
||||
auto it = uniforms_.find(str);
|
||||
|
||||
if(it != uniforms_.end())
|
||||
return it->second;
|
||||
|
||||
return uniform();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //SHADER_H
|
654
texture.h
Executable file
654
texture.h
Executable file
@ -0,0 +1,654 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_TEXTURE_H
|
||||
#define GLW_TEXTURE_H
|
||||
|
||||
#include <glm/common.hpp>
|
||||
#include <glm/exponential.hpp>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
#include <open-cpp-utils/template_utils.h>
|
||||
|
||||
namespace ocu = open_cpp_utils;
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Definitions
|
||||
// =====================================================================================================================
|
||||
|
||||
|
||||
using swizzle_t = glm::vec<4, enum_t>;
|
||||
using wrapping_t = glm::vec<3, enum_t>;
|
||||
|
||||
// Enums ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
enum texture_type : enum_t
|
||||
{
|
||||
texture1D = GL_TEXTURE_1D
|
||||
, texture1DArray = GL_TEXTURE_1D_ARRAY
|
||||
|
||||
, texture2D = GL_TEXTURE_2D
|
||||
, textureRect = GL_TEXTURE_RECTANGLE
|
||||
, texture2DArray = GL_TEXTURE_2D_ARRAY
|
||||
, texture2DMS = GL_TEXTURE_2D_MULTISAMPLE
|
||||
, texture2DMSArray = GL_TEXTURE_2D_MULTISAMPLE_ARRAY
|
||||
|
||||
, textureCubemap = GL_TEXTURE_CUBE_MAP
|
||||
, textureCubemapArray = GL_TEXTURE_CUBE_MAP_ARRAY
|
||||
|
||||
, texture3D = GL_TEXTURE_3D
|
||||
};
|
||||
|
||||
enum texture_param : enum_t
|
||||
{
|
||||
depth_stencil_mode = GL_DEPTH_STENCIL_TEXTURE_MODE
|
||||
|
||||
, base_mip_level = GL_TEXTURE_BASE_LEVEL
|
||||
, max_mip_level = GL_TEXTURE_MAX_LEVEL
|
||||
|
||||
, compare_mode = GL_TEXTURE_COMPARE_MODE
|
||||
, compare_func = GL_TEXTURE_COMPARE_FUNC
|
||||
|
||||
, lod_min = GL_TEXTURE_MIN_LOD
|
||||
, lod_max = GL_TEXTURE_MAX_LOD
|
||||
, lod_bias = GL_TEXTURE_LOD_BIAS
|
||||
|
||||
, min_filter = GL_TEXTURE_MIN_FILTER
|
||||
, mag_filter = GL_TEXTURE_MAG_FILTER
|
||||
|
||||
, swizzle = GL_TEXTURE_SWIZZLE_RGBA
|
||||
, swizzle_r = GL_TEXTURE_SWIZZLE_R
|
||||
, swizzle_g = GL_TEXTURE_SWIZZLE_G
|
||||
, swizzle_b = GL_TEXTURE_SWIZZLE_B
|
||||
, swizzle_a = GL_TEXTURE_SWIZZLE_A
|
||||
|
||||
, wrap_s = GL_TEXTURE_WRAP_S
|
||||
, wrap_t = GL_TEXTURE_WRAP_T
|
||||
, wrap_r = GL_TEXTURE_WRAP_R
|
||||
, border = GL_TEXTURE_BORDER_COLOR
|
||||
};
|
||||
|
||||
enum filtering : enum_t
|
||||
{
|
||||
nearest = GL_NEAREST
|
||||
, linear = GL_LINEAR
|
||||
, point = GL_NEAREST_MIPMAP_NEAREST
|
||||
, bilinear = GL_LINEAR_MIPMAP_NEAREST
|
||||
, trilinear = GL_LINEAR_MIPMAP_LINEAR
|
||||
};
|
||||
|
||||
enum wrapping : enum_t
|
||||
{
|
||||
clamp = GL_CLAMP_TO_EDGE
|
||||
, clamp_to_border = GL_CLAMP_TO_BORDER
|
||||
, mirrored = GL_MIRRORED_REPEAT
|
||||
, repeate = GL_REPEAT
|
||||
, mirrored_clamp = GL_MIRROR_CLAMP_TO_EDGE
|
||||
};
|
||||
|
||||
enum swizzle : enum_t
|
||||
{
|
||||
red = GL_TEXTURE_SWIZZLE_R
|
||||
, green = GL_TEXTURE_SWIZZLE_G
|
||||
, blue = GL_TEXTURE_SWIZZLE_B
|
||||
, alpha = GL_TEXTURE_SWIZZLE_A
|
||||
};
|
||||
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
class texture
|
||||
{
|
||||
// Constants ===========================================================================================================
|
||||
|
||||
public:
|
||||
inline static constexpr enum_t type = T_;
|
||||
inline static constexpr enum_t format = PF_;
|
||||
|
||||
inline static constexpr struct type_traits
|
||||
{
|
||||
static constexpr enum_t type = T_;
|
||||
static constexpr enum_t format = PF_;
|
||||
static constexpr bool layered = contains_enum<type, texture1DArray,texture2DArray,texture2DMSArray,textureCubemap,textureCubemapArray,texture3D>{};
|
||||
} traits {};
|
||||
|
||||
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
private:
|
||||
void get_current_params_();
|
||||
|
||||
// Constructors --------------------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
texture(size_t size);
|
||||
texture(glm::ivec2 size);
|
||||
texture(glm::ivec2 size, size_t samples);
|
||||
texture(glm::ivec3 size);
|
||||
texture(glm::ivec3 size, size_t samples);
|
||||
|
||||
texture(texture&& move);
|
||||
|
||||
~texture();
|
||||
|
||||
inline constexpr enum_t get_type() const { return type; }
|
||||
inline constexpr enum_t get_format() const { return format; }
|
||||
|
||||
// Handle --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* \brief ONLY USE THIS IF YOU KNOW WHAT YOU ARE DOING
|
||||
* \return The OpenGL name for the texture
|
||||
*/
|
||||
handle_t handle() { return handle_; }
|
||||
|
||||
|
||||
// Capacity ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
size_t size() const requires(contains_enum<type, texture1D>::value) { return size_.x; }
|
||||
glm::ivec2 size() const requires(contains_enum<type, texture1DArray, texture2D, texture2DMS, textureCubemap>::value) { return size_; }
|
||||
glm::ivec3 size() const requires(contains_enum<type, texture2DArray, texture2DMSArray, textureCubemapArray>::value) { return size_; }
|
||||
|
||||
void resize(size_t size);
|
||||
void resize(glm::ivec2 size);
|
||||
void resize(glm::ivec2 size, size_t samples);
|
||||
void resize(glm::ivec3 size);
|
||||
void resize(glm::ivec3 size, size_t samples);
|
||||
|
||||
size_t num_samples() const { return samples_; }
|
||||
|
||||
// Modifiers -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
void upload(const void* pixels, size_t size, index_t offset = 0, index_t level = 0, enum_t layout = r_i, enum_t type = uint8)
|
||||
requires(contains_enum<texture::type, texture1D>::value)
|
||||
{
|
||||
glTextureSubImage1D(handle_, level, offset, size, layout, type, pixels);
|
||||
glGenerateTextureMipmap(handle_);
|
||||
}
|
||||
|
||||
void upload(const void* pixels, glm::ivec2 size, glm::ivec2 offset = glm::ivec2(0), index_t level = 0, enum_t layout = r_i, enum_t type = uint8)
|
||||
requires(contains_enum<texture::type, texture1DArray, texture2D, textureCubemap>::value)
|
||||
{
|
||||
glTextureSubImage2D(handle_, level, offset.x, offset.y, size.x, size.y, layout, type, pixels);
|
||||
}
|
||||
|
||||
void upload(const void* pixels, glm::ivec3 size, glm::ivec3 offset = glm::ivec3(0), index_t level = 0, enum_t layout = r_i, enum_t type = uint8)
|
||||
requires(contains_enum<texture::type, texture2DArray, textureCubemapArray, texture3D>::value)
|
||||
{
|
||||
glTextureSubImage3D(handle_, level, offset.x, offset.y, offset.x, size.x, size.y, size.z, layout, type, pixels);
|
||||
}
|
||||
|
||||
void clear(size_t size = -1, index_t offset = 0, index_t level = 0, const void* data = nullptr, enum_t layout = r_i, enum_t type = uint8)
|
||||
{
|
||||
static_assert(contains_enum<texture::type, texture1D>::value);
|
||||
|
||||
size = size < 0 ? size_.x - offset : size;
|
||||
glClearTexSubImage(handle_, level, offset, 0, 0, size, 1, 1, layout, type, data);
|
||||
}
|
||||
|
||||
void clear(glm::ivec2 size = glm::ivec2(-1), glm::ivec2 offset = glm::ivec2(0), index_t level = 0, const void* data = nullptr, enum_t layout = r_i, enum_t type = uint8)
|
||||
{
|
||||
static_assert(contains_enum<texture::type, texture1DArray, texture2D, textureCubemap>::value);
|
||||
|
||||
size.x = size.x < 0 ? size_.x - offset.x : size.x;
|
||||
size.y = size.y < 0 ? size_.y - offset.y : size.y;
|
||||
glClearTexSubImage(handle_, level, offset.x, offset.y, 0, size.x, size.y, 1, layout, type, data);
|
||||
}
|
||||
|
||||
void clear(glm::ivec3 size = glm::ivec3(-1), glm::ivec3 offset = glm::ivec3(0), index_t level = 0, const void* data = nullptr, enum_t layout = r_i, enum_t type = uint8)
|
||||
{
|
||||
static_assert(contains_enum<texture::type, texture1DArray, texture2D, textureCubemap>::value);
|
||||
size.x = size.x < 0 ? size_.x - offset.x : size.x;
|
||||
size.y = size.y < 0 ? size_.y - offset.y : size.y;
|
||||
size.z = size.z < 0 ? size_.z - offset.z : size.z;
|
||||
glClearTexSubImage(handle_, level, offset.x, offset.y, offset.z, size.x, size.y, size.z, layout, type, data);
|
||||
}
|
||||
|
||||
template<enum_t OT_, enum_t OPF_>
|
||||
void copy(const texture<OT_, OPF_>& src, size_t size = -1,
|
||||
offset_t src_offset = 0, index_t src_level = 0,
|
||||
offset_t dst_offset = 0, index_t dst_level = 0)
|
||||
{
|
||||
using otexture = texture<OT_, OPF_>;
|
||||
static_assert(contains_enum<type, texture1D>::value && type == otexture::type);
|
||||
size = size < 0 ? src.size_.x - src_offset : size;
|
||||
|
||||
glCopyImageSubData(
|
||||
src.handle_, otexture::type, src_level, src_offset, 0, 0,
|
||||
handle_, type, dst_level, dst_offset, 0, 0,
|
||||
size, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
template<enum_t OT_, enum_t OPF_>
|
||||
void copy(const texture<OT_, OPF_>& src, glm::ivec2 size = glm::ivec2(-1),
|
||||
glm::ivec2 src_offset = glm::ivec2(0), index_t src_level = 0,
|
||||
glm::ivec2 dst_offset = glm::ivec2(0), index_t dst_level = 0)
|
||||
{
|
||||
using otexture = texture<OT_, OPF_>;
|
||||
static_assert(contains_enum<type, texture1DArray, texture2D, textureCubemap>::value && type == otexture::type);
|
||||
size.x = size.x < 0 ? src.size_.x - src_offset.x : size.x;
|
||||
size.y = size.y < 0 ? src.size_.y - src_offset.y : size.y;
|
||||
|
||||
glCopyImageSubData(
|
||||
src.handle_, otexture::type, src_level, src_offset.x, src_offset.y, 0,
|
||||
handle_, type, dst_level, dst_offset.x, dst_offset.y, 0,
|
||||
size.x, size.y, 0
|
||||
);
|
||||
}
|
||||
|
||||
template<enum_t OT_, enum_t OPF_>
|
||||
void copy(const texture<OT_, OPF_>& src, glm::ivec3 size = glm::ivec3(-1),
|
||||
glm::ivec3 src_offset = glm::ivec3(0), index_t src_level = 0,
|
||||
glm::ivec3 dst_offset = glm::ivec3(0), index_t dst_level = 0)
|
||||
{
|
||||
using otexture = texture<OT_, OPF_>;
|
||||
static_assert(contains_enum<type, texture1DArray, texture2D, textureCubemap>::value && type == otexture::type);
|
||||
size.x = size.x < 0 ? src.size_.x - src_offset.x : size.x;
|
||||
size.y = size.y < 0 ? src.size_.y - src_offset.y : size.y;
|
||||
size.z = size.z < 0 ? src.size_.z - src_offset.z : size.z;
|
||||
|
||||
glCopyImageSubData(
|
||||
src.handle_, otexture::type, src_level, src_offset.x, src_offset.y, src_offset.z,
|
||||
handle_, type, dst_level, dst_offset.x, dst_offset.y, dst_offset.z,
|
||||
size.x, size.y, size.z
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Binding -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void bind(location_t loc)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + loc);
|
||||
glBindTexture(type, handle_);
|
||||
}
|
||||
|
||||
void bind_image(location_t loc, enum_t access)
|
||||
{
|
||||
glBindImageTexture(loc, handle_, 0, traits.layered, 0, access, format);
|
||||
}
|
||||
|
||||
void bind_image(location_t loc, index_t level, bool layered, index_t layer, enum_t access, enum_t format)
|
||||
{
|
||||
glBindImageTexture(loc, handle_, level, layered, layer, access, format);
|
||||
}
|
||||
|
||||
|
||||
// Depth / Stencil -----------------------------------------------------------------------------------------------------
|
||||
|
||||
void set_ds_mode(enum_t mode) { glTextureParameteri(handle_, GL_DEPTH_STENCIL_TEXTURE_MODE, depth_stencil_mode_ = mode); }
|
||||
enum_t get_ds_mode() const { return depth_stencil_mode_; }
|
||||
|
||||
void set_compare_mode(enum_t mode) { glTextureParameteri(handle_, GL_TEXTURE_COMPARE_MODE, compare_mode_ = mode); }
|
||||
enum_t get_compare_mode() const { return compare_mode_; }
|
||||
|
||||
void set_compare_func(enum_t func) { glTextureParameteri(handle_, GL_TEXTURE_COMPARE_FUNC, compare_func_ = func); }
|
||||
enum_t get_compare_func() const { return compare_func_; }
|
||||
|
||||
void set_comparison(enum_t mode, enum_t func) { set_compare_mode(mode); set_compare_func(func); }
|
||||
|
||||
|
||||
// Mip Mapping ---------------------------------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Fix bug from optimization in resize, might be better to make a "rebuild" function
|
||||
void set_num_mip_levels(size_t value)
|
||||
requires(contains_enum<type, texture1D>::value)
|
||||
{ mip_levels_ = value; resize(size_.x); }
|
||||
|
||||
void set_num_mip_levels(size_t value)
|
||||
requires(contains_enum<type, texture1DArray, texture2D, textureCubemap>::value)
|
||||
{ mip_levels_ = value; resize(size_.x, size_.y); }
|
||||
|
||||
void set_num_mip_levels(size_t value)
|
||||
requires(contains_enum<type, texture2DArray, textureCubemapArray, texture3D>::value)
|
||||
{ mip_levels_ = value; resize(size_.x, size_.y, size_.z); }
|
||||
|
||||
size_t get_num_mip_levels() const { return mip_levels_; }
|
||||
|
||||
void set_base_mip_level(size_t value) { glTextureParameteri(handle_, GL_TEXTURE_BASE_LEVEL, base_mip_level_ = value); }
|
||||
size_t get_base_mip_level() const { return base_mip_level_; }
|
||||
|
||||
void set_max_mip_level(size_t value) { glTextureParameteri(handle_, GL_TEXTURE_MAX_LEVEL, max_mip_level_ = value); }
|
||||
size_t get_max_mip_level() const { return max_mip_level_; }
|
||||
|
||||
void set_lod_min(float value) { glTextureParameterf(handle_, GL_TEXTURE_MIN_LOD, lod_min_ = value); }
|
||||
float get_lod_min() const { return lod_min_; }
|
||||
|
||||
void set_lod_max(float value) { glTextureParameterf(handle_, GL_TEXTURE_MAX_LOD, lod_max_ = value); }
|
||||
float get_lod_max() const { return lod_max_; }
|
||||
|
||||
void set_lod_range(float min, float max) { set_lod_min(min); set_lod_max(max); }
|
||||
|
||||
void set_lod_bias(float value) { glTextureParameterf(handle_, GL_TEXTURE_LOD_BIAS, lod_bias_ = value); }
|
||||
float get_lod_bias() const { return lod_bias_; }
|
||||
|
||||
void generate_mipmaps() { glGenerateTextureMipmap(handle_); }
|
||||
|
||||
|
||||
// Filtering -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
void set_min_filter(enum_t value) { glTextureParameteri(handle_, GL_TEXTURE_MIN_FILTER, min_filter_ = value); }
|
||||
enum_t get_min_filter() const { return min_filter_; }
|
||||
|
||||
void set_mag_filter(enum_t value) { glTextureParameteri(handle_, GL_TEXTURE_MAG_FILTER, mag_filter_ = value); }
|
||||
enum_t get_mag_filter() const { return mag_filter_; }
|
||||
|
||||
|
||||
// Swizzling -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
void set_swizzle_r(enum_t swizzle) { glTextureParameteri(handle_, GL_TEXTURE_SWIZZLE_R, swizzle_.r = swizzle); }
|
||||
enum_t get_swizzle_r() const { return swizzle_.r; }
|
||||
|
||||
void set_swizzle_g(enum_t swizzle) { glTextureParameteri(handle_, GL_TEXTURE_SWIZZLE_G, swizzle_.g = swizzle); }
|
||||
enum_t get_swizzle_g() const { return swizzle_.g; }
|
||||
|
||||
void set_swizzle_b(enum_t swizzle) { glTextureParameteri(handle_, GL_TEXTURE_SWIZZLE_B, swizzle_.b = swizzle); }
|
||||
enum_t get_swizzle_b() const { return swizzle_.b; }
|
||||
|
||||
void set_swizzle_a(enum_t swizzle) { glTextureParameteri(handle_, GL_TEXTURE_SWIZZLE_A, swizzle_.a = swizzle); }
|
||||
enum_t get_swizzle_a() const { return swizzle_.a; }
|
||||
|
||||
void set_swizzle(const swizzle_t& swizzle) { glTextureParameterIuiv(handle_, GL_TEXTURE_SWIZZLE_RGBA, &(swizzle_ = swizzle).x); }
|
||||
const swizzle_t& get_swizzle() const { return swizzle_; }
|
||||
|
||||
|
||||
// Wrapping ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void set_wrapping_s(enum_t value) { glTextureParameteri(handle_, GL_TEXTURE_WRAP_S, wrapping_.x = value); }
|
||||
enum_t get_wrapping_s() const { return wrapping_.x; }
|
||||
|
||||
void set_wrapping_t(enum_t value) { glTextureParameteri(handle_, GL_TEXTURE_WRAP_T, wrapping_.y = value); }
|
||||
enum_t get_wrapping_t() const { return wrapping_.y; }
|
||||
|
||||
void set_wrapping_r(enum_t value) { glTextureParameteri(handle_, GL_TEXTURE_WRAP_R, wrapping_.z = value); }
|
||||
enum_t get_wrapping_r() const { return wrapping_.z; }
|
||||
|
||||
void set_wrapping(const wrapping_t& value)
|
||||
{
|
||||
glTextureParameteri(handle_, GL_TEXTURE_WRAP_S, wrapping_.x = value.x);
|
||||
glTextureParameteri(handle_, GL_TEXTURE_WRAP_T, wrapping_.y = value.y);
|
||||
glTextureParameteri(handle_, GL_TEXTURE_WRAP_R, wrapping_.z = value.z);
|
||||
}
|
||||
|
||||
const wrapping_t& get_wrapping() const { return wrapping_; }
|
||||
|
||||
void set_border_color(const glm::vec4& value) { glTextureParameterfv(handle_, GL_TEXTURE_BORDER_COLOR, &(border_color_ = value).x); }
|
||||
const glm::vec4& get_border_color() const { return border_color_; }
|
||||
|
||||
// Variables ===========================================================================================================
|
||||
|
||||
private:
|
||||
handle_t handle_;
|
||||
glm::ivec3 size_;
|
||||
size_t samples_, mip_levels_;
|
||||
|
||||
enum_t depth_stencil_mode_;
|
||||
size_t base_mip_level_, max_mip_level_;
|
||||
glm::vec4 border_color_;
|
||||
enum_t compare_mode_, compare_func_;
|
||||
float lod_min_, lod_max_, lod_bias_;
|
||||
enum_t min_filter_, mag_filter_;
|
||||
swizzle_t swizzle_;
|
||||
wrapping_t wrapping_;
|
||||
};
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
void texture<T_, PF_>::get_current_params_()
|
||||
{
|
||||
glGetTextureParameterIuiv(handle_, GL_DEPTH_STENCIL_TEXTURE_MODE, &depth_stencil_mode_);
|
||||
glGetTextureParameteriv(handle_, GL_TEXTURE_BASE_LEVEL, &base_mip_level_);
|
||||
glGetTextureParameteriv(handle_, GL_TEXTURE_MAX_LEVEL, &max_mip_level_);
|
||||
|
||||
glGetTextureParameterfv(handle_, GL_TEXTURE_BORDER_COLOR, &border_color_.x);
|
||||
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_COMPARE_MODE, &compare_mode_);
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_COMPARE_FUNC, &compare_func_);
|
||||
|
||||
glGetTextureParameterfv(handle_, GL_TEXTURE_MIN_LOD, &lod_min_);
|
||||
glGetTextureParameterfv(handle_, GL_TEXTURE_MAX_LOD, &lod_max_);
|
||||
glGetTextureParameterfv(handle_, GL_TEXTURE_LOD_BIAS, &lod_bias_);
|
||||
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_MIN_FILTER, &min_filter_);
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_MAG_FILTER, &mag_filter_);
|
||||
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_SWIZZLE_RGBA, &swizzle_.x);
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_WRAP_S, &wrapping_.x);
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_WRAP_T, &wrapping_.y);
|
||||
glGetTextureParameterIuiv(handle_, GL_TEXTURE_WRAP_R, &wrapping_.z);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::texture(size_t size)
|
||||
: handle_(NULL)
|
||||
, size_(size, size, size)
|
||||
, samples_(1), mip_levels_(0)
|
||||
, depth_stencil_mode_()
|
||||
, base_mip_level_(), max_mip_level_()
|
||||
, border_color_()
|
||||
, compare_mode_(), compare_func_()
|
||||
, lod_min_(), lod_max_(), lod_bias_()
|
||||
, min_filter_(), mag_filter_()
|
||||
, swizzle_(), wrapping_()
|
||||
{
|
||||
static_assert(contains_enum<type, texture1D>::value);
|
||||
|
||||
mip_levels_ = static_cast<size_t>(glm::log2(static_cast<float>(size)));
|
||||
mip_levels_ = std::max(mip_levels_ - 6, 1);
|
||||
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage1D(handle_, mip_levels_, format, size);
|
||||
|
||||
get_current_params_();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::texture(glm::ivec2 size)
|
||||
: handle_(NULL)
|
||||
, size_(size, 1)
|
||||
, samples_(1), mip_levels_(0)
|
||||
, depth_stencil_mode_()
|
||||
, base_mip_level_(), max_mip_level_()
|
||||
, border_color_()
|
||||
, compare_mode_(), compare_func_()
|
||||
, lod_min_(), lod_max_(), lod_bias_()
|
||||
, min_filter_(), mag_filter_()
|
||||
, swizzle_(), wrapping_()
|
||||
{
|
||||
static_assert(contains_enum<type, texture1DArray, texture2D, textureCubemap>::value);
|
||||
|
||||
mip_levels_ = static_cast<size_t>(glm::log2(static_cast<float>(min(size.x, size.y))));
|
||||
mip_levels_ = std::max(mip_levels_ - 6, 1);
|
||||
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage2D(handle_, mip_levels_, format, size.x, size.y);
|
||||
|
||||
get_current_params_();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::texture(glm::ivec2 size, size_t samples)
|
||||
: handle_(NULL)
|
||||
, size_(size, 1)
|
||||
, samples_(samples), mip_levels_(0)
|
||||
, depth_stencil_mode_()
|
||||
, base_mip_level_(), max_mip_level_()
|
||||
, border_color_()
|
||||
, compare_mode_(), compare_func_()
|
||||
, lod_min_(), lod_max_(), lod_bias_()
|
||||
, min_filter_(), mag_filter_()
|
||||
, swizzle_(), wrapping_()
|
||||
{
|
||||
static_assert(contains_enum<type, texture2DMS>::value);
|
||||
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage2DMultisample(handle_, samples, format, size.x, size.y, true);
|
||||
|
||||
get_current_params_();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::texture(glm::ivec3 size)
|
||||
: handle_(NULL)
|
||||
, size_(size)
|
||||
, samples_(1), mip_levels_(0)
|
||||
, depth_stencil_mode_()
|
||||
, base_mip_level_(), max_mip_level_()
|
||||
, border_color_()
|
||||
, compare_mode_(), compare_func_()
|
||||
, lod_min_(), lod_max_(), lod_bias_()
|
||||
, min_filter_(), mag_filter_()
|
||||
, swizzle_(), wrapping_()
|
||||
{
|
||||
static_assert(contains_enum<type, texture2DArray, textureCubemapArray, texture3D>::value);
|
||||
|
||||
mip_levels_ = static_cast<size_t>(glm::log2(static_cast<float>(min(size.x, size.y, size.z))));
|
||||
mip_levels_ = std::max(mip_levels_ - 6, 1);
|
||||
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage3D(handle_, mip_levels_, format, size.x, size.y, size.z);
|
||||
|
||||
get_current_params_();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::texture(glm::ivec3 size, size_t samples)
|
||||
: handle_(NULL)
|
||||
, size_(size)
|
||||
, samples_(samples), mip_levels_(0)
|
||||
, depth_stencil_mode_()
|
||||
, base_mip_level_(), max_mip_level_()
|
||||
, border_color_()
|
||||
, compare_mode_(), compare_func_()
|
||||
, lod_min_(), lod_max_(), lod_bias_()
|
||||
, min_filter_(), mag_filter_()
|
||||
, swizzle_(), wrapping_()
|
||||
{
|
||||
static_assert(contains_enum<type, texture2DMSArray>::value);
|
||||
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage3DMultisample(handle_, samples, format, size.x, size.y, size.z, true);
|
||||
|
||||
get_current_params_();
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::texture(texture&& move)
|
||||
: handle_(move.handle_)
|
||||
, size_(move.size_)
|
||||
, samples_(move.samples_)
|
||||
, mip_levels_(move.mip_levels_)
|
||||
, depth_stencil_mode_(move.depth_stencil_mode_)
|
||||
, base_mip_level_(move.base_mip_level_)
|
||||
, max_mip_level_(move.max_mip_level_)
|
||||
, border_color_(move.border_color_)
|
||||
, compare_mode_(move.compare_mode_)
|
||||
, compare_func_(move.compare_func_)
|
||||
, lod_min_(move.lod_min_)
|
||||
, lod_max_(move.lod_max_)
|
||||
, lod_bias_(move.lod_bias_)
|
||||
, min_filter_(move.min_filter_)
|
||||
, mag_filter_(move.mag_filter_)
|
||||
, swizzle_(move.swizzle_)
|
||||
, wrapping_(move.wrapping_)
|
||||
|
||||
{
|
||||
move.handle_ = 0;
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
texture<T_, PF_>::~texture()
|
||||
{
|
||||
if(handle_) glDeleteTextures(1, &handle_);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
void texture<T_, PF_>::resize(size_t size)
|
||||
{
|
||||
static_assert(contains_enum<type, texture1D>::value);
|
||||
|
||||
if(size == size_.x) return;
|
||||
|
||||
glDeleteTextures(1, &handle_);
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage1D(handle_, mip_levels_, format, size);
|
||||
size_ = glm::ivec3(size, 1, 1);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
void texture<T_, PF_>::resize(glm::ivec2 size)
|
||||
{
|
||||
static_assert(contains_enum<type, texture1DArray, texture2D, textureRect, textureCubemap>::value);
|
||||
|
||||
if(size.x == size_.x && size.y == size_.y) return;
|
||||
|
||||
glDeleteTextures(1, &handle_);
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage2D(handle_, mip_levels_, format, size.x, size.y);
|
||||
size_ = glm::ivec3(size, 1);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
void texture<T_, PF_>::resize(glm::ivec2 size, size_t samples)
|
||||
{
|
||||
static_assert(contains_enum<type, texture2DMS>::value);
|
||||
|
||||
if(size.x == size_.x && size.y == size_.y && samples == samples_) return;
|
||||
|
||||
glDeleteTextures(1, &handle_);
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage2DMultisample(handle_, samples_ = samples, format, size.x, size.y, true);
|
||||
size_ = glm::ivec3(size, 1);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
void texture<T_, PF_>::resize(glm::ivec3 size)
|
||||
{
|
||||
static_assert(contains_enum<type, texture2DArray, textureCubemapArray, texture3D>::value);
|
||||
|
||||
if(size.x == size_.x && size.y == size_.y && size.z == size_.z) return;
|
||||
|
||||
glDeleteTextures(1, &handle_);
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage3D(handle_, mip_levels_, format, size.x, size.y, size.z);
|
||||
size_ = glm::ivec3(size);
|
||||
}
|
||||
|
||||
template<enum_t T_, enum_t PF_>
|
||||
void texture<T_, PF_>::resize(glm::ivec3 size, size_t samples)
|
||||
{
|
||||
static_assert(contains_enum<type, texture2DMSArray>::value);
|
||||
|
||||
if(size.x == size_.x && size.y == size_.y && size.z == size_.z && samples == samples_) return;
|
||||
|
||||
glDeleteTextures(1, &handle_);
|
||||
glCreateTextures(type, 1, &handle_);
|
||||
glTextureStorage3DMultisample(handle_, samples_ = samples, format, size.x, size.y, size.z, true);
|
||||
size_ = glm::ivec3(size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // GLW_TEXTURE_H
|
83
texture_array.h
Executable file
83
texture_array.h
Executable file
@ -0,0 +1,83 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_TEXTURE_ARRAY_H
|
||||
#define GLW_TEXTURE_ARRAY_H
|
||||
|
||||
#include "common.h"
|
||||
#include "texture.h"
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
template<enum_t T_, enum_t...Fs_>
|
||||
class texarray
|
||||
{
|
||||
// Constants ===========================================================================================================
|
||||
|
||||
public:
|
||||
inline static constexpr enum_t type = T_;
|
||||
inline static constexpr size_t length = sizeof...(Fs_);
|
||||
|
||||
private:
|
||||
using array_type = std::tuple<texture<T_, Fs_>...>;
|
||||
|
||||
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
// Helpers
|
||||
template<int I = 0> void resize_(size_t size) { get<I>().resize(size); if constexpr (I < length - 1) resize_<I + 1>(size); }
|
||||
template<int I = 0> void resize_(glm::ivec2 size) { get<I>().resize(size); if constexpr (I < length - 1) resize_<I + 1>(size); }
|
||||
template<int I = 0> void resize_(glm::ivec2 size, size_t samples) { get<I>().resize(size); if constexpr (I < length - 1) resize_<I + 1>(size, samples); }
|
||||
template<int I = 0> void resize_(glm::ivec3 size) { get<I>().resize(size); if constexpr (I < length - 1) resize_<I + 1>(size); }
|
||||
template<int I = 0> void resize_(glm::ivec3 size, size_t samples) { get<I>().resize(size); if constexpr (I < length - 1) resize_<I + 1>(size, samples); }
|
||||
|
||||
public:
|
||||
texarray(size_t size) : array_(texture<T_, Fs_>{ size }...) { }
|
||||
texarray(glm::ivec2 size) : array_(texture<T_, Fs_>{ size }...) { }
|
||||
texarray(glm::ivec2 size, size_t samples) : array_(texture<T_, Fs_>{ size, samples }...) { }
|
||||
texarray(glm::ivec3 size) : array_(texture<T_, Fs_>{ size }...) { }
|
||||
texarray(glm::ivec3 size, size_t samples) : array_(texture<T_, Fs_>{ size, samples }...) { }
|
||||
|
||||
void resize(size_t size) { resize_(size); }
|
||||
void resize(glm::ivec2 size) { resize_(size); }
|
||||
void resize(glm::ivec2 size, size_t samples) { resize_(size, samples); }
|
||||
void resize(glm::ivec3 size) { resize_(size); }
|
||||
void resize(glm::ivec3 size, size_t samples) { resize_(size, samples); }
|
||||
|
||||
// Variables ===========================================================================================================
|
||||
|
||||
template <size_t _Index>
|
||||
constexpr std::tuple_element_t<_Index, array_type>& get() noexcept
|
||||
{
|
||||
return std::get<_Index>(array_);
|
||||
}
|
||||
|
||||
template <size_t _Index>
|
||||
constexpr const std::tuple_element_t<_Index, array_type>& get() const noexcept
|
||||
{
|
||||
return std::get<_Index>(array_);
|
||||
}
|
||||
|
||||
private:
|
||||
array_type array_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TEXTURE_ARRAY_H
|
62
timer.h
Executable file
62
timer.h
Executable file
@ -0,0 +1,62 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_TIMER_H
|
||||
#define GLW_TIMER_H
|
||||
|
||||
#include <cassert>
|
||||
#include "common.h"
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
class timer
|
||||
{
|
||||
private:
|
||||
enum
|
||||
{
|
||||
begin = 0
|
||||
, end = 1
|
||||
};
|
||||
|
||||
public:
|
||||
timer() : handles_{ 0 }, running_(false) { glCreateQueries(GL_TIMESTAMP, 2, handles_); }
|
||||
timer(const timer&) = delete;
|
||||
timer(timer&&) = default;
|
||||
~timer() { glDeleteQueries(2, handles_); }
|
||||
|
||||
void start() { assert(not running_); glQueryCounter(handles_[begin], GL_TIMESTAMP); running_ = true; }
|
||||
void stop() { assert(running_); glQueryCounter(handles_[end], GL_TIMESTAMP); running_ = false; }
|
||||
int64_t poll()
|
||||
{
|
||||
assert(not running_);
|
||||
int32_t available = false;
|
||||
while(not available) glGetQueryObjectiv(handles_[end], GL_QUERY_RESULT_AVAILABLE, &available);
|
||||
int64_t start; glGetQueryObjecti64v(handles_[begin], GL_QUERY_RESULT, &start);
|
||||
int64_t stop; glGetQueryObjecti64v(handles_[end], GL_QUERY_RESULT, &stop);
|
||||
return stop - start;
|
||||
}
|
||||
|
||||
private:
|
||||
handle_t handles_[2];
|
||||
bool running_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TIMER_H
|
114
vertex_descriptor.h
Executable file
114
vertex_descriptor.h
Executable file
@ -0,0 +1,114 @@
|
||||
// =====================================================================================================================
|
||||
// glw, an open-source library that wraps OpenGL structures into classes.
|
||||
// Copyright (C) 2024 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef GLW_VERTEX_DESCRIPTOR_H
|
||||
#define GLW_VERTEX_DESCRIPTOR_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <open-cpp-utils/dynarray.h>
|
||||
|
||||
namespace ocu = open_cpp_utils;
|
||||
|
||||
namespace glw
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Definitions
|
||||
// =====================================================================================================================
|
||||
|
||||
class vertex_descriptor
|
||||
{
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
private:
|
||||
struct attribute
|
||||
{
|
||||
size_t size;
|
||||
enum_t type;
|
||||
bool normalized;
|
||||
index_t offset;
|
||||
};
|
||||
|
||||
|
||||
// Functions ===========================================================================================================
|
||||
|
||||
public:
|
||||
vertex_descriptor();
|
||||
vertex_descriptor(const vertex_descriptor&);
|
||||
vertex_descriptor(vertex_descriptor&&) = default;
|
||||
~vertex_descriptor();
|
||||
|
||||
void add_attribute(enum_t type, size_t size, bool normalized);
|
||||
|
||||
void bind();
|
||||
|
||||
// Variables ===========================================================================================================
|
||||
|
||||
private:
|
||||
handle_t handle_;
|
||||
ocu::dynarray<attribute> attributes_;
|
||||
};
|
||||
|
||||
inline vertex_descriptor::vertex_descriptor()
|
||||
: handle_(NULL)
|
||||
{
|
||||
glCreateVertexArrays(1, &handle_);
|
||||
}
|
||||
|
||||
inline vertex_descriptor::vertex_descriptor(const vertex_descriptor& other)
|
||||
: handle_(NULL)
|
||||
{
|
||||
glCreateVertexArrays(1, &handle_);
|
||||
attributes_.reserve(other.attributes_.size());
|
||||
|
||||
for(const attribute& attrib : other.attributes_)
|
||||
{
|
||||
add_attribute(attrib.type, attrib.size, attrib.normalized);
|
||||
}
|
||||
}
|
||||
|
||||
inline vertex_descriptor::~vertex_descriptor()
|
||||
{
|
||||
glDeleteVertexArrays(1, &handle_);
|
||||
}
|
||||
|
||||
inline void vertex_descriptor::add_attribute(enum_t type, size_t size, bool normalized)
|
||||
{
|
||||
index_t offset = 0;
|
||||
|
||||
if(attributes_.empty() == false)
|
||||
{
|
||||
const attribute& prev = attributes_.back();
|
||||
offset = prev.offset + prev.size * size_of(prev.type);
|
||||
}
|
||||
|
||||
glEnableVertexArrayAttrib(handle_, attributes_.size());
|
||||
glVertexArrayAttribFormat(handle_, attributes_.size(), size, type, normalized, offset);
|
||||
|
||||
attributes_.push_back(attribute(size, type, normalized, offset));
|
||||
}
|
||||
|
||||
inline void vertex_descriptor::bind()
|
||||
{
|
||||
glBindVertexArray(handle_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //VERTEX_DESCRIPTOR_H
|
Loading…
x
Reference in New Issue
Block a user