[Feat] (MG_State/TextureState): Implement TextureState.

This commit is contained in:
BZLZHH
2025-08-10 23:13:22 +08:00
parent 93ca669929
commit 0b13cb5714
13 changed files with 918 additions and 12 deletions
+3
View File
@@ -54,6 +54,9 @@ set(SOURCE_FILES
MobileGL/MG_State/GLState/BufferState/BufferObject.cpp
MobileGL/MG_State/GLState/VertexArrayState/VertexArrayState.cpp
MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.cpp
MobileGL/MG_State/GLState/TextureState/TextureObject.cpp
MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp
MobileGL/MG_State/GLState/TextureState/TextureState.cpp
)
add_library(${CMAKE_PROJECT_NAME} SHARED
+43 -6
View File
@@ -8,7 +8,7 @@ namespace MobileGL {
m_errorState.RecordError(code, info);
}
bool GLContext::HasGLError() const {
Bool GLContext::HasGLError() const {
return m_errorState.HasGLError();
}
@@ -20,7 +20,7 @@ namespace MobileGL {
return m_errorState.PopGLError();
}
bool GLContext::HasNonGLError() const {
Bool GLContext::HasNonGLError() const {
return m_errorState.HasNonGLError();
}
@@ -79,11 +79,11 @@ namespace MobileGL {
m_bufferState.MarkBufferObjectForDeletion(index);
}
bool GLContext::ValidateBufferName(Uint index) const {
Bool GLContext::ValidateBufferName(Uint index) const {
return m_bufferState.ValidateName(index);
}
bool GLContext::ValidateBufferObject(Uint index) const {
Bool GLContext::ValidateBufferObject(Uint index) const {
return m_bufferState.ValidateBufferObject(index);
}
@@ -108,17 +108,54 @@ namespace MobileGL {
m_vertexArrayState.MarkVertexArrayForDeletion(index);
}
bool GLContext::ValidateVertexArrayName(Uint index) const {
Bool GLContext::ValidateVertexArrayName(Uint index) const {
return m_vertexArrayState.ValidateName(index);
}
bool GLContext::ValidateVertexArrayObject(Uint index) const {
Bool GLContext::ValidateVertexArrayObject(Uint index) const {
return m_vertexArrayState.ValidateVertexArrayObject(index);
}
SharedPtr<VertexArrayObject> GLContext::GetBoundVertexArray() {
return m_vertexArrayState.GetBoundVertexArray();
}
// Texture
Vector<Uint> GLContext::GenTextureNames(Uint number) {
return m_textureState.GenerateNames(number);
}
SharedPtr<ITextureObject> GLContext::GetTextureObject(Uint index) {
return m_textureState.GetTextureObject(index);
}
SharedPtr<ITextureObject> GLContext::CreateTextureObject(Uint index, TextureTarget target) {
return m_textureState.CreateTextureObject(index, target);
}
void GLContext::MarkTextureObjectForDeletion(Uint index) {
m_textureState.MarkTextureObjectForDeletion(index);
}
TextureUnit& GLContext::GetTextureUnitObject() {
return m_textureState.GetUnitObject();
}
Bool GLContext::ValidateTextureName(Uint index) const {
return m_textureState.ValidateName(index);
}
Bool GLContext::ValidateTextureObject(Uint index) const {
return m_textureState.ValidateTextureObject(index);
}
Int GLContext::GetActiveTextureUnit() const {
return m_textureState.GetActiveTextureUnit();
}
void GLContext::SetActiveTextureUnit(Int unit) {
m_textureState.SetActiveTextureUnit(unit);
}
} // namespace GLState
GLState::GLContext* pGLContext;
+22 -6
View File
@@ -1,9 +1,11 @@
#pragma once
#include <Includes.h>
#include "BufferState/BufferState.h"
#include "MG_Util/Types.h"
#include "VertexArrayState/VertexArrayState.h"
#include "ErrorState/Error.h"
#include "ProgramState/ProgramState.h"
#include "TextureState/TextureState.h"
namespace MobileGL {
namespace MG_State {
@@ -14,10 +16,10 @@ namespace MobileGL {
// Error
void RecordError(ErrorCode code, SharedPtr<ErrorInfo> info = nullptr);
bool HasGLError() const;
Bool HasGLError() const;
Optional<const Error> PeekGLError() const;
Optional<Error> PopGLError();
bool HasNonGLError() const;
Bool HasNonGLError() const;
Optional<const Error> PeekNonGLError() const;
Optional<Error> PopNonGLError();
void ClearErrors();
@@ -28,8 +30,8 @@ namespace MobileGL {
BindingSlot<BufferObject>& GetBufferBindingSlot(BufferTarget target);
SharedPtr<BufferObject> CreateBufferObject(Uint index);
void MarkBufferObjectForDeletion(Uint index);
bool ValidateBufferName(Uint index) const;
bool ValidateBufferObject(Uint index) const;
Bool ValidateBufferName(Uint index) const;
Bool ValidateBufferObject(Uint index) const;
// VertexArray
Vector<Uint> GenVertexArrayNames(Uint number);
@@ -37,10 +39,21 @@ namespace MobileGL {
void BindVertexArray(Uint index);
SharedPtr<VertexArrayObject> CreateVertexArrayObject(Uint index);
void MarkVertexArrayForDeletion(Uint index);
bool ValidateVertexArrayName(Uint index) const;
bool ValidateVertexArrayObject(Uint index) const;
Bool ValidateVertexArrayName(Uint index) const;
Bool ValidateVertexArrayObject(Uint index) const;
SharedPtr<VertexArrayObject> GetBoundVertexArray();
// Texture
Vector<Uint> GenTextureNames(Uint number);
SharedPtr<ITextureObject> GetTextureObject(Uint index);
SharedPtr<ITextureObject> CreateTextureObject(Uint index, TextureTarget target);
void MarkTextureObjectForDeletion(Uint index);
TextureUnit& GetTextureUnitObject();
Bool ValidateTextureName(Uint index) const;
Bool ValidateTextureObject(Uint index) const;
Int GetActiveTextureUnit() const;
void SetActiveTextureUnit(Int unit);
private:
// Error
ErrorState m_errorState;
@@ -50,6 +63,9 @@ namespace MobileGL {
// VertexArray
VertexArrayState m_vertexArrayState;
// Texture
TextureState m_textureState;
};
} // namespace GLState
@@ -0,0 +1,100 @@
#pragma once
#include "MG_Util/Types.h"
#include <Includes.h>
namespace MobileGL {
enum class SamplerFilterMode {
Nearest,
Linear,
SamplerFilterCount,
Unknown = -1
};
enum class SamplerMipmapMode {
None,
Nearest,
SamplerMipmapModeCount,
Unknown = -1
};
enum class SamplerWrapMode {
ClampToEdge,
MirroredRepeat,
Repeat,
ClampToBorder,
SamplerWrapModeCount,
Unknown = -1
};
enum class SamplerCompareMode {
None,
CompareToTexture,
SamplerCompareModeCount,
Unknown = -1
};
enum class CompareFunc {
Never,
Less,
Equal,
LessEqual,
Greater,
NotEqual,
GreaterEqual,
Always,
CompareFuncCount,
Unknown = -1
};
namespace MG_State {
namespace GLState {
class SamplerObject {
public:
SamplerObject()
: m_wrapS(SamplerWrapMode::Repeat), m_wrapT(SamplerWrapMode::Repeat),
m_wrapR(SamplerWrapMode::Repeat), m_minFilter(SamplerFilterMode::Linear),
m_magFilter(SamplerFilterMode::Linear), m_mipmapMode(SamplerMipmapMode::None), m_minLod(0.0f),
m_maxLod(1000.0f), m_lodBias(0.0f), m_compareMode(SamplerCompareMode::None),
m_compareFunc(CompareFunc::Less) {}
void SetWrapS(SamplerWrapMode mode) { m_wrapS = mode; }
void SetWrapT(SamplerWrapMode mode) { m_wrapT = mode; }
void SetWrapR(SamplerWrapMode mode) { m_wrapR = mode; }
void SetMinFilter(SamplerFilterMode mode) { m_minFilter = mode; }
void SetMagFilter(SamplerFilterMode mode) { m_magFilter = mode; }
void SetMipmapMode(SamplerMipmapMode mode) { m_mipmapMode = mode; }
void SetLodRange(Float minLod, Float maxLod) {
if (minLod > maxLod) {
THROW_EXCEPTION("minLod cannot be greater than maxLod");
}
m_minLod = minLod;
m_maxLod = maxLod;
}
void SetLodBias(Float bias) { m_lodBias = bias; }
void SetCompareFunc(CompareFunc func) { m_compareFunc = func; }
void SetCompareMode(SamplerCompareMode mode) { m_compareMode = mode; }
SamplerWrapMode GetWrapS() const { return m_wrapS; }
SamplerWrapMode GetWrapT() const { return m_wrapT; }
SamplerWrapMode GetWrapR() const { return m_wrapR; }
SamplerFilterMode GetMinFilter() const { return m_minFilter; }
SamplerFilterMode GetMagFilter() const { return m_magFilter; }
SamplerMipmapMode GetMipmapMode() const { return m_mipmapMode; }
Float GetMinLod() const { return m_minLod; }
Float GetMaxLod() const { return m_maxLod; }
Float GetLodBias() const { return m_lodBias; }
SamplerCompareMode GetCompareMode() const { return m_compareMode; }
CompareFunc GetCompareFunc() const { return m_compareFunc; }
private:
SamplerWrapMode m_wrapS, m_wrapT, m_wrapR;
SamplerFilterMode m_minFilter, m_magFilter;
SamplerMipmapMode m_mipmapMode;
Float m_minLod, m_maxLod;
Float m_lodBias;
SamplerCompareMode m_compareMode;
CompareFunc m_compareFunc;
};
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,72 @@
#include "TextureObject.h"
#include <MG_Util/Metrics/TextureMetrics.h>
namespace MobileGL {
namespace MG_State {
namespace GLState {
// TextureObjectBase implementations
TextureObjectBase::TextureObjectBase(TextureTarget target) : m_target(target), m_sampler(nullptr) {}
void TextureObjectBase::SetMipmapLevel(const MipmapLevelInput& level) {
SetMipmapImpl(level);
}
TextureSizedInternalFormat TextureObjectBase::GetFormat() const {
return m_internalFormat;
}
TextureTarget TextureObjectBase::GetTarget() const {
return m_target;
}
IntVec3 TextureObjectBase::GetBaseSize() const {
if (m_mipmaps.empty()) {
return {0, 0, 0};
}
return m_mipmaps[0].size;
}
SharedPtr<SamplerObject> TextureObjectBase::GetSamplerObject() const {
return m_sampler;
}
const Vector<MipmapLevelInternal>& TextureObjectBase::GetMipmaps() const {
return m_mipmaps;
}
void TextureObjectBase::SetInternalFormat(TextureSizedInternalFormat format) {
m_internalFormat = format;
}
// TextureObject1D
TextureObject1D::TextureObject1D() : TextureObjectBase(TextureTarget::Texture1D) {}
void TextureObject1D::SetMipmapImpl(const MipmapLevelInput& level) {
if (level.size.x() > 0) {
m_mipmaps.push_back(level);
}
}
// TextureObject2D
TextureObject2D::TextureObject2D() : TextureObjectBase(TextureTarget::Texture2D) {}
void TextureObject2D::SetMipmapImpl(const MipmapLevelInput& level) {
if (level.size.x() > 0 && level.size.y() > 0) {
m_mipmaps.push_back(level);
}
}
// TextureObject3D
TextureObject3D::TextureObject3D() : TextureObjectBase(TextureTarget::Texture3D) {}
void TextureObject3D::SetMipmapImpl(const MipmapLevelInput& level) {
if (level.size.x() > 0 && level.size.y() > 0 && level.size.z() > 0) {
m_mipmaps.push_back(level);
}
}
// TODO: Add other texture types as needed
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,221 @@
#pragma once
#include <Includes.h>
#include <MG_Util/Math/VectorTypes.h>
#include "MG_Util/Types.h"
#include "SamplerObject.h"
namespace MobileGL {
enum class TextureTarget {
Texture1D,
Texture2D,
Texture3D,
TextureCubeMap,
Texture2DArray,
Texture2DMultisample,
TextureCubeMapArray,
TextureTargetCount,
Unknown = -1
};
enum class TextureInputFormat {
Red,
RG,
RGB,
BFR,
RGBA,
BGRA,
RInteger,
RGInteger,
RGBInteger,
BGRInteger,
RGBAInteger,
BGRAInteger,
StencilIndex,
DepthComponent,
DepthStencil,
FormatCount,
Unknown = -1
};
enum class TextureSizedInternalFormat {
R8,
R8Snorm,
R16,
R16Snorm,
RG8,
RG8Snorm,
RG16,
RG16Snorm,
R3G3B2,
RGB4,
RGB5,
RGB8,
RGB8Snorm,
RGB10,
RGB12,
RGB16Snorm,
RGBA2,
RGBA4,
RGB5A1,
RGBA8,
RGBA8Snorm,
RGB10A2,
RGB10A2UI,
RGBA12,
RGBA16,
SRGB8,
SRGB8Alpha8,
R16F,
RG16F,
RGB16F,
RGBA16F,
R32F,
RG32F,
RGB32F,
RGBA32F,
R11FG11FB10F,
RGB9E5,
R8I,
R8UI,
R16I,
R16UI,
R32I,
R32UI,
RG8I,
RG8UI,
RG16I,
RG16UI,
RG32I,
RG32UI,
RGB8I,
RGB8UI,
RGB16I,
RGB16UI,
RGB32I,
RGB32UI,
RGBA8I,
RGBA8UI,
RGBA16I,
RGBA16UI,
RGBA32I,
RGBA32UI,
TextureSizedInternalFormatCount,
Unknown = -1
};
enum class TexturePixelDataType {
UnsignedByte,
Byte,
UnsignedShort,
Short,
UnsignedInt,
Int,
Float,
UnsignedByte332,
UnsignedByte233Rev,
UnsignedShort565,
UnsignedShort565Rev,
UnsignedShort4444,
UnsignedShort4444Rev,
UnsignedShort5551,
UnsignedShort1555Rev,
UnsignedInt8888,
UnsignedInt8888Rev,
UnsignedInt1010102,
UnsignedInt2101010Rev,
TypeCount,
Unknown = -1
};
namespace MG_State {
namespace GLState {
struct MipmapLevelBase {
IntVec3 size = {0, 0, 0};
Int level = 0;
Bool compressed = false;
Int compressedSize = 0;
};
struct MipmapLevelInput : MipmapLevelBase {
DataPtr inputData = {nullptr, 0};
};
struct MipmapLevelInternal : MipmapLevelBase {
Data data;
MipmapLevelInternal(const MipmapLevelInput& input) : MipmapLevelBase(input) {
if (input.inputData.data && input.inputData.size > 0) {
const Uint8* src = static_cast<const Uint8*>(input.inputData.data);
data.assign(src, src + input.inputData.size);
}
}
};
class ITextureObject {
public:
using TargetEnum = TextureTarget;
virtual ~ITextureObject() = default;
virtual void SetMipmapLevel(const MipmapLevelInput& level) = 0;
virtual TextureSizedInternalFormat GetFormat() const = 0;
virtual TextureTarget GetTarget() const = 0;
virtual IntVec3 GetBaseSize() const = 0;
virtual SharedPtr<SamplerObject> GetSamplerObject() const = 0;
virtual const Vector<MipmapLevelInternal>& GetMipmaps() const = 0;
virtual void SetInternalFormat(TextureSizedInternalFormat format) = 0;
};
class TextureObjectBase : public ITextureObject {
public:
TextureObjectBase(TextureTarget target);
virtual ~TextureObjectBase() = default;
void SetMipmapLevel(const MipmapLevelInput& level) override;
TextureSizedInternalFormat GetFormat() const override;
TextureTarget GetTarget() const override;
IntVec3 GetBaseSize() const override;
SharedPtr<SamplerObject> GetSamplerObject() const override;
const Vector<MipmapLevelInternal>& GetMipmaps() const override;
void SetInternalFormat(TextureSizedInternalFormat format) override;
protected:
virtual void SetMipmapImpl(const MipmapLevelInput& level) = 0;
const TextureTarget m_target = TextureTarget::Unknown;
TextureSizedInternalFormat m_internalFormat = TextureSizedInternalFormat::Unknown;
Vector<MipmapLevelInternal> m_mipmaps = {};
SharedPtr<SamplerObject> m_sampler = nullptr;
};
class TextureObject1D : public TextureObjectBase {
public:
explicit TextureObject1D();
protected:
void SetMipmapImpl(const MipmapLevelInput& level) override;
};
class TextureObject2D : public TextureObjectBase {
public:
explicit TextureObject2D();
protected:
void SetMipmapImpl(const MipmapLevelInput& level) override;
};
class TextureObject3D : public TextureObjectBase {
public:
explicit TextureObject3D();
protected:
void SetMipmapImpl(const MipmapLevelInput& level) override;
};
// TODO: Add other texture types as needed
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,91 @@
#include "TextureState.h"
#include "MG_State/GLState/TextureState/TextureObject.h"
#include "MG_Util/Types.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
TextureState::TextureState() : m_indexGenerator(1024, 1) {
for (int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) {
m_textureUnits[i] = TextureUnit();
}
}
SharedPtr<ITextureObject> TextureState::GetTextureObject(Uint index) {
auto it = m_textureObjects.find(index);
if (it != m_textureObjects.end()) {
return it->second;
}
return nullptr;
}
Vector<Uint> TextureState::GenerateNames(Uint number) {
Vector<Uint> textures(number);
m_indexGenerator.Generate(number, textures.data());
return textures;
}
SharedPtr<ITextureObject> TextureState::CreateTextureObject(Uint index, TextureTarget target) {
SharedPtr<ITextureObject> textureObject = nullptr;
switch (target) {
case TextureTarget::Texture1D:
textureObject = MakeShared<TextureObject1D>();
break;
case TextureTarget::Texture2D:
textureObject = MakeShared<TextureObject2D>();
break;
case TextureTarget::Texture3D:
textureObject = MakeShared<TextureObject3D>();
break;
default:
// TODO: implement more texture types
return nullptr;
}
m_textureObjects[index] = textureObject;
return textureObject;
}
void TextureState::MarkTextureObjectForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) {
auto it = m_textureObjects.find(index);
if (it != m_textureObjects.end()) {
for (auto& unit : m_textureUnits) {
auto& bindingSlots = unit.GetAllBindingSlots();
for (SizeT i = 0; i < bindingSlots.size(); ++i) {
if (bindingSlots[i].GetBoundObject() == it->second) {
bindingSlots[i].Bind(nullptr);
}
}
}
m_textureObjects.erase(it);
}
m_indexGenerator.Delete(index);
}
}
TextureUnit& TextureState::GetUnitObject() {
if (m_activeTextureUnit < 0 || m_activeTextureUnit >= MAX_TEXTURE_IMAGE_UNITS) {
THROW_EXCEPTION("Active texture unit is out of range");
}
return m_textureUnits[m_activeTextureUnit];
}
Int TextureState::GetActiveTextureUnit() const {
return m_activeTextureUnit;
}
void TextureState::SetActiveTextureUnit(Int unit) {
m_activeTextureUnit = unit;
}
Bool TextureState::ValidateName(Uint index) const {
return m_indexGenerator.IsValid(index);
}
Bool TextureState::ValidateTextureObject(Uint index) const {
return m_textureObjects.find(index) != m_textureObjects.end();
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,35 @@
#pragma once
#include <Includes.h>
#include <MG_Util/Miscellany/IndexGenerator.h>
#include "MG_State/GLState/TextureState/TextureObject.h"
#include "MG_Util/Types.h"
#include "TextureUnit.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
class TextureState {
public:
static constexpr int MAX_TEXTURE_IMAGE_UNITS = 32;
TextureState();
Vector<Uint> GenerateNames(Uint number);
SharedPtr<ITextureObject> CreateTextureObject(Uint index, TextureTarget target);
SharedPtr<ITextureObject> GetTextureObject(Uint index);
TextureUnit& GetUnitObject();
Int GetActiveTextureUnit() const;
void SetActiveTextureUnit(Int unit);
void MarkTextureObjectForDeletion(Uint index);
Bool ValidateName(Uint index) const;
Bool ValidateTextureObject(Uint index) const;
private:
Int m_activeTextureUnit = 0;
Array<TextureUnit, MAX_TEXTURE_IMAGE_UNITS> m_textureUnits;
IndexGenerator<Uint> m_indexGenerator;
UnorderedMap<GLuint, SharedPtr<ITextureObject>> m_textureObjects;
};
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,23 @@
#include "TextureUnit.h"
#include "MG_Util/Types.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
TextureUnit::TextureUnit() : m_sampler(nullptr) {
for (int i = 0; i < (int)TextureTarget::TextureTargetCount; ++i) {
m_slots[i] = BindingSlot<ITextureObject>(static_cast<TextureTarget>(i));
}
}
BindingSlot<ITextureObject>& TextureUnit::GetBindingSlot(TextureTarget target) {
return m_slots[(int)target];
}
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& TextureUnit::
GetAllBindingSlots() {
return m_slots;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,23 @@
#pragma once
#include <Includes.h>
#include "MG_State/GLState/TextureState/SamplerObject.h"
#include "MG_Util/Types.h"
#include "TextureObject.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
class TextureUnit {
public:
TextureUnit();
BindingSlot<ITextureObject>& GetBindingSlot(TextureTarget target);
SharedPtr<SamplerObject> GetSamplerObject() const;
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& GetAllBindingSlots();
private:
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount> m_slots;
SharedPtr<SamplerObject> m_sampler;
};
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
+191
View File
@@ -0,0 +1,191 @@
#pragma once
#include <Includes.h>
namespace MobileGL {
template <typename Derived, typename T, SizeT N>
struct VecBase {
Array<T, N> data;
VecBase() { std::fill(data.begin(), data.end(), T(0)); }
VecBase(std::initializer_list<T> init) {
std::copy_n(init.begin(), std::min(N, init.size()), data.begin());
if (init.size() < N) {
std::fill(data.begin() + init.size(), data.end(), T(0));
}
}
explicit VecBase(T scalar) { std::fill(data.begin(), data.end(), scalar); }
T& operator[](SizeT index) {
if (index >= N) throw std::out_of_range("Vector index out of range");
return data[index];
}
const T& operator[](SizeT index) const {
if (index >= N) throw std::out_of_range("Vector index out of range");
return data[index];
}
bool operator==(const VecBase& rhs) const { return data == rhs.data; }
bool operator!=(const VecBase& rhs) const { return !(*this == rhs); }
Derived operator+(const VecBase& rhs) const {
Derived result;
for (SizeT i = 0; i < N; ++i)
result[i] = data[i] + rhs[i];
return result;
}
Derived operator-(const VecBase& rhs) const {
Derived result;
for (SizeT i = 0; i < N; ++i)
result[i] = data[i] - rhs[i];
return result;
}
Derived operator*(T scalar) const {
Derived result;
for (SizeT i = 0; i < N; ++i)
result[i] = data[i] * scalar;
return result;
}
Derived operator/(T scalar) const {
if (scalar == 0) throw std::domain_error("Division by zero");
T inv = T(1) / scalar;
return *this * inv;
}
T Dot(const VecBase& rhs) const {
T result = T(0);
for (SizeT i = 0; i < N; ++i)
result += data[i] * rhs[i];
return result;
}
T Length() const { return std::sqrt(Dot(*this)); }
Derived Normalized() const {
T len = Length();
if (len > 0) {
return *this * (T(1) / len);
}
return static_cast<const Derived&>(*this);
}
};
template <typename T>
struct Vec2 : public VecBase<Vec2<T>, T, 2> {
using Base = VecBase<Vec2<T>, T, 2>;
using Base::Base;
Vec2(T x, T y) : Base{x, y} {}
T& x() { return (*this)[0]; }
T& y() { return (*this)[1]; }
const T& x() const { return (*this)[0]; }
const T& y() const { return (*this)[1]; }
T Cross(const Vec2& rhs) const { return x() * rhs.y() - y() * rhs.x(); }
Vec2 Rotated(T angle) const {
T cosA = std::cos(angle);
T sinA = std::sin(angle);
return {x() * cosA - y() * sinA, x() * sinA + y() * cosA};
}
};
template <typename T>
struct Vec3 : public VecBase<Vec3<T>, T, 3> {
using Base = VecBase<Vec3<T>, T, 3>;
using Base::Base;
Vec3(T x, T y, T z) : Base{x, y, z} {}
explicit Vec3(const Vec2<T>& v2, T z = T(0)) : Base{v2.x(), v2.y(), z} {}
T& x() { return (*this)[0]; }
T& y() { return (*this)[1]; }
T& z() { return (*this)[2]; }
const T& x() const { return (*this)[0]; }
const T& y() const { return (*this)[1]; }
const T& z() const { return (*this)[2]; }
Vec2<T> xy() const { return {x(), y()}; }
Vec2<T> xz() const { return {x(), z()}; }
Vec2<T> yz() const { return {y(), z()}; }
Vec3 Cross(const Vec3& rhs) const {
return {y() * rhs.z() - z() * rhs.y(), z() * rhs.x() - x() * rhs.z(), x() * rhs.y() - y() * rhs.x()};
}
};
template <typename T>
struct Vec4 : public VecBase<Vec4<T>, T, 4> {
using Base = VecBase<Vec4<T>, T, 4>;
using Base::Base;
Vec4(T x, T y, T z, T w) : Base{x, y, z, w} {}
explicit Vec4(const Vec3<T>& v3, T w = T(1)) : Base{v3.x(), v3.y(), v3.z(), w} {}
T& x() { return (*this)[0]; }
T& y() { return (*this)[1]; }
T& z() { return (*this)[2]; }
T& w() { return (*this)[3]; }
const T& x() const { return (*this)[0]; }
const T& y() const { return (*this)[1]; }
const T& z() const { return (*this)[2]; }
const T& w() const { return (*this)[3]; }
Vec3<T> xyz() const { return {x(), y(), z()}; }
Vec3<T> Homogenized() const { return (w() != 0) ? xyz() / w() : xyz(); }
};
using IntVec2 = Vec2<Int32>;
using IntVec3 = Vec3<Int32>;
using IntVec4 = Vec4<Int32>;
using UintVec2 = Vec2<Uint32>;
using UintVec3 = Vec3<Uint32>;
using UintVec4 = Vec4<Uint32>;
using FloatVec2 = Vec2<Float>;
using FloatVec3 = Vec3<Float>;
using FloatVec4 = Vec4<Float>;
using Size2D = IntVec2;
using Size3D = IntVec3;
using TextureSize = IntVec3;
using ColorRGB = FloatVec3;
using ColorRGBA = FloatVec4;
using ColorRGB8 = UintVec3;
using ColorRGBA8 = UintVec4;
namespace MG_Util {
template <typename Derived, typename T, SizeT N>
Derived Lerp(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b, Float t) {
Derived result;
for (SizeT i = 0; i < N; ++i)
result[i] = a[i] + (b[i] - a[i]) * t;
return result;
}
template <typename Derived, typename T, SizeT N>
Derived MultiplyComponents(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b) {
Derived result;
for (SizeT i = 0; i < N; ++i)
result[i] = a[i] * b[i];
return result;
}
template <typename Derived, typename T, SizeT N>
T Distance(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b) {
return (a - b).Length();
}
inline FloatVec3 Reflect(const FloatVec3& incident, const FloatVec3& normal) {
return incident - normal * (2.0f * incident.Dot(normal));
}
} // namespace MG_Util
} // namespace MobileGL
@@ -0,0 +1,85 @@
#include "TextureMetrics.h"
namespace MobileGL {
namespace MG_Util {
SizeT GetTexturePixelSize(TextureSizedInternalFormat internal) {
switch (internal) {
case TextureSizedInternalFormat::R8:
case TextureSizedInternalFormat::R8Snorm:
case TextureSizedInternalFormat::R8I:
case TextureSizedInternalFormat::R8UI:
return 1;
case TextureSizedInternalFormat::R16:
case TextureSizedInternalFormat::R16Snorm:
case TextureSizedInternalFormat::R16I:
case TextureSizedInternalFormat::R16UI:
case TextureSizedInternalFormat::R16F:
case TextureSizedInternalFormat::RG8:
case TextureSizedInternalFormat::RG8Snorm:
case TextureSizedInternalFormat::RG8I:
case TextureSizedInternalFormat::RG8UI:
return 2;
case TextureSizedInternalFormat::R3G3B2:
case TextureSizedInternalFormat::RGB4:
case TextureSizedInternalFormat::RGB5:
case TextureSizedInternalFormat::RGB8:
case TextureSizedInternalFormat::RGB8Snorm:
case TextureSizedInternalFormat::SRGB8:
case TextureSizedInternalFormat::RGB8I:
case TextureSizedInternalFormat::RGB8UI:
return 3;
case TextureSizedInternalFormat::RGBA2:
case TextureSizedInternalFormat::RGBA4:
case TextureSizedInternalFormat::RGB5A1:
case TextureSizedInternalFormat::RGBA8:
case TextureSizedInternalFormat::RGBA8Snorm:
case TextureSizedInternalFormat::RGBA8I:
case TextureSizedInternalFormat::RGBA8UI:
case TextureSizedInternalFormat::SRGB8Alpha8:
case TextureSizedInternalFormat::RGB10A2:
case TextureSizedInternalFormat::RGB10A2UI:
case TextureSizedInternalFormat::R32F:
case TextureSizedInternalFormat::RG16:
case TextureSizedInternalFormat::RG16Snorm:
case TextureSizedInternalFormat::RG16I:
case TextureSizedInternalFormat::RG16UI:
case TextureSizedInternalFormat::RG16F:
return 4;
case TextureSizedInternalFormat::RGBA12:
case TextureSizedInternalFormat::RGBA16:
case TextureSizedInternalFormat::RGBA16I:
case TextureSizedInternalFormat::RGBA16UI:
case TextureSizedInternalFormat::RGBA16F:
case TextureSizedInternalFormat::RG32F:
case TextureSizedInternalFormat::RG32I:
case TextureSizedInternalFormat::RG32UI:
return 8;
case TextureSizedInternalFormat::RGB16F:
case TextureSizedInternalFormat::RGB32F:
case TextureSizedInternalFormat::RGB16I:
case TextureSizedInternalFormat::RGB16UI:
case TextureSizedInternalFormat::RGB32I:
case TextureSizedInternalFormat::RGB32UI:
return 12;
case TextureSizedInternalFormat::RGBA32F:
case TextureSizedInternalFormat::RGBA32I:
case TextureSizedInternalFormat::RGBA32UI:
return 16;
case TextureSizedInternalFormat::R11FG11FB10F:
case TextureSizedInternalFormat::RGB9E5:
return 4;
default:
return 0;
}
}
} // namespace MG_Util
} // namespace MobileGL
@@ -0,0 +1,9 @@
#pragma once
#include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h>
namespace MobileGL {
namespace MG_Util {
SizeT GetTexturePixelSize(TextureSizedInternalFormat internal);
}
} // namespace MobileGL