@ -1,116 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <engine/geom/csg.hpp> | |||||
#include <tuple> | |||||
namespace geom { | |||||
namespace csg { | |||||
enum class polygon_classification | |||||
{ | |||||
coplanar, | |||||
front, | |||||
back, | |||||
spanning | |||||
}; | |||||
/** | |||||
* Classifies a polygon relative to a partitioning plane. | |||||
* | |||||
* @param partition Partitioning plane relative to which the polygon should be classified. | |||||
* @param poly Polygon to be classified. | |||||
* @return Classification of the polygon, relative to the plane. | |||||
*/ | |||||
static polygon_classification classify_polygon(const plane& partition, const polygon& poly) | |||||
{ | |||||
for (const float3& vertex: poly.vertices) | |||||
{ | |||||
} | |||||
return polygon_classification::coplanar; | |||||
} | |||||
/** | |||||
* Splits a polygon along a partitioning plane. | |||||
* | |||||
* @param poly Polygon to split. | |||||
* @param partition Partitioning plane along which the polygon should be split. | |||||
* @return List of polygons which were formed by splitting the specified polygon along the partitioning plane, along with their respective classifications relative to the partition. | |||||
*/ | |||||
std::list<std::tuple<polygon, polygon_classification>> split_polygon(const polygon& poly, const plane& partition) | |||||
{ | |||||
return {}; | |||||
} | |||||
bsp_tree::bsp_tree(const std::list<polygon>& polygons): | |||||
front(nullptr), | |||||
back(nullptr) | |||||
{ | |||||
//partition = polygons.front(); | |||||
std::list<polygon> front_polygons; | |||||
std::list<polygon> back_polygons; | |||||
// Classify all polygons relative to this node's partitioning plane | |||||
for (const polygon& p: polygons) | |||||
{ | |||||
polygon_classification classification = classify_polygon(partition, p); | |||||
switch (classification) | |||||
{ | |||||
case polygon_classification::coplanar: | |||||
coplanar_polygons.push_back(p); | |||||
break; | |||||
case polygon_classification::front: | |||||
front_polygons.push_back(p); | |||||
break; | |||||
case polygon_classification::back: | |||||
back_polygons.push_back(p); | |||||
break; | |||||
case polygon_classification::spanning: | |||||
break; | |||||
} | |||||
} | |||||
if (!front_polygons.empty()) | |||||
{ | |||||
// Make subtree containing all polygons in front of this node's plane | |||||
front = new bsp_tree(front_polygons); | |||||
} | |||||
if (!back_polygons.empty()) | |||||
{ | |||||
// Make subtree containing all polygons behind this node's plane | |||||
back = new bsp_tree(back_polygons); | |||||
} | |||||
} | |||||
bsp_tree::~bsp_tree() | |||||
{ | |||||
delete front; | |||||
delete back; | |||||
} | |||||
} // namespace csg | |||||
} // namespace geom |
@ -1,88 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_GEOM_CSG_HPP | |||||
#define ANTKEEPER_GEOM_CSG_HPP | |||||
#include <engine/utility/fundamental-types.hpp> | |||||
#include <list> | |||||
namespace geom { | |||||
/// Constructive solid geometry (CSG) | |||||
namespace csg { | |||||
struct plane | |||||
{ | |||||
float3 normal; | |||||
float distance; | |||||
}; | |||||
struct polygon | |||||
{ | |||||
std::list<float3> vertices; | |||||
void* shared; | |||||
}; | |||||
/** | |||||
* 3D solid represented by a collection of polygons. | |||||
*/ | |||||
typedef std::list<polygon> solid; | |||||
/** | |||||
* BSP tree node. | |||||
*/ | |||||
class bsp_tree | |||||
{ | |||||
public: | |||||
/** | |||||
* Recursively constructs a BSP tree from a collection of polygons. | |||||
* | |||||
* @param polygons Collection of polygons from which to create the BSP tree. | |||||
*/ | |||||
explicit bsp_tree(const std::list<polygon>& polygons); | |||||
/** | |||||
* Destroys a BSP tree. | |||||
*/ | |||||
~bsp_tree(); | |||||
private: | |||||
/// Partition which separates the front and back polygons. | |||||
plane partition; | |||||
/// Set of polygons which are coplanar with the partition. | |||||
std::list<polygon> coplanar_polygons; | |||||
/// Subtree containing all polygons in front of the partition. | |||||
bsp_tree* front; | |||||
/// Subtree containing all polygons behind the partition. | |||||
bsp_tree* back; | |||||
}; | |||||
solid op_union(const solid& a, const solid& b); | |||||
solid op_difference(const solid& a, const solid& b); | |||||
solid op_intersect(const solid& a, const solid& b); | |||||
} // namespace csg | |||||
} // namespace geom | |||||
#endif // ANTKEEPER_GEOM_CSG_HPP | |||||
@ -0,0 +1,666 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <engine/gl/opengl/gl-shader-variables.hpp> | |||||
#include <engine/gl/texture-1d.hpp> | |||||
#include <engine/gl/texture-2d.hpp> | |||||
#include <engine/gl/texture-3d.hpp> | |||||
#include <engine/gl/texture-cube.hpp> | |||||
#include <numeric> | |||||
namespace gl { | |||||
gl_shader_bool::gl_shader_bool(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
ivalues(size) | |||||
{} | |||||
void gl_shader_bool::update(bool value) const noexcept | |||||
{ | |||||
glUniform1i(gl_uniform_location, static_cast<GLint>(value)); | |||||
} | |||||
void gl_shader_bool::update(bool value, std::size_t index) const | |||||
{ | |||||
glUniform1i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value)); | |||||
} | |||||
void gl_shader_bool::update(std::span<const bool> values, std::size_t index) const | |||||
{ | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
ivalues[i] = static_cast<GLint>(values[i]); | |||||
} | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data()); | |||||
} | |||||
gl_shader_bool2::gl_shader_bool2(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
ivalues(size * 2) | |||||
{} | |||||
void gl_shader_bool2::update(const bool2& value) const noexcept | |||||
{ | |||||
glUniform2i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1])); | |||||
} | |||||
void gl_shader_bool2::update(const bool2& value, std::size_t index) const | |||||
{ | |||||
glUniform2i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1])); | |||||
} | |||||
void gl_shader_bool2::update(std::span<const bool2> values, std::size_t index) const | |||||
{ | |||||
GLint* ivalue = ivalues.data(); | |||||
for (const auto& value: values) | |||||
{ | |||||
*(++ivalue) = static_cast<GLint>(value[0]); | |||||
*(++ivalue) = static_cast<GLint>(value[1]); | |||||
} | |||||
glUniform2iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data()); | |||||
} | |||||
gl_shader_bool3::gl_shader_bool3(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
ivalues(size * 3) | |||||
{} | |||||
void gl_shader_bool3::update(const bool3& value) const noexcept | |||||
{ | |||||
glUniform3i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2])); | |||||
} | |||||
void gl_shader_bool3::update(const bool3& value, std::size_t index) const | |||||
{ | |||||
glUniform3i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2])); | |||||
} | |||||
void gl_shader_bool3::update(std::span<const bool3> values, std::size_t index) const | |||||
{ | |||||
GLint* ivalue = ivalues.data(); | |||||
for (const auto& value: values) | |||||
{ | |||||
*(++ivalue) = static_cast<GLint>(value[0]); | |||||
*(++ivalue) = static_cast<GLint>(value[1]); | |||||
*(++ivalue) = static_cast<GLint>(value[2]); | |||||
} | |||||
glUniform3iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data()); | |||||
} | |||||
gl_shader_bool4::gl_shader_bool4(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
ivalues(size * 4) | |||||
{} | |||||
void gl_shader_bool4::update(const bool4& value) const noexcept | |||||
{ | |||||
glUniform4i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]), static_cast<GLint>(value[3])); | |||||
} | |||||
void gl_shader_bool4::update(const bool4& value, std::size_t index) const | |||||
{ | |||||
glUniform4i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]), static_cast<GLint>(value[3])); | |||||
} | |||||
void gl_shader_bool4::update(std::span<const bool4> values, std::size_t index) const | |||||
{ | |||||
GLint* ivalue = ivalues.data(); | |||||
for (const auto& value: values) | |||||
{ | |||||
*(++ivalue) = static_cast<GLint>(value[0]); | |||||
*(++ivalue) = static_cast<GLint>(value[1]); | |||||
*(++ivalue) = static_cast<GLint>(value[2]); | |||||
*(++ivalue) = static_cast<GLint>(value[3]); | |||||
} | |||||
glUniform4iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data()); | |||||
} | |||||
gl_shader_int::gl_shader_int(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_int::update(int value) const noexcept | |||||
{ | |||||
glUniform1i(gl_uniform_location, value); | |||||
} | |||||
void gl_shader_int::update(int value, std::size_t index) const | |||||
{ | |||||
glUniform1i(gl_uniform_location + static_cast<GLint>(index), value); | |||||
} | |||||
void gl_shader_int::update(std::span<const int> values, std::size_t index) const | |||||
{ | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()); | |||||
} | |||||
gl_shader_int2::gl_shader_int2(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_int2::update(const int2& value) const noexcept | |||||
{ | |||||
glUniform2iv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_int2::update(const int2& value, std::size_t index) const | |||||
{ | |||||
glUniform2iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_int2::update(std::span<const int2> values, std::size_t index) const | |||||
{ | |||||
glUniform2iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_int3::gl_shader_int3(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_int3::update(const int3& value) const noexcept | |||||
{ | |||||
glUniform3iv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_int3::update(const int3& value, std::size_t index) const | |||||
{ | |||||
glUniform3iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_int3::update(std::span<const int3> values, std::size_t index) const | |||||
{ | |||||
glUniform3iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_int4::gl_shader_int4(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_int4::update(const int4& value) const noexcept | |||||
{ | |||||
glUniform4iv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_int4::update(const int4& value, std::size_t index) const | |||||
{ | |||||
glUniform4iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_int4::update(std::span<const int4> values, std::size_t index) const | |||||
{ | |||||
glUniform4iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_uint::gl_shader_uint(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_uint::update(unsigned int value) const noexcept | |||||
{ | |||||
glUniform1ui(gl_uniform_location, value); | |||||
} | |||||
void gl_shader_uint::update(unsigned int value, std::size_t index) const | |||||
{ | |||||
glUniform1ui(gl_uniform_location + static_cast<GLint>(index), value); | |||||
} | |||||
void gl_shader_uint::update(std::span<const unsigned int> values, std::size_t index) const | |||||
{ | |||||
glUniform1uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()); | |||||
} | |||||
gl_shader_uint2::gl_shader_uint2(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_uint2::update(const uint2& value) const noexcept | |||||
{ | |||||
glUniform2uiv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_uint2::update(const uint2& value, std::size_t index) const | |||||
{ | |||||
glUniform2uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_uint2::update(std::span<const uint2> values, std::size_t index) const | |||||
{ | |||||
glUniform2uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_uint3::gl_shader_uint3(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_uint3::update(const uint3& value) const noexcept | |||||
{ | |||||
glUniform3uiv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_uint3::update(const uint3& value, std::size_t index) const | |||||
{ | |||||
glUniform3uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_uint3::update(std::span<const uint3> values, std::size_t index) const | |||||
{ | |||||
glUniform3uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_uint4::gl_shader_uint4(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_uint4::update(const uint4& value) const noexcept | |||||
{ | |||||
glUniform4uiv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_uint4::update(const uint4& value, std::size_t index) const | |||||
{ | |||||
glUniform4uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_uint4::update(std::span<const uint4> values, std::size_t index) const | |||||
{ | |||||
glUniform4uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_float::gl_shader_float(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float::update(float value) const noexcept | |||||
{ | |||||
glUniform1f(gl_uniform_location, value); | |||||
} | |||||
void gl_shader_float::update(float value, std::size_t index) const | |||||
{ | |||||
glUniform1f(gl_uniform_location + static_cast<GLint>(index), value); | |||||
} | |||||
void gl_shader_float::update(std::span<const float> values, std::size_t index) const | |||||
{ | |||||
glUniform1fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()); | |||||
} | |||||
gl_shader_float2::gl_shader_float2(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float2::update(const float2& value) const noexcept | |||||
{ | |||||
glUniform2fv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_float2::update(const float2& value, std::size_t index) const | |||||
{ | |||||
glUniform2fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_float2::update(std::span<const float2> values, std::size_t index) const | |||||
{ | |||||
glUniform2fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_float3::gl_shader_float3(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float3::update(const float3& value) const noexcept | |||||
{ | |||||
glUniform3fv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_float3::update(const float3& value, std::size_t index) const | |||||
{ | |||||
glUniform3fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_float3::update(std::span<const float3> values, std::size_t index) const | |||||
{ | |||||
glUniform3fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_float4::gl_shader_float4(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float4::update(const float4& value) const noexcept | |||||
{ | |||||
glUniform4fv(gl_uniform_location, 1, value.data()); | |||||
} | |||||
void gl_shader_float4::update(const float4& value, std::size_t index) const | |||||
{ | |||||
glUniform4fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data()); | |||||
} | |||||
void gl_shader_float4::update(std::span<const float4> values, std::size_t index) const | |||||
{ | |||||
glUniform4fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data()); | |||||
} | |||||
gl_shader_float2x2::gl_shader_float2x2(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float2x2::update(const float2x2& value) const noexcept | |||||
{ | |||||
glUniformMatrix2fv(gl_uniform_location, 1, GL_FALSE, value.data()); | |||||
} | |||||
void gl_shader_float2x2::update(const float2x2& value, std::size_t index) const | |||||
{ | |||||
glUniformMatrix2fv(gl_uniform_location + static_cast<GLint>(index) * 2, 1, GL_FALSE, value.data()); | |||||
} | |||||
void gl_shader_float2x2::update(std::span<const float2x2> values, std::size_t index) const | |||||
{ | |||||
glUniformMatrix2fv(gl_uniform_location + static_cast<GLint>(index) * 2, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data()); | |||||
} | |||||
gl_shader_float3x3::gl_shader_float3x3(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float3x3::update(const float3x3& value) const noexcept | |||||
{ | |||||
glUniformMatrix3fv(gl_uniform_location, 1, GL_FALSE, value.data()); | |||||
} | |||||
void gl_shader_float3x3::update(const float3x3& value, std::size_t index) const | |||||
{ | |||||
glUniformMatrix3fv(gl_uniform_location + static_cast<GLint>(index) * 3, 1, GL_FALSE, value.data()); | |||||
} | |||||
void gl_shader_float3x3::update(std::span<const float3x3> values, std::size_t index) const | |||||
{ | |||||
glUniformMatrix3fv(gl_uniform_location + static_cast<GLint>(index) * 3, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data()); | |||||
} | |||||
gl_shader_float4x4::gl_shader_float4x4(std::size_t size, GLint gl_uniform_location): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location} | |||||
{} | |||||
void gl_shader_float4x4::update(const float4x4& value) const noexcept | |||||
{ | |||||
glUniformMatrix4fv(gl_uniform_location, 1, GL_FALSE, value.data()); | |||||
} | |||||
void gl_shader_float4x4::update(const float4x4& value, std::size_t index) const | |||||
{ | |||||
glUniformMatrix4fv(gl_uniform_location + static_cast<GLint>(index) * 4, 1, GL_FALSE, value.data()); | |||||
} | |||||
void gl_shader_float4x4::update(std::span<const float4x4> values, std::size_t index) const | |||||
{ | |||||
glUniformMatrix4fv(gl_uniform_location + static_cast<GLint>(index) * 4, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data()); | |||||
} | |||||
gl_shader_texture_1d::gl_shader_texture_1d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
gl_texture_unit_indices(size) | |||||
{ | |||||
std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index); | |||||
} | |||||
void gl_shader_texture_1d::update(const texture_1d& value) const noexcept | |||||
{ | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front())); | |||||
glBindTexture(GL_TEXTURE_1D, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location, gl_texture_unit_indices.front()); | |||||
} | |||||
void gl_shader_texture_1d::update(const texture_1d& value, std::size_t index) const | |||||
{ | |||||
const GLint gl_texture_index = gl_texture_unit_indices[index]; | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index)); | |||||
glBindTexture(GL_TEXTURE_1D, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index); | |||||
} | |||||
void gl_shader_texture_1d::update(std::span<const texture_1d* const> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_1D, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
void gl_shader_texture_1d::update(std::span<const std::shared_ptr<texture_1d>> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_1D, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
gl_shader_texture_2d::gl_shader_texture_2d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
gl_texture_unit_indices(size) | |||||
{ | |||||
std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index); | |||||
} | |||||
void gl_shader_texture_2d::update(const texture_2d& value) const noexcept | |||||
{ | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front())); | |||||
glBindTexture(GL_TEXTURE_2D, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location, gl_texture_unit_indices.front()); | |||||
} | |||||
void gl_shader_texture_2d::update(const texture_2d& value, std::size_t index) const | |||||
{ | |||||
const GLint gl_texture_index = gl_texture_unit_indices[index]; | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index)); | |||||
glBindTexture(GL_TEXTURE_2D, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index); | |||||
} | |||||
void gl_shader_texture_2d::update(std::span<const texture_2d* const> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_2D, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
void gl_shader_texture_2d::update(std::span<const std::shared_ptr<texture_2d>> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_2D, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
gl_shader_texture_3d::gl_shader_texture_3d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
gl_texture_unit_indices(size) | |||||
{ | |||||
std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index); | |||||
} | |||||
void gl_shader_texture_3d::update(const texture_3d& value) const noexcept | |||||
{ | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front())); | |||||
glBindTexture(GL_TEXTURE_3D, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location, gl_texture_unit_indices.front()); | |||||
} | |||||
void gl_shader_texture_3d::update(const texture_3d& value, std::size_t index) const | |||||
{ | |||||
const GLint gl_texture_index = gl_texture_unit_indices[index]; | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index)); | |||||
glBindTexture(GL_TEXTURE_3D, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index); | |||||
} | |||||
void gl_shader_texture_3d::update(std::span<const texture_3d* const> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_3D, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
void gl_shader_texture_3d::update(std::span<const std::shared_ptr<texture_3d>> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_3D, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
gl_shader_texture_cube::gl_shader_texture_cube(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index): | |||||
shader_variable(size), | |||||
gl_uniform_location{gl_uniform_location}, | |||||
gl_texture_unit_indices(size) | |||||
{ | |||||
std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index); | |||||
} | |||||
void gl_shader_texture_cube::update(const texture_cube& value) const noexcept | |||||
{ | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front())); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location, gl_texture_unit_indices.front()); | |||||
} | |||||
void gl_shader_texture_cube::update(const texture_cube& value, std::size_t index) const | |||||
{ | |||||
const GLint gl_texture_index = gl_texture_unit_indices[index]; | |||||
// Bind texture to texture unit | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index)); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, value.gl_texture_id); | |||||
// Pass texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index); | |||||
} | |||||
void gl_shader_texture_cube::update(std::span<const texture_cube* const> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
void gl_shader_texture_cube::update(std::span<const std::shared_ptr<texture_cube>> values, std::size_t index) const | |||||
{ | |||||
// Bind textures | |||||
for (std::size_t i = 0; i < values.size(); ++i) | |||||
{ | |||||
glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i])); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, values[i]->gl_texture_id); | |||||
} | |||||
// Pass texture unit indices to shader | |||||
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]); | |||||
} | |||||
} // namespace gl |
@ -0,0 +1,526 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_GL_GL_SHADER_VARIABLES_HPP | |||||
#define ANTKEEPER_GL_GL_SHADER_VARIABLES_HPP | |||||
#include <engine/gl/shader-variable.hpp> | |||||
#include <glad/glad.h> | |||||
#include <vector> | |||||
namespace gl { | |||||
/** | |||||
* Boolean shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_bool: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_bool(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::bool1; | |||||
} | |||||
void update(bool value) const noexcept override; | |||||
void update(bool value, std::size_t index) const override; | |||||
void update(std::span<const bool> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
mutable std::vector<GLint> ivalues; | |||||
}; | |||||
/** | |||||
* 2-dimensional boolean vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_bool2: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_bool2(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::bool2; | |||||
} | |||||
void update(const bool2& value) const noexcept override; | |||||
void update(const bool2& value, std::size_t index) const override; | |||||
void update(std::span<const bool2> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
mutable std::vector<GLint> ivalues; | |||||
}; | |||||
/** | |||||
* 3-dimensional boolean vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_bool3: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_bool3(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::bool3; | |||||
} | |||||
void update(const bool3& value) const noexcept override; | |||||
void update(const bool3& value, std::size_t index) const override; | |||||
void update(std::span<const bool3> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
mutable std::vector<GLint> ivalues; | |||||
}; | |||||
/** | |||||
* 4-dimensional boolean vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_bool4: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_bool4(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::bool4; | |||||
} | |||||
void update(const bool4& value) const noexcept override; | |||||
void update(const bool4& value, std::size_t index) const override; | |||||
void update(std::span<const bool4> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
mutable std::vector<GLint> ivalues; | |||||
}; | |||||
/** | |||||
* Signed integer shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_int: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_int(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::int1; | |||||
} | |||||
void update(int value) const noexcept override; | |||||
void update(int value, std::size_t index) const override; | |||||
void update(std::span<const int> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 2-dimensional signed integer vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_int2: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_int2(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::int2; | |||||
} | |||||
void update(const int2& value) const noexcept override; | |||||
void update(const int2& value, std::size_t index) const override; | |||||
void update(std::span<const int2> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 3-dimensional signed integer vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_int3: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_int3(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::int3; | |||||
} | |||||
void update(const int3& value) const noexcept override; | |||||
void update(const int3& value, std::size_t index) const override; | |||||
void update(std::span<const int3> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 4-dimensional signed integer vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_int4: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_int4(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::int4; | |||||
} | |||||
void update(const int4& value) const noexcept override; | |||||
void update(const int4& value, std::size_t index) const override; | |||||
void update(std::span<const int4> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* Unsigned integer shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_uint: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_uint(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::uint1; | |||||
} | |||||
void update(unsigned int value) const noexcept override; | |||||
void update(unsigned int value, std::size_t index) const override; | |||||
void update(std::span<const unsigned int> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 2-dimensional unsigned integer vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_uint2: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_uint2(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::uint2; | |||||
} | |||||
void update(const uint2& value) const noexcept override; | |||||
void update(const uint2& value, std::size_t index) const override; | |||||
void update(std::span<const uint2> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 3-dimensional unsigned integer vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_uint3: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_uint3(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::uint3; | |||||
} | |||||
void update(const uint3& value) const noexcept override; | |||||
void update(const uint3& value, std::size_t index) const override; | |||||
void update(std::span<const uint3> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 4-dimensional unsigned integer vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_uint4: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_uint4(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::uint4; | |||||
} | |||||
void update(const uint4& value) const noexcept override; | |||||
void update(const uint4& value, std::size_t index) const override; | |||||
void update(std::span<const uint4> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* Floating-point shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float1; | |||||
} | |||||
void update(float value) const noexcept override; | |||||
void update(float value, std::size_t index) const override; | |||||
void update(std::span<const float> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 2-dimensional floating-point vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float2: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float2(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float2; | |||||
} | |||||
void update(const float2& value) const noexcept override; | |||||
void update(const float2& value, std::size_t index) const override; | |||||
void update(std::span<const float2> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 3-dimensional floating-point vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float3: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float3(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float3; | |||||
} | |||||
void update(const float3& value) const noexcept override; | |||||
void update(const float3& value, std::size_t index) const override; | |||||
void update(std::span<const float3> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 4-dimensional floating-point vector shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float4: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float4(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float4; | |||||
} | |||||
void update(const float4& value) const noexcept override; | |||||
void update(const float4& value, std::size_t index) const override; | |||||
void update(std::span<const float4> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 2x2 floating-point matrix shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float2x2: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float2x2(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float2x2; | |||||
} | |||||
void update(const float2x2& value) const noexcept override; | |||||
void update(const float2x2& value, std::size_t index) const override; | |||||
void update(std::span<const float2x2> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 3x3 floating-point matrix shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float3x3: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float3x3(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float3x3; | |||||
} | |||||
void update(const float3x3& value) const noexcept override; | |||||
void update(const float3x3& value, std::size_t index) const override; | |||||
void update(std::span<const float3x3> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 4x4 floating-point matrix shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_float4x4: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_float4x4(std::size_t size, GLint gl_uniform_location); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::float4x4; | |||||
} | |||||
void update(const float4x4& value) const noexcept override; | |||||
void update(const float4x4& value, std::size_t index) const override; | |||||
void update(std::span<const float4x4> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
}; | |||||
/** | |||||
* 1-dimensional texture shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_texture_1d: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_texture_1d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_index); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::texture_1d; | |||||
} | |||||
void update(const texture_1d& value) const noexcept override; | |||||
void update(const texture_1d& value, std::size_t index) const override; | |||||
void update(std::span<const texture_1d* const> values, std::size_t index = 0) const override; | |||||
void update(std::span<const std::shared_ptr<texture_1d>> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
std::vector<GLint> gl_texture_unit_indices; | |||||
}; | |||||
/** | |||||
* 2-dimensional texture shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_texture_2d: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_texture_2d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::texture_2d; | |||||
} | |||||
void update(const texture_2d& value) const noexcept override; | |||||
void update(const texture_2d& value, std::size_t index) const override; | |||||
void update(std::span<const texture_2d* const> values, std::size_t index = 0) const override; | |||||
void update(std::span<const std::shared_ptr<texture_2d>> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
std::vector<GLint> gl_texture_unit_indices; | |||||
}; | |||||
/** | |||||
* 3-dimensional texture shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_texture_3d: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_texture_3d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_index); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::texture_3d; | |||||
} | |||||
void update(const texture_3d& value) const noexcept override; | |||||
void update(const texture_3d& value, std::size_t index) const override; | |||||
void update(std::span<const texture_3d* const> values, std::size_t index = 0) const override; | |||||
void update(std::span<const std::shared_ptr<texture_3d>> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
std::vector<GLint> gl_texture_unit_indices; | |||||
}; | |||||
/** | |||||
* Cube texture shader variable implementation using OpenGL. | |||||
*/ | |||||
class gl_shader_texture_cube: public shader_variable | |||||
{ | |||||
public: | |||||
gl_shader_texture_cube(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_index); | |||||
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override | |||||
{ | |||||
return shader_variable_type::texture_cube; | |||||
} | |||||
void update(const texture_cube& value) const noexcept override; | |||||
void update(const texture_cube& value, std::size_t index) const override; | |||||
void update(std::span<const texture_cube* const> values, std::size_t index = 0) const override; | |||||
void update(std::span<const std::shared_ptr<texture_cube>> values, std::size_t index = 0) const override; | |||||
private: | |||||
GLint gl_uniform_location; | |||||
std::vector<GLint> gl_texture_unit_indices; | |||||
}; | |||||
} // namespace gl | |||||
#endif // ANTKEEPER_GL_GL_SHADER_VARIABLES_HPP |
@ -1,773 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <engine/gl/shader-input.hpp> | |||||
#include <engine/gl/texture-1d.hpp> | |||||
#include <engine/gl/texture-2d.hpp> | |||||
#include <engine/gl/texture-3d.hpp> | |||||
#include <engine/gl/texture-cube.hpp> | |||||
#include <glad/glad.h> | |||||
namespace gl { | |||||
shader_input::shader_input(shader_program* program, std::size_t input_index, int gl_uniform_location, const std::string& name, shader_variable_type data_type, std::size_t element_count, int texture_unit): | |||||
program(program), | |||||
input_index(input_index), | |||||
gl_uniform_location(gl_uniform_location), | |||||
name(name), | |||||
data_type(data_type), | |||||
element_count(element_count), | |||||
texture_unit(texture_unit) | |||||
{} | |||||
shader_input::~shader_input() | |||||
{} | |||||
bool shader_input::upload(const bool& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1i(gl_uniform_location, static_cast<GLint>(value)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const bool2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
const GLint values[] = {value[0], value[1]}; | |||||
glUniform2iv(gl_uniform_location, 1, values); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const bool3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
const GLint values[] = {value[0], value[1], value[2]}; | |||||
glUniform3iv(gl_uniform_location, 1, values); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const bool4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
const GLint values[] = {value[0], value[1], value[2], value[3]}; | |||||
glUniform4iv(gl_uniform_location, 1, values); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const int& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1i(gl_uniform_location, value); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const int2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2iv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const int3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3iv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const int4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4iv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const unsigned int& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1ui(gl_uniform_location, value); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const uint2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2uiv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const uint3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3uiv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const uint4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4uiv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1f(gl_uniform_location, value); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2fv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3fv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4fv(gl_uniform_location, 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float2x2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix2fv(gl_uniform_location, 1, GL_FALSE, value[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float3x3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix3fv(gl_uniform_location, 1, GL_FALSE, value[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const float4x4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix4fv(gl_uniform_location, 1, GL_FALSE, value[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const texture_1d* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit); | |||||
glBindTexture(GL_TEXTURE_1D, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location, texture_unit); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const texture_2d* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit); | |||||
glBindTexture(GL_TEXTURE_2D, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location, texture_unit); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const texture_3d* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit); | |||||
glBindTexture(GL_TEXTURE_3D, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location, texture_unit); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(const texture_cube* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location, texture_unit); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index), static_cast<GLint>(value)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
const GLint values[] = {value[0], value[1]}; | |||||
glUniform2iv(gl_uniform_location + static_cast<int>(index), 1, values); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
const GLint values[] = {value[0], value[1], value[3]}; | |||||
glUniform3iv(gl_uniform_location + static_cast<int>(index), 1, values); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
const GLint values[] = {value[0], value[1], value[3], value[4]}; | |||||
glUniform4iv(gl_uniform_location + static_cast<int>(index), 1, values); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index), value); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2iv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3iv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4iv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const unsigned int& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1ui(gl_uniform_location + static_cast<int>(index), value); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const uint2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2uiv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const uint3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3uiv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const uint4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4uiv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1f(gl_uniform_location + static_cast<int>(index), value); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2fv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3fv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4fv(gl_uniform_location + static_cast<int>(index), 1, value.data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float2x2& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix2fv(gl_uniform_location + static_cast<int>(index) * 2, 1, GL_FALSE, value[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float3x3& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix3fv(gl_uniform_location + static_cast<int>(index) * 3, 1, GL_FALSE, value[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float4x4& value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix4fv(gl_uniform_location + static_cast<int>(index) * 4, 1, GL_FALSE, value[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_1d* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index)); | |||||
glBindTexture(GL_TEXTURE_1D, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index), texture_unit + static_cast<int>(index)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_2d* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index)); | |||||
glBindTexture(GL_TEXTURE_2D, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index), texture_unit + static_cast<int>(index)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_3d* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index)); | |||||
glBindTexture(GL_TEXTURE_3D, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index), texture_unit + static_cast<int>(index)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_cube* value) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index)); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, value->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index), texture_unit + static_cast<int>(index)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
int* int_values = new int[count]; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
int_values[i] = values[i]; | |||||
glUniform1iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &(*int_values)); | |||||
delete[] int_values; | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool2* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
int2* int2_values = new int2[count]; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
int2_values[i] = {values[i][0], values[i][1]}; | |||||
glUniform2iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &((*int2_values)[0])); | |||||
delete[] int2_values; | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool3* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
int3* int3_values = new int3[count]; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
int3_values[i] = {values[i][0], values[i][1], values[i][2]}; | |||||
glUniform3iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &((*int3_values)[0])); | |||||
delete[] int3_values; | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const bool4* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
int4* int4_values = new int4[count]; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
int4_values[i] = {values[i][0], values[i][1], values[i][2], values[i][3]}; | |||||
glUniform4iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &((*int4_values)[0])); | |||||
delete[] int4_values; | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &(*values)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int2* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int3* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const int4* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4iv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const unsigned int* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1uiv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &(*values)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const uint2* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2uiv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const uint3* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3uiv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const uint4* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4uiv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform1fv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), &(*values)); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float2* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform2fv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float3* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform3fv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float4* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniform4fv(gl_uniform_location + static_cast<int>(index), static_cast<GLsizei>(count), (*values).data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float2x2* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix2fv(gl_uniform_location + static_cast<int>(index) * 2, static_cast<GLsizei>(count), GL_FALSE, (*values)[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float3x3* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix3fv(gl_uniform_location + static_cast<int>(index) * 3, static_cast<GLsizei>(count), GL_FALSE, (*values)[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const float4x4* values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
glUniformMatrix4fv(gl_uniform_location + static_cast<int>(index) * 4, static_cast<GLsizei>(count), GL_FALSE, (*values)[0].data()); | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_1d** values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
{ | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index + i)); | |||||
glBindTexture(GL_TEXTURE_1D, values[i]->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index + i), texture_unit + static_cast<int>(index + i)); | |||||
} | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_2d** values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
{ | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index + i)); | |||||
glBindTexture(GL_TEXTURE_2D, values[i]->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index + i), texture_unit + static_cast<int>(index + i)); | |||||
} | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_3d** values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
{ | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index + i)); | |||||
glBindTexture(GL_TEXTURE_3D, values[i]->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index + i), texture_unit + static_cast<int>(index + i)); | |||||
} | |||||
return true; | |||||
} | |||||
bool shader_input::upload(std::size_t index, const texture_cube** values, std::size_t count) const | |||||
{ | |||||
if (gl_uniform_location == -1) | |||||
return false; | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
{ | |||||
// Bind texture to a texture unit reserved by this shader input | |||||
glActiveTexture(GL_TEXTURE0 + texture_unit + static_cast<int>(index + i)); | |||||
glBindTexture(GL_TEXTURE_CUBE_MAP, values[i]->gl_texture_id); | |||||
// Upload texture unit index to shader | |||||
glUniform1i(gl_uniform_location + static_cast<int>(index + i), texture_unit + static_cast<int>(index + i)); | |||||
} | |||||
return true; | |||||
} | |||||
} // namespace gl |
@ -1,202 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_GL_SHADER_INPUT_HPP | |||||
#define ANTKEEPER_GL_SHADER_INPUT_HPP | |||||
#include <engine/utility/fundamental-types.hpp> | |||||
#include <string> | |||||
namespace gl { | |||||
class shader_program; | |||||
class texture_1d; | |||||
class texture_2d; | |||||
class texture_3d; | |||||
class texture_cube; | |||||
enum class shader_variable_type; | |||||
/** | |||||
* Port through which data can be uploaded to shader variables. | |||||
*/ | |||||
class shader_input | |||||
{ | |||||
public: | |||||
/** | |||||
* Returns the type of data which can be passed through this input. | |||||
*/ | |||||
shader_variable_type get_data_type() const; | |||||
/** | |||||
* Returns `true` if the input data is stored in an array. | |||||
*/ | |||||
bool is_array() const; | |||||
/** | |||||
* Returns the number of elements the array can contain, or `1` if the data is not stored in an array. | |||||
*/ | |||||
std::size_t get_element_count() const; | |||||
/** | |||||
* Uploads a value to the shader. | |||||
* | |||||
* @param value Value to upload. | |||||
* @return `true` if the value was uploaded successfully, `false` otherwise. | |||||
*/ | |||||
///@{ | |||||
bool upload(const bool& value) const; | |||||
bool upload(const bool2& value) const; | |||||
bool upload(const bool3& value) const; | |||||
bool upload(const bool4& value) const; | |||||
bool upload(const int& value) const; | |||||
bool upload(const int2& value) const; | |||||
bool upload(const int3& value) const; | |||||
bool upload(const int4& value) const; | |||||
bool upload(const unsigned int& value) const; | |||||
bool upload(const uint2& value) const; | |||||
bool upload(const uint3& value) const; | |||||
bool upload(const uint4& value) const; | |||||
bool upload(const float& value) const; | |||||
bool upload(const float2& value) const; | |||||
bool upload(const float3& value) const; | |||||
bool upload(const float4& value) const; | |||||
bool upload(const float2x2& value) const; | |||||
bool upload(const float3x3& value) const; | |||||
bool upload(const float4x4& value) const; | |||||
bool upload(const texture_1d* value) const; | |||||
bool upload(const texture_2d* value) const; | |||||
bool upload(const texture_3d* value) const; | |||||
bool upload(const texture_cube* value) const; | |||||
///@} | |||||
/** | |||||
* Uploads a single array element to the shader. | |||||
* | |||||
* @param index Index of an array element. | |||||
* @param values Value to upload. | |||||
* @return `true` if the value was uploaded successfully, `false` otherwise. | |||||
*/ | |||||
///@{ | |||||
bool upload(std::size_t index, const bool& value) const; | |||||
bool upload(std::size_t index, const bool2& value) const; | |||||
bool upload(std::size_t index, const bool3& value) const; | |||||
bool upload(std::size_t index, const bool4& value) const; | |||||
bool upload(std::size_t index, const int& value) const; | |||||
bool upload(std::size_t index, const int2& value) const; | |||||
bool upload(std::size_t index, const int3& value) const; | |||||
bool upload(std::size_t index, const int4& value) const; | |||||
bool upload(std::size_t index, const unsigned int& value) const; | |||||
bool upload(std::size_t index, const uint2& value) const; | |||||
bool upload(std::size_t index, const uint3& value) const; | |||||
bool upload(std::size_t index, const uint4& value) const; | |||||
bool upload(std::size_t index, const float& value) const; | |||||
bool upload(std::size_t index, const float2& value) const; | |||||
bool upload(std::size_t index, const float3& value) const; | |||||
bool upload(std::size_t index, const float4& value) const; | |||||
bool upload(std::size_t index, const float2x2& value) const; | |||||
bool upload(std::size_t index, const float3x3& value) const; | |||||
bool upload(std::size_t index, const float4x4& value) const; | |||||
bool upload(std::size_t index, const texture_1d* value) const; | |||||
bool upload(std::size_t index, const texture_2d* value) const; | |||||
bool upload(std::size_t index, const texture_3d* value) const; | |||||
bool upload(std::size_t index, const texture_cube* value) const; | |||||
///@} | |||||
/** | |||||
* Uploads a range of array elements to the shader. | |||||
* | |||||
* @param index Index of the first array element. | |||||
* @param values Pointer to an array of values. | |||||
* @param count Number of elements to upload. | |||||
* @return `true` if the value was fed successfully, `false` otherwise. | |||||
*/ | |||||
///@{ | |||||
bool upload(std::size_t index, const bool* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const bool2* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const bool3* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const bool4* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const int* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const int2* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const int3* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const int4* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const unsigned int* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const uint2* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const uint3* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const uint4* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float2* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float3* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float4* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float2x2* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float3x3* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const float4x4* values, std::size_t count) const; | |||||
bool upload(std::size_t index, const texture_1d** values, std::size_t count) const; | |||||
bool upload(std::size_t index, const texture_2d** values, std::size_t count) const; | |||||
bool upload(std::size_t index, const texture_3d** values, std::size_t count) const; | |||||
bool upload(std::size_t index, const texture_cube** values, std::size_t count) const; | |||||
///@} | |||||
private: | |||||
friend class shader_program; | |||||
/** | |||||
* Creates a shader input. | |||||
* | |||||
* @param program Shader program with which this input is associated. | |||||
* @param gl_uniform_location Location of the shader uniform with which this shader input is associated. | |||||
* @param name Name of the input. | |||||
* @param data_type Type of data which can be passed through this input. | |||||
* @param element_count Number of elements which the array can contain, or `0` if input data is not stored in an array. | |||||
* @param texture_unit Texture unit to which texture shader variables can be bound, or `-1` if the data type is not a texture type. | |||||
*/ | |||||
shader_input(shader_program* program, std::size_t input_index, int gl_uniform_location, const std::string& name, shader_variable_type data_type, std::size_t element_count, int texture_unit); | |||||
/** | |||||
* Destroys a shader input. | |||||
*/ | |||||
~shader_input(); | |||||
shader_program* program; | |||||
std::size_t input_index; | |||||
int gl_uniform_location; | |||||
std::string name; | |||||
shader_variable_type data_type; | |||||
std::size_t element_count; | |||||
int texture_unit; | |||||
}; | |||||
inline shader_variable_type shader_input::get_data_type() const | |||||
{ | |||||
return data_type; | |||||
} | |||||
inline bool shader_input::is_array() const | |||||
{ | |||||
return (element_count > 1); | |||||
} | |||||
inline std::size_t shader_input::get_element_count() const | |||||
{ | |||||
return element_count; | |||||
} | |||||
} // namespace gl | |||||
#endif // ANTKEEPER_GL_SHADER_INPUT_HPP | |||||
@ -0,0 +1,364 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <engine/gl/shader-template.hpp> | |||||
#include <algorithm> | |||||
#include <engine/gl/shader-object.hpp> | |||||
#include <engine/gl/shader-program.hpp> | |||||
#include <engine/resources/resource-loader.hpp> | |||||
#include <engine/resources/resource-manager.hpp> | |||||
#include <engine/utility/text-file.hpp> | |||||
#include <engine/utility/hash/combine.hpp> | |||||
#include <sstream> | |||||
#include <unordered_set> | |||||
namespace gl { | |||||
shader_template::shader_template(const text_file& source_code): | |||||
template_source{source_code} | |||||
{ | |||||
find_directives(); | |||||
rehash(); | |||||
} | |||||
shader_template::shader_template(text_file&& source_code): | |||||
template_source{source_code} | |||||
{ | |||||
find_directives(); | |||||
rehash(); | |||||
} | |||||
void shader_template::source(const text_file& source_code) | |||||
{ | |||||
template_source = source_code; | |||||
find_directives(); | |||||
rehash(); | |||||
} | |||||
void shader_template::source(text_file&& source_code) | |||||
{ | |||||
template_source = source_code; | |||||
find_directives(); | |||||
rehash(); | |||||
} | |||||
std::string shader_template::configure(gl::shader_stage stage, const dictionary_type& definitions) const | |||||
{ | |||||
replace_stage_directives(stage); | |||||
replace_define_directives(definitions); | |||||
// Join vector of source lines into single string | |||||
std::string string; | |||||
for (const auto& line: template_source.lines) | |||||
{ | |||||
string += line; | |||||
string += '\n'; | |||||
} | |||||
return string; | |||||
} | |||||
std::unique_ptr<gl::shader_object> shader_template::compile(gl::shader_stage stage, const dictionary_type& definitions) const | |||||
{ | |||||
// Generate shader object source | |||||
const std::string object_source = configure(stage, definitions); | |||||
// Create shader object | |||||
std::unique_ptr<gl::shader_object> object = std::make_unique<gl::shader_object>(stage); | |||||
// Set shader object source | |||||
object->source(object_source); | |||||
// Compile shader object | |||||
object->compile(); | |||||
return object; | |||||
} | |||||
std::unique_ptr<gl::shader_program> shader_template::build(const dictionary_type& definitions) const | |||||
{ | |||||
std::unique_ptr<gl::shader_object> vertex_object; | |||||
std::unique_ptr<gl::shader_object> fragment_object; | |||||
std::unique_ptr<gl::shader_object> geometry_object; | |||||
// Create shader program | |||||
std::unique_ptr<gl::shader_program> program = std::make_unique<gl::shader_program>(); | |||||
if (has_vertex_directive()) | |||||
{ | |||||
// Compile vertex shader object and attach to shader program | |||||
vertex_object = compile(gl::shader_stage::vertex, definitions); | |||||
program->attach(*vertex_object); | |||||
} | |||||
if (has_fragment_directive()) | |||||
{ | |||||
// Compile fragment shader object and attach to shader program | |||||
fragment_object = compile(gl::shader_stage::fragment, definitions); | |||||
program->attach(*fragment_object); | |||||
} | |||||
if (has_geometry_directive()) | |||||
{ | |||||
// Compile fragment shader object and attach to shader program | |||||
geometry_object = compile(gl::shader_stage::geometry, definitions); | |||||
program->attach(*geometry_object); | |||||
} | |||||
// Link attached shader objects into shader program | |||||
program->link(); | |||||
// Detach all attached shader objects | |||||
program->detach_all(); | |||||
return program; | |||||
} | |||||
void shader_template::find_directives() | |||||
{ | |||||
// Reset directives | |||||
vertex_directives.clear(); | |||||
fragment_directives.clear(); | |||||
geometry_directives.clear(); | |||||
define_directives.clear(); | |||||
// Parse directives | |||||
for (std::size_t i = 0; i < template_source.lines.size(); ++i) | |||||
{ | |||||
std::istringstream line_stream(template_source.lines[i]); | |||||
std::string token; | |||||
// Detect `#pragma` directives | |||||
if (line_stream >> token && token == "#pragma") | |||||
{ | |||||
if (line_stream >> token) | |||||
{ | |||||
// Map line numbers of supported directives | |||||
if (token == "define") | |||||
{ | |||||
if (line_stream >> token) | |||||
{ | |||||
define_directives.insert({token, i}); | |||||
} | |||||
} | |||||
else if (token == "vertex") | |||||
{ | |||||
vertex_directives.insert(i); | |||||
} | |||||
else if (token == "fragment") | |||||
{ | |||||
fragment_directives.insert(i); | |||||
} | |||||
else if (token == "geometry") | |||||
{ | |||||
geometry_directives.insert(i); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
void shader_template::rehash() | |||||
{ | |||||
m_hash = 0; | |||||
for (const auto& line: template_source.lines) | |||||
{ | |||||
m_hash = hash::combine(m_hash, std::hash<std::string>{}(line)); | |||||
} | |||||
} | |||||
void shader_template::replace_stage_directives(gl::shader_stage stage) const | |||||
{ | |||||
// Determine stage directives according to the shader stage being generated | |||||
const char* vertex_directive = (stage == gl::shader_stage::vertex) ? "#define __VERTEX__" : "/* #undef __VERTEX__ */"; | |||||
const char* fragment_directive = (stage == gl::shader_stage::fragment) ? "#define __FRAGMENT__" : "/* #undef __FRAGMENT__ */"; | |||||
const char* geometry_directive = (stage == gl::shader_stage::geometry) ? "#define __GEOMETRY__" : "/* #undef __GEOMETRY__ */"; | |||||
// Handle `#pragma <stage>` directives | |||||
for (const auto directive_line: vertex_directives) | |||||
{ | |||||
template_source.lines[directive_line] = vertex_directive; | |||||
} | |||||
for (const auto directive_line: fragment_directives) | |||||
{ | |||||
template_source.lines[directive_line] = fragment_directive; | |||||
} | |||||
for (const auto directive_line: geometry_directives) | |||||
{ | |||||
template_source.lines[directive_line] = geometry_directive; | |||||
} | |||||
} | |||||
void shader_template::replace_define_directives(const dictionary_type& definitions) const | |||||
{ | |||||
// For each `#pragma define <key>` directive | |||||
for (const auto& define_directive: define_directives) | |||||
{ | |||||
// Get a reference to the directive line | |||||
std::string& line = template_source.lines[define_directive.second]; | |||||
// Check if the corresponding definition was given by the configuration | |||||
auto definitions_it = definitions.find(define_directive.first); | |||||
if (definitions_it != definitions.end()) | |||||
{ | |||||
// Definition found, replace `#pragma define <key>` with `#define <key>` or `#define <key> <value>` | |||||
line = "#define " + define_directive.first; | |||||
if (!definitions_it->second.empty()) | |||||
{ | |||||
line += " " + definitions_it->second; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
// Definition not found, replace `#pragma define <key>` with the comment `/* #undef <key> */`. | |||||
line = "/* #undef " + define_directive.first + " */"; | |||||
} | |||||
} | |||||
} | |||||
bool shader_template::has_vertex_directive() const noexcept | |||||
{ | |||||
return !vertex_directives.empty(); | |||||
} | |||||
bool shader_template::has_fragment_directive() const noexcept | |||||
{ | |||||
return !fragment_directives.empty(); | |||||
} | |||||
bool shader_template::has_geometry_directive() const noexcept | |||||
{ | |||||
return !geometry_directives.empty(); | |||||
} | |||||
bool shader_template::has_define_directive(const std::string& key) const | |||||
{ | |||||
return (define_directives.find(key) != define_directives.end()); | |||||
} | |||||
} // namespace gl | |||||
/** | |||||
* Scans a text file for the presence of a `#pragma once` directive. | |||||
* | |||||
* @param source Text file to scan. | |||||
* | |||||
* @return `true` if the file contains a `#pragma once` directive, `false` otherwise. | |||||
*/ | |||||
static bool has_pragma_once(const text_file& source) | |||||
{ | |||||
for (const auto& line: source.lines) | |||||
{ | |||||
std::istringstream line_stream(line); | |||||
std::string token; | |||||
// If line contains a `#pragma once` directive | |||||
if (line_stream >> token && token == "#pragma") | |||||
{ | |||||
if (line_stream >> token && token == "once") | |||||
{ | |||||
return true; | |||||
} | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* Handles `#pragma include` directives by loading the specified text files and inserting them in place. | |||||
*/ | |||||
static void handle_includes(text_file& source, std::unordered_set<std::filesystem::path>& include_once, resource_manager& resource_manager) | |||||
{ | |||||
// For each line in the source | |||||
for (std::size_t i = 0; i < source.lines.size(); ++i) | |||||
{ | |||||
std::string token; | |||||
std::istringstream line_stream(source.lines[i]); | |||||
// If line contains a `#pragma include` directive | |||||
if (line_stream >> token && token == "#pragma" && | |||||
line_stream >> token && token == "include") | |||||
{ | |||||
// If third token is enclosed in quotes or angled brackets | |||||
if (line_stream >> token && token.size() > 2 && | |||||
((token.front() == '\"' && token.back() == '\"') || | |||||
(token.front() == '<' && token.back() == '>'))) | |||||
{ | |||||
// Extract include path | |||||
const std::filesystem::path path = token.substr(1, token.length() - 2); | |||||
// Skip pre-included files that contain a `#pragma once` directive | |||||
if (include_once.contains(path)) | |||||
{ | |||||
source.lines[i] = "/* #pragma exclude " + token + " */"; | |||||
continue; | |||||
} | |||||
// Load include file | |||||
const auto include_file = resource_manager.load<text_file>(path); | |||||
if (!include_file) | |||||
{ | |||||
source.lines[i] = "#error file not found: " + path.string(); | |||||
continue; | |||||
} | |||||
// If file has `#pragma once` directive | |||||
if (has_pragma_once(*include_file)) | |||||
{ | |||||
// Add file to set of files to include once | |||||
include_once.insert(path); | |||||
} | |||||
// Create a copy of the include file | |||||
text_file include_file_copy = *include_file; | |||||
// Handle `#pragma include` directives inside include file | |||||
handle_includes(include_file_copy, include_once, resource_manager); | |||||
// Replace #pragma include directive with include file contents | |||||
source.lines.erase(source.lines.begin() + i); | |||||
source.lines.insert(source.lines.begin() + i, include_file_copy.lines.begin(), include_file_copy.lines.end()); | |||||
i += include_file_copy.lines.size() - 1; | |||||
} | |||||
else | |||||
{ | |||||
source.lines[i] = "#error malformed include directive: \"" + source.lines[i] + "\""; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
template <> | |||||
std::unique_ptr<gl::shader_template> resource_loader<gl::shader_template>::load(::resource_manager& resource_manager, deserialize_context& ctx) | |||||
{ | |||||
// Load shader template source file | |||||
const auto source_file = resource_loader<text_file>::load(resource_manager, ctx); | |||||
// Make a copy of the shader template source file | |||||
text_file source_file_copy = *source_file; | |||||
// Handle `#pragma include` directives | |||||
std::unordered_set<std::filesystem::path> include_once; | |||||
include_once.insert(ctx.path()); | |||||
handle_includes(source_file_copy, include_once, resource_manager); | |||||
// Construct shader template | |||||
return std::make_unique<gl::shader_template>(std::move(source_file_copy)); | |||||
} |
@ -0,0 +1,396 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <engine/gl/shader-variable.hpp> | |||||
#include <stdexcept> | |||||
namespace gl { | |||||
static const char* type_mismatch_error = "Shader variable type mismatch"; | |||||
shader_variable::shader_variable(std::size_t size) noexcept: | |||||
m_size{size} | |||||
{} | |||||
void shader_variable::update(bool value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const bool2& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const bool3& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const bool4& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(int value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const int2& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const int3& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const int4& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(unsigned int value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const uint2& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const uint3& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const uint4& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(float value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float2& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float3& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float4& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float2x2& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float3x3& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float4x4& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_1d& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_2d& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_3d& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_cube& value) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(bool value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const bool2& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const bool3& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const bool4& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(int value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const int2& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const int3& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const int4& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(unsigned int value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const uint2& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const uint3& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const uint4& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(float value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float2& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float3& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float4& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float2x2& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float3x3& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const float4x4& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_1d& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_2d& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_3d& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(const texture_cube& value, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const bool> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const bool2> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const bool3> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const bool4> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const int> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const int2> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const int3> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const int4> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const unsigned int> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const uint2> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const uint3> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const uint4> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float2> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float3> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float4> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float2x2> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float3x3> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const float4x4> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const texture_1d* const> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const texture_2d* const> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const texture_3d* const> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const texture_cube* const> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const std::shared_ptr<texture_1d>> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const std::shared_ptr<texture_2d>> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const std::shared_ptr<texture_3d>> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
void shader_variable::update(std::span<const std::shared_ptr<texture_cube>> values, std::size_t index) const | |||||
{ | |||||
throw std::invalid_argument(type_mismatch_error); | |||||
} | |||||
} // namespace gl |
@ -0,0 +1,195 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_GL_SHADER_INPUT_HPP | |||||
#define ANTKEEPER_GL_SHADER_INPUT_HPP | |||||
#include <engine/utility/fundamental-types.hpp> | |||||
#include <engine/gl/shader-variable-type.hpp> | |||||
#include <cstdint> | |||||
#include <span> | |||||
#include <memory> | |||||
namespace gl { | |||||
class texture_1d; | |||||
class texture_2d; | |||||
class texture_3d; | |||||
class texture_cube; | |||||
/** | |||||
* Shader program variable. | |||||
*/ | |||||
class shader_variable | |||||
{ | |||||
public: | |||||
/** | |||||
* Destructs a shader variable. | |||||
*/ | |||||
virtual ~shader_variable() = default; | |||||
/** | |||||
* Returns the shader variable data type. | |||||
*/ | |||||
[[nodiscard]] virtual constexpr shader_variable_type type() const noexcept = 0; | |||||
/** | |||||
* Returns the number of elements in an array variable, or `1` if the variable is not an array. | |||||
*/ | |||||
[[nodiscard]] inline std::size_t size() const noexcept | |||||
{ | |||||
return m_size; | |||||
} | |||||
/** | |||||
* Updates the value of the variable. If the variable is an array, the value of the first element will be updated. | |||||
* | |||||
* @param value Update value. | |||||
* | |||||
* @throw std::invalid_argument Shader variable type mismatch. | |||||
*/ | |||||
///@{ | |||||
virtual void update(bool value) const; | |||||
virtual void update(const bool2& value) const; | |||||
virtual void update(const bool3& value) const; | |||||
virtual void update(const bool4& value) const; | |||||
virtual void update(int value) const; | |||||
virtual void update(const int2& value) const; | |||||
virtual void update(const int3& value) const; | |||||
virtual void update(const int4& value) const; | |||||
virtual void update(unsigned int value) const; | |||||
virtual void update(const uint2& value) const; | |||||
virtual void update(const uint3& value) const; | |||||
virtual void update(const uint4& value) const; | |||||
virtual void update(float value) const; | |||||
virtual void update(const float2& value) const; | |||||
virtual void update(const float3& value) const; | |||||
virtual void update(const float4& value) const; | |||||
virtual void update(const float2x2& value) const; | |||||
virtual void update(const float3x3& value) const; | |||||
virtual void update(const float4x4& value) const; | |||||
virtual void update(const texture_1d& value) const; | |||||
virtual void update(const texture_2d& value) const; | |||||
virtual void update(const texture_3d& value) const; | |||||
virtual void update(const texture_cube& value) const; | |||||
///@} | |||||
/** | |||||
* Updates the value of a single element in an array variable. | |||||
* | |||||
* @param value Update value. | |||||
* @param index Index of the element to update. | |||||
* | |||||
* @throw std::invalid_argument Shader variable type mismatch. | |||||
*/ | |||||
/// @{ | |||||
virtual void update(bool value, std::size_t index) const; | |||||
virtual void update(const bool2& value, std::size_t index) const; | |||||
virtual void update(const bool3& value, std::size_t index) const; | |||||
virtual void update(const bool4& value, std::size_t index) const; | |||||
virtual void update(int value, std::size_t index) const; | |||||
virtual void update(const int2& value, std::size_t index) const; | |||||
virtual void update(const int3& value, std::size_t index) const; | |||||
virtual void update(const int4& value, std::size_t index) const; | |||||
virtual void update(unsigned int value, std::size_t index) const; | |||||
virtual void update(const uint2& value, std::size_t index) const; | |||||
virtual void update(const uint3& value, std::size_t index) const; | |||||
virtual void update(const uint4& value, std::size_t index) const; | |||||
virtual void update(float value, std::size_t index) const; | |||||
virtual void update(const float2& value, std::size_t index) const; | |||||
virtual void update(const float3& value, std::size_t index) const; | |||||
virtual void update(const float4& value, std::size_t index) const; | |||||
virtual void update(const float2x2& value, std::size_t index) const; | |||||
virtual void update(const float3x3& value, std::size_t index) const; | |||||
virtual void update(const float4x4& value, std::size_t index) const; | |||||
virtual void update(const texture_1d& value, std::size_t index) const; | |||||
virtual void update(const texture_2d& value, std::size_t index) const; | |||||
virtual void update(const texture_3d& value, std::size_t index) const; | |||||
virtual void update(const texture_cube& value, std::size_t index) const; | |||||
///@} | |||||
/** | |||||
* Updates the values of one or more elements in an array variable. | |||||
* | |||||
* @param values Contiguous sequence of update values. | |||||
* @param index Index of the first element to update. | |||||
* | |||||
* @throw std::invalid_argument Shader variable type mismatch. | |||||
*/ | |||||
///@{ | |||||
virtual void update(std::span<const bool> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const bool2> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const bool3> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const bool4> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const int> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const int2> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const int3> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const int4> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const unsigned int> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const uint2> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const uint3> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const uint4> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float2> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float3> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float4> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float2x2> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float3x3> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const float4x4> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const texture_1d* const> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const texture_2d* const> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const texture_3d* const> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const texture_cube* const> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const std::shared_ptr<texture_1d>> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const std::shared_ptr<texture_2d>> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const std::shared_ptr<texture_3d>> values, std::size_t index = 0) const; | |||||
virtual void update(std::span<const std::shared_ptr<texture_cube>> values, std::size_t index = 0) const; | |||||
///@} | |||||
protected: | |||||
/** | |||||
* Constructs a shader variable. | |||||
* | |||||
* @param size Number of elements in the array, or `1` if the variable is not an array. | |||||
*/ | |||||
explicit shader_variable(std::size_t size) noexcept; | |||||
private: | |||||
const std::size_t m_size; | |||||
}; | |||||
} // namespace gl | |||||
#endif // ANTKEEPER_GL_SHADER_VARIABLE_HPP |
@ -0,0 +1,80 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <engine/i18n/string-table.hpp> | |||||
#include <engine/resources/deserializer.hpp> | |||||
#include <engine/resources/resource-loader.hpp> | |||||
/** | |||||
* Deserializes a string table. | |||||
* | |||||
* @param[out] file Text file to serialize. | |||||
* @param[in,out] ctx Deserialize context. | |||||
* | |||||
* @throw deserialize_error Read error. | |||||
*/ | |||||
template <> | |||||
void deserializer<i18n::string_table>::deserialize(i18n::string_table& table, deserialize_context& ctx) | |||||
{ | |||||
table.rows.clear(); | |||||
std::vector<std::string> row; | |||||
std::string entry; | |||||
char c; | |||||
while (ctx.read8(reinterpret_cast<std::byte*>(&c), 1) == 1) | |||||
{ | |||||
if (c == '\t') | |||||
{ | |||||
row.push_back(entry); | |||||
entry.clear(); | |||||
} | |||||
else if (c == '\n') | |||||
{ | |||||
row.push_back(entry); | |||||
entry.clear(); | |||||
table.rows.push_back(row); | |||||
row.clear(); | |||||
} | |||||
else if (c != '\r') | |||||
{ | |||||
entry.push_back(c); | |||||
} | |||||
} | |||||
if (!entry.empty()) | |||||
{ | |||||
row.push_back(entry); | |||||
} | |||||
if (!row.empty()) | |||||
{ | |||||
table.rows.push_back(row); | |||||
} | |||||
} | |||||
template <> | |||||
std::unique_ptr<i18n::string_table> resource_loader<i18n::string_table>::load(::resource_manager& resource_manager, deserialize_context& ctx) | |||||
{ | |||||
auto resource = std::make_unique<i18n::string_table>(); | |||||
deserializer<i18n::string_table>().deserialize(*resource, ctx); | |||||
return resource; | |||||
} |
@ -1,460 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_RENDER_MATERIAL_PROPERTY_HPP | |||||
#define ANTKEEPER_RENDER_MATERIAL_PROPERTY_HPP | |||||
#include <engine/animation/tween.hpp> | |||||
#include <engine/gl/shader-variable-type.hpp> | |||||
#include <engine/gl/shader-input.hpp> | |||||
#include <engine/math/interpolation.hpp> | |||||
#include <engine/utility/fundamental-types.hpp> | |||||
#include <engine/gl/shader-program.hpp> | |||||
#include <engine/gl/texture-1d.hpp> | |||||
#include <engine/gl/texture-2d.hpp> | |||||
#include <engine/gl/texture-3d.hpp> | |||||
#include <engine/gl/texture-cube.hpp> | |||||
#include <cstddef> | |||||
namespace render { | |||||
class material; | |||||
/** | |||||
* Abstract base class for material properties. | |||||
*/ | |||||
class material_property_base | |||||
{ | |||||
public: | |||||
/** | |||||
* Connects the material property to a shader input. | |||||
* | |||||
* @param input Shader input to which the material property should be connected. | |||||
* @return `true` if the property was connected to the input successfully, `false` otherwise. | |||||
*/ | |||||
bool connect(const gl::shader_input* input); | |||||
/** | |||||
* Disconnects the material property from its shader input. | |||||
*/ | |||||
void disconnect(); | |||||
/** | |||||
* Sets state 0 = state 1. | |||||
*/ | |||||
virtual void update_tweens() = 0; | |||||
/** | |||||
* Uploads the material property to its shader program. | |||||
* | |||||
* @param a Interpolation factor. Should be on `[0.0, 1.0]`. | |||||
* @return `true` if the property was uploaded successfully, `false` otherwise. | |||||
*/ | |||||
virtual bool upload(double a) const = 0; | |||||
/** | |||||
* Returns the type of data which the property contains. | |||||
*/ | |||||
virtual gl::shader_variable_type get_data_type() const = 0; | |||||
/** | |||||
* Returns `true` if the material property is connected to a shader input, `false` otherwise. | |||||
*/ | |||||
bool is_connected() const; | |||||
/** | |||||
* Creates a copy of this material property. | |||||
*/ | |||||
virtual material_property_base* clone() const = 0; | |||||
protected: | |||||
material_property_base(); | |||||
const gl::shader_input* input; | |||||
}; | |||||
inline bool material_property_base::is_connected() const | |||||
{ | |||||
return (input != nullptr); | |||||
} | |||||
/** | |||||
* A property of a material which can be uploaded to a shader program via a shader input. | |||||
* | |||||
* @tparam T Property data type. | |||||
*/ | |||||
template <class T> | |||||
class material_property: public material_property_base | |||||
{ | |||||
public: | |||||
typedef tween<T> tween_type; | |||||
typedef typename tween<T>::interpolator_type interpolator_type; | |||||
/// Default tween interpolator function for this material property type. | |||||
static T default_interpolator(const T& x, const T& y, double a); | |||||
/** | |||||
* Creates a material property. | |||||
* | |||||
* @param element_count Number of elements in the property array. | |||||
*/ | |||||
material_property(std::size_t element_count); | |||||
/** | |||||
* Destroys a material property. | |||||
*/ | |||||
virtual ~material_property(); | |||||
material_property(const material_property<T>&) = delete; | |||||
material_property<T>& operator=(const material_property<T>&) = delete; | |||||
/// @copydoc material_property_base::update_tweens() | |||||
virtual void update_tweens(); | |||||
/// @copydoc material_property_base::upload() const | |||||
virtual bool upload(double a) const; | |||||
/** | |||||
* Sets the value of this property. | |||||
* | |||||
* @param value Value to set. | |||||
*/ | |||||
void set_value(const T& value); | |||||
/** | |||||
* Sets the value of a single element in this array property. | |||||
* | |||||
* @param index Index of an array element. | |||||
* @param value Value to set. | |||||
*/ | |||||
void set_value(std::size_t index, const T& value); | |||||
/** | |||||
* Sets the values of a range of elements in this array property. | |||||
* | |||||
* @param index Index of the first array element to set. | |||||
* @param values Pointer to an array of values to set. | |||||
* @param count Number of elements to set. | |||||
*/ | |||||
void set_values(std::size_t index, const T* values, std::size_t count); | |||||
/** | |||||
* Sets the tween interpolator function. | |||||
* | |||||
* @param interpolator Tween interpolator function. | |||||
*/ | |||||
void set_tween_interpolator(interpolator_type interpolator); | |||||
/// Returns the value of the first element in this property. | |||||
const T& get_value() const; | |||||
/** | |||||
* Returns the value of the first element in this property. | |||||
* | |||||
* @param index Index of an array element. | |||||
* @return Value of the element at the specified index. | |||||
*/ | |||||
const T& get_value(std::size_t index) const; | |||||
/// @copydoc material_property_base::get_data_type() const | |||||
virtual gl::shader_variable_type get_data_type() const; | |||||
/// @copydoc material_property_base::clone() const | |||||
virtual material_property_base* clone() const; | |||||
private: | |||||
std::size_t element_count; | |||||
tween<T>* values; | |||||
}; | |||||
template <typename T> | |||||
inline T material_property<T>::default_interpolator(const T& x, const T& y, double a) | |||||
{ | |||||
return y; | |||||
} | |||||
template <> | |||||
inline float material_property<float>::default_interpolator(const float& x, const float& y, double a) | |||||
{ | |||||
return math::lerp<float, float>(x, y, static_cast<float>(a)); | |||||
} | |||||
template <> | |||||
inline float2 material_property<float2>::default_interpolator(const float2& x, const float2& y, double a) | |||||
{ | |||||
return math::lerp<float2, float>(x, y, static_cast<float>(a)); | |||||
} | |||||
template <> | |||||
inline float3 material_property<float3>::default_interpolator(const float3& x, const float3& y, double a) | |||||
{ | |||||
return math::lerp<float3, float>(x, y, static_cast<float>(a)); | |||||
} | |||||
template <> | |||||
inline float4 material_property<float4>::default_interpolator(const float4& x, const float4& y, double a) | |||||
{ | |||||
return math::lerp<float4, float>(x, y, static_cast<float>(a)); | |||||
} | |||||
template <class T> | |||||
material_property<T>::material_property(std::size_t element_count): | |||||
element_count(element_count), | |||||
values(nullptr) | |||||
{ | |||||
values = new tween<T>[element_count]; | |||||
set_tween_interpolator(default_interpolator); | |||||
} | |||||
template <class T> | |||||
material_property<T>::~material_property() | |||||
{ | |||||
delete[] values; | |||||
} | |||||
template <class T> | |||||
void material_property<T>::update_tweens() | |||||
{ | |||||
for (std::size_t i = 0; i < element_count; ++i) | |||||
{ | |||||
values[i].update(); | |||||
} | |||||
} | |||||
template <class T> | |||||
bool material_property<T>::upload(double a) const | |||||
{ | |||||
if (!is_connected()) | |||||
{ | |||||
return false; | |||||
} | |||||
if (element_count > 1) | |||||
{ | |||||
for (std::size_t i = 0; i < element_count; ++i) | |||||
{ | |||||
if (!input->upload(i, values[i].interpolate(static_cast<float>(a)))) | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
else | |||||
{ | |||||
return input->upload(values[0].interpolate(static_cast<float>(a))); | |||||
} | |||||
} | |||||
template <class T> | |||||
void material_property<T>::set_value(const T& value) | |||||
{ | |||||
values[0][1] = value; | |||||
} | |||||
template <class T> | |||||
void material_property<T>::set_value(std::size_t index, const T& value) | |||||
{ | |||||
values[index][1] = value; | |||||
} | |||||
template <class T> | |||||
void material_property<T>::set_values(std::size_t index, const T* values, std::size_t count) | |||||
{ | |||||
for (std::size_t i = 0; i < count; ++i) | |||||
{ | |||||
this->values[index + i][1] = values[i]; | |||||
} | |||||
} | |||||
template <class T> | |||||
void material_property<T>::set_tween_interpolator(interpolator_type interpolator) | |||||
{ | |||||
for (std::size_t i = 0; i < element_count; ++i) | |||||
{ | |||||
this->values[i].set_interpolator(interpolator); | |||||
} | |||||
} | |||||
template <class T> | |||||
inline const T& material_property<T>::get_value() const | |||||
{ | |||||
return values[0][1]; | |||||
} | |||||
template <class T> | |||||
inline const T& material_property<T>::get_value(std::size_t index) const | |||||
{ | |||||
return values[index][1]; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<bool>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::bool1; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<bool2>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::bool2; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<bool3>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::bool3; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<bool4>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::bool4; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<int>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::int1; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<int2>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::int2; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<int3>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::int3; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<int4>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::int4; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<unsigned int>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::uint1; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<uint2>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::uint2; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<uint3>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::uint3; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<uint4>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::uint4; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float1; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float2>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float2; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float3>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float3; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float4>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float4; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float2x2>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float2x2; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float3x3>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float3x3; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<float4x4>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::float4x4; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<const gl::texture_1d*>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::texture_1d; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<const gl::texture_2d*>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::texture_2d; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<const gl::texture_3d*>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::texture_3d; | |||||
} | |||||
template <> | |||||
inline gl::shader_variable_type material_property<const gl::texture_cube*>::get_data_type() const | |||||
{ | |||||
return gl::shader_variable_type::texture_cube; | |||||
} | |||||
template <class T> | |||||
material_property_base* material_property<T>::clone() const | |||||
{ | |||||
material_property<T>* property = new material_property<T>(element_count); | |||||
for (std::size_t i = 0; i < element_count; ++i) | |||||
{ | |||||
property->values[i][0] = values[i][0]; | |||||
property->values[i][1] = values[i][1]; | |||||
} | |||||
property->input = input; | |||||
return property; | |||||
} | |||||
} // namespace render | |||||
#endif // ANTKEEPER_RENDER_MATERIAL_PROPERTY_HPP |
@ -0,0 +1,373 @@ | |||||
/* | |||||
* Copyright (C) 2023 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code 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. | |||||
* | |||||
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_RENDER_MATERIAL_VARIABLE_HPP | |||||
#define ANTKEEPER_RENDER_MATERIAL_VARIABLE_HPP | |||||
#include <engine/utility/fundamental-types.hpp> | |||||
#include <engine/gl/texture-1d.hpp> | |||||
#include <engine/gl/texture-2d.hpp> | |||||
#include <engine/gl/texture-3d.hpp> | |||||
#include <engine/gl/texture-cube.hpp> | |||||
#include <engine/render/material-variable-type.hpp> | |||||
#include <memory> | |||||
#include <vector> | |||||
namespace render { | |||||
/** | |||||
* Abstract base class for material variables. | |||||
*/ | |||||
class material_variable_base | |||||
{ | |||||
public: | |||||
/** | |||||
* Destructs a material variable base. | |||||
*/ | |||||
virtual ~material_variable_base() = default; | |||||
/** | |||||
* Returns the material variable data type. | |||||
*/ | |||||
[[nodiscard]] virtual constexpr material_variable_type type() const noexcept = 0; | |||||
/** | |||||
* Returns the number of elements in an array variable, or `1` if the variable is not an array. | |||||
*/ | |||||
[[nodiscard]] virtual std::size_t size() const noexcept = 0; | |||||
/** | |||||
* Creates a copy of this material property. | |||||
*/ | |||||
[[nodiscard]] virtual std::unique_ptr<material_variable_base> clone() const = 0; | |||||
}; | |||||
/** | |||||
* Material variable. | |||||
* | |||||
* @tparam T Material variable value type. | |||||
*/ | |||||
template <class T> | |||||
class material_variable: public material_variable_base | |||||
{ | |||||
public: | |||||
/// Material variable element type. | |||||
using element_type = T; | |||||
/** | |||||
* Constructs a material variable. | |||||
* | |||||
* @param size Number of elements in the array, or `1` if the variable is not an array. | |||||
* @param value Value with which to initialize the elements. | |||||
*/ | |||||
inline material_variable(std::size_t size, const element_type& value = element_type()): | |||||
elements(size, value) | |||||
{} | |||||
/** | |||||
* Constructs a material variable with a single element. | |||||
*/ | |||||
inline material_variable(): | |||||
material_variable(1) | |||||
{} | |||||
/** | |||||
* Constructs a material variable from a list of element values. | |||||
* | |||||
* @param list List of element values. | |||||
*/ | |||||
inline material_variable(std::initializer_list<element_type> list): | |||||
elements(list) | |||||
{} | |||||
[[nodiscard]] virtual constexpr material_variable_type type() const noexcept override; | |||||
[[nodiscard]] inline std::size_t size() const noexcept override | |||||
{ | |||||
return elements.size(); | |||||
} | |||||
[[nodiscard]] inline std::unique_ptr<material_variable_base> clone() const override | |||||
{ | |||||
return std::make_unique<material_variable<T>>(*this); | |||||
} | |||||
/** | |||||
* Sets the value of the the variable, or the value of the first element if the variable is an array. | |||||
* | |||||
* @param value Value to set. | |||||
*/ | |||||
inline void set(const element_type& value) | |||||
{ | |||||
elements.front() = value; | |||||
} | |||||
/** | |||||
* Sets the value of a single element in an array variable. | |||||
* | |||||
* @param index Index of an element. | |||||
* @param value Value to set. | |||||
*/ | |||||
inline void set(std::size_t index, const element_type& value) | |||||
{ | |||||
elements[index] = value; | |||||
} | |||||
/** | |||||
* Returns a reference to the first element in the array. | |||||
*/ | |||||
[[nodiscard]] inline const element_type& get() const | |||||
{ | |||||
return elements.front(); | |||||
} | |||||
/** | |||||
* Returns a reference to the element at a given index. | |||||
* | |||||
* @param index Index of an element. | |||||
* | |||||
* @return Reference to the element at @p index. | |||||
*/ | |||||
[[nodiscard]] inline const element_type& get(std::size_t index) const | |||||
{ | |||||
return elements[index]; | |||||
} | |||||
/** | |||||
* Returns a pointer to the element array. | |||||
*/ | |||||
[[nodiscard]] inline const element_type* data() const noexcept | |||||
{ | |||||
return elements.data(); | |||||
} | |||||
private: | |||||
std::vector<element_type> elements; | |||||
}; | |||||
/// Boolean material variable. | |||||
using material_bool = material_variable<bool>; | |||||
/// 2-dimensional boolean vector material variable. | |||||
using material_bool2 = material_variable<bool2>; | |||||
/// 3-dimensional boolean vector material variable. | |||||
using material_bool3 = material_variable<bool3>; | |||||
/// 4-dimensional boolean vector material variable. | |||||
using material_bool4 = material_variable<bool4>; | |||||
/// Integer material variable. | |||||
using material_int = material_variable<int>; | |||||
/// 2-dimensional integer vector material variable. | |||||
using material_int2 = material_variable<int2>; | |||||
/// 3-dimensional integer vector material variable. | |||||
using material_int3 = material_variable<int3>; | |||||
/// 4-dimensional integer vector material variable. | |||||
using material_int4 = material_variable<int4>; | |||||
/// Unsigned integer material variable. | |||||
using material_uint = material_variable<unsigned int>; | |||||
/// 2-dimensional unsigned integer vector material variable. | |||||
using material_uint2 = material_variable<uint2>; | |||||
/// 3-dimensional unsigned integer vector material variable. | |||||
using material_uint3 = material_variable<uint3>; | |||||
/// 4-dimensional unsigned integer vector material variable. | |||||
using material_uint4 = material_variable<uint4>; | |||||
/// Floating-point material variable. | |||||
using material_float = material_variable<float>; | |||||
/// 2-dimensional floating-point vector material variable. | |||||
using material_float2 = material_variable<float2>; | |||||
/// 3-dimensional floating-point vector material variable. | |||||
using material_float3 = material_variable<float3>; | |||||
/// 4-dimensional floating-point vector material variable. | |||||
using material_float4 = material_variable<float4>; | |||||
/// 2x2 floating-point matrix material variable. | |||||
using material_float2x2 = material_variable<float2x2>; | |||||
/// 3x3 floating-point matrix material variable. | |||||
using material_float3x3 = material_variable<float3x3>; | |||||
/// 4x4 floating-point matrix material variable. | |||||
using material_float4x4 = material_variable<float4x4>; | |||||
/// 1-dimensional texture material variable. | |||||
using material_texture_1d = material_variable<std::shared_ptr<gl::texture_1d>>; | |||||
/// 2-dimensional texture material variable. | |||||
using material_texture_2d = material_variable<std::shared_ptr<gl::texture_2d>>; | |||||
/// 3-dimensional texture material variable. | |||||
using material_texture_3d = material_variable<std::shared_ptr<gl::texture_3d>>; | |||||
/// Cube texture material variable. | |||||
using material_texture_cube = material_variable<std::shared_ptr<gl::texture_cube>>; | |||||
template <> | |||||
inline constexpr material_variable_type material_bool::type() const noexcept | |||||
{ | |||||
return material_variable_type::bool1; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_bool2::type() const noexcept | |||||
{ | |||||
return material_variable_type::bool2; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_bool3::type() const noexcept | |||||
{ | |||||
return material_variable_type::bool3; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_bool4::type() const noexcept | |||||
{ | |||||
return material_variable_type::bool4; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_int::type() const noexcept | |||||
{ | |||||
return material_variable_type::int1; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_int2::type() const noexcept | |||||
{ | |||||
return material_variable_type::int2; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_int3::type() const noexcept | |||||
{ | |||||
return material_variable_type::int3; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_int4::type() const noexcept | |||||
{ | |||||
return material_variable_type::int4; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_uint::type() const noexcept | |||||
{ | |||||
return material_variable_type::uint1; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_uint2::type() const noexcept | |||||
{ | |||||
return material_variable_type::uint2; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_uint3::type() const noexcept | |||||
{ | |||||
return material_variable_type::uint3; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_uint4::type() const noexcept | |||||
{ | |||||
return material_variable_type::uint4; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float::type() const noexcept | |||||
{ | |||||
return material_variable_type::float1; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float2::type() const noexcept | |||||
{ | |||||
return material_variable_type::float2; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float3::type() const noexcept | |||||
{ | |||||
return material_variable_type::float3; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float4::type() const noexcept | |||||
{ | |||||
return material_variable_type::float4; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float2x2::type() const noexcept | |||||
{ | |||||
return material_variable_type::float2x2; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float3x3::type() const noexcept | |||||
{ | |||||
return material_variable_type::float3x3; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_float4x4::type() const noexcept | |||||
{ | |||||
return material_variable_type::float4x4; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_texture_1d::type() const noexcept | |||||
{ | |||||
return material_variable_type::texture_1d; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_texture_2d::type() const noexcept | |||||
{ | |||||
return material_variable_type::texture_2d; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_texture_3d::type() const noexcept | |||||
{ | |||||
return material_variable_type::texture_3d; | |||||
} | |||||
template <> | |||||
inline constexpr material_variable_type material_texture_cube::type() const noexcept | |||||
{ | |||||
return material_variable_type::texture_cube; | |||||
} | |||||
} // namespace render | |||||
#endif // ANTKEEPER_RENDER_MATERIAL_VARIABLE_HPP |